Skip to content

Revive: Cachex Arena, a browser port of our COMP30024 minimax agent and A* search - #11

Merged
rNLKJA merged 14 commits into
mainfrom
revive/web
Oct 5, 2026
Merged

rNLKJA merged 14 commits into
mainfrom
revive/web

Conversation

@rNLKJA

@rNLKJA rNLKJA commented Oct 5, 2026

Copy link
Copy Markdown
Owner

Summary

This PR revives the COMP30024 (Semester 1, 2022) Cachex project as Cachex Arena. It is a static Next.js app that runs a line-by-line TypeScript port of our original A* search and minimax agent in the browser.

Live demo: https://cachex-ai.vercel.app

Structure

  • The original submission was moved into coursework/ with git mv, so history is kept. Its contents are unchanged, and coursework/README.md explains how to run it with uv on Python 3.12.
  • scripts/ holds uv (PEP 723) scripts that import the unchanged Python:
    • generate_parity_fixtures.py writes the Vitest parity fixtures.
    • benchmark_agent.py writes the agent-vs-random benchmark. It pins PYTHONHASHSEED=0, so its output is byte-for-byte reproducible.
  • web/ is the deployable Next.js 16 app (React 19, Tailwind v4, shadcn/ui, next-themes, lucide). It is the Vercel root.
  • .github/workflows/ci.yml runs pnpm install --frozen-lockfile, then lint, typecheck, test and build in web/.

App

  • /: the landing page. It covers the rules, what the coursework asked, what we built, the evaluation weights, key results from the original code (the _4399 agent won 144 of 160 games, 90%, against the random agent) and an About section with credits.
  • /play: play the minimax agent or the random baseline on boards from 3×3 to 10×10, as either colour. It has STEAL, capture animations, undo, a move log, a "why that move?" panel and keyboard play. The agent runs in a Web Worker.
  • /spectate: AI vs AI with play, pause and step, a speed control, seeded replays and an evaluation trend chart.
  • /astar: the A* Lab. You can edit boards, animate open and closed sets, compare Manhattan with Euclidean, import or export the original sample_input.json format, and check results against the recorded outputs. It also re-runs the notebook's heuristic study in a worker, using the notebook's insertion counter on every size from 2 to 99.

Parity

847 Vitest tests check the port against fixtures generated by the original Python:

  • A* paths and node counts.
  • CPython set-order tie-breaking.
  • Referee board states and captures.
  • Evaluation features, minimax and Player.action.
  • Full self-play games.
  • The recorded sample_output*.txt files, read straight from coursework/.

Review fixes in this branch

  • Benchmark reproducibility.
  • Keyboard focus is kept on the board after each move.
  • AA-contrast text tokens.
  • Candidate bars that ignore the 1e-5 tie-break bias.
  • The heuristic study's metric and board sizes.
  • Sample preset provenance.
  • Mobile table, header and chart.
  • The dark-mode edge glow.
  • Spectator state.
  • Slider labels and tool tooltips.
  • Sticky board columns.
  • 404 metadata.
  • Repo hygiene.

Run locally

cd web
pnpm install
pnpm dev        # http://localhost:3000
pnpm lint && pnpm typecheck && pnpm test && pnpm build

Notes

  • The university's specification PDFs are still under coursework/Project Part A/specification/. The website does not serve them; whether to remove them from the public repo is the owner's call.

🤖 Generated with Claude Code

rNLKJA and others added 14 commits October 5, 2026 22:31
Relocate both project parts, the archived README and the original Python
environment files with git mv so history is preserved. Folder-relative
paths are unchanged, so the original commands still run from their
directories.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…itest

Create the deployable app under web/ (pnpm, strict TypeScript, ESLint,
Prettier) and add the shadcn/ui primitives the UI uses. Replace the root
.gitignore, whose Python template ignored every lib/ directory.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- cachex/: referee board and game rules (captures, STEAL, win/draw)
- agent/: Board_4399, evaluation features, weights.json, minimax with
  alpha-beta, opening book, dynamic depth and the random baseline
