Inspiration
We were heavily inspired by the board game Settlers of Catan and the California Gold rush. All of us are very interested in ML, RL, and Theory-of-Mind so we wanted to do something to strengthen our ML skills this hackathon. So we chose to game around the Californian Gold Rush and model the NPC as a RL model.
What it does
Gold Rush is a 1v1 turn-based strategy game on a 20x20 grid. Players take turns buying mines and rivers, upgrading assets, or yielding their turn. Mines yield higher income but have a risk of collapsing (which wipes a percentage of your money), while rivers are safer but pay less. You can't buy rivers back-to-back; you have to grab a mine in between. Rivers/Mines cost more the farther they are from your starting position, so both players are looking at the same board but with different price tags. First to $500 wins the match, best of 5 wins the game. In the top you can see that we are able to hopefully predict your next move. Oh and you're playing against a DQN we trained via self-play, so good luck.
How we built it
The game itself is pure vanilla JS. We split the codebase into small single-responsibility files: consts.js for config, player.js/mine.js/riverMine.js for game objects, turnSystem.js for buy/upgrade/income logic, renderer.js for sprite drawing, ui.js for DOM stuff, and index.js to wire it all together. The grid is a 20x20 array, and everything runs client-side with no backend.
For the AI opponent, we wrote a full Python port of the game as a Gymnasium environment (gold_rush_env.py) so we could train a Double DQN via self-play. The model takes three parallel inputs (a 6-channel spatial grid through a CNN, a 14-feature-per-asset table through a shared MLP, and 8 global scalars) and outputs Q-values over 61 discrete actions (buy, upgrade, or skip). We trained it with PyTorch, exported to ONNX, and run inference in the browser using ONNX Runtime Web. The JS inference wrapper (ai.js) reconstructs the exact same observation tensors the Python env produces and applies the action mask before argmax.
We also hooked up Gemini (3.1 Flash Lite) to predict the human player's next move before each turn. It gets a compact text prompt with the board state, recent action history, and available moves, then returns a predicted action with a confidence level. It's not used for decision-making.
Challenges We Ran Into
Google changed the available Gemini models mid-hackathon, so we kept hitting token/rate limits and had to swap model versions until we found one that worked. ONNX Runtime Web also had some quirks (we had to disable multithreading and handle external data files before inference would actually run in the browser).
The biggest headache was reward tuning; both in the actual game and in the ML model. On the game side, we went through a bunch of iterations on the income and risk functions to make taking risks actually worth it. On the DQN side, our first trained model just spammed rivers every turn because they're safe guaranteed income. We had to reshape the reward structure to get it to understand when risk is worth taking: things like rewarding money lead and penalizing passive play.
And honestly, a surprising amount of time went into art. Finding and making sprites that looked decent and fit the top-down grid perspective was way more tedious than expected.
Accomplishments that we're proud of
Honestly we're just really happy with how the whole thing came together. We built a full game with a trained DQN opponent, a Gemini-powered prediction system, and custom art: all in under 24 hours with zero prior JS experience. The fact that the AI actually plays intelligently and doesn't just skip every turn feels like a win on its own. Going from none of us knowing how to deploy an ML model in a browser to having a working ONNX pipeline running inference in real-time is something we're genuinely proud of. And one of us is an ABSOLUTE BEGINNER!
What we learned
None of us had any real JS experience going in, so building an entire game in vanilla JS with HTML5 Canvas was a crash course in itself. Beyond that, we picked up a ton: PyTorch and Gymnasium for training the DQN, ONNX for model export, ONNX Runtime Web for running inference in the browser, and the Gemini API for the prediction feature. We also got way more comfortable with reward shaping and self-play training; none of us had ever actually deployed an RL model into a live app before. Going from "train a model in Python" to "have it make decisions in a browser game" was a completely new pipeline for all of us.
Built With
- gym
- javascript
- machine-learning
- onnx
- python
- torch
- video-game
Log in or sign up for Devpost to join the conversation.