Treasure Hunt is a fully static browser game that pits you against an intelligent JavaScript agent in a race through a randomized 8×8 maze. Every cell is either open or blocked, the treasure is always at positionDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/apursley2012/treasure-hunt-game/llms.txt
Use this file to discover all available pages before exploring further.
[7, 7], and both you and the agent start at [0, 0]. The board is freshly generated each round, guaranteed to have at least one valid path from start to treasure, so no two games play the same way. The project was rebuilt from a Python deep Q-learning exercise involving a pirate agent, Keras, and a Jupyter Notebook — the browser version keeps the same maze rules, reward logic, and agent-versus-player spirit without requiring any backend or build toolchain.
Quickstart
Run the game locally or deploy to GitHub Pages in minutes.
How to Play
Learn the controls, HUD elements, and win conditions.
Maze Rules
Understand how the board is generated and what makes a move valid.
Architecture Overview
Explore the three JavaScript modules that power the game.
Origin: From Python Deep Q-Learning to Browser Game
The original project was a reinforcement-learning assignment written for a Python and Jupyter Notebook environment. A pirate agent learned to navigate an 8×8 maze by collecting rewards for forward progress and accumulating penalties for hitting walls or revisiting cells. The training loop used Keras for the neural network, NumPy for matrix operations, and a customGameExperience replay buffer to feed batches of past moves back into the model.
That workflow is excellent for learning but impractical to demonstrate from a public portfolio URL. GitHub Pages cannot run Python, instantiate a Keras model, or execute a training loop. The browser demo solves this by replacing the trained neural network with a JavaScript CompetitiveAgent that uses BFS-based pathfinding and configurable difficulty settings to recreate the feel of racing a trained agent — without pretending the browser is a machine-learning backend.
The original Python source files are preserved in source/original-python/ so the technical origin of the project remains visible alongside the playable demo.
Key Contrast: Original vs. Browser Demo
| Area | Original Python / Keras Version | Browser Demo Version |
|---|---|---|
| Runtime | Python, Jupyter Notebook, Keras | HTML, CSS, JavaScript (ES modules) |
| Main goal | Train an agent through deep Q-learning | Let a visitor race an intelligent agent |
| Hosting | Local machine-learning environment | GitHub Pages (fully static) |
| Data storage | Training memory during execution | Browser session only |
| Maze | 8×8 fixed grid | 8×8 randomized grid |
| Agent type | Deep Q-learning model (Keras) | JavaScript behavior inspired by the trained-agent goal |
| User experience | Developer-focused notebook | Portfolio-ready interactive game |
Key Features
Randomized mazes.createRandomMaze() in treasure-maze.js carves a unique main path using a depth-first backtracking algorithm, then fills in dead-end branches to reach a target open-cell density. Every generated board is validated to have a BFS path of at least 11 moves, so trivially small mazes are discarded automatically.
Three difficulty modes. The DIFFICULTY_SETTINGS object in q-agent.js defines Easy, Medium, and Hard. Each mode sets a moveDelay (milliseconds between agent moves), a startDelay (agent head-start delay), a mistakeRate (probability of an exploratory detour instead of the optimal step), and a hesitateRate (probability of skipping a turn entirely).
Reward tracking. TreasureMaze in treasure-maze.js calculates a per-move reward and accumulates it in totalReward. Valid moves to unvisited cells earn −0.04, revisiting a cell earns −0.25, invalid moves into walls earn −0.75, reaching the treasure earns +1.0, and being trapped with no valid adjacent cells earns minReward − 1. The gameStatus() method returns "lose" when totalReward drops below minReward (−0.5 × rows × cols, i.e. −32 on the standard board).
Keyboard and button controls. Players move with ArrowLeft, ArrowRight, ArrowUp, ArrowDown or a, w, d, s. On-screen buttons using data-action="up|down|left|right" provide the same four directions for touch and mouse users.
Zero-dependency static deployment. The entire game is three JavaScript ES modules, one HTML file, and one CSS file. There is no bundler, no npm install, and no build step. Deployment to GitHub Pages requires only a .nojekyll file in the repository root.
Architecture Overview
The game is composed of three ES modules loaded byindex.html through a single <script type="module" src="./assets/js/app.js"></script> tag.
treasure-maze.js
Defines the maze environment. Exports constants (LEFT, UP, RIGHT, DOWN), a TreasureMaze class that tracks player position, visited cells, reward accumulation, and game status, the createRandomMaze() generator, the findShortestPath() BFS utility, and supporting helpers (key(), cloneMaze(), isInside(), shuffle()).
The TreasureMaze class exposes an act(action) method that updates player position, calculates the step reward, adds it to totalReward, and returns the new state. Its gameStatus() method returns "win", "lose", or "not_over" based on position and cumulative reward.
q-agent.js
Defines the browser-safe intelligent agent. Exports DIFFICULTY_SETTINGS (the Easy / Medium / Hard configuration objects) and the CompetitiveAgent class. The agent runs findShortestPath() on every turn to compute the next optimal step (choosePolicyMove()), and randomly deviates to chooseExplorationMove() based on mistakeRate. It also skips turns based on hesitateRate and records the description of each move in lastMove for display in the HUD.
app.js
Connects the interface to the game logic. It imports from both treasure-maze.js and q-agent.js, queries all DOM elements, renders the board grid into #maze-board, updates the HUD labels on every move, manages the agent’s setInterval timer during a race, and handles keyboard events and button clicks. The newMaze(), resetRace(), startRace(), and movePlayer() functions in app.js orchestrate the full game loop.