{"spec_id":"maze-printable","library":"letsplot","language":"python","code":"\"\"\" anyplot.ai\nmaze-printable: Printable Maze Puzzle\nLibrary: letsplot 4.9.0 | Python 3.13.13\nQuality: 73/100 | Updated: 2026-05-16\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport pandas as pd\nfrom lets_plot import *\n\n\nLetsPlot.setup_html()\n\n# Theme tokens\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\n\n# Maze parameters\nnp.random.seed(42)\nwidth = 25\nheight = 25\n\n# Initialize maze grid (walls = 1, passages = 0)\n# We use a (2*height+1) x (2*width+1) grid to represent walls between cells\nmaze = np.ones((2 * height + 1, 2 * width + 1), dtype=int)\n\n# Initialize visited array for cells\nvisited = np.zeros((height, width), dtype=bool)\n\n# DFS maze generation with iterative approach\nstack = [(0, 0)]\nvisited[0, 0] = True\nmaze[1, 1] = 0  # Start cell is passage\n\ndirections = [(0, 1), (1, 0), (0, -1), (-1, 0)]\n\nwhile stack:\n    cy, cx = stack[-1]\n    neighbors = []\n    for dy, dx in directions:\n        ny, nx = cy + dy, cx + dx\n        if 0 <= ny < height and 0 <= nx < width and not visited[ny, nx]:\n            neighbors.append((ny, nx, dy, dx))\n\n    if neighbors:\n        ny, nx, dy, dx = neighbors[np.random.randint(len(neighbors))]\n        visited[ny, nx] = True\n        # Remove wall between current and next cell\n        maze[2 * cy + 1 + dy, 2 * cx + 1 + dx] = 0\n        # Mark next cell as passage\n        maze[2 * ny + 1, 2 * nx + 1] = 0\n        stack.append((ny, nx))\n    else:\n        stack.pop()\n\n# Create entrance and exit openings in the outer wall\n# Entrance: remove wall at maze[0, 1] (top of first passage cell)\n# Exit: remove wall at maze[2*height, 2*width-1] (bottom of last passage cell)\nmaze[0, 1] = 0  # Entrance opening\nmaze[2 * height, 2 * width - 1] = 0  # Exit opening\n\n# Create data for plotting walls as rectangles\nwall_data = []\nmaze_rows = maze.shape[0]\nfor y in range(maze_rows):\n    for x in range(maze.shape[1]):\n        if maze[y, x] == 1:\n            wall_data.append({\"xmin\": x, \"xmax\": x + 1, \"ymin\": maze_rows - y - 1, \"ymax\": maze_rows - y})\n\ndf_walls = pd.DataFrame(wall_data)\n\n# Start and goal positions (outside the maze at entrance/exit)\nstart_x = 1.5\nstart_y = maze_rows + 0.5  # Just above the entrance\ngoal_x = 2 * width - 1 + 0.5  # = 49.5\ngoal_y = -0.5  # Just below the exit\n\ndf_markers = pd.DataFrame({\"x\": [start_x, goal_x], \"y\": [start_y, goal_y], \"label\": [\"S\", \"G\"]})\n\n# Create plot with axis limits to include markers fully\nplot = (\n    ggplot()\n    + geom_rect(\n        aes(xmin=\"xmin\", xmax=\"xmax\", ymin=\"ymin\", ymax=\"ymax\"), data=df_walls, fill=\"black\", color=\"black\", size=0\n    )\n    + geom_text(aes(x=\"x\", y=\"y\", label=\"label\"), data=df_markers, size=10, fontface=\"bold\", color=INK)\n    + coord_fixed(ratio=1, xlim=(-1.5, maze.shape[1] + 0.5), ylim=(-1.5, maze_rows + 1.5))\n    + theme_void()\n    + theme(\n        plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n        plot_title=element_text(size=24, hjust=0.5, color=INK),\n        plot_margin=[40, 40, 40, 40],\n    )\n    + labs(title=\"maze-printable · letsplot · anyplot.ai\")\n    + ggsize(1200, 1200)\n)\n\n# Save as PNG and HTML\nggsave(plot, f\"plot-{THEME}.png\", scale=3)\nggsave(plot, f\"plot-{THEME}.html\")\n"}