{"spec_id":"maze-printable","library":"pygal","language":"python","code":"\"\"\" anyplot.ai\nmaze-printable: Printable Maze Puzzle\nLibrary: pygal 3.1.0 | Python 3.13.13\nQuality: 87/100 | Updated: 2026-05-16\n\"\"\"\n\nimport os\nimport re\nimport sys\nfrom importlib import import_module\n\n\n# Prevent module name conflict with pygal.py script\nsys.path = [p for p in sys.path if \"implementations\" not in p]\n\nimport cairosvg\nimport numpy as np\n\n\npygal_module = import_module(\"pygal\")\nStyle = import_module(\"pygal.style\").Style\n\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\n\n# Theme-adaptive colors for maze walls and background\nif THEME == \"light\":\n    PAGE_BG = \"#FAF8F1\"\n    WALL_COLOR = \"#000000\"  # Black walls on light background (printable)\nelse:\n    PAGE_BG = \"#1A1A17\"\n    WALL_COLOR = \"#FFFFFF\"  # White walls on dark background\n\n# Seed for reproducibility\nnp.random.seed(42)\n\n# Maze dimensions (25x25 as specified in spec)\nmaze_width = 25\nmaze_height = 25\n\n# Generate maze using DFS algorithm\n# Each cell: 0 = wall, 1 = passage\ngrid_h = maze_height * 2 + 1\ngrid_w = maze_width * 2 + 1\nmaze = np.zeros((grid_h, grid_w), dtype=int)\n\n# Initialize cells (passages between walls)\nfor y in range(maze_height):\n    for x in range(maze_width):\n        maze[y * 2 + 1, x * 2 + 1] = 1\n\n# DFS maze generation\nstack = [(0, 0)]\nvisited = set()\nvisited.add((0, 0))\n\ndirections = [(0, 1), (1, 0), (0, -1), (-1, 0)]\n\nwhile stack:\n    cx, cy = stack[-1]\n    neighbors = []\n    for dx, dy in directions:\n        nx, ny = cx + dx, cy + dy\n        if 0 <= nx < maze_width and 0 <= ny < maze_height and (nx, ny) not in visited:\n            neighbors.append((nx, ny, dx, dy))\n\n    if neighbors:\n        idx = np.random.randint(len(neighbors))\n        nx, ny, dx, dy = neighbors[idx]\n        # Remove wall between current and neighbor\n        maze[cy * 2 + 1 + dy, cx * 2 + 1 + dx] = 1\n        visited.add((nx, ny))\n        stack.append((nx, ny))\n    else:\n        stack.pop()\n\n# Create entrance (top-left) and exit (bottom-right)\nmaze[0, 1] = 1  # Entrance at top\nmaze[grid_h - 1, grid_w - 2] = 1  # Exit at bottom\n\n# Mark start and goal positions in the maze data\n# Start: first cell after entrance (row 1, col 1)\nstart_y, start_x = 1, 1\n# Goal: last cell before exit (row grid_h-2, col grid_w-2)\ngoal_y, goal_x = grid_h - 2, grid_w - 2\n\n# All walls are the same color - create enough entries for each row\ncolors = tuple([WALL_COLOR] * grid_h)\n\n# Custom style - clean for printability\ncustom_style = Style(\n    background=PAGE_BG,\n    plot_background=PAGE_BG,\n    foreground=WALL_COLOR,\n    foreground_strong=WALL_COLOR,\n    foreground_subtle=WALL_COLOR,\n    colors=colors,\n    title_font_size=96,\n    label_font_size=1,\n    major_label_font_size=1,\n    legend_font_size=1,\n    value_font_size=1,\n    font_family=\"monospace\",\n)\n\n# Use Dot chart to create grid representation\nchart = pygal_module.Dot(\n    width=3600,\n    height=3600,\n    style=custom_style,\n    title=\"maze-printable · pygal · anyplot.ai\",\n    show_legend=False,\n    show_x_labels=False,\n    show_y_labels=False,\n    dots_size=32,\n    margin=100,\n)\n\n# Add wall rows - walls show as dots, passages are empty\nfor y in range(grid_h):\n    row_data = []\n    for x in range(grid_w):\n        if maze[y, x] == 0:  # Wall\n            row_data.append(1)\n        else:  # Passage\n            row_data.append(None)\n    chart.add(\"\", row_data)\n\n# First, create a helper chart with dots at start and goal positions to find exact coordinates\nhelper_chart = pygal_module.Dot(\n    width=3600,\n    height=3600,\n    style=custom_style,\n    title=\"maze-printable · pygal · anyplot.ai\",\n    show_legend=False,\n    show_x_labels=False,\n    show_y_labels=False,\n    dots_size=32,\n    margin=100,\n)\n\n# Add rows with dots only at start and goal positions\nfor y in range(grid_h):\n    row_data = []\n    for x in range(grid_w):\n        if (x == start_x and y == start_y) or (x == goal_x and y == goal_y):\n            row_data.append(1)\n        else:\n            row_data.append(None)\n    helper_chart.add(\"\", row_data)\n\n# Extract circle positions from helper chart\nhelper_svg = helper_chart.render().decode(\"utf-8\")\ncircles = re.findall(r'<circle[^>]*cx=\"([^\"]+)\"[^>]*cy=\"([^\"]+)\"', helper_svg)\n\n# Get start and goal positions (first circle is start, second is goal)\n# Note: pygal applies a transform to the plot group, so we need to add offsets\n# The plot group has transform=\"translate(margin, title_area_height + margin)\"\n# margin = 100, title_area_height ~ 106 (based on title_font_size 96)\nplot_x_offset = 100\nplot_y_offset = 206  # Accounts for title area and margin\n\nif len(circles) >= 2:\n    s_x = float(circles[0][0]) + plot_x_offset\n    s_y = float(circles[0][1]) + plot_y_offset\n    g_x = float(circles[1][0]) + plot_x_offset\n    g_y = float(circles[1][1]) + plot_y_offset\nelse:\n    # Fallback positions\n    s_x, s_y = 300, 400\n    g_x, g_y = 3350, 3350\n\n# Render the main maze chart\nsvg_string = chart.render().decode(\"utf-8\")\n\n# Create S and G text elements with bold styling - sized to fit within a cell\n# Cell spacing is approximately 64px, so font-size of 50 fits well\ns_marker = f'''<text x=\"{s_x}\" y=\"{s_y}\" font-family=\"Arial, sans-serif\" font-size=\"50\" font-weight=\"bold\" fill=\"{WALL_COLOR}\" text-anchor=\"middle\" dominant-baseline=\"central\">S</text>'''\ng_marker = f'''<text x=\"{g_x}\" y=\"{g_y}\" font-family=\"Arial, sans-serif\" font-size=\"50\" font-weight=\"bold\" fill=\"{WALL_COLOR}\" text-anchor=\"middle\" dominant-baseline=\"central\">G</text>'''\n\n# Insert markers before the closing </svg> tag\nsvg_with_markers = svg_string.replace(\"</svg>\", f\"{s_marker}\\n{g_marker}\\n</svg>\")\n\n# Use cairosvg to convert SVG to PNG\ncairosvg.svg2png(bytestring=svg_with_markers.encode(\"utf-8\"), write_to=f\"plot-{THEME}.png\")\n\n# Also save HTML version with markers\nhtml_template = f\"\"\"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"utf-8\">\n<title>maze-printable · pygal · anyplot.ai</title>\n</head>\n<body style=\"margin:0;padding:0;background:{PAGE_BG};\">\n{svg_with_markers}\n</body>\n</html>\"\"\"\n\nwith open(f\"plot-{THEME}.html\", \"w\", encoding=\"utf-8\") as f:\n    f.write(html_template)\n"}