Developer Portal
A curated repository of full hosted applications and handy utility scripts.
"Imagine a technological advancement coming along that is so profound, the aspirations of the individual are only oppressed by the stretch of their imaginationβlike the AI Mad Hatter skipping through the rabbit hole of ones and zeros, creating anything that comes to mind, creating binary chaos for the hell of it, to learn from it, to do it just because you can."
Hosted Applications
Utility Scripts

Language Reference Guide
Aetherforge β Procedural Dungeon Engine
An over-engineered procedural multi-layer dungeon generator featuring Binary Space Partitioning (BSP), Cellular Automata, A* corridor pathfinding, dynamic themes, weighted entity placement, and ANSI/PPM rendering.
1#!/usr/bin/env python32"""3ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ4β AETHERFORGE β Procedural Multi-Layer Dungeon Generator β5β Extremely over-engineered for fun β6β β7β Features: β8β β’ Binary Space Partitioning (BSP) room generation β9β β’ Cellular automata cave refinement β10β β’ Multi-level dungeons with vertical connectivity β11β β’ A* pathfinding for intelligent corridor carving β12β β’ Procedural theme system (Stone, Crystal, Biomechanical, Eldritch) β13β β’ Seeded RNG for full reproducibility β14β β’ Entity placement (monsters, loot, traps, stairs) with weighted rarity β15β β’ ASCII + ANSI truecolor rendering β16β β’ Export to JSON / PPM image / interactive terminal viewer β17β β’ Full CLI with subcommands + config profiles β18β β’ Logging, progress, statistics, and validation β19ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ20"""21 22from __future__ import annotations23 24import argparse25import hashlib26import json27import logging28import math29import random30import sys31import time32from collections import deque33from dataclasses import dataclass, field, asdict34from enum import Enum, auto35from pathlib import Path36from typing import Dict, List, Optional, Set, Tuple, Iterator37 38# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ39# Core geometry & helpers40# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ41 42@dataclass(frozen=True, order=True)43class Point:44 x: int45 y: int46 47 def __add__(self, other: Point) -> Point:48 return Point(self.x + other.x, self.y + other.y)49 50 def neighbors4(self) -> Iterator[Point]:51 yield Point(self.x + 1, self.y)52 yield Point(self.x - 1, self.y)53 yield Point(self.x, self.y + 1)54 yield Point(self.x, self.y - 1)55 56 def neighbors8(self) -> Iterator[Point]:57 for dx in (-1, 0, 1):58 for dy in (-1, 0, 1):59 if dx == 0 and dy == 0:60 continue61 yield Point(self.x + dx, self.y + dy)62 63@dataclass64class Rect:65 x: int66 y: int67 w: int68 h: int69 70 @property71 def center(self) -> Point:72 return Point(self.x + self.w // 2, self.y + self.h // 2)73 74 @property75 def area(self) -> int:76 return self.w * self.h77 78 def intersects(self, other: Rect) -> bool:79 return not (self.x + self.w <= other.x or other.x + other.w <= self.x or80 self.y + self.h <= other.y or other.y + other.h <= self.y)81 82 def inflate(self, amount: int) -> Rect:83 return Rect(self.x - amount, self.y - amount, self.w + 2 * amount, self.h + 2 * amount)84 85class Tile(Enum):86 VOID = auto()87 WALL = auto()88 FLOOR = auto()89 DOOR = auto()90 STAIRS_DOWN = auto()91 STAIRS_UP = auto()92 WATER = auto()93 LAVA = auto()94 CRYSTAL = auto()95 CORRUPTION = auto()96 97class EntityType(Enum):98 MONSTER = auto()99 LOOT = auto()100 TRAP = auto()101 SHRINE = auto()102 NPC = auto()103 104@dataclass105class Entity:106 kind: EntityType107 name: str108 rarity: float # 0.0 β 1.0109 glyph: str110 color: Tuple[int, int, int]111 data: Dict = field(default_factory=dict)112 113# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ114# Themes115# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ116 117@dataclass118class Theme:119 name: str120 wall_glyph: str121 floor_glyph: str122 door_glyph: str123 wall_color: Tuple[int, int, int]124 floor_color: Tuple[int, int, int]125 door_color: Tuple[int, int, int]126 special_tiles: Dict[Tile, Tuple[str, Tuple[int, int, int]]]127 monster_pool: List[Tuple[str, str, float]] # name, glyph, rarity128 loot_pool: List[Tuple[str, str, float]]129 130THEMES = {131 "stone": Theme(132 name="Ancient Stone",133 wall_glyph="β", floor_glyph="Β·", door_glyph="+",134 wall_color=(90, 90, 110), floor_color=(50, 50, 60),135 door_color=(140, 100, 60),136 special_tiles={137 Tile.WATER: ("β", (40, 90, 160)),138 Tile.CRYSTAL: ("β§", (180, 220, 255)),139 },140 monster_pool=[141 ("Goblin", "g", 0.6), ("Skeleton", "s", 0.45),142 ("Orc", "O", 0.3), ("Wraith", "W", 0.12), ("Ancient Guardian", "G", 0.04)143 ],144 loot_pool=[145 ("Copper Coin", "$", 0.7), ("Iron Sword", "/", 0.35),146 ("Healing Potion", "!", 0.4), ("Spell Scroll", "?", 0.18),147 ("Amulet of Yendor", "Ξ©", 0.01)148 ]149 ),150 "crystal": Theme(151 name="Crystal Caverns",152 wall_glyph="β", floor_glyph="β", door_glyph="β",153 wall_color=(120, 60, 180), floor_color=(40, 20, 70),154 door_color=(200, 150, 255),155 special_tiles={156 Tile.CRYSTAL: ("β¦", (220, 180, 255)),157 Tile.WATER: ("β", (80, 180, 255)),158 },159 monster_pool=[160 ("Crystal Spider", "c", 0.55), ("Geode Golem", "G", 0.25),161 ("Prism Drake", "D", 0.08), ("Void Shard", "v", 0.15)162 ],163 loot_pool=[164 ("Prism Shard", "*", 0.5), ("Resonance Crystal", "β", 0.25),165 ("Ethereal Blade", "β ", 0.12), ("Heart of the Cavern", "β₯", 0.03)166 ]167 ),168 "biomech": Theme(169 name="Biomechanical Hive",170 wall_glyph="β¬", floor_glyph="β", door_glyph="β ",171 wall_color=(80, 140, 90), floor_color=(30, 50, 35),172 door_color=(180, 220, 100),173 special_tiles={174 Tile.CORRUPTION: ("β", (120, 40, 40)),175 Tile.LAVA: ("β", (220, 80, 20)),176 },177 monster_pool=[178 ("Flesh Drone", "d", 0.6), ("Spinal Crawler", "C", 0.35),179 ("Hive Queen", "Q", 0.07), ("Nanite Swarm", "n", 0.2)180 ],181 loot_pool=[182 ("Bio-Gel", "o", 0.55), ("Neural Implant", "Β€", 0.22),183 ("Organic Blade", "β«", 0.15), ("Core Sample", "β", 0.05)184 ]185 ),186 "eldritch": Theme(187 name="Eldritch Depths",188 wall_glyph="β", floor_glyph=" ", door_glyph="Ξ",189 wall_color=(60, 20, 80), floor_color=(15, 5, 25),190 door_color=(160, 40, 180),191 special_tiles={192 Tile.CORRUPTION: ("β", (90, 20, 110)),193 Tile.WATER: ("β", (40, 10, 70)),194 },195 monster_pool=[196 ("Shoggoth Spawn", "s", 0.5), ("Cultist", "k", 0.4),197 ("Star Vampire", "V", 0.18), ("The Unnamed", "?", 0.05)198 ],199 loot_pool=[200 ("Tome of the Void", "T", 0.3), ("Eye of the Deep", "β", 0.2),201 ("Black Star", "β
", 0.08), ("Fragment of Azathoth", "β", 0.02)202 ]203 ),204}205 206# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ207# BSP Node208# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ209 210class BSPNode:211 def __init__(self, rect: Rect):212 self.rect = rect213 self.left: Optional[BSPNode] = None214 self.right: Optional[BSPNode] = None215 self.room: Optional[Rect] = None216 217 @property218 def is_leaf(self) -> bool:219 return self.left is None and self.right is None220 221 def split(self, min_size: int, rng: random.Random) -> bool:222 if not self.is_leaf:223 return False224 225 # Decide split direction226 if self.rect.w > self.rect.h and self.rect.w / self.rect.h >= 1.25:227 horizontal = False228 elif self.rect.h > self.rect.w and self.rect.h / self.rect.w >= 1.25:229 horizontal = True230 else:231 horizontal = rng.random() < 0.5232 233 max_size = (self.rect.h if horizontal else self.rect.w) - min_size234 if max_size <= min_size:235 return False236 237 split_pos = rng.randint(min_size, max_size)238 239 if horizontal:240 self.left = BSPNode(Rect(self.rect.x, self.rect.y, self.rect.w, split_pos))241 self.right = BSPNode(Rect(self.rect.x, self.rect.y + split_pos, self.rect.w, self.rect.h - split_pos))242 else:243 self.left = BSPNode(Rect(self.rect.x, self.rect.y, split_pos, self.rect.h))244 self.right = BSPNode(Rect(self.rect.x + split_pos, self.rect.y, self.rect.w - split_pos, self.rect.h))245 246 return True247 248 def create_room(self, rng: random.Random, min_room: int, max_room: int) -> None:249 if not self.is_leaf:250 if self.left:251 self.left.create_room(rng, min_room, max_room)252 if self.right:253 self.right.create_room(rng, min_room, max_room)254 return255 256 room_w = rng.randint(min_room, min(max_room, self.rect.w - 2))257 room_h = rng.randint(min_room, min(max_room, self.rect.h - 2))258 room_x = self.rect.x + rng.randint(1, self.rect.w - room_w - 1)259 room_y = self.rect.y + rng.randint(1, self.rect.h - room_h - 1)260 self.room = Rect(room_x, room_y, room_w, room_h)261 262 def get_leaves(self) -> List[BSPNode]:263 if self.is_leaf:264 return [self]265 leaves = []266 if self.left:267 leaves.extend(self.left.get_leaves())268 if self.right:269 leaves.extend(self.right.get_leaves())270 return leaves271 272 def get_room(self) -> Optional[Rect]:273 if self.room:274 return self.room275 if self.left:276 r = self.left.get_room()277 if r:278 return r279 if self.right:280 return self.right.get_room()281 return None282 283# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ284# A* Pathfinding (for corridors)285# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ286 287def astar(start: Point, goal: Point, walkable: Set[Point], width: int, height: int) -> List[Point]:288 def heuristic(a: Point, b: Point) -> float:289 return abs(a.x - b.x) + abs(a.y - b.y)290 291 open_set = {start}292 came_from: Dict[Point, Point] = {}293 g_score = {start: 0.0}294 f_score = {start: heuristic(start, goal)}295 296 while open_set:297 current = min(open_set, key=lambda p: f_score.get(p, float("inf")))298 if current == goal:299 path = []300 while current in came_from:301 path.append(current)302 current = came_from[current]303 path.append(start)304 return path[::-1]305 306 open_set.remove(current)307 for neighbor in current.neighbors4():308 if not (0 <= neighbor.x < width and 0 <= neighbor.y < height):309 continue310 # Prefer already walkable tiles but allow walls (we will carve)311 tentative_g = g_score[current] + (1.0 if neighbor in walkable else 1.8)312 313 if tentative_g < g_score.get(neighbor, float("inf")):314 came_from[neighbor] = current315 g_score[neighbor] = tentative_g316 f_score[neighbor] = tentative_g + heuristic(neighbor, goal)317 open_set.add(neighbor)318 319 return [] # no path (should be rare)320 321# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ322# The Dungeon itself323# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ324 325class Level:326 def __init__(self, width: int, height: int, depth: int, theme: Theme, rng: random.Random):327 self.width = width328 self.height = height329 self.depth = depth330 self.theme = theme331 self.rng = rng332 self.tiles: List[List[Tile]] = [[Tile.VOID for _ in range(width)] for _ in range(height)]333 self.entities: Dict[Point, Entity] = {}334 self.rooms: List[Rect] = []335 self.stairs_down: Optional[Point] = None336 self.stairs_up: Optional[Point] = None337 338 def in_bounds(self, p: Point) -> bool:339 return 0 <= p.x < self.width and 0 <= p.y < self.height340 341 def set_tile(self, p: Point, tile: Tile) -> None:342 if self.in_bounds(p):343 self.tiles[p.y][p.x] = tile344 345 def get_tile(self, p: Point) -> Tile:346 if self.in_bounds(p):347 return self.tiles[p.y][p.x]348 return Tile.VOID349 350 def carve_room(self, room: Rect) -> None:351 for y in range(room.y, room.y + room.h):352 for x in range(room.x, room.x + room.w):353 self.set_tile(Point(x, y), Tile.FLOOR)354 355 def carve_corridor(self, path: List[Point]) -> None:356 for p in path:357 self.set_tile(p, Tile.FLOOR)358 # occasionally make it wider359 if self.rng.random() < 0.15:360 for n in p.neighbors4():361 if self.get_tile(n) == Tile.WALL:362 self.set_tile(n, Tile.FLOOR)363 364 def place_walls(self) -> None:365 for y in range(self.height):366 for x in range(self.width):367 p = Point(x, y)368 if self.get_tile(p) == Tile.FLOOR:369 for n in p.neighbors8():370 if self.get_tile(n) == Tile.VOID:371 self.set_tile(n, Tile.WALL)372 373 def cellular_automata_pass(self, birth_limit: int = 4, death_limit: int = 3) -> None:374 """One pass of cellular automata to make caves more organic."""375 new_tiles = [[Tile.VOID for _ in range(self.width)] for _ in range(self.height)]376 for y in range(self.height):377 for x in range(self.width):378 p = Point(x, y)379 if self.get_tile(p) not in (Tile.FLOOR, Tile.WALL):380 new_tiles[y][x] = self.get_tile(p)381 continue382 wall_count = sum(1 for n in p.neighbors8() if self.get_tile(n) in (Tile.WALL, Tile.VOID))383 if self.get_tile(p) == Tile.FLOOR:384 new_tiles[y][x] = Tile.WALL if wall_count > death_limit else Tile.FLOOR385 else:386 new_tiles[y][x] = Tile.FLOOR if wall_count < birth_limit else Tile.WALL387 self.tiles = new_tiles388 389 def place_doors(self) -> None:390 for room in self.rooms:391 for y in range(room.y - 1, room.y + room.h + 1):392 for x in range(room.x - 1, room.x + room.w + 1):393 p = Point(x, y)394 if self.get_tile(p) != Tile.FLOOR:395 continue396 # Door candidate: floor tile adjacent to exactly two walls in a line397 walls = [n for n in p.neighbors4() if self.get_tile(n) == Tile.WALL]398 if len(walls) == 2 and (walls[0].x == walls[1].x or walls[0].y == walls[1].y):399 if self.rng.random() < 0.35:400 self.set_tile(p, Tile.DOOR)401 402 def place_special_tiles(self) -> None:403 for room in self.rooms:404 if self.rng.random() < 0.25:405 # small water/lava/crystal patch406 cx, cy = room.center.x, room.center.y407 for _ in range(self.rng.randint(3, 12)):408 p = Point(cx + self.rng.randint(-3, 3), cy + self.rng.randint(-3, 3))409 if self.get_tile(p) == Tile.FLOOR:410 special = self.rng.choice(list(self.theme.special_tiles.keys()))411 self.set_tile(p, special)412 413 def place_entities(self, density: float = 0.04) -> None:414 floor_tiles = [Point(x, y) for y in range(self.height) for x in range(self.width)415 if self.get_tile(Point(x, y)) == Tile.FLOOR]416 self.rng.shuffle(floor_tiles)417 418 count = int(len(floor_tiles) * density)419 for p in floor_tiles[:count]:420 if p in self.entities:421 continue422 roll = self.rng.random()423 if roll < 0.55:424 # monster425 name, glyph, rarity = self.rng.choices(426 self.theme.monster_pool,427 weights=[1.0 - r for _, _, r in self.theme.monster_pool]428 )[0]429 if self.rng.random() < rarity + 0.3:430 self.entities[p] = Entity(EntityType.MONSTER, name, rarity, glyph,431 (220, 60, 60))432 elif roll < 0.85:433 name, glyph, rarity = self.rng.choices(434 self.theme.loot_pool,435 weights=[1.0 - r for _, _, r in self.theme.loot_pool]436 )[0]437 self.entities[p] = Entity(EntityType.LOOT, name, rarity, glyph,438 (255, 215, 0))439 else:440 self.entities[p] = Entity(EntityType.TRAP, "Hidden Trap", 0.4, "^",441 (180, 40, 40))442 443 def place_stairs(self, is_first: bool, is_last: bool) -> None:444 if not self.rooms:445 return446 # Prefer larger rooms447 candidates = sorted(self.rooms, key=lambda r: r.area, reverse=True)448 if not is_first:449 room = candidates[0]450 self.stairs_up = room.center451 self.set_tile(self.stairs_up, Tile.STAIRS_UP)452 if not is_last:453 room = candidates[1] if len(candidates) > 1 else candidates[0]454 self.stairs_down = room.center455 self.set_tile(self.stairs_down, Tile.STAIRS_DOWN)456 457class Dungeon:458 def __init__(self, width: int, height: int, levels: int, theme_name: str,459 seed: Optional[int] = None, min_room: int = 5, max_room: int = 12):460 self.width = width461 self.height = height462 self.levels_count = levels463 self.theme = THEMES[theme_name]464 self.seed = seed if seed is not None else random.randint(0, 2**32 - 1)465 self.rng = random.Random(self.seed)466 self.min_room = min_room467 self.max_room = max_room468 self.levels: List[Level] = []469 470 def generate(self) -> None:471 logging.info(f"Forging {self.levels_count}-level dungeon | seed={self.seed} | theme={self.theme.name}")472 start = time.perf_counter()473 474 for depth in range(self.levels_count):475 logging.info(f" β Generating level {depth + 1}/{self.levels_count}...")476 level = Level(self.width, self.height, depth, self.theme, self.rng)477 self._generate_level(level)478 self.levels.append(level)479 480 elapsed = time.perf_counter() - start481 logging.info(f"Dungeon forged in {elapsed:.2f}s")482 483 def _generate_level(self, level: Level) -> None:484 # 1. BSP485 root = BSPNode(Rect(0, 0, self.width, self.height))486 self._split_bsp(root, max_depth=6)487 488 # 2. Rooms489 root.create_room(self.rng, self.min_room, self.max_room)490 leaves = root.get_leaves()491 for leaf in leaves:492 if leaf.room:493 level.carve_room(leaf.room)494 level.rooms.append(leaf.room)495 496 # 3. Connect rooms with A*497 walkable = {Point(x, y) for y in range(self.height) for x in range(self.width)498 if level.get_tile(Point(x, y)) == Tile.FLOOR}499 rooms = [leaf.room for leaf in leaves if leaf.room]500 for i in range(len(rooms) - 1):501 start = rooms[i].center502 goal = rooms[i + 1].center503 path = astar(start, goal, walkable, self.width, self.height)504 if path:505 level.carve_corridor(path)506 walkable.update(path)507 508 # 4. Walls + optional cellular pass for organic feel509 level.place_walls()510 if self.rng.random() < 0.6:511 level.cellular_automata_pass()512 513 # 5. Doors, specials, entities, stairs514 level.place_doors()515 level.place_special_tiles()516 level.place_entities(density=0.035 + level.depth * 0.008)517 level.place_stairs(is_first=(level.depth == 0),518 is_last=(level.depth == self.levels_count - 1))519 520 def _split_bsp(self, node: BSPNode, max_depth: int, depth: int = 0) -> None:521 if depth >= max_depth:522 return523 if node.split(min_size=self.min_room + 4, rng=self.rng):524 if node.left:525 self._split_bsp(node.left, max_depth, depth + 1)526 if node.right:527 self._split_bsp(node.right, max_depth, depth + 1)528 529 # ββ Rendering ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ530 531 def render_ascii(self, level_idx: int = 0, use_color: bool = True) -> str:532 level = self.levels[level_idx]533 lines = []534 for y in range(level.height):535 row = []536 for x in range(level.width):537 p = Point(x, y)538 tile = level.get_tile(p)539 entity = level.entities.get(p)540 541 if entity:542 glyph = entity.glyph543 color = entity.color544 else:545 glyph, color = self._tile_to_glyph(tile, level.theme)546 547 if use_color and sys.stdout.isatty():548 r, g, b = color549 row.append(f"\033[38;2;{r};{g};{b}m{glyph}\033[0m")550 else:551 row.append(glyph)552 lines.append("".join(row))553 return "\n".join(lines)554 555 def _tile_to_glyph(self, tile: Tile, theme: Theme) -> Tuple[str, Tuple[int, int, int]]:556 if tile == Tile.WALL:557 return theme.wall_glyph, theme.wall_color558 if tile == Tile.FLOOR:559 return theme.floor_glyph, theme.floor_color560 if tile == Tile.DOOR:561 return theme.door_glyph, theme.door_color562 if tile == Tile.STAIRS_DOWN:563 return ">", (255, 255, 100)564 if tile == Tile.STAIRS_UP:565 return "<", (255, 255, 100)566 if tile in theme.special_tiles:567 return theme.special_tiles[tile]568 return " ", (0, 0, 0)569 570 def export_json(self, path: Path) -> None:571 data = {572 "seed": self.seed,573 "theme": self.theme.name,574 "width": self.width,575 "height": self.height,576 "levels": []577 }578 for lvl in self.levels:579 level_data = {580 "depth": lvl.depth,581 "tiles": [[t.name for t in row] for row in lvl.tiles],582 "entities": {583 f"{p.x},{p.y}": {584 "kind": e.kind.name,585 "name": e.name,586 "rarity": e.rarity,587 "glyph": e.glyph588 } for p, e in lvl.entities.items()589 },590 "stairs_up": asdict(lvl.stairs_up) if lvl.stairs_up else None,591 "stairs_down": asdict(lvl.stairs_down) if lvl.stairs_down else None,592 }593 data["levels"].append(level_data)594 path.write_text(json.dumps(data, indent=2), encoding="utf-8")595 logging.info(f"Exported JSON β {path}")596 597 def export_ppm(self, path: Path, level_idx: int = 0, scale: int = 4) -> None:598 level = self.levels[level_idx]599 w, h = level.width * scale, level.height * scale600 header = f"P3\n{w} {h}\n255\n"601 pixels = []602 for y in range(level.height):603 for _ in range(scale):604 row = []605 for x in range(level.width):606 p = Point(x, y)607 tile = level.get_tile(p)608 entity = level.entities.get(p)609 if entity:610 color = entity.color611 else:612 _, color = self._tile_to_glyph(tile, level.theme)613 row.extend([f"{color[0]} {color[1]} {color[2]}"] * scale)614 pixels.append(" ".join(row))615 path.write_text(header + "\n".join(pixels), encoding="utf-8")616 logging.info(f"Exported PPM image β {path}")617 618 def stats(self) -> str:619 lines = [f"Seed: {self.seed}", f"Theme: {self.theme.name}", f"Levels: {len(self.levels)}"]620 for i, lvl in enumerate(self.levels):621 floors = sum(1 for row in lvl.tiles for t in row if t == Tile.FLOOR)622 entities = len(lvl.entities)623 monsters = sum(1 for e in lvl.entities.values() if e.kind == EntityType.MONSTER)624 loot = sum(1 for e in lvl.entities.values() if e.kind == EntityType.LOOT)625 lines.append(f" Level {i}: {len(lvl.rooms)} rooms | {floors} floor tiles | "626 f"{entities} entities ({monsters} monsters, {loot} loot)")627 return "\n".join(lines)628 629# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ630# CLI631# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ632 633def setup_logging(verbose: bool) -> None:634 level = logging.DEBUG if verbose else logging.INFO635 logging.basicConfig(636 level=level,637 format="%(asctime)s β %(levelname)-8s β %(message)s",638 datefmt="%H:%M:%S"639 )640 641def main() -> None:642 if hasattr(sys.stdout, 'reconfigure'):643 sys.stdout.reconfigure(encoding='utf-8')644 if hasattr(sys.stderr, 'reconfigure'):645 sys.stderr.reconfigure(encoding='utf-8')646 647 parser = argparse.ArgumentParser(648 description="Aetherforge β Procedural Multi-Layer Dungeon Generator",649 formatter_class=argparse.RawDescriptionHelpFormatter,650 epilog="""651Examples:652 python aetherforge.py generate --width 80 --height 40 --levels 3 --theme crystal653 python aetherforge.py generate -s 42 --theme eldritch --export-json dungeon.json654 python aetherforge.py generate --theme biomech --export-ppm map.ppm --scale 6655 """656 )657 sub = parser.add_subparsers(dest="command", required=True)658 659 gen = sub.add_parser("generate", help="Forge a new dungeon")660 gen.add_argument("-W", "--width", type=int, default=70, help="Map width")661 gen.add_argument("-H", "--height", type=int, default=35, help="Map height")662 gen.add_argument("-l", "--levels", type=int, default=1, help="Number of levels")663 gen.add_argument("-t", "--theme", choices=list(THEMES.keys()), default="stone")664 gen.add_argument("-s", "--seed", type=int, default=None, help="RNG seed")665 gen.add_argument("--min-room", type=int, default=5)666 gen.add_argument("--max-room", type=int, default=11)667 gen.add_argument("--export-json", type=Path, help="Export full dungeon as JSON")668 gen.add_argument("--export-ppm", type=Path, help="Export level 0 as PPM image")669 gen.add_argument("--scale", type=int, default=5, help="PPM pixel scale")670 gen.add_argument("--no-color", action="store_true", help="Disable ANSI colors")671 gen.add_argument("-v", "--verbose", action="store_true")672 673 args = parser.parse_args()674 setup_logging(args.verbose)675 676 if args.command == "generate":677 dungeon = Dungeon(678 width=args.width,679 height=args.height,680 levels=args.levels,681 theme_name=args.theme,682 seed=args.seed,683 min_room=args.min_room,684 max_room=args.max_room685 )686 dungeon.generate()687 688 print("\n" + dungeon.stats() + "\n")689 print(dungeon.render_ascii(0, use_color=not args.no_color))690 691 if args.export_json:692 dungeon.export_json(args.export_json)693 if args.export_ppm:694 dungeon.export_ppm(args.export_ppm, scale=args.scale)695 696if __name__ == "__main__":697 main()Semi-complex File Organizer
Organizes loose files into categorized folders based on file extensions with collision protection, dry-run safety previews, and recursive scanning.
1#!/usr/bin/env python32"""3Semi-complex File Organizer Utility4Organizes files into categorized folders based on extension.5"""6 7import argparse8import logging9import shutil10from collections import defaultdict11from pathlib import Path12from typing import Dict, List, Set13 14# Category mapping (extension β folder name)15CATEGORIES: Dict[str, Set[str]] = {16 "Images": {".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp", ".tiff", ".svg", ".heic"},17 "Documents": {".pdf", ".doc", ".docx", ".txt", ".rtf", ".odt", ".xls", ".xlsx", ".ppt", ".pptx", ".csv", ".md"},18 "Videos": {".mp4", ".mkv", ".avi", ".mov", ".wmv", ".flv", ".webm", ".m4v"},19 "Audio": {".mp3", ".wav", ".flac", ".aac", ".ogg", ".m4a", ".wma"},20 "Archives": {".zip", ".rar", ".7z", ".tar", ".gz", ".bz2", ".xz"},21 "Code": {".py", ".js", ".ts", ".html", ".css", ".java", ".cpp", ".c", ".h", ".go", ".rs", ".sh", ".json", ".yaml", ".yml", ".toml"},22}23 24def setup_logging(log_file: Path, verbose: bool) -> None:25 """Configure logging to console + file."""26 level = logging.DEBUG if verbose else logging.INFO27 logging.basicConfig(28 level=level,29 format="%(asctime)s | %(levelname)-8s | %(message)s",30 datefmt="%Y-%m-%d %H:%M:%S",31 handlers=[32 logging.FileHandler(log_file, encoding="utf-8"),33 logging.StreamHandler(),34 ],35 )36 37def get_category(extension: str) -> str:38 """Return the category folder name for a given extension."""39 ext = extension.lower()40 for category, extensions in CATEGORIES.items():41 if ext in extensions:42 return category43 return "Other"44 45def unique_path(destination: Path) -> Path:46 """Generate a unique path if the target already exists."""47 if not destination.exists():48 return destination49 50 stem = destination.stem51 suffix = destination.suffix52 parent = destination.parent53 counter = 154 55 while True:56 new_name = f"{stem}_{counter}{suffix}"57 candidate = parent / new_name58 if not candidate.exists():59 return candidate60 counter += 161 62def organize_files(63 source: Path,64 recursive: bool,65 dry_run: bool,66) -> Dict[str, List[Path]]:67 """68 Scan the source directory and move files into category folders.69 Returns a dict of category β list of moved files.70 """71 moved: Dict[str, List[Path]] = defaultdict(list)72 pattern = "**/*" if recursive else "*"73 74 files = [p for p in source.glob(pattern) if p.is_file()]75 76 if not files:77 logging.warning("No files found to organize.")78 return moved79 80 logging.info(f"Found {len(files)} file(s) to process...")81 82 for file_path in files:83 # Skip the log file itself and any category folders we create84 if file_path.name.startswith("organize_") or file_path.parent.name in CATEGORIES or file_path.parent.name == "Other":85 continue86 87 category = get_category(file_path.suffix)88 target_dir = source / category89 target_path = unique_path(target_dir / file_path.name)90 91 if dry_run:92 logging.info(f"[DRY-RUN] Would move: {file_path.relative_to(source)} β {category}/{target_path.name}")93 else:94 target_dir.mkdir(exist_ok=True)95 try:96 shutil.move(str(file_path), str(target_path))97 logging.info(f"Moved: {file_path.relative_to(source)} β {category}/{target_path.name}")98 moved[category].append(target_path)99 except Exception as e:100 logging.error(f"Failed to move {file_path}: {e}")101 102 return moved103 104def print_summary(moved: Dict[str, List[Path]], dry_run: bool) -> None:105 """Print a nice summary of the operation."""106 action = "Would move" if dry_run else "Moved"107 total = sum(len(files) for files in moved.values())108 109 print("\n" + "=" * 50)110 print(f"{'DRY-RUN SUMMARY' if dry_run else 'SUMMARY'}")111 print("=" * 50)112 113 if total == 0:114 print("No files were processed.")115 return116 117 for category in sorted(moved.keys()):118 count = len(moved[category])119 print(f" {category:<12} : {count:>4} file(s)")120 121 print("-" * 50)122 print(f" {'Total':<12} : {total:>4} file(s)")123 print("=" * 50)124 125def main() -> None:126 parser = argparse.ArgumentParser(127 description="Organize files into categorized folders by extension.",128 formatter_class=argparse.RawDescriptionHelpFormatter,129 epilog="""130Examples:131 python file_organizer.py ~/Downloads132 python file_organizer.py . --recursive --dry-run133 python file_organizer.py /path/to/folder -v134 """,135 )136 parser.add_argument(137 "directory",138 type=Path,139 help="Directory to organize (default: current directory)",140 nargs="?",141 default=Path.cwd(),142 )143 parser.add_argument(144 "-r", "--recursive",145 action="store_true",146 help="Process subdirectories recursively",147 )148 parser.add_argument(149 "-d", "--dry-run",150 action="store_true",151 help="Show what would be done without actually moving files",152 )153 parser.add_argument(154 "-v", "--verbose",155 action="store_true",156 help="Enable verbose (debug) logging",157 )158 159 args = parser.parse_args()160 source = args.directory.resolve()161 162 if not source.is_dir():163 print(f"Error: '{source}' is not a valid directory.")164 return165 166 log_file = source / "organize_log.txt"167 setup_logging(log_file, args.verbose)168 169 logging.info(f"Starting organization of: {source}")170 logging.info(f"Recursive: {args.recursive} | Dry-run: {args.dry_run}")171 172 moved = organize_files(source, args.recursive, args.dry_run)173 print_summary(moved, args.dry_run)174 175 if not args.dry_run and moved:176 logging.info(f"Log saved to: {log_file}")177 178if __name__ == "__main__":179 main()Extract Audio from Video
A quick FFmpeg one-liner to extract high-quality MP3 audio from any MP4 video file.
1ffmpeg -i input.mp4 -q:a 0 -map a output.mp3UART Hardware Connection
A self-contained script using Mix.install to spawn a GenServer worker and communicate with hardware over a serial connection.
1# uart_demo.exs2 3Mix.install([4 {:circuits_uart, "~> 1.5"}5])6 7alias Circuits.UART8 9{:ok, pid} = UART.start_link()10 11IO.inspect(UART.enumerate(), label: "Available Ports")12 13UART.open(pid, "COM3", speed: 115200, active: false)14 15UART.write(pid, "PING\r\n")16 17{:ok, data} = UART.read(pid, 1000)18IO.inspect(data, label: "Response")