Inspiration

A slot machine looks random, but the machines in House Edge have memory. Outcomes from several spins ago can interact, machines of the same type can behave differently, and the relationships underneath can change.

We wanted to answer two questions: What pattern best explains this machine’s history, and how much should we trust that explanation? Instead of predicting one payout, we built a forecaster that assigns probabilities to all five outcomes: 0×, 1×, 2×, 5× and 20×.

These patterns belong to the challenge’s synthetic simulator; they are not claims about real casino machines.

How we built it

We began by checking our scoring implementation against the organizers’ tools. The competition measures squared probability error, averages it within episodes and conditions, and compares it with a frozen reference forecast.

Our main-round model grew from simple frequency baselines into a rule-prior regime forecaster. It separates the chance of winning from the payout distribution given a win, then combines them into the required five probabilities.

For each machine, the model weighs competing explanations:

  • Its behavior has remained stable.
  • Its behavior is drifting gradually.
  • Its behavior changed at an earlier point.

Rather than selecting one explanation with complete confidence, it averages their forecasts using evidence from the observed history. Rule probabilities learned across training machines help stabilize forecasts when an individual history is short.

We preserved actual tick positions throughout. Missing observations remain unknown, and every forecast uses information strictly before its prediction cutoff.

Round 2: adapting when the rules change

Round two tested whether our approach could relearn patterns rather than carry over a successful main-round model unchanged.

We refitted the pipeline using adaptation training data only. It discovered nine recurring multi-spin interaction rules, alongside eight single-lag rules. We also relearned the machine-type defaults, rule probabilities and payout-size parameters.

Before scoring candidates, we froze a validation split that kept all eight related machines in each episode together. We used the selection half to compare the refitted regime model with a newly trained mixture-model fallback, then froze our choice before revealing the check half.

Reproducibility

We treated the submission package as part of the project.

The adaptation entry contains the source, saved adaptation models, README, reproduction command and exactly pinned dependencies. Prediction runs offline without retraining or an external API.

A fresh extraction of the final ZIP reproduced the complete test CSV byte for byte using:

  • Python 3.13.6 with only NumPy 2.4.2 installed.
  • Test queries and histories, with no answer files available.
  • Two CPU cores.
  • 86.17 seconds of prediction time.

The organizers’ format checker accepted all 1,536 test queries, and archive inspection passed. Local reproduction was verified on Windows; native Linux execution was not independently tested.

AI coding assistants supported implementation, experimentation and review. Agreement between assistants was never sufficient by itself—we checked their work against executable tests and the organizers’ tools.

Challenges we ran into

Distinguishing change from noise. A model that reacts too quickly invents changes; one that reacts too slowly misses them. Averaging competing explanations helped us manage that uncertainty.

Learning from incomplete histories. Sparse observations can make accidental patterns look convincing. Sharing information through training-derived priors helped reduce overreaction.

Avoiding validation overfitting. Repeated experimentation makes familiar validation data less reliable. We documented decisions and preserved the round-two check half until after selecting the model. Validation results still cannot guarantee hidden-test performance.

Rejecting attractive ideas. Several extensions—including extra peer features, calibration corrections and a group-regime classifier—failed to show dependable gains or made forecasts worse. Leaving them out was part of building the final model.

Adapting the whole pipeline. Round two required more than updating a checkpoint. We had to rediscover the rules, rebuild the model, compare candidates and reproduce the final forecasts within a short deadline.

Our strongest result was a forecasting process that could learn new relationships, represent uncertainty and produce a reproducible submission when the underlying patterns changed.

Built With

  • bayesian-inference
  • changepoint-detection
  • claude-code
  • expectation-maximization
  • git
  • model-averaging
  • numpy
  • openai-codex
  • python
  • time-series-forecasting
Share this project:

Updates

Submission history