- astar/: CachexBoard.AStar with a CPython set-order simulation so
  neighbour tie-breaking matches the original exactly

scripts/generate_parity_fixtures.py runs the original Python (uv) to record
expected outputs; vitest replays them (831 parity and unit tests).
scripts/benchmark_agent.py records the original agent's results against
the original random agent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Cache CPython neighbour orders per board size (keeping a few sizes) and
memoise tuple hashes so large heuristic studies stay cheap. Check the
weights.json copy byte for byte against the original.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Dark charcoal-indigo and warm paper themes with player tokens,
  Bricolage Grotesque headings, Geist UI text and next-themes
- Sticky header, footer, skip link, icon, 404 page and OG image
- HexBoard: pointy-top SVG board with glowing goal edges, bevelled
  tiles, placement and capture animations, win highlights, overlays for
  the A* lab and roving-tabindex keyboard play
- Drop unused shadcn components and dependencies

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agents run in a Web Worker (main-thread fallback). Play supports either
colour, the steal rule, undo and board sizes 3 to 10; spectator mode has
play/pause/step, a speed control, seeded replays and an evaluation trend.
Both show a move log and a 'why that move?' panel with the opening-book
rule, instant win, or search depth, top candidates and feature breakdown.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Edit tiles, start and goal, pick Manhattan or Euclidean and the original
block-colour option, animate open/closed sets, compare both heuristics,
import/export the sample_input.json format and check presets against the
recorded outputs. The notebook's random-board experiment reruns in a Web
Worker and charts node expansions per board size.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Explain the game with live mini-boards, paraphrase both project parts,
list the evaluation weights, show the benchmark against the random agent
from the original code, and credit the team. The hero board is a real
self-play game by the ported agent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Document the routes, stack, repository layout, local development, how the
parity fixtures and benchmark are generated from the original Python, and
credits. Add coursework/README.md describing the preserved submission and
how to run it with uv. CI runs lint, typecheck, tests and build for web/.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The original get_valid_actions builds a set of ("PLACE", r, q) tuples, and
CPython randomises str hashes per process, so the order passed to
random.shuffle changed between runs despite the per-game seed. The script
now re-executes itself with PYTHONHASHSEED=0; two runs produce
byte-identical JSON. Regenerated the benchmark (144 of 160 wins, 90%) and
updated the README.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The heuristic study now charts the notebook's `order` insertion counter
  (pushes - 1) instead of queue pops, over every size from 2 to 99 as the
  notebook did, with copy and counts that match.
- The study chart is drawn at its container's real width so axis labels
  stay legible on phones.
- sample_output.txt and sample_output2.txt were written by the notebook
  with heuristic="manhattan"; the presets now say so, and a new test reads
  the recorded files from coursework/ and checks both heuristics.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- /play keeps the board interactive for the whole match, so keyboard
  focus stays on the board while the agent replies.
- Text-safe --gold-ink and player ink tokens (WCAG AA in light mode) for
  gold and red/blue text.
- "Why that move?" bars compare scores at displayed precision, so the
  original 1e-5 tie-break bias no longer looks like a real gap.
- Landing benchmark table no longer wraps values at 390px; header nav fits
  at 375px.
- Goal-edge glow uses a userSpaceOnUse filter region (no clipped
  rectangle in dark mode).
- Spectator: a finished game ends auto-play; move delay reads "600 ms";
  evaluation trend has an empty state.
- A* Lab: size picker shows imported sizes, sliders forward their labels
  and value text to the Radix thumb, icon tools get tooltips, the lab opens
  with the heuristic the sample output was recorded with.
- Board columns are sticky on large screens.
- 404 page has its own title and an accurate board label.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Ignore and untrack create-next-app's AGENTS.md and CLAUDE.md.
- Add web/public/.gitkeep so the folder in the README tree exists.
- Remove the unused describeAction helper.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rNLKJA
rNLKJA merged commit 18be4a9 into main Oct 5, 2026
2 checks passed
@rNLKJA
rNLKJA deleted the revive/web branch October 5, 2026 13:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant