fix!(lua): G.GAME state survives menu+start — a previous run's won flag marks later losses as wins

Aperta
#232 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
4/5
Tempo stimato
3-5 giorni
Idoneità per principianti
48/100
Tipo di issue
Bug
Chiarezza
Abbastanza chiara
Stato di attività
Tranquilla
Stack tecnologico
lua, python
Ambito
api, backend, testing

Direzione di ricerca

Inizia dal percorso menu→start in start.lua, poi esamina src/lua/utils/gamestate.lua:739 e play.lua:125 per capire come won viene serializzato e utilizzato. Riproduci una vittoria seguita da una sconfitta su un’istanza di lunga durata usando le tracce delle azioni o i bundle di riproduzione citati, quindi confronta ogni esecuzione con un simulatore in un processo nuovo. Il lavoro è completato quando i quattro campi di stato elencati vengono ricostruiti per ogni esecuzione e bot.py non registra le sconfitte come vittorie.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Description

Starting a new run via menu + start on a long-lived instance does not fully
reset run state. We catalogued four distinct cross-run leaks, each confirmed by
replaying the identical action trace on a vanilla-faithful simulator (fresh
G.GAME every run) and diffing the full gamestate after every action.

  1. G.GAME.won — after any win in the session, a later run's GAME_OVER
    loss reports won = true. 16 instances observed; e.g. seed ESVPE7W2: 696
    chips vs Amber Acorn, unambiguous loss, live gamestate won = true — leaked
    from the previous run's ante-8 win on the same instance.
    src/lua/utils/gamestate.lua:739 serializes the raw global
    (state_data.won = G.GAME.won), so the stale value flows straight to
    clients; play.lua:125 also branches on it.
  2. G.GAME.last_tarot_planet — a fresh run's first Fool copied the tarot
    last used in the previous seed's run.
  3. G.GAME.pool_flags — gros_michel_extinct leaked: a run that never
    owned a Gros Michel was offered Cavendish in the shop (seed LS4ECDCB).
    Extinction only rolls for owned jokers at round end, so this is
    vanilla-impossible in-run.
  4. G.GAME.used_jokers key loss (mechanism unidentified, same family):
    live's shop offered j_banner while Banner sat in play (seed LS6VZ3ES) —
    impossible under the no-repeat pool. RNG forensics showed both sides drawing
    identical raw picks from the same stream; the sim resampled per no-repeat,
    live kept the duplicate, i.e. live had lost the key.

Root cause is presumably in how the run is rebuilt through the menu→start path
versus a fresh process launch (possibly SMODS-side), but balatrobot's start
endpoint is the natural place to defend against it.

Impact

This corrupts benchmark results, not just convenience:

  • balatrollm runs its whole task list through long-lived instances (the
    executor's port pool starts instances once) and starts each run with
    menu+start. bot.py ends a run as won when gamestate["won"] is truthy — so
    a loss that occurs on an instance after that instance has produced any win can
    be recorded and published as a win (run_won in the leaderboard data and
    the CC0 dataset).
  • Leaks 2–4 make seeded runs non-reproducible: shop and consumable outcomes
    depend on what earlier seeds did in the same instance.

Suggested Fix

In start.lua, after the run initializes, explicitly reset the leak-prone keys:
G.GAME.won = false, clear last_tarot_planet, and verify pool_flags /
used_jokers are freshly built. Alternatively (or additionally), document that
benchmark-grade data requires one process per run.

Repro bundles (action trace + both gamestates + field diff) available for every
seed cited.

Lingua principale
Python
Stelle
80
Fork
23
Metriche di merge delle PR
Nessuna PR unita negli ultimi 30g

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di coder/balatrobot

Tutte le issue di coder/balatrobot

Issue simili

Altre issue su Python

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.