diff --git a/.gitignore b/.gitignore index ce83ce4..16def7b 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,9 @@ src/**/*.c # Local session / lock files .compute.lock .claude/ +# ...except checked-in project skills, which are documentation for the next session. +!web/.claude/ +!web/.claude/** # Rust build output target/ @@ -29,10 +32,13 @@ tools/julia/ .ruff_cache # Web dependencies and locally exported models. The verified public browser -# policy below is the one exception: it is deliberately served as a static asset. +# policies below are the exception: they are deliberately served as static assets, +# and the deploy builds straight from the repo, so an ignored model ships as a 404. web/node_modules/ web/*.tsbuildinfo web/public/models/*.onnx web/public/models/*.json !web/public/models/jax-ppo.onnx !web/public/models/jax-ppo.json +!web/public/models/borealis.onnx +!web/public/models/borealis.json diff --git a/configs/jax_ppo/match-selfplay.yaml b/configs/jax_ppo/match-selfplay.yaml new file mode 100644 index 0000000..4dd42f6 --- /dev/null +++ b/configs/jax_ppo/match-selfplay.yaml @@ -0,0 +1,50 @@ +# Classic Lost Cities: three rounds, self-play. +# +# rollout_steps is deliberately shorter than a match. Early self-play stalls +# rounds badly (untrained matches run ~900 plies), and the env carries across +# updates, so a long match simply spans several rollouts -- the GAE truncation +# bootstrap keeps that unbiased. Sizing the scan to the worst-case match instead +# would blow up the rollout tensors, which are already doubled by training both +# seats and widened by the critic's 681-dim privileged view. +run: + experiment_name: match-selfplay + seed: 20260715 + learner_seat: 0 + total_updates: 300 + log_every: 10 + checkpoint_every: 50 + artifact_root: runs/jax-ppo-match + +opponent: + name: discard_only # unused: self-play + +network: + hidden_size: 512 + num_layers: 3 + +ppo: + batch_games: 512 + rollout_steps: 256 + gamma: 1.0 + gae_lambda: 0.97 # a match is ~3x a round; 0.95 reaches too little of it + clip_epsilon: 0.2 + entropy_coef: 0.01 + value_coef: 0.5 + max_grad_norm: 0.5 + learning_rate: 0.0003 + epochs: 4 + minibatches: 32 + +reward: + terminal_scale: 50.0 + # Counted in learner actions now, not padded scan steps. Held slightly above + # zero: the match-terminal signal alone is one bounded number per ~160 plies. + potential_shaping_initial: 1.0 + potential_shaping_final: 0.05 + potential_shaping_anneal_steps: 20000000 + +evaluation: + games: 2000 + duplicate: true + shuffle_bank_seed: 20260715 + batch_games: 512 diff --git a/data/human-play/game-records.jsonl b/data/human-play/game-records.jsonl new file mode 100644 index 0000000..ba8cd35 --- /dev/null +++ b/data/human-play/game-records.jsonl @@ -0,0 +1,111 @@ +{"format":"lost-cities-web-game-v1","gameId":"338fb8e7-6f01-4979-8cb6-8403b1be3cec","seed":"3z7aag","startedAt":"2026-07-14T13:51:30.385Z","finishedAt":"2026-07-14T13:53:37.109Z","initialDeckOrder":[51,40,38,25,7,22,30,45,43,3,23,24,41,35,46,28,20,33,53,42,39,10,31,12,18,37,32,34,11,36,4,15,50,49,0,8,14,27,48,1,56,54,57,9,55,19,2,26,52,21,59,5,58,13,6,29,16,17,47,44],"moves":[{"ply":1,"player":"human","action":48,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[7,22,25,30,38,40,45,51],"ai":[3,23,24,28,35,41,43,46]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":60,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[7,20,22,25,30,40,45,51],"ai":[3,23,24,28,35,41,43,46]},"scoresAfter":[-40,-16]},{"ply":3,"player":"human","action":60,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[7,20,22,25,30,40,45,51],"ai":[3,23,24,28,33,35,43,46]},"scoresAfter":[-34,-16]},{"ply":4,"player":"ai","action":72,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[7,20,22,25,30,45,51,53],"ai":[3,23,24,28,33,35,43,46]},"scoresAfter":[-34,-10]},{"ply":5,"player":"human","action":42,"playedCard":25,"placeType":"discard","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[7,20,22,25,30,45,51,53],"ai":[3,23,24,28,33,35,42,46]},"scoresAfter":[-34,-10]},{"ply":6,"player":"ai","action":78,"playedCard":42,"placeType":"discard","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[7,20,22,30,39,45,51,53],"ai":[3,23,24,28,33,35,42,46]},"scoresAfter":[-34,-10]},{"ply":7,"player":"human","action":82,"playedCard":51,"placeType":"discard","drawSource":"discard_3","drawnCard":42,"handsBefore":{"human":[7,20,22,30,39,45,51,53],"ai":[3,10,23,24,28,33,35,46]},"scoresAfter":[-34,-10]},{"ply":8,"player":"ai","action":84,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[7,20,22,30,39,42,45,53],"ai":[3,10,23,24,28,33,35,46]},"scoresAfter":[-34,-1]},{"ply":9,"player":"human","action":60,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[7,20,22,30,39,42,45,53],"ai":[3,10,23,24,28,31,33,35]},"scoresAfter":[-24,-1]},{"ply":10,"player":"ai","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[7,12,20,22,30,39,45,53],"ai":[3,10,23,24,28,31,33,35]},"scoresAfter":[-24,-19]},{"ply":11,"player":"human","action":66,"playedCard":39,"placeType":"discard","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[7,12,20,22,30,39,45,53],"ai":[10,18,23,24,28,31,33,35]},"scoresAfter":[-24,-19]},{"ply":12,"player":"ai","action":36,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[7,12,20,22,30,37,45,53],"ai":[10,18,23,24,28,31,33,35]},"scoresAfter":[-24,-59]},{"ply":13,"player":"human","action":66,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[7,12,20,22,30,37,45,53],"ai":[10,18,23,28,31,32,33,35]},"scoresAfter":[-24,-59]},{"ply":14,"player":"ai","action":12,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[7,12,20,22,30,34,45,53],"ai":[10,18,23,28,31,32,33,35]},"scoresAfter":[-24,-74]},{"ply":15,"player":"human","action":12,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[7,12,20,22,30,34,45,53],"ai":[10,11,23,28,31,32,33,35]},"scoresAfter":[-64,-74]},{"ply":16,"player":"ai","action":3,"playedCard":10,"placeType":"play","drawSource":"discard_2","drawnCard":25,"handsBefore":{"human":[7,20,22,30,34,36,45,53],"ai":[10,11,23,28,31,32,33,35]},"scoresAfter":[-64,-65]},{"ply":17,"player":"human","action":66,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[7,20,22,30,34,36,45,53],"ai":[11,23,25,28,31,32,33,35]},"scoresAfter":[-64,-65]},{"ply":18,"player":"ai","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[4,7,20,22,30,34,45,53],"ai":[11,23,25,28,31,32,33,35]},"scoresAfter":[-64,-55]},{"ply":19,"player":"human","action":6,"playedCard":4,"placeType":"discard","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[4,7,20,22,30,34,45,53],"ai":[15,23,25,28,31,32,33,35]},"scoresAfter":[-64,-55]},{"ply":20,"player":"ai","action":12,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[7,20,22,30,34,45,50,53],"ai":[15,23,25,28,31,32,33,35]},"scoresAfter":[-64,-45]},{"ply":21,"player":"human","action":6,"playedCard":7,"placeType":"discard","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[7,20,22,30,34,45,50,53],"ai":[15,25,28,31,32,33,35,49]},"scoresAfter":[-64,-45]},{"ply":22,"player":"ai","action":12,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[0,20,22,30,34,45,50,53],"ai":[15,25,28,31,32,33,35,49]},"scoresAfter":[-64,-65]},{"ply":23,"player":"human","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[0,20,22,30,34,45,50,53],"ai":[8,15,28,31,32,33,35,49]},"scoresAfter":[-64,-65]},{"ply":24,"player":"ai","action":6,"playedCard":8,"placeType":"discard","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[14,20,22,30,34,45,50,53],"ai":[8,15,28,31,32,33,35,49]},"scoresAfter":[-64,-65]},{"ply":25,"player":"human","action":0,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[14,20,22,30,34,45,50,53],"ai":[15,27,28,31,32,33,35,49]},"scoresAfter":[-84,-65]},{"ply":26,"player":"ai","action":90,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[20,22,30,34,45,48,50,53],"ai":[15,27,28,31,32,33,35,49]},"scoresAfter":[-84,-65]},{"ply":27,"player":"human","action":48,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[20,22,30,34,45,48,50,53],"ai":[1,15,27,28,31,32,33,35]},"scoresAfter":[-68,-65]},{"ply":28,"player":"ai","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[20,22,30,34,48,50,53,56],"ai":[1,15,27,28,31,32,33,35]},"scoresAfter":[-68,-65]},{"ply":29,"player":"human","action":66,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[20,22,30,34,48,50,53,56],"ai":[15,27,28,31,32,33,35,54]},"scoresAfter":[-68,-65]},{"ply":30,"player":"ai","action":84,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[20,22,30,34,48,53,56,57],"ai":[15,27,28,31,32,33,35,54]},"scoresAfter":[-68,-80]},{"ply":31,"player":"human","action":53,"playedCard":48,"placeType":"play","drawSource":"discard_4","drawnCard":50,"handsBefore":{"human":[20,22,30,34,48,53,56,57],"ai":[9,15,27,28,31,32,33,35]},"scoresAfter":[-108,-80]},{"ply":32,"player":"ai","action":6,"playedCard":9,"placeType":"discard","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[20,22,30,34,50,53,56,57],"ai":[9,15,27,28,31,32,33,35]},"scoresAfter":[-108,-80]},{"ply":33,"player":"human","action":53,"playedCard":50,"placeType":"play","drawSource":"discard_4","drawnCard":49,"handsBefore":{"human":[20,22,30,34,50,53,56,57],"ai":[15,27,28,31,32,33,35,55]},"scoresAfter":[-128,-80]},{"ply":34,"player":"ai","action":84,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[20,22,30,34,49,53,56,57],"ai":[15,27,28,31,32,33,35,55]},"scoresAfter":[-128,-74]},{"ply":35,"player":"human","action":53,"playedCard":49,"placeType":"play","drawSource":"discard_4","drawnCard":51,"handsBefore":{"human":[20,22,30,34,49,53,56,57],"ai":[15,19,27,28,31,32,33,35]},"scoresAfter":[-148,-74]},{"ply":36,"player":"ai","action":24,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[20,22,30,34,51,53,56,57],"ai":[15,19,27,28,31,32,33,35]},"scoresAfter":[-148,-68]},{"ply":37,"player":"human","action":48,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[20,22,30,34,51,53,56,57],"ai":[2,15,19,28,31,32,33,35]},"scoresAfter":[-140,-68]},{"ply":38,"player":"ai","action":36,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[20,22,26,30,34,53,56,57],"ai":[2,15,19,28,31,32,33,35]},"scoresAfter":[-140,-59]},{"ply":39,"player":"human","action":60,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[20,22,26,30,34,53,56,57],"ai":[2,15,19,31,32,33,35,52]},"scoresAfter":[-124,-59]},{"ply":40,"player":"ai","action":36,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[20,21,22,26,30,34,56,57],"ai":[2,15,19,31,32,33,35,52]},"scoresAfter":[-124,-41]},{"ply":41,"player":"human","action":72,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[20,21,22,26,30,34,56,57],"ai":[2,15,19,32,33,35,52,59]},"scoresAfter":[-96,-41]},{"ply":42,"player":"ai","action":36,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[5,20,21,22,26,30,34,57],"ai":[2,15,19,32,33,35,52,59]},"scoresAfter":[-96,-20]},{"ply":43,"player":"human","action":84,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[5,20,21,22,26,30,34,57],"ai":[2,15,19,33,35,52,58,59]},"scoresAfter":[-64,-20]},{"ply":44,"player":"ai","action":72,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[5,13,20,21,22,26,30,34],"ai":[2,15,19,33,35,52,58,59]},"scoresAfter":[-64,-11]},{"ply":45,"player":"human","action":13,"playedCard":13,"placeType":"play","drawSource":"discard_0","drawnCard":9,"handsBefore":{"human":[5,13,20,21,22,26,30,34],"ai":[2,6,15,19,33,35,52,59]},"scoresAfter":[-84,-11]},{"ply":46,"player":"ai","action":48,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[5,9,20,21,22,26,30,34],"ai":[2,6,15,19,33,35,52,59]},"scoresAfter":[-84,13]},{"ply":47,"player":"human","action":25,"playedCard":20,"placeType":"play","drawSource":"discard_0","drawnCard":1,"handsBefore":{"human":[5,9,20,21,22,26,30,34],"ai":[2,6,15,19,29,35,52,59]},"scoresAfter":[-56,13]},{"ply":48,"player":"ai","action":60,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[1,5,9,21,22,26,30,34],"ai":[2,6,15,19,29,35,52,59]},"scoresAfter":[-56,63]},{"ply":49,"player":"human","action":37,"playedCard":21,"placeType":"play","drawSource":"discard_0","drawnCard":8,"handsBefore":{"human":[1,5,9,21,22,26,30,34],"ai":[2,6,15,16,19,29,52,59]},"scoresAfter":[-24,63]},{"ply":50,"player":"ai","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[1,5,8,9,22,26,30,34],"ai":[2,6,15,16,19,29,52,59]},"scoresAfter":[-24,73]},{"ply":51,"player":"human","action":48,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[1,5,8,9,22,26,30,34],"ai":[2,6,15,16,17,19,29,52]},"scoresAfter":[12,73]},{"ply":52,"player":"ai","action":78,"playedCard":29,"placeType":"discard","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[1,5,8,9,26,30,34,47],"ai":[2,6,15,16,17,19,29,52]},"scoresAfter":[12,73]}],"finalScores":[12,73],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[51,40,38,25,7,22,30,45,43,3,23,24,41,35,46,28,20,33,53,42,39,10,31,12,18,37,32,34,11,36,4,15,50,49,0,8,14,27,48,1,56,54,57,9,55,19,2,26,52,21,59,5,58,13,6,29,16,17,47,44],"drawPtr":60,"cardLoc":[5,1,2,4,5,1,2,5,1,1,4,4,3,3,3,2,2,2,4,2,3,3,3,4,4,4,1,4,4,5,1,4,4,4,1,4,5,5,3,5,3,4,3,4,2,3,4,1,3,3,3,3,2,3,4,4,3,3,4,4],"handPublic":[false,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[0,9,0,8,8],[10,10,10,9,10]],"colHandshakes":[[0,3,0,1,3],[0,0,2,0,0]],"colLength":[[0,6,0,4,7],[3,2,8,3,4]],"piles":[[4,7,0],[],[29],[39,37,36],[]],"toMove":0,"stepCount":52,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"1318ed9f-fd4d-40e1-962c-b94924419954","seed":"e7pupi","startedAt":"2026-07-14T13:54:40.837Z","finishedAt":"2026-07-14T13:56:44.427Z","initialDeckOrder":[17,23,13,25,19,55,49,1,18,5,58,50,45,4,2,15,30,9,16,59,21,34,36,6,12,53,57,14,33,46,29,54,31,56,10,8,26,48,39,35,20,24,42,38,27,40,32,3,43,41,51,52,37,22,11,28,0,44,7,47],"moves":[{"ply":1,"player":"human","action":12,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[1,13,17,19,23,25,49,55],"ai":[2,4,5,15,18,45,50,58]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":0,"playedCard":2,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[1,17,19,23,25,30,49,55],"ai":[2,4,5,15,18,45,50,58]},"scoresAfter":[-40,-40]},{"ply":3,"player":"human","action":12,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[1,17,19,23,25,30,49,55],"ai":[4,5,9,15,18,45,50,58]},"scoresAfter":[-32,-40]},{"ply":4,"player":"ai","action":72,"playedCard":50,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[1,16,19,23,25,30,49,55],"ai":[4,5,9,15,18,45,50,58]},"scoresAfter":[-32,-80]},{"ply":5,"player":"human","action":24,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[1,16,19,23,25,30,49,55],"ai":[4,5,9,15,18,45,58,59]},"scoresAfter":[-20,-80]},{"ply":6,"player":"ai","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[1,16,21,23,25,30,49,55],"ai":[4,5,9,15,18,45,58,59]},"scoresAfter":[-20,-74]},{"ply":7,"player":"human","action":24,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[1,16,21,23,25,30,49,55],"ai":[5,9,15,18,34,45,58,59]},"scoresAfter":[-4,-74]},{"ply":8,"player":"ai","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[1,16,23,25,30,36,49,55],"ai":[5,9,15,18,34,45,58,59]},"scoresAfter":[-4,-66]},{"ply":9,"player":"human","action":24,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[1,16,23,25,30,36,49,55],"ai":[6,9,15,18,34,45,58,59]},"scoresAfter":[16,-66]},{"ply":10,"player":"ai","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[1,12,16,25,30,36,49,55],"ai":[6,9,15,18,34,45,58,59]},"scoresAfter":[16,-56]},{"ply":11,"player":"human","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[1,12,16,25,30,36,49,55],"ai":[9,15,18,34,45,53,58,59]},"scoresAfter":[16,-56]},{"ply":12,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[12,16,25,30,36,49,55,57],"ai":[9,15,18,34,45,53,58,59]},"scoresAfter":[16,-40]},{"ply":13,"player":"human","action":60,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[12,16,25,30,36,49,55,57],"ai":[14,15,18,34,45,53,58,59]},"scoresAfter":[-24,-40]},{"ply":14,"player":"ai","action":18,"playedCard":15,"placeType":"discard","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[12,16,25,30,33,36,55,57],"ai":[14,15,18,34,45,53,58,59]},"scoresAfter":[-24,-40]},{"ply":15,"player":"human","action":24,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[12,16,25,30,33,36,55,57],"ai":[14,18,34,45,46,53,58,59]},"scoresAfter":[-64,-40]},{"ply":16,"player":"ai","action":18,"playedCard":18,"placeType":"discard","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[12,16,29,30,33,36,55,57],"ai":[14,18,34,45,46,53,58,59]},"scoresAfter":[-64,-40]},{"ply":17,"player":"human","action":24,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[12,16,29,30,33,36,55,57],"ai":[14,34,45,46,53,54,58,59]},"scoresAfter":[-56,-40]},{"ply":18,"player":"ai","action":6,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[12,16,30,31,33,36,55,57],"ai":[14,34,45,46,53,54,58,59]},"scoresAfter":[-56,-40]},{"ply":19,"player":"human","action":24,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[12,16,30,31,33,36,55,57],"ai":[34,45,46,53,54,56,58,59]},"scoresAfter":[-46,-40]},{"ply":20,"player":"ai","action":0,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[10,12,16,31,33,36,55,57],"ai":[34,45,46,53,54,56,58,59]},"scoresAfter":[-46,-51]},{"ply":21,"player":"human","action":36,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[10,12,16,31,33,36,55,57],"ai":[8,45,46,53,54,56,58,59]},"scoresAfter":[-34,-51]},{"ply":22,"player":"ai","action":12,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[10,12,16,26,33,36,55,57],"ai":[8,45,46,53,54,56,58,59]},"scoresAfter":[-34,-63]},{"ply":23,"player":"human","action":42,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[10,12,16,26,33,36,55,57],"ai":[8,46,48,53,54,56,58,59]},"scoresAfter":[-34,-63]},{"ply":24,"player":"ai","action":12,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[10,12,16,33,36,39,55,57],"ai":[8,46,48,53,54,56,58,59]},"scoresAfter":[-34,-54]},{"ply":25,"player":"human","action":54,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[10,12,16,33,36,39,55,57],"ai":[8,35,48,53,54,56,58,59]},"scoresAfter":[-34,-54]},{"ply":26,"player":"ai","action":12,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[10,12,16,20,33,39,55,57],"ai":[8,35,48,53,54,56,58,59]},"scoresAfter":[-34,-44]},{"ply":27,"player":"human","action":66,"playedCard":39,"placeType":"discard","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[10,12,16,20,33,39,55,57],"ai":[8,24,48,53,54,56,58,59]},"scoresAfter":[-34,-44]},{"ply":28,"player":"ai","action":24,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[10,12,16,20,33,42,55,57],"ai":[8,24,48,53,54,56,58,59]},"scoresAfter":[-34,-64]},{"ply":29,"player":"human","action":66,"playedCard":42,"placeType":"discard","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[10,12,16,20,33,42,55,57],"ai":[8,24,38,53,54,56,58,59]},"scoresAfter":[-34,-64]},{"ply":30,"player":"ai","action":6,"playedCard":8,"placeType":"discard","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[10,12,16,20,27,33,55,57],"ai":[8,24,38,53,54,56,58,59]},"scoresAfter":[-34,-64]},{"ply":31,"player":"human","action":18,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[10,12,16,20,27,33,55,57],"ai":[24,38,40,53,54,56,58,59]},"scoresAfter":[-34,-64]},{"ply":32,"player":"ai","action":6,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[10,16,20,27,32,33,55,57],"ai":[24,38,40,53,54,56,58,59]},"scoresAfter":[-34,-64]},{"ply":33,"player":"human","action":48,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[10,16,20,27,32,33,55,57],"ai":[3,38,40,53,54,56,58,59]},"scoresAfter":[-20,-64]},{"ply":34,"player":"ai","action":36,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[10,16,20,27,33,43,55,57],"ai":[3,38,40,53,54,56,58,59]},"scoresAfter":[-20,-52]},{"ply":35,"player":"human","action":48,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[10,16,20,27,33,43,55,57],"ai":[3,38,40,41,54,56,58,59]},"scoresAfter":[-4,-52]},{"ply":36,"player":"ai","action":48,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[10,16,20,27,43,51,55,57],"ai":[3,38,40,41,54,56,58,59]},"scoresAfter":[-4,-37]},{"ply":37,"player":"human","action":60,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[10,16,20,27,43,51,55,57],"ai":[3,38,40,41,52,56,58,59]},"scoresAfter":[0,-37]},{"ply":38,"player":"ai","action":60,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[10,16,20,27,37,43,55,57],"ai":[3,38,40,41,52,56,58,59]},"scoresAfter":[0,-16]},{"ply":39,"player":"human","action":72,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[10,16,20,27,37,43,55,57],"ai":[3,22,38,40,41,52,58,59]},"scoresAfter":[12,-16]},{"ply":40,"player":"ai","action":72,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[10,11,16,20,27,37,43,57],"ai":[3,22,38,40,41,52,58,59]},"scoresAfter":[12,11]},{"ply":41,"player":"human","action":85,"playedCard":57,"placeType":"play","drawSource":"discard_0","drawnCard":8,"handsBefore":{"human":[10,11,16,20,27,37,43,57],"ai":[3,22,28,38,40,41,52,59]},"scoresAfter":[28,11]},{"ply":42,"player":"ai","action":13,"playedCard":22,"placeType":"play","drawSource":"discard_0","drawnCard":1,"handsBefore":{"human":[8,10,11,16,20,27,37,43],"ai":[3,22,28,38,40,41,52,59]},"scoresAfter":[28,0]},{"ply":43,"player":"human","action":4,"playedCard":8,"placeType":"play","drawSource":"discard_3","drawnCard":42,"handsBefore":{"human":[8,10,11,16,20,27,37,43],"ai":[1,3,28,38,40,41,52,59]},"scoresAfter":[15,0]},{"ply":44,"player":"ai","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[10,11,16,20,27,37,42,43],"ai":[1,3,28,38,40,41,52,59]},"scoresAfter":[15,30]},{"ply":45,"player":"human","action":4,"playedCard":10,"placeType":"play","drawSource":"discard_3","drawnCard":39,"handsBefore":{"human":[10,11,16,20,27,37,42,43],"ai":[0,1,3,28,38,40,41,52]},"scoresAfter":[24,30]},{"ply":46,"player":"ai","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[11,16,20,27,37,39,42,43],"ai":[0,1,3,28,38,40,41,52]},"scoresAfter":[24,30]},{"ply":47,"player":"human","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[11,16,20,27,37,39,42,43],"ai":[1,3,28,38,40,41,44,52]},"scoresAfter":[34,30]},{"ply":48,"player":"ai","action":30,"playedCard":28,"placeType":"discard","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[7,16,20,27,37,39,42,43],"ai":[1,3,28,38,40,41,44,52]},"scoresAfter":[34,30]}],"finalScores":[34,30],"outcome":"YOU WIN","finalState":{"deckOrder":[17,23,13,25,19,55,49,1,18,5,58,50,45,4,2,15,30,9,16,59,21,34,36,6,12,53,57,14,33,46,29,54,31,56,10,8,26,48,39,35,20,24,42,38,27,40,32,3,43,41,51,52,37,22,11,28,0,44,7,47],"drawPtr":60,"cardLoc":[5,2,4,2,4,4,4,1,3,4,3,3,5,3,5,5,1,3,5,3,1,3,4,3,5,3,5,1,5,3,3,3,3,3,4,4,5,1,2,1,2,2,1,1,2,4,4,2,4,3,4,3,2,4,4,3,4,3,4,4],"handPublic":[false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,10,8,0,8],[8,9,10,9,10]],"colHandshakes":[[0,1,1,0,1],[1,0,0,0,2]],"colLength":[[3,5,6,0,4],[5,1,2,2,7]],"piles":[[0],[15,18,14,12],[26,24,28],[36],[]],"toMove":0,"stepCount":48,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"8b9a1760-38a0-4e2d-96eb-122d1b96c477","seed":"jsrmix","startedAt":"2026-07-14T13:56:47.111Z","finishedAt":"2026-07-14T13:59:05.057Z","initialDeckOrder":[40,29,43,13,37,10,31,1,45,6,25,27,16,41,8,54,55,39,20,0,23,30,52,26,58,14,24,15,32,53,44,50,28,35,49,17,36,12,22,21,9,42,4,59,48,57,51,33,47,56,46,5,19,18,3,38,2,34,11,7],"moves":[{"ply":1,"player":"human","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[1,10,13,29,31,37,40,43],"ai":[6,8,16,25,27,41,45,54]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[10,13,29,31,37,40,43,55],"ai":[6,8,16,25,27,41,45,54]},"scoresAfter":[-40,-15]},{"ply":3,"player":"human","action":48,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[10,13,29,31,37,40,43,55],"ai":[8,16,25,27,39,41,45,54]},"scoresAfter":[-80,-15]},{"ply":4,"player":"ai","action":24,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[10,13,20,29,31,40,43,55],"ai":[8,16,25,27,39,41,45,54]},"scoresAfter":[-80,-55]},{"ply":5,"player":"human","action":60,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[10,13,20,29,31,40,43,55],"ai":[0,8,16,27,39,41,45,54]},"scoresAfter":[-74,-55]},{"ply":6,"player":"ai","action":48,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[10,13,20,23,29,31,43,55],"ai":[0,8,16,27,39,41,45,54]},"scoresAfter":[-74,-73]},{"ply":7,"player":"human","action":12,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[10,13,20,23,29,31,43,55],"ai":[0,8,16,27,30,41,45,54]},"scoresAfter":[-114,-73]},{"ply":8,"player":"ai","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[10,20,23,29,31,43,52,55],"ai":[0,8,16,27,30,41,45,54]},"scoresAfter":[-114,-73]},{"ply":9,"player":"human","action":78,"playedCard":52,"placeType":"discard","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[10,20,23,29,31,43,52,55],"ai":[8,16,26,27,30,41,45,54]},"scoresAfter":[-114,-73]},{"ply":10,"player":"ai","action":60,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[10,20,23,29,31,43,55,58],"ai":[8,16,26,27,30,41,45,54]},"scoresAfter":[-114,-69]},{"ply":11,"player":"human","action":36,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[10,20,23,29,31,43,55,58],"ai":[8,14,16,26,27,30,45,54]},"scoresAfter":[-130,-69]},{"ply":12,"player":"ai","action":12,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[10,20,23,24,31,43,55,58],"ai":[8,14,16,26,27,30,45,54]},"scoresAfter":[-130,-109]},{"ply":13,"player":"human","action":42,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[10,20,23,24,31,43,55,58],"ai":[8,15,16,26,27,30,45,54]},"scoresAfter":[-130,-109]},{"ply":14,"player":"ai","action":3,"playedCard":8,"placeType":"play","drawSource":"discard_2","drawnCard":24,"handsBefore":{"human":[10,20,23,31,32,43,55,58],"ai":[8,15,16,26,27,30,45,54]},"scoresAfter":[-130,-102]},{"ply":15,"player":"human","action":36,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[10,20,23,31,32,43,55,58],"ai":[15,16,24,26,27,30,45,54]},"scoresAfter":[-124,-102]},{"ply":16,"player":"ai","action":24,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[10,20,23,32,43,53,55,58],"ai":[15,16,24,26,27,30,45,54]},"scoresAfter":[-124,-122]},{"ply":17,"player":"human","action":41,"playedCard":32,"placeType":"play","drawSource":"discard_4","drawnCard":52,"handsBefore":{"human":[10,20,23,32,43,53,55,58],"ai":[15,16,26,27,30,44,45,54]},"scoresAfter":[-117,-122]},{"ply":18,"player":"ai","action":24,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[10,20,23,43,52,53,55,58],"ai":[15,16,26,27,30,44,45,54]},"scoresAfter":[-117,-142]},{"ply":19,"player":"human","action":48,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[10,20,23,43,52,53,55,58],"ai":[15,16,27,30,44,45,50,54]},"scoresAfter":[-134,-142]},{"ply":20,"player":"ai","action":48,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[10,20,23,28,43,53,55,58],"ai":[15,16,27,30,44,45,50,54]},"scoresAfter":[-134,-135]},{"ply":21,"player":"human","action":60,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[10,20,23,28,43,53,55,58],"ai":[15,16,27,30,35,45,50,54]},"scoresAfter":[-130,-135]},{"ply":22,"player":"ai","action":60,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[10,20,23,28,43,49,55,58],"ai":[15,16,27,30,35,45,50,54]},"scoresAfter":[-130,-127]},{"ply":23,"player":"human","action":72,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[10,20,23,28,43,49,55,58],"ai":[15,16,17,27,30,35,50,54]},"scoresAfter":[-124,-127]},{"ply":24,"player":"ai","action":90,"playedCard":54,"placeType":"discard","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[10,20,23,28,36,43,49,58],"ai":[15,16,17,27,30,35,50,54]},"scoresAfter":[-124,-127]},{"ply":25,"player":"human","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[10,20,23,28,36,43,49,58],"ai":[12,15,16,17,27,30,35,50]},"scoresAfter":[-115,-127]},{"ply":26,"player":"ai","action":0,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[10,20,22,23,28,36,43,49],"ai":[12,15,16,17,27,30,35,50]},"scoresAfter":[-115,-147]},{"ply":27,"player":"human","action":12,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[10,20,22,23,28,36,43,49],"ai":[15,16,17,21,27,30,35,50]},"scoresAfter":[-101,-147]},{"ply":28,"player":"ai","action":0,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[9,10,22,23,28,36,43,49],"ai":[15,16,17,21,27,30,35,50]},"scoresAfter":[-101,-141]},{"ply":29,"player":"human","action":24,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[9,10,22,23,28,36,43,49],"ai":[16,17,21,27,30,35,42,50]},"scoresAfter":[-83,-141]},{"ply":30,"player":"ai","action":0,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[4,9,10,23,28,36,43,49],"ai":[16,17,21,27,30,35,42,50]},"scoresAfter":[-83,-132]},{"ply":31,"player":"human","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[4,9,10,23,28,36,43,49],"ai":[17,21,27,30,35,42,50,59]},"scoresAfter":[-77,-132]},{"ply":32,"player":"ai","action":0,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[9,10,23,28,36,43,48,49],"ai":[17,21,27,30,35,42,50,59]},"scoresAfter":[-77,-120]},{"ply":33,"player":"human","action":24,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[9,10,23,28,36,43,48,49],"ai":[21,27,30,35,42,50,57,59]},"scoresAfter":[-57,-120]},{"ply":34,"player":"ai","action":0,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[9,10,28,36,43,48,49,51],"ai":[21,27,30,35,42,50,57,59]},"scoresAfter":[-57,-96]},{"ply":35,"player":"human","action":42,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[9,10,28,36,43,48,49,51],"ai":[27,30,33,35,42,50,57,59]},"scoresAfter":[-57,-96]},{"ply":36,"player":"ai","action":78,"playedCard":57,"placeType":"discard","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[9,10,28,43,47,48,49,51],"ai":[27,30,33,35,42,50,57,59]},"scoresAfter":[-57,-96]},{"ply":37,"player":"human","action":78,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[9,10,28,43,47,48,49,51],"ai":[27,30,33,35,42,50,56,59]},"scoresAfter":[-57,-96]},{"ply":38,"player":"ai","action":0,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[9,10,28,43,46,47,48,51],"ai":[27,30,33,35,42,50,56,59]},"scoresAfter":[-57,-88]},{"ply":39,"player":"human","action":36,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[9,10,28,43,46,47,48,51],"ai":[5,30,33,35,42,50,56,59]},"scoresAfter":[-45,-88]},{"ply":40,"player":"ai","action":12,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[9,10,19,28,46,47,48,51],"ai":[5,30,33,35,42,50,56,59]},"scoresAfter":[-45,-68]},{"ply":41,"player":"human","action":48,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[9,10,19,28,46,47,48,51],"ai":[5,18,33,35,42,50,56,59]},"scoresAfter":[-27,-68]},{"ply":42,"player":"ai","action":24,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[3,9,10,19,28,47,48,51],"ai":[5,18,33,35,42,50,56,59]},"scoresAfter":[-27,-36]},{"ply":43,"player":"human","action":60,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[3,9,10,19,28,47,48,51],"ai":[5,18,35,38,42,50,56,59]},"scoresAfter":[-7,-36]},{"ply":44,"player":"ai","action":24,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[2,3,9,10,19,28,48,51],"ai":[5,18,35,38,42,50,56,59]},"scoresAfter":[-7,4]},{"ply":45,"player":"human","action":25,"playedCard":9,"placeType":"play","drawSource":"discard_0","drawnCard":0,"handsBefore":{"human":[2,3,9,10,19,28,48,51],"ai":[5,18,34,38,42,50,56,59]},"scoresAfter":[9,4]},{"ply":46,"player":"ai","action":70,"playedCard":50,"placeType":"discard","drawSource":"discard_3","drawnCard":36,"handsBefore":{"human":[0,2,3,10,19,28,48,51],"ai":[5,18,34,38,42,50,56,59]},"scoresAfter":[9,4]},{"ply":47,"player":"human","action":36,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[0,2,3,10,19,28,48,51],"ai":[5,18,34,36,38,42,56,59]},"scoresAfter":[27,4]},{"ply":48,"player":"ai","action":30,"playedCard":34,"placeType":"discard","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[0,2,3,11,19,28,48,51],"ai":[5,18,34,36,38,42,56,59]},"scoresAfter":[27,4]}],"finalScores":[27,4],"outcome":"YOU WIN","finalState":{"deckOrder":[40,29,43,13,37,10,31,1,45,6,25,27,16,41,8,54,55,39,20,0,23,30,52,26,58,14,24,15,32,53,44,50,28,35,49,17,36,12,22,21,9,42,4,59,48,57,51,33,47,56,46,5,19,18,3,38,2,34,11,7],"drawPtr":60,"cardLoc":[1,3,1,1,3,2,4,2,4,3,3,1,4,3,4,4,4,4,2,1,3,4,3,3,4,4,4,4,1,3,4,3,3,4,5,4,2,3,2,4,3,4,2,3,4,4,3,3,1,5,5,1,3,3,5,3,2,5,3,2],"handPublic":[true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[9,10,7,10,9],[7,8,10,8,0]],"colHandshakes":[[1,1,0,1,0],[0,2,3,0,0]],"colLength":[[4,4,3,5,4],[2,6,7,4,0]],"piles":[[],[],[34],[],[54,57,49,50]],"toMove":0,"stepCount":48,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"acf54d24-5784-481c-9704-80a616a41a83","seed":"odlvvm","startedAt":"2026-07-14T13:59:06.466Z","finishedAt":"2026-07-14T14:01:46.522Z","initialDeckOrder":[48,27,22,0,7,35,34,11,31,49,8,24,59,40,5,10,14,47,55,20,18,51,41,54,12,30,2,33,15,45,25,44,4,39,38,50,56,29,21,9,3,13,37,17,1,43,19,42,23,26,36,46,28,57,6,16,53,52,58,32],"moves":[{"ply":1,"player":"human","action":0,"playedCard":0,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[0,7,11,22,27,34,35,48],"ai":[5,8,10,24,31,40,49,59]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[7,11,14,22,27,34,35,48],"ai":[5,8,10,24,31,40,49,59]},"scoresAfter":[-40,-16]},{"ply":3,"player":"human","action":48,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[7,11,14,22,27,34,35,48],"ai":[8,10,24,31,40,47,49,59]},"scoresAfter":[-58,-16]},{"ply":4,"player":"ai","action":24,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[7,11,14,22,34,35,48,55],"ai":[8,10,24,31,40,47,49,59]},"scoresAfter":[-58,-56]},{"ply":5,"player":"human","action":24,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[7,11,14,22,34,35,48,55],"ai":[8,10,20,31,40,47,49,59]},"scoresAfter":[-98,-56]},{"ply":6,"player":"ai","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[7,11,18,22,34,35,48,55],"ai":[8,10,20,31,40,47,49,59]},"scoresAfter":[-98,-49]},{"ply":7,"player":"human","action":48,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[7,11,18,22,34,35,48,55],"ai":[10,20,31,40,47,49,51,59]},"scoresAfter":[-89,-49]},{"ply":8,"player":"ai","action":60,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[7,11,18,22,35,41,48,55],"ai":[10,20,31,40,47,49,51,59]},"scoresAfter":[-89,-89]},{"ply":9,"player":"human","action":48,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[7,11,18,22,35,41,48,55],"ai":[10,20,31,40,47,51,54,59]},"scoresAfter":[-79,-89]},{"ply":10,"player":"ai","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[7,11,12,18,22,41,48,55],"ai":[10,20,31,40,47,51,54,59]},"scoresAfter":[-79,-80]},{"ply":11,"player":"human","action":24,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[7,11,12,18,22,41,48,55],"ai":[20,30,31,40,47,51,54,59]},"scoresAfter":[-99,-80]},{"ply":12,"player":"ai","action":0,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[2,7,11,18,22,41,48,55],"ai":[20,30,31,40,47,51,54,59]},"scoresAfter":[-99,-93]},{"ply":13,"player":"human","action":0,"playedCard":2,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[2,7,11,18,22,41,48,55],"ai":[30,31,33,40,47,51,54,59]},"scoresAfter":[-119,-93]},{"ply":14,"player":"ai","action":60,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[7,11,15,18,22,41,48,55],"ai":[30,31,33,40,47,51,54,59]},"scoresAfter":[-119,-89]},{"ply":15,"player":"human","action":24,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[7,11,15,18,22,41,48,55],"ai":[30,31,33,40,45,47,54,59]},"scoresAfter":[-113,-89]},{"ply":16,"player":"ai","action":72,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[7,11,18,22,25,41,48,55],"ai":[30,31,33,40,45,47,54,59]},"scoresAfter":[-113,-79]},{"ply":17,"player":"human","action":24,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[7,11,18,22,25,41,48,55],"ai":[30,31,33,40,44,45,47,59]},"scoresAfter":[-98,-79]},{"ply":18,"player":"ai","action":0,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[4,7,11,22,25,41,48,55],"ai":[30,31,33,40,44,45,47,59]},"scoresAfter":[-98,-69]},{"ply":19,"player":"human","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[4,7,11,22,25,41,48,55],"ai":[31,33,39,40,44,45,47,59]},"scoresAfter":[-89,-69]},{"ply":20,"player":"ai","action":0,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[7,11,22,25,38,41,48,55],"ai":[31,33,39,40,44,45,47,59]},"scoresAfter":[-89,-57]},{"ply":21,"player":"human","action":78,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[7,11,22,25,38,41,48,55],"ai":[33,39,40,44,45,47,50,59]},"scoresAfter":[-89,-57]},{"ply":22,"player":"ai","action":78,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[7,11,22,25,38,41,55,56],"ai":[33,39,40,44,45,47,50,59]},"scoresAfter":[-89,-57]},{"ply":23,"player":"human","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[7,11,22,25,38,41,55,56],"ai":[29,33,39,40,44,45,47,59]},"scoresAfter":[-71,-57]},{"ply":24,"player":"ai","action":12,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[11,21,22,25,38,41,55,56],"ai":[29,33,39,40,44,45,47,59]},"scoresAfter":[-71,-41]},{"ply":25,"player":"human","action":12,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[11,21,22,25,38,41,55,56],"ai":[9,29,39,40,44,45,47,59]},"scoresAfter":[-47,-41]},{"ply":26,"player":"ai","action":6,"playedCard":9,"placeType":"discard","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[3,11,22,25,38,41,55,56],"ai":[9,29,39,40,44,45,47,59]},"scoresAfter":[-47,-41]},{"ply":27,"player":"human","action":55,"playedCard":38,"placeType":"discard","drawSource":"discard_0","drawnCard":9,"handsBefore":{"human":[3,11,22,25,38,41,55,56],"ai":[13,29,39,40,44,45,47,59]},"scoresAfter":[-47,-41]},{"ply":28,"player":"ai","action":88,"playedCard":59,"placeType":"play","drawSource":"discard_3","drawnCard":38,"handsBefore":{"human":[3,9,11,22,25,41,55,56],"ai":[13,29,39,40,44,45,47,59]},"scoresAfter":[-47,-21]},{"ply":29,"player":"human","action":12,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[3,9,11,22,25,41,55,56],"ai":[13,29,38,39,40,44,45,47]},"scoresAfter":[-23,-21]},{"ply":30,"player":"ai","action":24,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[3,11,22,25,37,41,55,56],"ai":[13,29,38,39,40,44,45,47]},"scoresAfter":[-23,-61]},{"ply":31,"player":"human","action":54,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[3,11,22,25,37,41,55,56],"ai":[13,17,29,39,40,44,45,47]},"scoresAfter":[-23,-61]},{"ply":32,"player":"ai","action":10,"playedCard":13,"placeType":"discard","drawSource":"discard_3","drawnCard":37,"handsBefore":{"human":[1,3,11,22,25,41,55,56],"ai":[13,17,29,39,40,44,45,47]},"scoresAfter":[-23,-61]},{"ply":33,"player":"human","action":24,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[1,3,11,22,25,41,55,56],"ai":[17,29,37,39,40,44,45,47]},"scoresAfter":[7,-61]},{"ply":34,"player":"ai","action":24,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[1,3,22,25,41,43,55,56],"ai":[17,29,37,39,40,44,45,47]},"scoresAfter":[7,-81]},{"ply":35,"player":"human","action":24,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[1,3,22,25,41,43,55,56],"ai":[17,19,29,39,40,44,45,47]},"scoresAfter":[34,-81]},{"ply":36,"player":"ai","action":36,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[1,3,25,41,42,43,55,56],"ai":[17,19,29,39,40,44,45,47]},"scoresAfter":[34,-75]},{"ply":37,"player":"human","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[1,3,25,41,42,43,55,56],"ai":[17,19,23,29,40,44,45,47]},"scoresAfter":[34,-75]},{"ply":38,"player":"ai","action":24,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[3,25,26,41,42,43,55,56],"ai":[17,19,23,29,40,44,45,47]},"scoresAfter":[34,-65]},{"ply":39,"player":"human","action":30,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[3,25,26,41,42,43,55,56],"ai":[17,19,29,36,40,44,45,47]},"scoresAfter":[34,-65]},{"ply":40,"player":"ai","action":48,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[3,25,41,42,43,46,55,56],"ai":[17,19,29,36,40,44,45,47]},"scoresAfter":[34,-56]},{"ply":41,"player":"human","action":24,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[3,25,41,42,43,46,55,56],"ai":[17,19,28,29,36,44,45,47]},"scoresAfter":[18,-56]},{"ply":42,"player":"ai","action":35,"playedCard":28,"placeType":"discard","drawSource":"discard_4","drawnCard":50,"handsBefore":{"human":[3,25,42,43,46,55,56,57],"ai":[17,19,28,29,36,44,45,47]},"scoresAfter":[18,-56]},{"ply":43,"player":"human","action":29,"playedCard":42,"placeType":"play","drawSource":"discard_4","drawnCard":48,"handsBefore":{"human":[3,25,42,43,46,55,56,57],"ai":[17,19,29,36,44,45,47,50]},"scoresAfter":[23,-56]},{"ply":44,"player":"ai","action":48,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[3,25,43,46,48,55,56,57],"ai":[17,19,29,36,44,45,47,50]},"scoresAfter":[23,-35]},{"ply":45,"player":"human","action":27,"playedCard":43,"placeType":"play","drawSource":"discard_2","drawnCard":28,"handsBefore":{"human":[3,25,43,46,48,55,56,57],"ai":[6,17,19,29,36,45,47,50]},"scoresAfter":[29,-35]},{"ply":46,"player":"ai","action":60,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[3,25,28,46,48,55,56,57],"ai":[6,17,19,29,36,45,47,50]},"scoresAfter":[29,-11]},{"ply":47,"player":"human","action":36,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[3,25,28,46,48,55,56,57],"ai":[6,16,17,19,29,36,47,50]},"scoresAfter":[38,-11]},{"ply":48,"player":"ai","action":72,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[3,25,28,48,53,55,56,57],"ai":[6,16,17,19,29,36,47,50]},"scoresAfter":[38,19]},{"ply":49,"player":"human","action":42,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[3,25,28,48,53,55,56,57],"ai":[6,16,17,19,29,36,50,52]},"scoresAfter":[38,19]},{"ply":50,"player":"ai","action":6,"playedCard":6,"placeType":"discard","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[3,25,28,53,55,56,57,58],"ai":[6,16,17,19,29,36,50,52]},"scoresAfter":[38,19]}],"finalScores":[38,19],"outcome":"YOU WIN","finalState":{"deckOrder":[48,27,22,0,7,35,34,11,31,49,8,24,59,40,5,10,14,47,55,20,18,51,41,54,12,30,2,33,15,45,25,44,4,39,38,50,56,29,21,9,3,13,37,17,1,43,19,42,23,26,36,46,28,57,6,16,53,52,58,32],"drawPtr":60,"cardLoc":[3,5,3,1,3,4,5,3,4,3,4,3,3,5,3,3,2,2,3,2,4,3,3,4,4,1,5,3,1,2,4,4,2,4,3,3,2,4,4,4,4,3,3,3,4,4,3,4,5,4,2,4,2,1,4,1,1,1,1,4],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false],"colTop":[[10,9,10,9,0],[9,10,8,10,10]],"colHandshakes":[[2,2,0,0,0],[0,0,1,2,1]],"colLength":[[6,6,3,4,0],[3,2,4,7,4]],"piles":[[1,6],[13],[26],[],[48]],"toMove":0,"stepCount":50,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"05f43161-4039-4d9a-a8f5-2de83a5117ed","seed":"u1zi54","startedAt":"2026-07-14T14:01:47.955Z","finishedAt":"2026-07-14T14:04:01.716Z","initialDeckOrder":[2,0,3,48,10,36,9,43,27,41,38,4,32,35,51,33,57,1,42,34,28,18,31,7,24,46,37,20,14,55,45,17,15,8,23,22,40,53,52,25,59,54,21,13,26,49,6,58,47,5,16,56,29,19,30,39,12,50,44,11],"moves":[{"ply":1,"player":"human","action":12,"playedCard":2,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[0,2,3,9,10,36,43,48],"ai":[4,27,32,33,35,38,41,51]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":84,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[0,3,9,10,36,43,48,57],"ai":[4,27,32,33,35,38,41,51]},"scoresAfter":[-40,-18]},{"ply":3,"player":"human","action":0,"playedCard":0,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[0,3,9,10,36,43,48,57],"ai":[1,4,27,32,33,35,38,41]},"scoresAfter":[-60,-18]},{"ply":4,"player":"ai","action":72,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[3,9,10,36,42,43,48,57],"ai":[1,4,27,32,33,35,38,41]},"scoresAfter":[-60,-58]},{"ply":5,"player":"human","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[3,9,10,36,42,43,48,57],"ai":[1,4,27,32,33,34,35,41]},"scoresAfter":[-54,-58]},{"ply":6,"player":"ai","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[9,10,28,36,42,43,48,57],"ai":[1,4,27,32,33,34,35,41]},"scoresAfter":[-54,-58]},{"ply":7,"player":"human","action":36,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[9,10,28,36,42,43,48,57],"ai":[4,18,27,32,33,34,35,41]},"scoresAfter":[-94,-58]},{"ply":8,"player":"ai","action":12,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[9,10,28,31,42,43,48,57],"ai":[4,18,27,32,33,34,35,41]},"scoresAfter":[-94,-73]},{"ply":9,"player":"human","action":72,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[9,10,28,31,42,43,48,57],"ai":[4,7,27,32,33,34,35,41]},"scoresAfter":[-134,-73]},{"ply":10,"player":"ai","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[9,10,24,28,31,42,43,57],"ai":[4,7,27,32,33,34,35,41]},"scoresAfter":[-134,-90]},{"ply":11,"player":"human","action":24,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[9,10,24,28,31,42,43,57],"ai":[7,27,32,33,34,35,41,46]},"scoresAfter":[-174,-90]},{"ply":12,"player":"ai","action":12,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[9,10,28,31,37,42,43,57],"ai":[7,27,32,33,34,35,41,46]},"scoresAfter":[-174,-108]},{"ply":13,"player":"human","action":24,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[9,10,28,31,37,42,43,57],"ai":[7,20,32,33,34,35,41,46]},"scoresAfter":[-168,-108]},{"ply":14,"player":"ai","action":12,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[9,10,14,31,37,42,43,57],"ai":[7,20,32,33,34,35,41,46]},"scoresAfter":[-168,-101]},{"ply":15,"player":"human","action":30,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[9,10,14,31,37,42,43,57],"ai":[7,32,33,34,35,41,46,55]},"scoresAfter":[-168,-101]},{"ply":16,"player":"ai","action":84,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[9,10,31,37,42,43,45,57],"ai":[7,32,33,34,35,41,46,55]},"scoresAfter":[-168,-95]},{"ply":17,"player":"human","action":36,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[9,10,31,37,42,43,45,57],"ai":[7,17,32,33,34,35,41,46]},"scoresAfter":[-188,-95]},{"ply":18,"player":"ai","action":24,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[9,10,15,31,42,43,45,57],"ai":[7,17,32,33,34,35,41,46]},"scoresAfter":[-188,-88]},{"ply":19,"player":"human","action":30,"playedCard":15,"placeType":"discard","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[9,10,15,31,42,43,45,57],"ai":[7,8,17,33,34,35,41,46]},"scoresAfter":[-188,-88]},{"ply":20,"player":"ai","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[9,10,23,31,42,43,45,57],"ai":[7,8,17,33,34,35,41,46]},"scoresAfter":[-188,-82]},{"ply":21,"player":"human","action":48,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[9,10,23,31,42,43,45,57],"ai":[8,17,22,33,34,35,41,46]},"scoresAfter":[-173,-82]},{"ply":22,"player":"ai","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[9,10,23,31,40,43,45,57],"ai":[8,17,22,33,34,35,41,46]},"scoresAfter":[-173,-75]},{"ply":23,"player":"human","action":60,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[9,10,23,31,40,43,45,57],"ai":[17,22,33,34,35,41,46,53]},"scoresAfter":[-155,-75]},{"ply":24,"player":"ai","action":12,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[9,10,23,31,40,45,52,57],"ai":[17,22,33,34,35,41,46,53]},"scoresAfter":[-155,-66]},{"ply":25,"player":"human","action":72,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[9,10,23,31,40,45,52,57],"ai":[17,25,33,34,35,41,46,53]},"scoresAfter":[-149,-66]},{"ply":26,"player":"ai","action":6,"playedCard":17,"placeType":"discard","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[9,10,23,31,40,45,57,59],"ai":[17,25,33,34,35,41,46,53]},"scoresAfter":[-149,-66]},{"ply":27,"player":"human","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[9,10,23,31,40,45,57,59],"ai":[25,33,34,35,41,46,53,54]},"scoresAfter":[-125,-66]},{"ply":28,"player":"ai","action":12,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[10,21,23,31,40,45,57,59],"ai":[25,33,34,35,41,46,53,54]},"scoresAfter":[-125,-58]},{"ply":29,"player":"human","action":2,"playedCard":10,"placeType":"play","drawSource":"discard_1","drawnCard":17,"handsBefore":{"human":[10,21,23,31,40,45,57,59],"ai":[13,25,34,35,41,46,53,54]},"scoresAfter":[-98,-58]},{"ply":30,"player":"ai","action":78,"playedCard":53,"placeType":"discard","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[17,21,23,31,40,45,57,59],"ai":[13,25,34,35,41,46,53,54]},"scoresAfter":[-98,-58]},{"ply":31,"player":"human","action":65,"playedCard":45,"placeType":"play","drawSource":"discard_4","drawnCard":53,"handsBefore":{"human":[17,21,23,31,40,45,57,59],"ai":[13,25,26,34,35,41,46,54]},"scoresAfter":[-74,-58]},{"ply":32,"player":"ai","action":30,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[17,21,23,31,40,53,57,59],"ai":[13,25,26,34,35,41,46,54]},"scoresAfter":[-74,-58]},{"ply":33,"player":"human","action":60,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[17,21,23,31,40,53,57,59],"ai":[13,25,34,35,41,46,49,54]},"scoresAfter":[-66,-58]},{"ply":34,"player":"ai","action":24,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[6,17,21,23,31,40,57,59],"ai":[13,25,34,35,41,46,49,54]},"scoresAfter":[-66,-49]},{"ply":35,"player":"human","action":74,"playedCard":57,"placeType":"play","drawSource":"discard_1","drawnCard":15,"handsBefore":{"human":[6,17,21,23,31,40,57,59],"ai":[13,25,35,41,46,49,54,58]},"scoresAfter":[-50,-49]},{"ply":36,"player":"ai","action":24,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[6,15,17,21,23,31,40,59],"ai":[13,25,35,41,46,49,54,58]},"scoresAfter":[-50,-39]},{"ply":37,"player":"human","action":86,"playedCard":59,"placeType":"play","drawSource":"discard_1","drawnCard":14,"handsBefore":{"human":[6,15,17,21,23,31,40,59],"ai":[13,25,41,46,47,49,54,58]},"scoresAfter":[-30,-39]},{"ply":38,"player":"ai","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[6,14,15,17,21,23,31,40],"ai":[13,25,41,46,47,49,54,58]},"scoresAfter":[-30,-30]},{"ply":39,"player":"human","action":12,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[6,14,15,17,21,23,31,40],"ai":[5,13,25,41,46,47,49,54]},"scoresAfter":[-70,-30]},{"ply":40,"player":"ai","action":36,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[6,15,16,17,21,23,31,40],"ai":[5,13,25,41,46,47,49,54]},"scoresAfter":[-70,-22]},{"ply":41,"player":"human","action":12,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[6,15,16,17,21,23,31,40],"ai":[5,13,25,46,47,49,54,56]},"scoresAfter":[-66,-22]},{"ply":42,"player":"ai","action":36,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[6,16,17,21,23,29,31,40],"ai":[5,13,25,46,47,49,54,56]},"scoresAfter":[-66,-4]},{"ply":43,"player":"human","action":12,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[6,16,17,21,23,29,31,40],"ai":[5,13,19,25,47,49,54,56]},"scoresAfter":[-60,-4]},{"ply":44,"player":"ai","action":48,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[6,17,21,23,29,30,31,40],"ai":[5,13,19,25,47,49,54,56]},"scoresAfter":[-60,16]},{"ply":45,"player":"human","action":12,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[6,17,21,23,29,30,31,40],"ai":[5,13,19,25,39,49,54,56]},"scoresAfter":[-52,16]},{"ply":46,"player":"ai","action":18,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[6,12,21,23,29,30,31,40],"ai":[5,13,19,25,39,49,54,56]},"scoresAfter":[-52,16]},{"ply":47,"player":"human","action":26,"playedCard":21,"placeType":"play","drawSource":"discard_1","drawnCard":13,"handsBefore":{"human":[6,12,21,23,29,30,31,40],"ai":[5,19,25,39,49,50,54,56]},"scoresAfter":[-36,16]},{"ply":48,"player":"ai","action":18,"playedCard":19,"placeType":"discard","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[6,12,13,23,29,30,31,40],"ai":[5,19,25,39,49,50,54,56]},"scoresAfter":[-36,16]},{"ply":49,"player":"human","action":36,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[6,12,13,23,29,30,31,40],"ai":[5,25,39,44,49,50,54,56]},"scoresAfter":[-16,16]}],"finalScores":[-16,16],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[2,0,3,48,10,36,9,43,27,41,38,4,32,35,51,33,57,1,42,34,28,18,31,7,24,46,37,20,14,55,45,17,15,8,23,22,40,53,52,25,59,54,21,13,26,49,6,58,47,5,16,56,29,19,30,39,12,50,44,11],"drawPtr":60,"cardLoc":[3,5,3,3,4,2,1,4,4,3,3,1,1,1,3,3,3,3,4,5,4,3,4,3,3,2,5,4,3,1,1,1,4,4,4,4,3,3,4,2,1,4,3,3,2,3,4,4,3,2,2,4,3,3,2,4,2,3,4,3],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[9,10,3,8,10],[7,9,10,10,9]],"colHandshakes":[[2,1,1,2,1],[0,0,0,1,0]],"colLength":[[5,6,2,5,5],[3,3,5,4,3]],"piles":[[1],[19],[26],[],[]],"toMove":1,"stepCount":49,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"7f0423a3-a025-4e78-ba6b-b74f49b78283","seed":"fcghpv","startedAt":"2026-07-14T14:04:03.491Z","finishedAt":"2026-07-14T14:06:11.222Z","initialDeckOrder":[52,43,56,22,40,34,15,38,47,54,39,10,41,36,24,9,45,11,12,25,37,44,0,32,35,16,49,57,51,31,20,53,1,26,2,55,33,3,46,48,6,29,30,19,42,5,21,50,58,23,4,14,7,8,18,13,27,59,28,17],"moves":[{"ply":1,"player":"human","action":36,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[15,22,34,38,40,43,52,56],"ai":[9,10,24,36,39,41,47,54]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":36,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[15,22,34,40,43,45,52,56],"ai":[9,10,24,36,39,41,47,54]},"scoresAfter":[-40,-40]},{"ply":3,"player":"human","action":36,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[15,22,34,40,43,45,52,56],"ai":[9,10,11,24,39,41,47,54]},"scoresAfter":[-34,-40]},{"ply":4,"player":"ai","action":48,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[12,15,22,34,43,45,52,56],"ai":[9,10,11,24,39,41,47,54]},"scoresAfter":[-34,-36]},{"ply":5,"player":"human","action":0,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[12,15,22,34,43,45,52,56],"ai":[9,10,11,24,25,41,47,54]},"scoresAfter":[-74,-36]},{"ply":6,"player":"ai","action":36,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[15,22,34,37,43,45,52,56],"ai":[9,10,11,24,25,41,47,54]},"scoresAfter":[-74,-76]},{"ply":7,"player":"human","action":0,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[15,22,34,37,43,45,52,56],"ai":[9,10,11,25,41,44,47,54]},"scoresAfter":[-70,-76]},{"ply":8,"player":"ai","action":48,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[0,22,34,37,43,45,52,56],"ai":[9,10,11,25,41,44,47,54]},"scoresAfter":[-70,-68]},{"ply":9,"player":"human","action":42,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[0,22,34,37,43,45,52,56],"ai":[9,10,11,25,32,44,47,54]},"scoresAfter":[-70,-68]},{"ply":10,"player":"ai","action":36,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[0,22,34,35,43,45,52,56],"ai":[9,10,11,25,32,44,47,54]},"scoresAfter":[-70,-88]},{"ply":11,"player":"human","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[0,22,34,35,43,45,52,56],"ai":[9,10,11,16,32,44,47,54]},"scoresAfter":[-70,-88]},{"ply":12,"player":"ai","action":84,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[22,34,35,43,45,49,52,56],"ai":[9,10,11,16,32,44,47,54]},"scoresAfter":[-70,-103]},{"ply":13,"player":"human","action":60,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[22,34,35,43,45,49,52,56],"ai":[9,10,11,16,32,44,47,57]},"scoresAfter":[-110,-103]},{"ply":14,"player":"ai","action":84,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[22,34,35,43,45,51,52,56],"ai":[9,10,11,16,32,44,47,57]},"scoresAfter":[-110,-95]},{"ply":15,"player":"human","action":60,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[22,34,35,43,45,51,52,56],"ai":[9,10,11,16,31,32,44,47]},"scoresAfter":[-106,-95]},{"ply":16,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[20,22,34,35,43,45,52,56],"ai":[9,10,11,16,31,32,44,47]},"scoresAfter":[-106,-107]},{"ply":17,"player":"human","action":72,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[20,22,34,35,43,45,52,56],"ai":[10,11,16,31,32,44,47,53]},"scoresAfter":[-100,-107]},{"ply":18,"player":"ai","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[1,20,22,34,35,43,45,56],"ai":[10,11,16,31,32,44,47,53]},"scoresAfter":[-100,-98]},{"ply":19,"player":"human","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[1,20,22,34,35,43,45,56],"ai":[11,16,26,31,32,44,47,53]},"scoresAfter":[-100,-98]},{"ply":20,"player":"ai","action":24,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[2,20,22,34,35,43,45,56],"ai":[11,16,26,31,32,44,47,53]},"scoresAfter":[-100,-118]},{"ply":21,"player":"human","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[2,20,22,34,35,43,45,56],"ai":[11,16,31,32,44,47,53,55]},"scoresAfter":[-100,-118]},{"ply":22,"player":"ai","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[20,22,33,34,35,43,45,56],"ai":[11,16,31,32,44,47,53,55]},"scoresAfter":[-100,-108]},{"ply":23,"player":"human","action":0,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[20,22,33,34,35,43,45,56],"ai":[3,16,31,32,44,47,53,55]},"scoresAfter":[-86,-108]},{"ply":24,"player":"ai","action":6,"playedCard":3,"placeType":"discard","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[22,33,34,35,43,45,46,56],"ai":[3,16,31,32,44,47,53,55]},"scoresAfter":[-86,-108]},{"ply":25,"player":"human","action":48,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[22,33,34,35,43,45,46,56],"ai":[16,31,32,44,47,48,53,55]},"scoresAfter":[-74,-108]},{"ply":26,"player":"ai","action":0,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[6,22,33,34,35,45,46,56],"ai":[16,31,32,44,47,48,53,55]},"scoresAfter":[-74,-125]},{"ply":27,"player":"human","action":60,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[6,22,33,34,35,45,46,56],"ai":[29,31,32,44,47,48,53,55]},"scoresAfter":[-58,-125]},{"ply":28,"player":"ai","action":78,"playedCard":53,"placeType":"discard","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[6,22,30,33,34,35,46,56],"ai":[29,31,32,44,47,48,53,55]},"scoresAfter":[-58,-125]},{"ply":29,"player":"human","action":72,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[6,22,30,33,34,35,46,56],"ai":[19,29,31,32,44,47,48,55]},"scoresAfter":[-40,-125]},{"ply":30,"player":"ai","action":48,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[6,22,30,33,34,35,42,56],"ai":[19,29,31,32,44,47,48,55]},"scoresAfter":[-40,-111]},{"ply":31,"player":"human","action":29,"playedCard":30,"placeType":"play","drawSource":"discard_4","drawnCard":53,"handsBefore":{"human":[6,22,30,33,34,35,42,56],"ai":[5,19,29,31,32,47,48,55]},"scoresAfter":[-55,-111]},{"ply":32,"player":"ai","action":12,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[6,22,33,34,35,42,53,56],"ai":[5,19,29,31,32,47,48,55]},"scoresAfter":[-55,-105]},{"ply":33,"player":"human","action":72,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[6,22,33,34,35,42,53,56],"ai":[5,21,29,31,32,47,48,55]},"scoresAfter":[-47,-105]},{"ply":34,"player":"ai","action":12,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[6,22,33,34,35,42,50,56],"ai":[5,21,29,31,32,47,48,55]},"scoresAfter":[-47,-97]},{"ply":35,"player":"human","action":84,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[6,22,33,34,35,42,50,56],"ai":[5,29,31,32,47,48,55,58]},"scoresAfter":[-33,-97]},{"ply":36,"player":"ai","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[6,22,23,33,34,35,42,50],"ai":[5,29,31,32,47,48,55,58]},"scoresAfter":[-33,-88]},{"ply":37,"player":"human","action":12,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[6,22,23,33,34,35,42,50],"ai":[4,5,29,31,32,47,48,55]},"scoresAfter":[-15,-88]},{"ply":38,"player":"ai","action":24,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[6,14,23,33,34,35,42,50],"ai":[4,5,29,31,32,47,48,55]},"scoresAfter":[-15,-72]},{"ply":39,"player":"human","action":24,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[6,14,23,33,34,35,42,50],"ai":[4,5,7,31,32,47,48,55]},"scoresAfter":[5,-72]},{"ply":40,"player":"ai","action":36,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[6,8,14,33,34,35,42,50],"ai":[4,5,7,31,32,47,48,55]},"scoresAfter":[5,-48]},{"ply":41,"player":"human","action":36,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[6,8,14,33,34,35,42,50],"ai":[4,5,7,18,32,47,48,55]},"scoresAfter":[13,-48]},{"ply":42,"player":"ai","action":48,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[6,8,13,14,34,35,42,50],"ai":[4,5,7,18,32,47,48,55]},"scoresAfter":[13,-20]},{"ply":43,"player":"human","action":49,"playedCard":34,"placeType":"play","drawSource":"discard_0","drawnCard":3,"handsBefore":{"human":[6,8,13,14,34,35,42,50],"ai":[4,5,7,18,27,47,48,55]},"scoresAfter":[22,-20]},{"ply":44,"player":"ai","action":60,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[3,6,8,13,14,35,42,50],"ai":[4,5,7,18,27,47,48,55]},"scoresAfter":[22,0]},{"ply":45,"player":"human","action":60,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[3,6,8,13,14,35,42,50],"ai":[4,5,7,18,27,48,55,59]},"scoresAfter":[32,0]},{"ply":46,"player":"ai","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[3,6,8,13,14,28,42,50],"ai":[4,5,7,18,27,48,55,59]},"scoresAfter":[32,10]}],"finalScores":[32,10],"outcome":"YOU WIN","finalState":{"deckOrder":[52,43,56,22,40,34,15,38,47,54,39,10,41,36,24,9,45,11,12,25,37,44,0,32,35,16,49,57,51,31,20,53,1,26,2,55,33,3,46,48,6,29,30,19,42,5,21,50,58,23,4,14,7,8,18,13,27,59,28,17],"drawPtr":60,"cardLoc":[5,5,5,1,2,2,1,2,1,4,4,4,3,1,1,3,4,2,2,4,3,4,3,3,4,4,4,2,1,4,3,4,4,3,3,3,4,5,3,4,3,4,1,3,4,3,3,4,2,3,1,3,3,3,4,2,3,4,4,4],"handPublic":[false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[0,10,10,9,7],[10,8,7,10,10]],"colHandshakes":[[0,1,0,1,1],[0,0,3,1,0]],"colLength":[[0,5,4,5,5],[3,3,6,5,4]],"piles":[[0,1,2],[],[],[37],[]],"toMove":0,"stepCount":46,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"2213ee93-4294-41ac-8633-3a46be46433e","seed":"p7pp6x","startedAt":"2026-07-14T14:06:12.821Z","finishedAt":"2026-07-14T14:08:30.017Z","initialDeckOrder":[26,39,3,8,59,51,32,10,17,35,34,53,31,54,15,49,28,4,24,47,38,55,52,25,50,40,6,2,33,14,9,20,27,23,12,36,58,46,37,48,7,42,19,5,29,43,41,1,0,11,21,56,45,57,18,16,13,44,22,30],"moves":[{"ply":1,"player":"human","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[3,8,10,26,32,39,51,59],"ai":[15,17,31,34,35,49,53,54]},"scoresAfter":[-18,0]},{"ply":2,"player":"ai","action":0,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[8,10,26,28,32,39,51,59],"ai":[15,17,31,34,35,49,53,54]},"scoresAfter":[-18,-18]},{"ply":3,"player":"human","action":24,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[8,10,26,28,32,39,51,59],"ai":[4,17,31,34,35,49,53,54]},"scoresAfter":[-58,-18]},{"ply":4,"player":"ai","action":72,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[8,10,24,28,32,39,51,59],"ai":[4,17,31,34,35,49,53,54]},"scoresAfter":[-58,-34]},{"ply":5,"player":"human","action":24,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[8,10,24,28,32,39,51,59],"ai":[4,17,31,34,35,47,49,54]},"scoresAfter":[-78,-34]},{"ply":6,"player":"ai","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[8,10,28,32,38,39,51,59],"ai":[4,17,31,34,35,47,49,54]},"scoresAfter":[-78,-51]},{"ply":7,"player":"human","action":72,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[8,10,28,32,38,39,51,59],"ai":[17,31,34,35,47,49,54,55]},"scoresAfter":[-96,-51]},{"ply":8,"player":"ai","action":72,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[8,10,28,32,38,39,52,59],"ai":[17,31,34,35,47,49,54,55]},"scoresAfter":[-96,-46]},{"ply":9,"player":"human","action":72,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[8,10,28,32,38,39,52,59],"ai":[17,25,31,34,35,47,49,55]},"scoresAfter":[-93,-46]},{"ply":10,"player":"ai","action":84,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[8,10,28,32,38,39,50,59],"ai":[17,25,31,34,35,47,49,55]},"scoresAfter":[-93,-40]},{"ply":11,"player":"human","action":78,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[8,10,28,32,38,39,50,59],"ai":[17,25,31,34,35,40,47,49]},"scoresAfter":[-93,-40]},{"ply":12,"player":"ai","action":0,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[6,8,10,28,32,38,39,59],"ai":[17,25,31,34,35,40,47,49]},"scoresAfter":[-93,-36]},{"ply":13,"player":"human","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[6,8,10,28,32,38,39,59],"ai":[2,25,31,34,35,40,47,49]},"scoresAfter":[-88,-36]},{"ply":14,"player":"ai","action":90,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[8,10,28,32,33,38,39,59],"ai":[2,25,31,34,35,40,47,49]},"scoresAfter":[-88,-36]},{"ply":15,"player":"human","action":24,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[8,10,28,32,33,38,39,59],"ai":[2,14,25,31,34,35,40,47]},"scoresAfter":[-79,-36]},{"ply":16,"player":"ai","action":24,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[8,9,10,32,33,38,39,59],"ai":[2,14,25,31,34,35,40,47]},"scoresAfter":[-79,-76]},{"ply":17,"player":"human","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[8,9,10,32,33,38,39,59],"ai":[2,14,20,31,34,35,40,47]},"scoresAfter":[-72,-76]},{"ply":18,"player":"ai","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[9,10,27,32,33,38,39,59],"ai":[2,14,20,31,34,35,40,47]},"scoresAfter":[-72,-76]},{"ply":19,"player":"human","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[9,10,27,32,33,38,39,59],"ai":[14,20,23,31,34,35,40,47]},"scoresAfter":[-64,-76]},{"ply":20,"player":"ai","action":12,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[10,12,27,32,33,38,39,59],"ai":[14,20,23,31,34,35,40,47]},"scoresAfter":[-64,-69]},{"ply":21,"player":"human","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[10,12,27,32,33,38,39,59],"ai":[14,23,31,34,35,36,40,47]},"scoresAfter":[-55,-69]},{"ply":22,"player":"ai","action":12,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[12,27,32,33,38,39,58,59],"ai":[14,23,31,34,35,36,40,47]},"scoresAfter":[-55,-59]},{"ply":23,"player":"human","action":54,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[12,27,32,33,38,39,58,59],"ai":[14,31,34,35,36,40,46,47]},"scoresAfter":[-55,-59]},{"ply":24,"player":"ai","action":48,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[12,27,32,33,37,39,58,59],"ai":[14,31,34,35,36,40,46,47]},"scoresAfter":[-55,-99]},{"ply":25,"player":"human","action":54,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[12,27,32,33,37,39,58,59],"ai":[14,31,34,35,40,46,47,48]},"scoresAfter":[-55,-99]},{"ply":26,"player":"ai","action":90,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[7,12,27,32,33,39,58,59],"ai":[14,31,34,35,40,46,47,48]},"scoresAfter":[-55,-99]},{"ply":27,"player":"human","action":66,"playedCard":39,"placeType":"discard","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[7,12,27,32,33,39,58,59],"ai":[14,31,34,35,40,42,46,47]},"scoresAfter":[-55,-99]},{"ply":28,"player":"ai","action":16,"playedCard":31,"placeType":"play","drawSource":"discard_3","drawnCard":39,"handsBefore":{"human":[7,12,19,27,32,33,58,59],"ai":[14,31,34,35,40,42,46,47]},"scoresAfter":[-55,-87]},{"ply":29,"player":"human","action":18,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[7,12,19,27,32,33,58,59],"ai":[14,34,35,39,40,42,46,47]},"scoresAfter":[-55,-87]},{"ply":30,"player":"ai","action":16,"playedCard":34,"placeType":"play","drawSource":"discard_3","drawnCard":37,"handsBefore":{"human":[5,7,19,27,32,33,58,59],"ai":[14,34,35,39,40,42,46,47]},"scoresAfter":[-55,-69]},{"ply":31,"player":"human","action":48,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[5,7,19,27,32,33,58,59],"ai":[14,35,37,39,40,42,46,47]},"scoresAfter":[-34,-69]},{"ply":32,"player":"ai","action":16,"playedCard":35,"placeType":"play","drawSource":"discard_3","drawnCard":38,"handsBefore":{"human":[5,7,19,27,29,33,58,59],"ai":[14,35,37,39,40,42,46,47]},"scoresAfter":[-34,-49]},{"ply":33,"player":"human","action":60,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[5,7,19,27,29,33,58,59],"ai":[14,37,38,39,40,42,46,47]},"scoresAfter":[-10,-49]},{"ply":34,"player":"ai","action":12,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[5,7,19,27,29,43,58,59],"ai":[14,37,38,39,40,42,46,47]},"scoresAfter":[-10,-69]},{"ply":35,"player":"human","action":42,"playedCard":27,"placeType":"discard","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[5,7,19,27,29,43,58,59],"ai":[14,38,39,40,41,42,46,47]},"scoresAfter":[-10,-69]},{"ply":36,"player":"ai","action":12,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[1,5,7,19,29,43,58,59],"ai":[14,38,39,40,41,42,46,47]},"scoresAfter":[-10,-89]},{"ply":37,"player":"human","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[1,5,7,19,29,43,58,59],"ai":[0,14,39,40,41,42,46,47]},"scoresAfter":[-10,-89]},{"ply":38,"player":"ai","action":24,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[5,7,11,19,29,43,58,59],"ai":[0,14,39,40,41,42,46,47]},"scoresAfter":[-10,-81]},{"ply":39,"player":"human","action":24,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[5,7,11,19,29,43,58,59],"ai":[0,14,21,40,41,42,46,47]},"scoresAfter":[0,-81]},{"ply":40,"player":"ai","action":36,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[5,7,19,29,43,56,58,59],"ai":[0,14,21,40,41,42,46,47]},"scoresAfter":[0,-69]},{"ply":41,"player":"human","action":60,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[5,7,19,29,43,56,58,59],"ai":[0,14,21,41,42,45,46,47]},"scoresAfter":[7,-69]},{"ply":42,"player":"ai","action":41,"playedCard":41,"placeType":"play","drawSource":"discard_4","drawnCard":48,"handsBefore":{"human":[5,7,19,29,43,57,58,59],"ai":[0,14,21,41,42,45,46,47]},"scoresAfter":[7,-53]},{"ply":43,"player":"human","action":60,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[5,7,19,29,43,57,58,59],"ai":[0,14,21,42,45,46,47,48]},"scoresAfter":[15,-53]},{"ply":44,"player":"ai","action":38,"playedCard":42,"placeType":"play","drawSource":"discard_1","drawnCard":12,"handsBefore":{"human":[5,7,18,19,29,43,58,59],"ai":[0,14,21,42,45,46,47,48]},"scoresAfter":[15,-33]},{"ply":45,"player":"human","action":72,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[5,7,18,19,29,43,58,59],"ai":[0,12,14,21,45,46,47,48]},"scoresAfter":[24,-33]},{"ply":46,"player":"ai","action":53,"playedCard":45,"placeType":"play","drawSource":"discard_4","drawnCard":49,"handsBefore":{"human":[5,7,16,18,19,29,43,59],"ai":[0,12,14,21,45,46,47,48]},"scoresAfter":[24,19]},{"ply":47,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[5,7,16,18,19,29,43,59],"ai":[0,12,14,21,46,47,48,49]},"scoresAfter":[34,19]},{"ply":48,"player":"ai","action":53,"playedCard":46,"placeType":"play","drawSource":"discard_4","drawnCard":50,"handsBefore":{"human":[5,7,13,16,18,19,29,43],"ai":[0,12,14,21,46,47,48,49]},"scoresAfter":[34,55]},{"ply":49,"player":"human","action":30,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[5,7,13,16,18,19,29,43],"ai":[0,12,14,21,47,48,49,50]},"scoresAfter":[34,55]},{"ply":50,"player":"ai","action":50,"playedCard":47,"placeType":"play","drawSource":"discard_1","drawnCard":13,"handsBefore":{"human":[5,7,16,18,19,29,43,44],"ai":[0,12,14,21,47,48,49,50]},"scoresAfter":[34,95]},{"ply":51,"player":"human","action":90,"playedCard":44,"placeType":"discard","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[5,7,16,18,19,29,43,44],"ai":[0,12,13,14,21,48,49,50]},"scoresAfter":[34,95]},{"ply":52,"player":"ai","action":78,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[5,7,16,18,19,22,29,43],"ai":[0,12,13,14,21,48,49,50]},"scoresAfter":[34,95]}],"finalScores":[34,95],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[26,39,3,8,59,51,32,10,17,35,34,53,31,54,15,49,28,4,24,47,38,55,52,25,50,40,6,2,33,14,9,20,27,23,12,36,58,46,37,48,7,42,19,5,29,43,41,1,0,11,21,56,45,57,18,16,13,44,22,30],"drawPtr":60,"cardLoc":[2,5,5,3,4,1,3,1,3,3,3,3,2,2,2,4,1,4,1,1,4,2,1,4,3,4,3,5,3,1,2,4,3,3,4,4,4,4,4,4,4,4,4,1,5,4,4,4,2,5,2,3,3,4,4,4,3,3,3,3],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,true,false,false,false,false,false,false,false,false,false],"colTop":[[10,0,8,0,10],[3,10,10,10,6]],"colHandshakes":[[0,0,2,0,0],[0,0,1,3,0]],"colLength":[[6,0,5,0,6],[1,4,4,10,3]],"piles":[[2,1],[],[27],[44],[49]],"toMove":0,"stepCount":52,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"ce10c12c-2a4f-40f6-b8cc-393e9fcbf0e4","seed":"en5uco","startedAt":"2026-07-14T14:08:31.484Z","finishedAt":"2026-07-14T14:11:44.691Z","initialDeckOrder":[52,27,42,36,31,38,48,53,10,55,46,0,35,22,49,24,4,5,28,7,50,15,34,56,39,3,32,43,41,54,17,33,47,51,1,14,44,37,9,45,16,21,13,57,40,30,26,8,58,29,6,20,23,12,19,59,11,2,25,18],"moves":[{"ply":1,"player":"human","action":60,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[27,31,36,38,42,48,52,53],"ai":[0,10,22,24,35,46,49,55]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":72,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[4,27,31,36,38,42,52,53],"ai":[0,10,22,24,35,46,49,55]},"scoresAfter":[-40,-40]},{"ply":3,"player":"human","action":72,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[4,27,31,36,38,42,52,53],"ai":[0,5,10,22,24,35,46,55]},"scoresAfter":[-34,-40]},{"ply":4,"player":"ai","action":84,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[4,27,28,31,36,38,42,53],"ai":[0,5,10,22,24,35,46,55]},"scoresAfter":[-34,-28]},{"ply":5,"player":"human","action":12,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[4,27,28,31,36,38,42,53],"ai":[0,5,7,10,22,24,35,46]},"scoresAfter":[-52,-28]},{"ply":6,"player":"ai","action":0,"playedCard":0,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[4,28,31,36,38,42,50,53],"ai":[0,5,7,10,22,24,35,46]},"scoresAfter":[-52,-68]},{"ply":7,"player":"human","action":12,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[4,28,31,36,38,42,50,53],"ai":[5,7,10,15,22,24,35,46]},"scoresAfter":[-49,-68]},{"ply":8,"player":"ai","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[4,31,34,36,38,42,50,53],"ai":[5,7,10,15,22,24,35,46]},"scoresAfter":[-49,-60]},{"ply":9,"player":"human","action":84,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[4,31,34,36,38,42,50,53],"ai":[7,10,15,22,24,35,46,56]},"scoresAfter":[-41,-60]},{"ply":10,"player":"ai","action":84,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[4,31,34,36,38,39,42,50],"ai":[7,10,15,22,24,35,46,56]},"scoresAfter":[-41,-46]},{"ply":11,"player":"human","action":36,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[4,31,34,36,38,39,42,50],"ai":[3,7,10,15,22,24,35,46]},"scoresAfter":[-81,-46]},{"ply":12,"player":"ai","action":12,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[4,31,32,34,38,39,42,50],"ai":[3,7,10,15,22,24,35,46]},"scoresAfter":[-81,-34]},{"ply":13,"player":"human","action":12,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[4,31,32,34,38,39,42,50],"ai":[3,10,15,22,24,35,43,46]},"scoresAfter":[-75,-34]},{"ply":14,"player":"ai","action":6,"playedCard":3,"placeType":"discard","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[4,32,34,38,39,41,42,50],"ai":[3,10,15,22,24,35,43,46]},"scoresAfter":[-75,-34]},{"ply":15,"player":"human","action":48,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[4,32,34,38,39,41,42,50],"ai":[10,15,22,24,35,43,46,54]},"scoresAfter":[-71,-34]},{"ply":16,"player":"ai","action":60,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[4,17,32,34,38,41,42,50],"ai":[10,15,22,24,35,43,46,54]},"scoresAfter":[-71,-48]},{"ply":17,"player":"human","action":60,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[4,17,32,34,38,41,42,50],"ai":[10,15,22,24,33,35,46,54]},"scoresAfter":[-63,-48]},{"ply":18,"player":"ai","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[4,17,32,34,38,42,47,50],"ai":[10,15,22,24,33,35,46,54]},"scoresAfter":[-63,-30]},{"ply":19,"player":"human","action":60,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[4,17,32,34,38,42,47,50],"ai":[15,22,24,33,35,46,51,54]},"scoresAfter":[-53,-30]},{"ply":20,"player":"ai","action":60,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[1,4,17,32,34,38,47,50],"ai":[15,22,24,33,35,46,51,54]},"scoresAfter":[-53,-21]},{"ply":21,"player":"human","action":36,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[1,4,17,32,34,38,47,50],"ai":[14,15,22,24,33,35,51,54]},"scoresAfter":[-46,-21]},{"ply":22,"player":"ai","action":90,"playedCard":54,"placeType":"discard","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[1,4,17,34,38,44,47,50],"ai":[14,15,22,24,33,35,51,54]},"scoresAfter":[-46,-21]},{"ply":23,"player":"human","action":60,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[1,4,17,34,38,44,47,50],"ai":[14,15,22,24,33,35,37,51]},"scoresAfter":[-32,-21]},{"ply":24,"player":"ai","action":0,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[1,4,9,17,34,38,47,50],"ai":[14,15,22,24,33,35,37,51]},"scoresAfter":[-32,-61]},{"ply":25,"player":"human","action":71,"playedCard":38,"placeType":"discard","drawSource":"discard_4","drawnCard":54,"handsBefore":{"human":[1,4,9,17,34,38,47,50],"ai":[15,22,24,33,35,37,45,51]},"scoresAfter":[-32,-61]},{"ply":26,"player":"ai","action":90,"playedCard":51,"placeType":"discard","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[1,4,9,17,34,47,50,54],"ai":[15,22,24,33,35,37,45,51]},"scoresAfter":[-32,-61]},{"ply":27,"player":"human","action":84,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[1,4,9,17,34,47,50,54],"ai":[15,16,22,24,33,35,37,45]},"scoresAfter":[-22,-61]},{"ply":28,"player":"ai","action":0,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[1,4,9,17,21,34,47,50],"ai":[15,16,22,24,33,35,37,45]},"scoresAfter":[-22,-57]},{"ply":29,"player":"human","action":90,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[1,4,9,17,21,34,47,50],"ai":[13,16,22,24,33,35,37,45]},"scoresAfter":[-22,-57]},{"ply":30,"player":"ai","action":54,"playedCard":33,"placeType":"discard","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[1,4,9,17,21,34,47,57],"ai":[13,16,22,24,33,35,37,45]},"scoresAfter":[-22,-57]},{"ply":31,"player":"human","action":84,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[1,4,9,17,21,34,47,57],"ai":[13,16,22,24,35,37,40,45]},"scoresAfter":[-6,-57]},{"ply":32,"player":"ai","action":15,"playedCard":16,"placeType":"play","drawSource":"discard_2","drawnCard":33,"handsBefore":{"human":[1,4,9,17,21,30,34,47],"ai":[13,16,22,24,35,37,40,45]},"scoresAfter":[-6,-51]},{"ply":33,"player":"human","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[1,4,9,17,21,30,34,47],"ai":[13,22,24,33,35,37,40,45]},"scoresAfter":[-6,-51]},{"ply":34,"player":"ai","action":12,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[4,9,17,21,26,30,34,47],"ai":[13,22,24,33,35,37,40,45]},"scoresAfter":[-6,-33]},{"ply":35,"player":"human","action":72,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[4,9,17,21,26,30,34,47],"ai":[8,13,24,33,35,37,40,45]},"scoresAfter":[3,-33]},{"ply":36,"player":"ai","action":24,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[4,9,17,21,26,30,47,58],"ai":[8,13,24,33,35,37,40,45]},"scoresAfter":[3,-73]},{"ply":37,"player":"human","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[4,9,17,21,26,30,47,58],"ai":[8,13,29,33,35,37,40,45]},"scoresAfter":[21,-73]},{"ply":38,"player":"ai","action":24,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[4,6,9,17,21,26,30,47],"ai":[8,13,29,33,35,37,40,45]},"scoresAfter":[21,-65]},{"ply":39,"player":"human","action":66,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[4,6,9,17,21,26,30,47],"ai":[8,13,20,33,35,37,40,45]},"scoresAfter":[21,-65]},{"ply":40,"player":"ai","action":36,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[4,6,9,17,21,23,30,47],"ai":[8,13,20,33,35,37,40,45]},"scoresAfter":[21,-49]},{"ply":41,"player":"human","action":36,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[4,6,9,17,21,23,30,47],"ai":[8,12,13,20,35,37,40,45]},"scoresAfter":[5,-49]},{"ply":42,"player":"ai","action":48,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[4,6,9,19,21,23,30,47],"ai":[8,12,13,20,35,37,40,45]},"scoresAfter":[5,-29]},{"ply":43,"player":"human","action":41,"playedCard":19,"placeType":"play","drawSource":"discard_4","drawnCard":50,"handsBefore":{"human":[4,6,9,19,21,23,30,47],"ai":[8,12,13,20,37,40,45,59]},"scoresAfter":[11,-29]},{"ply":44,"player":"ai","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[4,6,9,21,23,30,47,50],"ai":[8,12,13,20,37,40,45,59]},"scoresAfter":[11,-9]},{"ply":45,"player":"human","action":41,"playedCard":21,"placeType":"play","drawSource":"discard_4","drawnCard":51,"handsBefore":{"human":[4,6,9,21,23,30,47,50],"ai":[8,11,12,13,20,37,40,45]},"scoresAfter":[19,-9]},{"ply":46,"player":"ai","action":12,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[4,6,9,23,30,47,50,51],"ai":[8,11,12,13,20,37,40,45]},"scoresAfter":[19,11]},{"ply":47,"player":"human","action":40,"playedCard":23,"placeType":"play","drawSource":"discard_3","drawnCard":38,"handsBefore":{"human":[4,6,9,23,30,47,50,51],"ai":[2,8,12,13,20,37,40,45]},"scoresAfter":[29,11]},{"ply":48,"player":"ai","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[4,6,9,30,38,47,50,51],"ai":[2,8,12,13,20,37,40,45]},"scoresAfter":[29,11]},{"ply":49,"player":"human","action":60,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[4,6,9,30,38,47,50,51],"ai":[8,12,13,20,25,37,40,45]},"scoresAfter":[49,11]}],"finalScores":[49,11],"outcome":"YOU WIN","finalState":{"deckOrder":[52,27,42,36,31,38,48,53,10,55,46,0,35,22,49,24,4,5,28,7,50,15,34,56,39,3,32,43,41,54,17,33,47,51,1,14,44,37,9,45,16,21,13,57,40,30,26,8,58,29,6,20,23,12,19,59,11,2,25,18],"drawPtr":60,"cardLoc":[4,5,5,5,1,4,1,4,2,1,4,4,2,2,4,4,4,3,1,3,2,3,4,3,4,2,5,3,3,4,1,3,3,4,3,4,3,2,1,3,2,3,3,4,3,2,4,3,3,4,1,1,3,3,3,4,4,3,3,4],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,true,true,false,false,false,false,false,false,false,false],"colTop":[[0,10,9,10,9],[10,9,10,9,10]],"colHandshakes":[[0,0,0,1,1],[1,1,1,0,1]],"colLength":[[0,4,5,6,6],[5,4,4,2,4]],"piles":[[3,1,2],[],[26],[],[]],"toMove":1,"stepCount":49,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"0dc932ad-4590-4ad5-a146-73fa5d586f15","seed":"ebefbj","startedAt":"2026-07-14T14:11:45.926Z","finishedAt":"2026-07-14T14:14:39.808Z","initialDeckOrder":[49,4,39,35,15,55,30,7,9,48,6,20,27,3,33,1,54,25,22,12,0,51,41,28,16,8,26,52,11,18,40,58,36,24,53,17,47,29,14,59,13,43,56,42,45,10,19,34,38,31,5,50,21,37,44,23,2,46,32,57],"moves":[{"ply":1,"player":"human","action":30,"playedCard":15,"placeType":"discard","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[4,7,15,30,35,39,49,55],"ai":[1,3,6,9,20,27,33,48]},"scoresAfter":[0,0]},{"ply":2,"player":"ai","action":54,"playedCard":20,"placeType":"discard","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[4,7,30,35,39,49,54,55],"ai":[1,3,6,9,20,27,33,48]},"scoresAfter":[0,0]},{"ply":3,"player":"human","action":60,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[4,7,30,35,39,49,54,55],"ai":[1,3,6,9,25,27,33,48]},"scoresAfter":[-40,0]},{"ply":4,"player":"ai","action":48,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[4,7,22,30,35,39,54,55],"ai":[1,3,6,9,25,27,33,48]},"scoresAfter":[-40,-40]},{"ply":5,"player":"human","action":68,"playedCard":39,"placeType":"discard","drawSource":"discard_1","drawnCard":20,"handsBefore":{"human":[4,7,22,30,35,39,54,55],"ai":[1,3,6,9,12,27,33,48]},"scoresAfter":[-40,-40]},{"ply":6,"player":"ai","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[4,7,20,22,30,35,54,55],"ai":[1,3,6,9,12,27,33,48]},"scoresAfter":[-40,-80]},{"ply":7,"player":"human","action":74,"playedCard":54,"placeType":"play","drawSource":"discard_1","drawnCard":15,"handsBefore":{"human":[4,7,20,22,30,35,54,55],"ai":[0,3,6,9,12,27,33,48]},"scoresAfter":[-30,-80]},{"ply":8,"player":"ai","action":0,"playedCard":0,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[4,7,15,20,22,30,35,55],"ai":[0,3,6,9,12,27,33,48]},"scoresAfter":[-30,-100]},{"ply":9,"player":"human","action":24,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[4,7,15,20,22,30,35,55],"ai":[3,6,9,12,27,33,48,51]},"scoresAfter":[-48,-100]},{"ply":10,"player":"ai","action":90,"playedCard":51,"placeType":"discard","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[4,7,20,22,30,35,41,55],"ai":[3,6,9,12,27,33,48,51]},"scoresAfter":[-48,-100]},{"ply":11,"player":"human","action":84,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[4,7,20,22,30,35,41,55],"ai":[3,6,9,12,27,28,33,48]},"scoresAfter":[-36,-100]},{"ply":12,"player":"ai","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[4,7,16,20,22,30,35,41],"ai":[3,6,9,12,27,28,33,48]},"scoresAfter":[-36,-94]},{"ply":13,"player":"human","action":24,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[4,7,16,20,22,30,35,41],"ai":[6,8,9,12,27,28,33,48]},"scoresAfter":[-33,-94]},{"ply":14,"player":"ai","action":94,"playedCard":48,"placeType":"discard","drawSource":"discard_3","drawnCard":39,"handsBefore":{"human":[4,7,20,22,26,30,35,41],"ai":[6,8,9,12,27,28,33,48]},"scoresAfter":[-33,-94]},{"ply":15,"player":"human","action":48,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[4,7,20,22,26,30,35,41],"ai":[6,8,9,12,27,28,33,39]},"scoresAfter":[-73,-94]},{"ply":16,"player":"ai","action":54,"playedCard":27,"placeType":"discard","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[4,7,20,22,30,35,41,52],"ai":[6,8,9,12,27,28,33,39]},"scoresAfter":[-73,-94]},{"ply":17,"player":"human","action":81,"playedCard":41,"placeType":"discard","drawSource":"discard_2","drawnCard":27,"handsBefore":{"human":[4,7,20,22,30,35,41,52],"ai":[6,8,9,11,12,28,33,39]},"scoresAfter":[-73,-94]},{"ply":18,"player":"ai","action":54,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[4,7,20,22,27,30,35,52],"ai":[6,8,9,11,12,28,33,39]},"scoresAfter":[-73,-94]},{"ply":19,"player":"human","action":48,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[4,7,20,22,27,30,35,52],"ai":[6,8,9,11,18,28,33,39]},"scoresAfter":[-69,-94]},{"ply":20,"player":"ai","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[4,7,20,22,30,35,40,52],"ai":[6,8,9,11,18,28,33,39]},"scoresAfter":[-69,-79]},{"ply":21,"player":"human","action":48,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[4,7,20,22,30,35,40,52],"ai":[8,9,11,18,28,33,39,58]},"scoresAfter":[-59,-79]},{"ply":22,"player":"ai","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[4,7,20,22,35,36,40,52],"ai":[8,9,11,18,28,33,39,58]},"scoresAfter":[-59,-58]},{"ply":23,"player":"human","action":6,"playedCard":4,"placeType":"discard","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[4,7,20,22,35,36,40,52],"ai":[9,11,18,24,28,33,39,58]},"scoresAfter":[-59,-58]},{"ply":24,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[7,20,22,35,36,40,52,53],"ai":[9,11,18,24,28,33,39,58]},"scoresAfter":[-59,-34]},{"ply":25,"player":"human","action":6,"playedCard":7,"placeType":"discard","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[7,20,22,35,36,40,52,53],"ai":[11,17,18,24,28,33,39,58]},"scoresAfter":[-59,-34]},{"ply":26,"player":"ai","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[20,22,35,36,40,47,52,53],"ai":[11,17,18,24,28,33,39,58]},"scoresAfter":[-59,-4]},{"ply":27,"player":"human","action":40,"playedCard":36,"placeType":"play","drawSource":"discard_3","drawnCard":41,"handsBefore":{"human":[20,22,35,36,40,47,52,53],"ai":[17,18,24,28,29,33,39,58]},"scoresAfter":[-99,-4]},{"ply":28,"player":"ai","action":24,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[20,22,35,40,41,47,52,53],"ai":[17,18,24,28,29,33,39,58]},"scoresAfter":[-99,-24]},{"ply":29,"player":"human","action":36,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[20,22,35,40,41,47,52,53],"ai":[14,17,18,28,29,33,39,58]},"scoresAfter":[-93,-24]},{"ply":30,"player":"ai","action":24,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[20,22,35,41,47,52,53,59],"ai":[14,17,18,28,29,33,39,58]},"scoresAfter":[-93,-39]},{"ply":31,"player":"human","action":36,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[20,22,35,41,47,52,53,59],"ai":[13,14,17,28,29,33,39,58]},"scoresAfter":[-85,-39]},{"ply":32,"player":"ai","action":18,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[20,22,35,43,47,52,53,59],"ai":[13,14,17,28,29,33,39,58]},"scoresAfter":[-85,-39]},{"ply":33,"player":"human","action":36,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[20,22,35,43,47,52,53,59],"ai":[13,17,28,29,33,39,56,58]},"scoresAfter":[-73,-39]},{"ply":34,"player":"ai","action":72,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[20,22,35,42,47,52,53,59],"ai":[13,17,28,29,33,39,56,58]},"scoresAfter":[-73,-52]},{"ply":35,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[20,22,35,42,47,52,53,59],"ai":[13,17,28,29,33,39,45,58]},"scoresAfter":[-53,-52]},{"ply":36,"player":"ai","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[10,20,22,35,42,47,52,53],"ai":[13,17,28,29,33,39,45,58]},"scoresAfter":[-53,-43]},{"ply":37,"player":"human","action":12,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[10,20,22,35,42,47,52,53],"ai":[13,17,19,28,29,33,39,45]},"scoresAfter":[-46,-43]},{"ply":38,"player":"ai","action":24,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[10,22,34,35,42,47,52,53],"ai":[13,17,19,28,29,33,39,45]},"scoresAfter":[-46,-37]},{"ply":39,"player":"human","action":24,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[10,22,34,35,42,47,52,53],"ai":[13,17,28,29,33,38,39,45]},"scoresAfter":[-28,-37]},{"ply":40,"player":"ai","action":24,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[10,22,31,35,42,47,52,53],"ai":[13,17,28,29,33,38,39,45]},"scoresAfter":[-28,-28]},{"ply":41,"player":"human","action":36,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[10,22,31,35,42,47,52,53],"ai":[5,13,17,29,33,38,39,45]},"scoresAfter":[-8,-28]},{"ply":42,"player":"ai","action":36,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[10,22,31,42,47,50,52,53],"ai":[5,13,17,29,33,38,39,45]},"scoresAfter":[-8,-16]},{"ply":43,"player":"human","action":12,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[10,22,31,42,47,50,52,53],"ai":[5,13,17,21,33,38,39,45]},"scoresAfter":[1,-16]},{"ply":44,"player":"ai","action":36,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[10,31,37,42,47,50,52,53],"ai":[5,13,17,21,33,38,39,45]},"scoresAfter":[1,-8]},{"ply":45,"player":"human","action":66,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[10,31,37,42,47,50,52,53],"ai":[5,13,17,33,38,39,44,45]},"scoresAfter":[1,-8]},{"ply":46,"player":"ai","action":36,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[10,23,31,37,42,47,52,53],"ai":[5,13,17,33,38,39,44,45]},"scoresAfter":[1,16]},{"ply":47,"player":"human","action":12,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[10,23,31,37,42,47,52,53],"ai":[2,5,13,17,38,39,44,45]},"scoresAfter":[11,16]},{"ply":48,"player":"ai","action":30,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[10,31,37,42,46,47,52,53],"ai":[2,5,13,17,38,39,44,45]},"scoresAfter":[11,16]},{"ply":49,"player":"human","action":48,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[10,31,37,42,46,47,52,53],"ai":[2,5,17,32,38,39,44,45]},"scoresAfter":[29,16]}],"finalScores":[29,16],"outcome":"YOU WIN","finalState":{"deckOrder":[49,4,39,35,15,55,30,7,9,48,6,20,27,3,33,1,54,25,22,12,0,51,41,28,16,8,26,52,11,18,40,58,36,24,53,17,47,29,14,59,13,43,56,42,45,10,19,34,38,31,5,50,21,37,44,23,2,46,32,57],"drawPtr":60,"cardLoc":[4,4,2,4,5,2,4,5,4,4,1,4,5,5,5,3,3,2,4,4,3,4,3,3,4,4,3,3,4,4,3,1,2,4,3,3,3,1,2,2,3,3,1,3,2,2,3,1,5,3,5,5,1,1,3,3,4,1,4,3],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[0,10,10,9,10],[10,8,8,0,9]],"colHandshakes":[[0,0,1,1,1],[2,0,2,0,0]],"colLength":[[0,5,5,5,4],[7,3,5,0,2]],"piles":[[4,7],[12,14,13],[],[],[51,48,50]],"toMove":1,"stepCount":49,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"d1d64058-0c9d-43a2-868b-b6e27944f907","seed":"san0yu","startedAt":"2026-07-14T14:14:40.764Z","finishedAt":"2026-07-14T14:16:27.792Z","initialDeckOrder":[58,38,53,2,52,48,33,37,55,22,51,20,45,19,15,31,32,40,11,29,57,4,41,44,6,23,25,50,13,12,43,46,54,56,18,30,49,5,24,7,9,59,35,17,10,26,47,3,34,39,1,0,42,16,8,36,28,14,21,27],"moves":[{"ply":1,"player":"human","action":48,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[2,33,37,38,48,52,53,58],"ai":[15,19,20,22,31,45,51,55]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":72,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[2,32,33,37,38,52,53,58],"ai":[15,19,20,22,31,45,51,55]},"scoresAfter":[-40,-18]},{"ply":3,"player":"human","action":60,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[2,32,33,37,38,52,53,58],"ai":[15,19,20,22,31,40,45,55]},"scoresAfter":[-34,-18]},{"ply":4,"player":"ai","action":84,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[2,11,32,33,37,38,53,58],"ai":[15,19,20,22,31,40,45,55]},"scoresAfter":[-34,-12]},{"ply":5,"player":"human","action":0,"playedCard":2,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[2,11,32,33,37,38,53,58],"ai":[15,19,20,22,29,31,40,45]},"scoresAfter":[-74,-12]},{"ply":6,"player":"ai","action":48,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[11,32,33,37,38,53,57,58],"ai":[15,19,20,22,29,31,40,45]},"scoresAfter":[-74,-28]},{"ply":7,"player":"human","action":60,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[11,32,33,37,38,53,57,58],"ai":[4,15,19,20,22,31,40,45]},"scoresAfter":[-66,-28]},{"ply":8,"player":"ai","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[11,32,33,37,38,41,57,58],"ai":[4,15,19,20,22,31,40,45]},"scoresAfter":[-66,-45]},{"ply":9,"player":"human","action":72,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[11,32,33,37,38,41,57,58],"ai":[15,19,20,22,31,40,44,45]},"scoresAfter":[-50,-45]},{"ply":10,"player":"ai","action":48,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[6,11,32,33,37,38,41,58],"ai":[15,19,20,22,31,40,44,45]},"scoresAfter":[-50,-39]},{"ply":11,"player":"human","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[6,11,32,33,37,38,41,58],"ai":[15,19,20,22,23,40,44,45]},"scoresAfter":[-32,-39]},{"ply":12,"player":"ai","action":60,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[6,11,25,32,33,37,38,41],"ai":[15,19,20,22,23,40,44,45]},"scoresAfter":[-32,-56]},{"ply":13,"player":"human","action":24,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[6,11,25,32,33,37,38,41],"ai":[15,19,20,22,23,44,45,50]},"scoresAfter":[-72,-56]},{"ply":14,"player":"ai","action":90,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[6,11,13,32,33,37,38,41],"ai":[15,19,20,22,23,44,45,50]},"scoresAfter":[-72,-56]},{"ply":15,"player":"human","action":30,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[6,11,13,32,33,37,38,41],"ai":[12,15,19,20,22,23,44,45]},"scoresAfter":[-72,-56]},{"ply":16,"player":"ai","action":74,"playedCard":44,"placeType":"play","drawSource":"discard_1","drawnCard":13,"handsBefore":{"human":[6,11,32,33,37,38,41,43],"ai":[12,15,19,20,22,23,44,45]},"scoresAfter":[-72,-49]},{"ply":17,"player":"human","action":54,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[6,11,32,33,37,38,41,43],"ai":[12,13,15,19,20,22,23,45]},"scoresAfter":[-72,-49]},{"ply":18,"player":"ai","action":0,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[6,11,32,33,38,41,43,46],"ai":[12,13,15,19,20,22,23,45]},"scoresAfter":[-72,-89]},{"ply":19,"player":"human","action":52,"playedCard":38,"placeType":"play","drawSource":"discard_3","drawnCard":37,"handsBefore":{"human":[6,11,32,33,38,41,43,46],"ai":[13,15,19,20,22,23,45,54]},"scoresAfter":[-112,-89]},{"ply":20,"player":"ai","action":0,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[6,11,32,33,37,41,43,46],"ai":[13,15,19,20,22,23,45,54]},"scoresAfter":[-112,-109]},{"ply":21,"player":"human","action":48,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[6,11,32,33,37,41,43,46],"ai":[15,19,20,22,23,45,54,56]},"scoresAfter":[-132,-109]},{"ply":22,"player":"ai","action":84,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[6,11,18,32,33,41,43,46],"ai":[15,19,20,22,23,45,54,56]},"scoresAfter":[-132,-102]},{"ply":23,"player":"human","action":60,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[6,11,18,32,33,41,43,46],"ai":[15,19,20,22,23,30,45,54]},"scoresAfter":[-120,-102]},{"ply":24,"player":"ai","action":90,"playedCard":54,"placeType":"discard","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[6,11,18,32,33,43,46,49],"ai":[15,19,20,22,23,30,45,54]},"scoresAfter":[-120,-102]},{"ply":25,"player":"human","action":90,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[6,11,18,32,33,43,46,49],"ai":[5,15,19,20,22,23,30,45]},"scoresAfter":[-120,-102]},{"ply":26,"player":"ai","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[6,11,18,24,32,33,43,46],"ai":[5,15,19,20,22,23,30,45]},"scoresAfter":[-120,-98]},{"ply":27,"player":"human","action":36,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[6,11,18,24,32,33,43,46],"ai":[7,15,19,20,22,23,30,45]},"scoresAfter":[-140,-98]},{"ply":28,"player":"ai","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[6,9,11,18,32,33,43,46],"ai":[7,15,19,20,22,23,30,45]},"scoresAfter":[-140,-92]},{"ply":29,"player":"human","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[6,9,11,18,32,33,43,46],"ai":[15,19,20,22,23,30,45,59]},"scoresAfter":[-130,-92]},{"ply":30,"player":"ai","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[9,11,18,32,33,35,43,46],"ai":[15,19,20,22,23,30,45,59]},"scoresAfter":[-130,-82]},{"ply":31,"player":"human","action":36,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[9,11,18,32,33,35,43,46],"ai":[15,17,19,20,22,23,30,45]},"scoresAfter":[-109,-82]},{"ply":32,"player":"ai","action":0,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[9,10,11,18,33,35,43,46],"ai":[15,17,19,20,22,23,30,45]},"scoresAfter":[-109,-76]},{"ply":33,"player":"human","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[9,10,11,18,33,35,43,46],"ai":[17,19,20,22,23,26,30,45]},"scoresAfter":[-93,-76]},{"ply":34,"player":"ai","action":0,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[10,11,18,33,35,43,46,47],"ai":[17,19,20,22,23,26,30,45]},"scoresAfter":[-93,-64]},{"ply":35,"player":"human","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[10,11,18,33,35,43,46,47],"ai":[3,19,20,22,23,26,30,45]},"scoresAfter":[-75,-64]},{"ply":36,"player":"ai","action":84,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[11,18,33,34,35,43,46,47],"ai":[3,19,20,22,23,26,30,45]},"scoresAfter":[-75,-56]},{"ply":37,"player":"human","action":29,"playedCard":33,"placeType":"play","drawSource":"discard_4","drawnCard":49,"handsBefore":{"human":[11,18,33,34,35,43,46,47],"ai":[3,19,20,22,23,26,30,39]},"scoresAfter":[-51,-56]},{"ply":38,"player":"ai","action":12,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[11,18,34,35,43,46,47,49],"ai":[3,19,20,22,23,26,30,39]},"scoresAfter":[-51,-38]},{"ply":39,"player":"human","action":24,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[11,18,34,35,43,46,47,49],"ai":[1,3,20,22,23,26,30,39]},"scoresAfter":[-24,-38]},{"ply":40,"player":"ai","action":24,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[0,11,18,35,43,46,47,49],"ai":[1,3,20,22,23,26,30,39]},"scoresAfter":[-24,-17]},{"ply":41,"player":"human","action":36,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[0,11,18,35,43,46,47,49],"ai":[1,3,22,23,26,30,39,42]},"scoresAfter":[6,-17]},{"ply":42,"player":"ai","action":24,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[0,11,16,18,43,46,47,49],"ai":[1,3,22,23,26,30,39,42]},"scoresAfter":[6,10]},{"ply":43,"player":"human","action":17,"playedCard":11,"placeType":"play","drawSource":"discard_4","drawnCard":54,"handsBefore":{"human":[0,11,16,18,43,46,47,49],"ai":[1,3,8,23,26,30,39,42]},"scoresAfter":[26,10]},{"ply":44,"player":"ai","action":24,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[0,16,18,43,46,47,49,54],"ai":[1,3,8,23,26,30,39,42]},"scoresAfter":[26,17]},{"ply":45,"player":"human","action":36,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[0,16,18,43,46,47,49,54],"ai":[1,3,23,26,30,36,39,42]},"scoresAfter":[44,17]},{"ply":46,"player":"ai","action":24,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[0,16,18,28,46,47,49,54],"ai":[1,3,23,26,30,36,39,42]},"scoresAfter":[44,67]},{"ply":47,"player":"human","action":53,"playedCard":46,"placeType":"play","drawSource":"discard_4","drawnCard":50,"handsBefore":{"human":[0,16,18,28,46,47,49,54],"ai":[1,3,14,26,30,36,39,42]},"scoresAfter":[71,67]},{"ply":48,"player":"ai","action":30,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[0,16,18,28,47,49,50,54],"ai":[1,3,14,26,30,36,39,42]},"scoresAfter":[71,67]},{"ply":49,"player":"human","action":48,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[0,16,18,28,47,49,50,54],"ai":[1,3,21,26,30,36,39,42]},"scoresAfter":[101,67]}],"finalScores":[101,67],"outcome":"YOU WIN","finalState":{"deckOrder":[58,38,53,2,52,48,33,37,55,22,51,20,45,19,15,31,32,40,11,29,57,4,41,44,6,23,25,50,13,12,43,46,54,56,18,30,49,5,24,7,9,59,35,17,10,26,47,3,34,39,1,0,42,16,8,36,28,14,21,27],"drawPtr":60,"cardLoc":[1,2,3,2,4,4,3,4,4,3,3,3,4,4,5,4,1,4,1,4,4,2,4,4,3,3,2,1,1,4,2,4,3,3,3,3,2,3,3,2,4,3,2,3,4,4,3,3,3,1,1,4,3,3,1,4,4,3,3,4],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,false,false,false,true,false,false,false,false,false],"colTop":[[10,0,10,10,9],[7,10,6,8,10]],"colHandshakes":[[1,0,2,2,1],[0,2,0,0,0]],"colLength":[[5,0,6,6,5],[4,8,2,3,4]],"piles":[[],[14],[],[],[]],"toMove":1,"stepCount":49,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"70050289-b1c4-4b3a-af5c-cd9c71fdefc4","seed":"5x16n3","startedAt":"2026-07-14T14:16:28.875Z","finishedAt":"2026-07-14T14:18:26.208Z","initialDeckOrder":[21,19,0,32,59,48,33,10,49,56,43,7,18,14,1,30,50,13,46,55,41,8,12,23,15,4,28,47,35,34,45,25,42,54,57,24,6,11,53,52,20,29,5,22,39,40,44,36,9,3,51,37,58,38,26,17,2,31,27,16],"moves":[{"ply":1,"player":"human","action":72,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[0,10,19,21,32,33,48,59],"ai":[1,7,14,18,30,43,49,56]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[0,10,19,21,32,33,50,59],"ai":[1,7,14,18,30,43,49,56]},"scoresAfter":[-40,-40]},{"ply":3,"player":"human","action":72,"playedCard":50,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[0,10,19,21,32,33,50,59],"ai":[7,13,14,18,30,43,49,56]},"scoresAfter":[-60,-40]},{"ply":4,"player":"ai","action":48,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[0,10,19,21,32,33,46,59],"ai":[7,13,14,18,30,43,49,56]},"scoresAfter":[-60,-55]},{"ply":5,"player":"human","action":0,"playedCard":0,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[0,10,19,21,32,33,46,59],"ai":[7,13,14,18,43,49,55,56]},"scoresAfter":[-100,-55]},{"ply":6,"player":"ai","action":48,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[10,19,21,32,33,41,46,59],"ai":[7,13,14,18,43,49,55,56]},"scoresAfter":[-100,-69]},{"ply":7,"player":"human","action":60,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[10,19,21,32,33,41,46,59],"ai":[7,8,13,14,18,49,55,56]},"scoresAfter":[-116,-69]},{"ply":8,"player":"ai","action":60,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[10,12,19,21,32,33,46,59],"ai":[7,8,13,14,18,49,55,56]},"scoresAfter":[-116,-109]},{"ply":9,"player":"human","action":12,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[10,12,19,21,32,33,46,59],"ai":[7,8,13,14,18,23,55,56]},"scoresAfter":[-156,-109]},{"ply":10,"player":"ai","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[10,15,19,21,32,33,46,59],"ai":[7,8,13,14,18,23,55,56]},"scoresAfter":[-156,-97]},{"ply":11,"player":"human","action":12,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[10,15,19,21,32,33,46,59],"ai":[4,8,13,14,18,23,55,56]},"scoresAfter":[-152,-97]},{"ply":12,"player":"ai","action":6,"playedCard":4,"placeType":"discard","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[10,19,21,28,32,33,46,59],"ai":[4,8,13,14,18,23,55,56]},"scoresAfter":[-152,-97]},{"ply":13,"player":"human","action":36,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[10,19,21,28,32,33,46,59],"ai":[8,13,14,18,23,47,55,56]},"scoresAfter":[-169,-97]},{"ply":14,"player":"ai","action":60,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[10,19,21,32,33,35,46,59],"ai":[8,13,14,18,23,47,55,56]},"scoresAfter":[-169,-87]},{"ply":15,"player":"human","action":36,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[10,19,21,32,33,35,46,59],"ai":[8,13,14,18,23,34,55,56]},"scoresAfter":[-162,-87]},{"ply":16,"player":"ai","action":60,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[10,19,21,33,35,45,46,59],"ai":[8,13,14,18,23,34,55,56]},"scoresAfter":[-162,-78]},{"ply":17,"player":"human","action":36,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[10,19,21,33,35,45,46,59],"ai":[8,13,14,18,23,25,55,56]},"scoresAfter":[-154,-78]},{"ply":18,"player":"ai","action":66,"playedCard":25,"placeType":"discard","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[10,19,21,35,42,45,46,59],"ai":[8,13,14,18,23,25,55,56]},"scoresAfter":[-154,-78]},{"ply":19,"player":"human","action":48,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[10,19,21,35,42,45,46,59],"ai":[8,13,14,18,23,54,55,56]},"scoresAfter":[-149,-78]},{"ply":20,"player":"ai","action":12,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[10,19,21,35,45,46,57,59],"ai":[8,13,14,18,23,54,55,56]},"scoresAfter":[-149,-118]},{"ply":21,"player":"human","action":36,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[10,19,21,35,45,46,57,59],"ai":[8,14,18,23,24,54,55,56]},"scoresAfter":[-139,-118]},{"ply":22,"player":"ai","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[6,10,19,21,45,46,57,59],"ai":[8,14,18,23,24,54,55,56]},"scoresAfter":[-139,-104]},{"ply":23,"player":"human","action":48,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[6,10,19,21,45,46,57,59],"ai":[11,14,18,23,24,54,55,56]},"scoresAfter":[-131,-104]},{"ply":24,"player":"ai","action":60,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[6,10,19,21,46,53,57,59],"ai":[11,14,18,23,24,54,55,56]},"scoresAfter":[-131,-94]},{"ply":25,"player":"human","action":48,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[6,10,19,21,46,53,57,59],"ai":[11,14,18,23,24,52,55,56]},"scoresAfter":[-122,-94]},{"ply":26,"player":"ai","action":72,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[6,10,19,20,21,53,57,59],"ai":[11,14,18,23,24,52,55,56]},"scoresAfter":[-122,-82]},{"ply":27,"player":"human","action":60,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[6,10,19,20,21,53,57,59],"ai":[11,14,18,23,24,29,52,56]},"scoresAfter":[-110,-82]},{"ply":28,"player":"ai","action":66,"playedCard":29,"placeType":"discard","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[5,6,10,19,20,21,57,59],"ai":[11,14,18,23,24,29,52,56]},"scoresAfter":[-110,-82]},{"ply":29,"player":"human","action":72,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[5,6,10,19,20,21,57,59],"ai":[11,14,18,22,23,24,52,56]},"scoresAfter":[-86,-82]},{"ply":30,"player":"ai","action":12,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[5,6,10,19,20,21,39,59],"ai":[11,14,18,22,23,24,52,56]},"scoresAfter":[-86,-102]},{"ply":31,"player":"human","action":85,"playedCard":59,"placeType":"play","drawSource":"discard_0","drawnCard":4,"handsBefore":{"human":[5,6,10,19,20,21,39,59],"ai":[11,18,22,23,24,40,52,56]},"scoresAfter":[-56,-102]},{"ply":32,"player":"ai","action":66,"playedCard":40,"placeType":"discard","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[4,5,6,10,19,20,21,39],"ai":[11,18,22,23,24,40,52,56]},"scoresAfter":[-56,-102]},{"ply":33,"player":"human","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[4,5,6,10,19,20,21,39],"ai":[11,18,22,23,24,44,52,56]},"scoresAfter":[-50,-102]},{"ply":34,"player":"ai","action":54,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[5,6,10,19,20,21,36,39],"ai":[11,18,22,23,24,44,52,56]},"scoresAfter":[-50,-102]},{"ply":35,"player":"human","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[5,6,10,19,20,21,36,39],"ai":[9,11,18,22,23,44,52,56]},"scoresAfter":[-42,-102]},{"ply":36,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[3,6,10,19,20,21,36,39],"ai":[9,11,18,22,23,44,52,56]},"scoresAfter":[-42,-86]},{"ply":37,"player":"human","action":12,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[3,6,10,19,20,21,36,39],"ai":[11,18,22,23,44,51,52,56]},"scoresAfter":[-32,-86]},{"ply":38,"player":"ai","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[3,10,19,20,21,36,37,39],"ai":[11,18,22,23,44,51,52,56]},"scoresAfter":[-32,-66]},{"ply":39,"player":"human","action":24,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[3,10,19,20,21,36,37,39],"ai":[18,22,23,44,51,52,56,58]},"scoresAfter":[-20,-66]},{"ply":40,"player":"ai","action":76,"playedCard":56,"placeType":"play","drawSource":"discard_3","drawnCard":40,"handsBefore":{"human":[3,10,20,21,36,37,38,39],"ai":[18,22,23,44,51,52,56,58]},"scoresAfter":[-20,-52]},{"ply":41,"player":"human","action":24,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[3,10,20,21,36,37,38,39],"ai":[18,22,23,40,44,51,52,58]},"scoresAfter":[-6,-52]},{"ply":42,"player":"ai","action":3,"playedCard":18,"placeType":"play","drawSource":"discard_2","drawnCard":24,"handsBefore":{"human":[3,10,21,26,36,37,38,39],"ai":[18,22,23,40,44,51,52,58]},"scoresAfter":[-6,-37]},{"ply":43,"player":"human","action":24,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[3,10,21,26,36,37,38,39],"ai":[22,23,24,40,44,51,52,58]},"scoresAfter":[10,-37]},{"ply":44,"player":"ai","action":3,"playedCard":22,"placeType":"play","drawSource":"discard_2","drawnCard":29,"handsBefore":{"human":[3,10,17,26,36,37,38,39],"ai":[22,23,24,40,44,51,52,58]},"scoresAfter":[10,-10]},{"ply":45,"player":"human","action":12,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[3,10,17,26,36,37,38,39],"ai":[23,24,29,40,44,51,52,58]},"scoresAfter":[28,-10]},{"ply":46,"player":"ai","action":3,"playedCard":23,"placeType":"play","drawSource":"discard_2","drawnCard":25,"handsBefore":{"human":[2,3,17,26,36,37,38,39],"ai":[23,24,29,40,44,51,52,58]},"scoresAfter":[28,20]},{"ply":47,"player":"human","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[2,3,17,26,36,37,38,39],"ai":[24,25,29,40,44,51,52,58]},"scoresAfter":[28,20]},{"ply":48,"player":"ai","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[3,17,26,31,36,37,38,39],"ai":[24,25,29,40,44,51,52,58]},"scoresAfter":[28,38]},{"ply":49,"player":"human","action":42,"playedCard":31,"placeType":"discard","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[3,17,26,31,36,37,38,39],"ai":[24,25,27,29,40,44,51,52]},"scoresAfter":[28,38]}],"finalScores":[28,38],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[21,19,0,32,59,48,33,10,49,56,43,7,18,14,1,30,50,13,46,55,41,8,12,23,15,4,28,47,35,34,45,25,42,54,57,24,6,11,53,52,20,29,5,22,39,40,44,36,9,3,51,37,58,38,26,17,2,31,27,16],"drawPtr":60,"cardLoc":[3,4,5,1,3,3,3,4,4,4,3,4,3,4,4,3,1,1,4,3,3,3,4,4,2,2,1,2,3,2,4,5,3,3,4,3,1,1,1,1,2,3,3,4,2,3,3,4,3,4,3,2,2,3,4,4,4,3,4,3],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,false,false,false,true,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[9,8,10,9,10],[10,10,9,10,9]],"colHandshakes":[[1,1,0,0,2],[1,2,0,0,1]],"colLength":[[5,5,4,4,5],[5,5,2,2,5]],"piles":[[2],[],[31],[],[]],"toMove":1,"stepCount":49,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"1eb408ef-c682-4049-bc56-07cbd8e9d41a","seed":"cinzpz","startedAt":"2026-07-14T14:18:27.543Z","finishedAt":"2026-07-14T14:20:28.517Z","initialDeckOrder":[35,23,53,11,0,46,55,20,26,52,50,4,9,59,27,8,40,28,43,49,13,6,51,39,47,5,3,48,58,57,12,41,7,17,44,38,2,30,1,36,29,22,42,21,19,14,25,18,24,32,31,34,37,56,16,15,33,45,54,10],"moves":[{"ply":1,"player":"human","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[0,11,20,23,35,46,53,55],"ai":[4,8,9,26,27,50,52,59]},"scoresAfter":[0,0]},{"ply":2,"player":"ai","action":42,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[11,20,23,35,40,46,53,55],"ai":[4,8,9,26,27,50,52,59]},"scoresAfter":[0,0]},{"ply":3,"player":"human","action":48,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[11,20,23,35,40,46,53,55],"ai":[4,8,9,27,28,50,52,59]},"scoresAfter":[-17,0]},{"ply":4,"player":"ai","action":3,"playedCard":4,"placeType":"play","drawSource":"discard_2","drawnCard":26,"handsBefore":{"human":[11,20,23,35,43,46,53,55],"ai":[4,8,9,27,28,50,52,59]},"scoresAfter":[-17,-17]},{"ply":5,"player":"human","action":48,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[11,20,23,35,43,46,53,55],"ai":[8,9,26,27,28,50,52,59]},"scoresAfter":[-11,-17]},{"ply":6,"player":"ai","action":30,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[11,20,23,35,46,49,53,55],"ai":[8,9,26,27,28,50,52,59]},"scoresAfter":[-11,-17]},{"ply":7,"player":"human","action":60,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[11,20,23,35,46,49,53,55],"ai":[8,9,13,27,28,50,52,59]},"scoresAfter":[-51,-17]},{"ply":8,"player":"ai","action":24,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[6,11,20,23,35,46,53,55],"ai":[8,9,13,27,28,50,52,59]},"scoresAfter":[-51,-57]},{"ply":9,"player":"human","action":72,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[6,11,20,23,35,46,53,55],"ai":[8,9,27,28,50,51,52,59]},"scoresAfter":[-43,-57]},{"ply":10,"player":"ai","action":48,"playedCard":50,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[6,11,20,23,35,39,46,55],"ai":[8,9,27,28,50,51,52,59]},"scoresAfter":[-43,-97]},{"ply":11,"player":"human","action":84,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[6,11,20,23,35,39,46,55],"ai":[8,9,27,28,47,51,52,59]},"scoresAfter":[-31,-97]},{"ply":12,"player":"ai","action":61,"playedCard":51,"placeType":"play","drawSource":"discard_0","drawnCard":0,"handsBefore":{"human":[5,6,11,20,23,35,39,46],"ai":[8,9,27,28,47,51,52,59]},"scoresAfter":[-31,-93]},{"ply":13,"player":"human","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[5,6,11,20,23,35,39,46],"ai":[0,8,9,27,28,47,52,59]},"scoresAfter":[-47,-93]},{"ply":14,"player":"ai","action":72,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[3,6,11,20,23,35,39,46],"ai":[0,8,9,27,28,47,52,59]},"scoresAfter":[-47,-87]},{"ply":15,"player":"human","action":12,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[3,6,11,20,23,35,39,46],"ai":[0,8,9,27,28,47,48,59]},"scoresAfter":[-42,-87]},{"ply":16,"player":"ai","action":36,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[3,11,20,23,35,39,46,58],"ai":[0,8,9,27,28,47,48,59]},"scoresAfter":[-42,-105]},{"ply":17,"player":"human","action":6,"playedCard":3,"placeType":"discard","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[3,11,20,23,35,39,46,58],"ai":[0,8,9,28,47,48,57,59]},"scoresAfter":[-42,-105]},{"ply":18,"player":"ai","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[11,12,20,23,35,39,46,58],"ai":[0,8,9,28,47,48,57,59]},"scoresAfter":[-42,-105]},{"ply":19,"player":"human","action":12,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[11,12,20,23,35,39,46,58],"ai":[8,9,28,41,47,48,57,59]},"scoresAfter":[-82,-105]},{"ply":20,"player":"ai","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[7,11,20,23,35,39,46,58],"ai":[8,9,28,41,47,48,57,59]},"scoresAfter":[-82,-98]},{"ply":21,"player":"human","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[7,11,20,23,35,39,46,58],"ai":[9,17,28,41,47,48,57,59]},"scoresAfter":[-76,-98]},{"ply":22,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[11,20,23,35,39,44,46,58],"ai":[9,17,28,41,47,48,57,59]},"scoresAfter":[-76,-90]},{"ply":23,"player":"human","action":60,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[11,20,23,35,39,44,46,58],"ai":[17,28,38,41,47,48,57,59]},"scoresAfter":[-69,-90]},{"ply":24,"player":"ai","action":0,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[2,11,20,23,35,39,46,58],"ai":[17,28,38,41,47,48,57,59]},"scoresAfter":[-69,-82]},{"ply":25,"player":"human","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[2,11,20,23,35,39,46,58],"ai":[28,30,38,41,47,48,57,59]},"scoresAfter":[-69,-82]},{"ply":26,"player":"ai","action":0,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[1,11,20,23,35,39,46,58],"ai":[28,30,38,41,47,48,57,59]},"scoresAfter":[-69,-79]},{"ply":27,"player":"human","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[1,11,20,23,35,39,46,58],"ai":[30,36,38,41,47,48,57,59]},"scoresAfter":[-69,-79]},{"ply":28,"player":"ai","action":0,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[11,20,23,29,35,39,46,58],"ai":[30,36,38,41,47,48,57,59]},"scoresAfter":[-69,-74]},{"ply":29,"player":"human","action":66,"playedCard":39,"placeType":"discard","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[11,20,23,29,35,39,46,58],"ai":[22,36,38,41,47,48,57,59]},"scoresAfter":[-69,-74]},{"ply":30,"player":"ai","action":0,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[11,20,23,29,35,42,46,58],"ai":[22,36,38,41,47,48,57,59]},"scoresAfter":[-69,-56]},{"ply":31,"player":"human","action":36,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[11,20,23,29,35,42,46,58],"ai":[21,36,38,41,47,48,57,59]},"scoresAfter":[-85,-56]},{"ply":32,"player":"ai","action":66,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[11,19,20,23,35,42,46,58],"ai":[21,36,38,41,47,48,57,59]},"scoresAfter":[-85,-56]},{"ply":33,"player":"human","action":12,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[11,19,20,23,35,42,46,58],"ai":[14,21,36,38,41,47,57,59]},"scoresAfter":[-73,-56]},{"ply":34,"player":"ai","action":48,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[11,20,23,25,35,42,46,58],"ai":[14,21,36,38,41,47,57,59]},"scoresAfter":[-73,-72]},{"ply":35,"player":"human","action":42,"playedCard":25,"placeType":"discard","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[11,20,23,25,35,42,46,58],"ai":[14,18,21,36,38,47,57,59]},"scoresAfter":[-73,-72]},{"ply":36,"player":"ai","action":54,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[11,20,23,24,35,42,46,58],"ai":[14,18,21,36,38,47,57,59]},"scoresAfter":[-73,-72]},{"ply":37,"player":"human","action":42,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[11,20,23,24,35,42,46,58],"ai":[14,18,21,32,36,47,57,59]},"scoresAfter":[-73,-72]},{"ply":38,"player":"ai","action":36,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[11,20,23,31,35,42,46,58],"ai":[14,18,21,32,36,47,57,59]},"scoresAfter":[-73,-65]},{"ply":39,"player":"human","action":36,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[11,20,23,31,35,42,46,58],"ai":[14,18,21,34,36,47,57,59]},"scoresAfter":[-67,-65]},{"ply":40,"player":"ai","action":36,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[11,20,23,35,37,42,46,58],"ai":[14,18,21,34,36,47,57,59]},"scoresAfter":[-67,-56]},{"ply":41,"player":"human","action":54,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[11,20,23,35,37,42,46,58],"ai":[14,18,21,36,47,56,57,59]},"scoresAfter":[-67,-56]},{"ply":42,"player":"ai","action":48,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[11,16,20,23,35,42,46,58],"ai":[14,18,21,36,47,56,57,59]},"scoresAfter":[-67,-46]},{"ply":43,"player":"human","action":25,"playedCard":20,"placeType":"play","drawSource":"discard_0","drawnCard":1,"handsBefore":{"human":[11,16,20,23,35,42,46,58],"ai":[14,15,18,21,36,56,57,59]},"scoresAfter":[-53,-46]},{"ply":44,"player":"ai","action":60,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[1,11,16,23,35,42,46,58],"ai":[14,15,18,21,36,56,57,59]},"scoresAfter":[-53,-32]},{"ply":45,"player":"human","action":73,"playedCard":46,"placeType":"play","drawSource":"discard_0","drawnCard":2,"handsBefore":{"human":[1,11,16,23,35,42,46,58],"ai":[14,15,18,21,33,36,57,59]},"scoresAfter":[-44,-32]},{"ply":46,"player":"ai","action":72,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[1,2,11,16,23,35,42,58],"ai":[14,15,18,21,33,36,57,59]},"scoresAfter":[-44,-16]},{"ply":47,"player":"human","action":28,"playedCard":11,"placeType":"play","drawSource":"discard_3","drawnCard":37,"handsBefore":{"human":[1,2,11,16,23,35,42,58],"ai":[14,15,18,21,33,36,45,59]},"scoresAfter":[-34,-16]},{"ply":48,"player":"ai","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[1,2,16,23,35,37,42,58],"ai":[14,15,18,21,33,36,45,59]},"scoresAfter":[-34,4]},{"ply":49,"player":"human","action":39,"playedCard":23,"placeType":"play","drawSource":"discard_2","drawnCard":24,"handsBefore":{"human":[1,2,16,23,35,37,42,58],"ai":[14,15,18,21,33,36,45,54]},"scoresAfter":[-14,4]},{"ply":50,"player":"ai","action":78,"playedCard":45,"placeType":"discard","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[1,2,16,24,35,37,42,58],"ai":[14,15,18,21,33,36,45,54]},"scoresAfter":[-14,4]}],"finalScores":[-14,4],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[35,23,53,11,0,46,55,20,26,52,50,4,9,59,27,8,40,28,43,49,13,6,51,39,47,5,3,48,58,57,12,41,7,17,44,38,2,30,1,36,29,22,42,21,19,14,25,18,24,32,31,34,37,56,16,15,33,45,54,10],"drawPtr":60,"cardLoc":[5,1,1,5,4,3,3,3,4,4,2,3,3,4,2,2,1,4,2,3,3,2,4,3,1,5,5,4,4,3,4,3,4,2,4,1,2,1,5,5,3,4,1,3,3,5,3,4,5,3,4,4,4,3,2,3,4,4,1,4],"handPublic":[false,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,10,6,9,6],[8,9,9,10,10]],"colHandshakes":[[0,1,0,0,1],[0,1,0,0,1]],"colLength":[[4,4,2,4,3],[3,3,5,2,6]],"piles":[[3,0],[],[26,25],[39,38,45],[48]],"toMove":0,"stepCount":50,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"6625627d-cbf1-4bb4-812b-2d9b89332022","seed":"wrsv3q","startedAt":"2026-07-14T14:20:29.790Z","finishedAt":"2026-07-14T14:23:10.860Z","initialDeckOrder":[13,32,10,11,29,14,45,58,6,41,30,47,34,26,28,37,7,56,19,51,50,25,40,20,4,33,5,3,52,23,57,49,38,46,36,21,17,1,44,31,27,48,9,42,39,24,59,18,12,35,54,8,53,2,22,55,16,15,43,0],"moves":[{"ply":1,"player":"human","action":30,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[10,11,13,14,29,32,45,58],"ai":[6,26,28,30,34,37,41,47]},"scoresAfter":[0,0]},{"ply":2,"player":"ai","action":12,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[7,10,11,14,29,32,45,58],"ai":[6,26,28,30,34,37,41,47]},"scoresAfter":[0,-40]},{"ply":3,"player":"human","action":42,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[7,10,11,14,29,32,45,58],"ai":[6,28,30,34,37,41,47,56]},"scoresAfter":[0,-40]},{"ply":4,"player":"ai","action":48,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[7,10,11,19,29,32,45,58],"ai":[6,28,30,34,37,41,47,56]},"scoresAfter":[0,-80]},{"ply":5,"player":"human","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[7,10,11,19,29,32,45,58],"ai":[6,28,30,34,41,47,51,56]},"scoresAfter":[-14,-80]},{"ply":6,"player":"ai","action":72,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[10,11,19,29,32,45,50,58],"ai":[6,28,30,34,41,47,51,56]},"scoresAfter":[-14,-98]},{"ply":7,"player":"human","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[10,11,19,29,32,45,50,58],"ai":[6,25,28,30,34,41,47,56]},"scoresAfter":[-5,-98]},{"ply":8,"player":"ai","action":12,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[11,19,29,32,40,45,50,58],"ai":[6,25,28,30,34,41,47,56]},"scoresAfter":[-5,-118]},{"ply":9,"player":"human","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[11,19,29,32,40,45,50,58],"ai":[6,20,28,30,34,41,47,56]},"scoresAfter":[5,-118]},{"ply":10,"player":"ai","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[4,19,29,32,40,45,50,58],"ai":[6,20,28,30,34,41,47,56]},"scoresAfter":[5,-133]},{"ply":11,"player":"human","action":6,"playedCard":4,"placeType":"discard","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[4,19,29,32,40,45,50,58],"ai":[20,28,30,33,34,41,47,56]},"scoresAfter":[5,-133]},{"ply":12,"player":"ai","action":60,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[5,19,29,32,40,45,50,58],"ai":[20,28,30,33,34,41,47,56]},"scoresAfter":[5,-125]},{"ply":13,"player":"human","action":6,"playedCard":5,"placeType":"discard","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[5,19,29,32,40,45,50,58],"ai":[3,20,28,30,33,34,47,56]},"scoresAfter":[5,-125]},{"ply":14,"player":"ai","action":84,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[19,29,32,40,45,50,52,58],"ai":[3,20,28,30,33,34,47,56]},"scoresAfter":[5,-118]},{"ply":15,"player":"human","action":36,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[19,29,32,40,45,50,52,58],"ai":[3,20,23,28,30,33,34,47]},"scoresAfter":[-12,-118]},{"ply":16,"player":"ai","action":84,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[19,29,32,45,50,52,57,58],"ai":[3,20,23,28,30,33,34,47]},"scoresAfter":[-12,-98]},{"ply":17,"player":"human","action":48,"playedCard":50,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[19,29,32,45,50,52,57,58],"ai":[3,20,23,28,30,33,34,49]},"scoresAfter":[-52,-98]},{"ply":18,"player":"ai","action":6,"playedCard":3,"placeType":"discard","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[19,29,32,38,45,52,57,58],"ai":[3,20,23,28,30,33,34,49]},"scoresAfter":[-52,-98]},{"ply":19,"player":"human","action":60,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[19,29,32,38,45,52,57,58],"ai":[20,23,28,30,33,34,46,49]},"scoresAfter":[-46,-98]},{"ply":20,"player":"ai","action":90,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[19,29,32,36,38,45,57,58],"ai":[20,23,28,30,33,34,46,49]},"scoresAfter":[-46,-98]},{"ply":21,"player":"human","action":42,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[19,29,32,36,38,45,57,58],"ai":[20,21,23,28,30,33,34,46]},"scoresAfter":[-46,-98]},{"ply":22,"player":"ai","action":0,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[17,19,29,32,38,45,57,58],"ai":[20,21,23,28,30,33,34,46]},"scoresAfter":[-46,-111]},{"ply":23,"player":"human","action":24,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[17,19,29,32,38,45,57,58],"ai":[1,21,23,28,30,33,34,46]},"scoresAfter":[-62,-111]},{"ply":24,"player":"ai","action":12,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[17,19,32,38,44,45,57,58],"ai":[1,21,23,28,30,33,34,46]},"scoresAfter":[-62,-103]},{"ply":25,"player":"human","action":42,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[17,19,32,38,44,45,57,58],"ai":[1,23,28,30,31,33,34,46]},"scoresAfter":[-62,-103]},{"ply":26,"player":"ai","action":12,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[17,19,27,32,44,45,57,58],"ai":[1,23,28,30,31,33,34,46]},"scoresAfter":[-62,-93]},{"ply":27,"player":"human","action":6,"playedCard":17,"placeType":"discard","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[17,19,27,32,44,45,57,58],"ai":[1,28,30,31,33,34,46,48]},"scoresAfter":[-62,-93]},{"ply":28,"player":"ai","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[9,19,27,32,44,45,57,58],"ai":[1,28,30,31,33,34,46,48]},"scoresAfter":[-62,-93]},{"ply":29,"player":"human","action":18,"playedCard":19,"placeType":"discard","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[9,19,27,32,44,45,57,58],"ai":[28,30,31,33,34,42,46,48]},"scoresAfter":[-62,-93]},{"ply":30,"player":"ai","action":78,"playedCard":46,"placeType":"discard","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[9,27,32,39,44,45,57,58],"ai":[28,30,31,33,34,42,46,48]},"scoresAfter":[-62,-93]},{"ply":31,"player":"human","action":42,"playedCard":39,"placeType":"discard","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[9,27,32,39,44,45,57,58],"ai":[24,28,30,31,33,34,42,48]},"scoresAfter":[-62,-93]},{"ply":32,"player":"ai","action":0,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[9,27,32,44,45,57,58,59],"ai":[24,28,30,31,33,34,42,48]},"scoresAfter":[-62,-113]},{"ply":33,"player":"human","action":64,"playedCard":57,"placeType":"play","drawSource":"discard_3","drawnCard":39,"handsBefore":{"human":[9,27,32,44,45,57,58,59],"ai":[18,28,30,31,33,34,42,48]},"scoresAfter":[-46,-113]},{"ply":34,"player":"ai","action":90,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[9,27,32,39,44,45,58,59],"ai":[18,28,30,31,33,34,42,48]},"scoresAfter":[-46,-113]},{"ply":35,"player":"human","action":52,"playedCard":44,"placeType":"play","drawSource":"discard_3","drawnCard":46,"handsBefore":{"human":[9,27,32,39,44,45,58,59],"ai":[12,18,28,30,31,33,34,42]},"scoresAfter":[-39,-113]},{"ply":36,"player":"ai","action":24,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[9,27,32,39,45,46,58,59],"ai":[12,18,28,30,31,33,34,42]},"scoresAfter":[-39,-101]},{"ply":37,"player":"human","action":48,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[9,27,32,39,45,46,58,59],"ai":[12,18,30,31,33,34,35,42]},"scoresAfter":[-31,-101]},{"ply":38,"player":"ai","action":24,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[9,27,32,39,46,54,58,59],"ai":[12,18,30,31,33,34,35,42]},"scoresAfter":[-31,-81]},{"ply":39,"player":"human","action":48,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[9,27,32,39,46,54,58,59],"ai":[8,12,18,31,33,34,35,42]},"scoresAfter":[-22,-81]},{"ply":40,"player":"ai","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[9,27,32,39,53,54,58,59],"ai":[8,12,18,31,33,34,35,42]},"scoresAfter":[-22,-74]},{"ply":41,"player":"human","action":72,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[9,27,32,39,53,54,58,59],"ai":[2,12,18,31,33,34,35,42]},"scoresAfter":[-4,-74]},{"ply":42,"player":"ai","action":36,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[9,22,27,32,39,53,54,59],"ai":[2,12,18,31,33,34,35,42]},"scoresAfter":[-4,-50]},{"ply":43,"player":"human","action":86,"playedCard":59,"placeType":"play","drawSource":"discard_1","drawnCard":19,"handsBefore":{"human":[9,22,27,32,39,53,54,59],"ai":[2,12,18,33,34,35,42,55]},"scoresAfter":[16,-50]},{"ply":44,"player":"ai","action":41,"playedCard":33,"placeType":"play","drawSource":"discard_4","drawnCard":48,"handsBefore":{"human":[9,19,22,27,32,39,53,54],"ai":[2,12,18,33,34,35,42,55]},"scoresAfter":[16,-18]},{"ply":45,"player":"human","action":48,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[9,19,22,27,32,39,53,54],"ai":[2,12,18,34,35,42,48,55]},"scoresAfter":[23,-18]},{"ply":46,"player":"ai","action":37,"playedCard":34,"placeType":"play","drawSource":"discard_0","drawnCard":1,"handsBefore":{"human":[9,16,19,22,27,39,53,54],"ai":[2,12,18,34,35,42,48,55]},"scoresAfter":[23,38]},{"ply":47,"player":"human","action":42,"playedCard":22,"placeType":"discard","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[9,16,19,22,27,39,53,54],"ai":[1,2,12,18,35,42,48,55]},"scoresAfter":[23,38]},{"ply":48,"player":"ai","action":48,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[9,15,16,19,27,39,53,54],"ai":[1,2,12,18,35,42,48,55]},"scoresAfter":[23,78]},{"ply":49,"player":"human","action":42,"playedCard":19,"placeType":"discard","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[9,15,16,19,27,39,53,54],"ai":[1,2,12,18,42,43,48,55]},"scoresAfter":[23,78]}],"finalScores":[23,78],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[13,32,10,11,29,14,45,58,6,41,30,47,34,26,28,37,7,56,19,51,50,25,40,20,4,33,5,3,52,23,57,49,38,46,36,21,17,1,44,31,27,48,9,42,39,24,59,18,12,35,54,8,53,2,22,55,16,15,43,0],"drawPtr":60,"cardLoc":[1,2,2,5,5,5,4,3,4,1,3,3,2,5,5,1,1,5,2,5,4,4,5,4,4,4,4,1,4,3,4,4,3,4,4,4,5,4,5,1,3,4,2,2,3,3,3,4,2,5,3,4,3,1,1,2,4,3,3,3],"handPublic":[false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,0,7,9,10],[7,10,10,10,7]],"colHandshakes":[[0,0,0,0,1],[0,0,3,1,0]],"colLength":[[3,0,2,4,5],[2,3,9,3,2]],"piles":[[4,5,3],[13,14,17,22,19],[],[36,38],[49]],"toMove":1,"stepCount":49,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"78fe117a-40fc-4e65-ab09-2386ae3af2dd","seed":"ez96sn","startedAt":"2026-07-14T14:23:11.845Z","finishedAt":"2026-07-14T14:26:09.979Z","initialDeckOrder":[1,23,26,37,52,45,12,56,22,41,53,25,29,11,42,34,3,54,50,35,39,5,57,55,59,40,47,33,15,4,10,27,24,2,58,20,28,30,51,18,49,32,46,48,36,13,7,17,44,14,31,9,19,8,43,16,38,0,6,21],"moves":[{"ply":1,"player":"human","action":12,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[1,12,23,26,37,45,52,56],"ai":[11,22,25,29,34,41,42,53]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":84,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[1,3,23,26,37,45,52,56],"ai":[11,22,25,29,34,41,42,53]},"scoresAfter":[-40,-16]},{"ply":3,"player":"human","action":48,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[1,3,23,26,37,45,52,56],"ai":[11,22,25,29,34,41,42,54]},"scoresAfter":[-80,-16]},{"ply":4,"player":"ai","action":60,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[1,3,23,26,45,50,52,56],"ai":[11,22,25,29,34,41,42,54]},"scoresAfter":[-80,-32]},{"ply":5,"player":"human","action":60,"playedCard":50,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[1,3,23,26,45,50,52,56],"ai":[11,22,25,29,34,35,42,54]},"scoresAfter":[-120,-32]},{"ply":6,"player":"ai","action":84,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[1,3,23,26,39,45,52,56],"ai":[11,22,25,29,34,35,42,54]},"scoresAfter":[-120,-27]},{"ply":7,"player":"human","action":48,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[1,3,23,26,39,45,52,56],"ai":[5,11,22,25,29,34,35,42]},"scoresAfter":[-116,-27]},{"ply":8,"player":"ai","action":84,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[1,3,23,26,45,52,56,57],"ai":[5,11,22,25,29,34,35,42]},"scoresAfter":[-116,-22]},{"ply":9,"player":"human","action":60,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[1,3,23,26,45,52,56,57],"ai":[5,11,22,25,29,34,35,55]},"scoresAfter":[-110,-22]},{"ply":10,"player":"ai","action":84,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[1,3,23,26,45,56,57,59],"ai":[5,11,22,25,29,34,35,55]},"scoresAfter":[-110,-16]},{"ply":11,"player":"human","action":60,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[1,3,23,26,45,56,57,59],"ai":[5,11,22,25,29,34,35,40]},"scoresAfter":[-96,-16]},{"ply":12,"player":"ai","action":36,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[1,3,23,26,45,47,57,59],"ai":[5,11,22,25,29,34,35,40]},"scoresAfter":[-96,-56]},{"ply":13,"player":"human","action":72,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[1,3,23,26,45,47,57,59],"ai":[5,11,22,29,33,34,35,40]},"scoresAfter":[-80,-56]},{"ply":14,"player":"ai","action":90,"playedCard":40,"placeType":"discard","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[1,3,15,23,26,45,47,59],"ai":[5,11,22,29,33,34,35,40]},"scoresAfter":[-80,-56]},{"ply":15,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[1,3,15,23,26,45,47,59],"ai":[4,5,11,22,29,33,34,35]},"scoresAfter":[-60,-56]},{"ply":16,"player":"ai","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[1,3,10,15,23,26,45,47],"ai":[4,5,11,22,29,33,34,35]},"scoresAfter":[-60,-73]},{"ply":17,"player":"human","action":36,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[1,3,10,15,23,26,45,47],"ai":[5,11,22,27,29,33,34,35]},"scoresAfter":[-56,-73]},{"ply":18,"player":"ai","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[1,3,10,23,24,26,45,47],"ai":[5,11,22,27,29,33,34,35]},"scoresAfter":[-56,-69]},{"ply":19,"player":"human","action":54,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[1,3,10,23,24,26,45,47],"ai":[2,11,22,27,29,33,34,35]},"scoresAfter":[-56,-69]},{"ply":20,"player":"ai","action":15,"playedCard":11,"placeType":"play","drawSource":"discard_2","drawnCard":24,"handsBefore":{"human":[1,3,10,23,26,45,47,58],"ai":[2,11,22,27,29,33,34,35]},"scoresAfter":[-56,-59]},{"ply":21,"player":"human","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[1,3,10,23,26,45,47,58],"ai":[2,22,24,27,29,33,34,35]},"scoresAfter":[-56,-59]},{"ply":22,"player":"ai","action":12,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[3,10,20,23,26,45,47,58],"ai":[2,22,24,27,29,33,34,35]},"scoresAfter":[-56,-70]},{"ply":23,"player":"human","action":6,"playedCard":3,"placeType":"discard","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[3,10,20,23,26,45,47,58],"ai":[2,24,27,28,29,33,34,35]},"scoresAfter":[-56,-70]},{"ply":24,"player":"ai","action":12,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[10,20,23,26,30,45,47,58],"ai":[2,24,27,28,29,33,34,35]},"scoresAfter":[-56,-90]},{"ply":25,"player":"human","action":42,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[10,20,23,26,30,45,47,58],"ai":[2,27,28,29,33,34,35,51]},"scoresAfter":[-56,-90]},{"ply":26,"player":"ai","action":93,"playedCard":51,"placeType":"discard","drawSource":"discard_2","drawnCard":26,"handsBefore":{"human":[10,18,20,23,30,45,47,58],"ai":[2,27,28,29,33,34,35,51]},"scoresAfter":[-56,-90]},{"ply":27,"player":"human","action":12,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[10,18,20,23,30,45,47,58],"ai":[2,26,27,28,29,33,34,35]},"scoresAfter":[-46,-90]},{"ply":28,"player":"ai","action":12,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[10,20,23,30,45,47,49,58],"ai":[2,26,27,28,29,33,34,35]},"scoresAfter":[-46,-110]},{"ply":29,"player":"human","action":12,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[10,20,23,30,45,47,49,58],"ai":[2,27,28,29,32,33,34,35]},"scoresAfter":[-32,-110]},{"ply":30,"player":"ai","action":12,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[10,23,30,45,46,47,49,58],"ai":[2,27,28,29,32,33,34,35]},"scoresAfter":[-32,-102]},{"ply":31,"player":"human","action":12,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[10,23,30,45,46,47,49,58],"ai":[2,28,29,32,33,34,35,48]},"scoresAfter":[-12,-102]},{"ply":32,"player":"ai","action":12,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[10,30,36,45,46,47,49,58],"ai":[2,28,29,32,33,34,35,48]},"scoresAfter":[-12,-90]},{"ply":33,"player":"human","action":82,"playedCard":49,"placeType":"discard","drawSource":"discard_3","drawnCard":40,"handsBefore":{"human":[10,30,36,45,46,47,49,58],"ai":[2,13,29,32,33,34,35,48]},"scoresAfter":[-12,-90]},{"ply":34,"player":"ai","action":18,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[10,30,36,40,45,46,47,58],"ai":[2,13,29,32,33,34,35,48]},"scoresAfter":[-12,-90]},{"ply":35,"player":"human","action":36,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[10,30,36,40,45,46,47,58],"ai":[2,7,29,32,33,34,35,48]},"scoresAfter":[-6,-90]},{"ply":36,"player":"ai","action":18,"playedCard":7,"placeType":"discard","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[10,17,30,36,45,46,47,58],"ai":[2,7,29,32,33,34,35,48]},"scoresAfter":[-6,-90]},{"ply":37,"player":"human","action":42,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[10,17,30,36,45,46,47,58],"ai":[2,29,32,33,34,35,44,48]},"scoresAfter":[-6,-90]},{"ply":38,"player":"ai","action":72,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[10,14,17,30,45,46,47,58],"ai":[2,29,32,33,34,35,44,48]},"scoresAfter":[-6,-83]},{"ply":39,"player":"human","action":18,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[10,14,17,30,45,46,47,58],"ai":[2,29,31,32,33,34,35,48]},"scoresAfter":[-6,-83]},{"ply":40,"player":"ai","action":12,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[9,10,17,30,45,46,47,58],"ai":[2,29,31,32,33,34,35,48]},"scoresAfter":[-6,-67]},{"ply":41,"player":"human","action":48,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[9,10,17,30,45,46,47,58],"ai":[2,19,31,32,33,34,35,48]},"scoresAfter":[10,-67]},{"ply":42,"player":"ai","action":25,"playedCard":31,"placeType":"play","drawSource":"discard_0","drawnCard":7,"handsBefore":{"human":[8,9,10,17,30,46,47,58],"ai":[2,19,31,32,33,34,35,48]},"scoresAfter":[10,-43]},{"ply":43,"player":"human","action":64,"playedCard":46,"placeType":"play","drawSource":"discard_3","drawnCard":36,"handsBefore":{"human":[8,9,10,17,30,46,47,58],"ai":[2,7,19,32,33,34,35,48]},"scoresAfter":[28,-43]},{"ply":44,"player":"ai","action":37,"playedCard":32,"placeType":"play","drawSource":"discard_0","drawnCard":3,"handsBefore":{"human":[8,9,10,17,30,36,47,58],"ai":[2,7,19,32,33,34,35,48]},"scoresAfter":[28,5]},{"ply":45,"player":"human","action":73,"playedCard":47,"placeType":"play","drawSource":"discard_0","drawnCard":1,"handsBefore":{"human":[8,9,10,17,30,36,47,58],"ai":[2,3,7,19,33,34,35,48]},"scoresAfter":[48,5]},{"ply":46,"player":"ai","action":23,"playedCard":3,"placeType":"discard","drawSource":"discard_4","drawnCard":49,"handsBefore":{"human":[1,8,9,10,17,30,36,58],"ai":[2,3,7,19,33,34,35,48]},"scoresAfter":[48,5]},{"ply":47,"player":"human","action":5,"playedCard":1,"placeType":"play","drawSource":"discard_4","drawnCard":51,"handsBefore":{"human":[1,8,9,10,17,30,36,58],"ai":[2,7,19,33,34,35,48,49]},"scoresAfter":[8,5]},{"ply":48,"player":"ai","action":18,"playedCard":7,"placeType":"discard","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[8,9,10,17,30,36,51,58],"ai":[2,7,19,33,34,35,48,49]},"scoresAfter":[8,5]},{"ply":49,"player":"human","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[8,9,10,17,30,36,51,58],"ai":[2,19,33,34,35,43,48,49]},"scoresAfter":[22,5]},{"ply":50,"player":"ai","action":25,"playedCard":33,"placeType":"play","drawSource":"discard_0","drawnCard":7,"handsBefore":{"human":[9,10,16,17,30,36,51,58],"ai":[2,19,33,34,35,43,48,49]},"scoresAfter":[22,37]},{"ply":51,"player":"human","action":1,"playedCard":9,"placeType":"play","drawSource":"discard_0","drawnCard":3,"handsBefore":{"human":[9,10,16,17,30,36,51,58],"ai":[2,7,19,34,35,43,48,49]},"scoresAfter":[38,37]},{"ply":52,"player":"ai","action":38,"playedCard":34,"placeType":"play","drawSource":"discard_1","drawnCard":14,"handsBefore":{"human":[3,10,16,17,30,36,51,58],"ai":[2,7,19,34,35,43,48,49]},"scoresAfter":[38,73]},{"ply":53,"player":"human","action":12,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[3,10,16,17,30,36,51,58],"ai":[2,7,14,19,35,43,48,49]},"scoresAfter":[56,73]},{"ply":54,"player":"ai","action":48,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[3,16,17,30,36,38,51,58],"ai":[2,7,14,19,35,43,48,49]},"scoresAfter":[56,113]},{"ply":55,"player":"human","action":54,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[3,16,17,30,36,38,51,58],"ai":[0,2,7,14,19,43,48,49]},"scoresAfter":[56,113]},{"ply":56,"player":"ai","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[3,6,16,17,30,38,51,58],"ai":[0,2,7,14,19,43,48,49]},"scoresAfter":[56,113]}],"finalScores":[56,113],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[1,23,26,37,52,45,12,56,22,41,53,25,29,11,42,34,3,54,50,35,39,5,57,55,59,40,47,33,15,4,10,27,24,2,58,20,28,30,51,18,49,32,46,48,36,13,7,17,44,14,31,9,19,8,43,16,38,0,6,21],"drawPtr":60,"cardLoc":[5,3,2,1,4,4,1,2,3,3,3,4,3,5,2,3,1,1,3,2,3,2,4,3,4,4,4,4,4,4,1,4,4,4,4,4,5,3,1,3,3,4,4,2,4,3,3,3,2,2,3,1,3,4,4,4,3,3,1,3],"handPublic":[false,false,false,true,false,false,false,true,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,true,false,false,false,false,false,false,false,false],"colTop":[[9,10,0,10,10],[10,9,10,7,6]],"colHandshakes":[[1,1,0,1,1],[0,0,3,0,0]],"colLength":[[4,5,0,6,5],[3,1,11,3,3]],"piles":[[0],[13],[],[36],[]],"toMove":0,"stepCount":56,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"6c350a91-e346-4be3-a0b3-d7f9a80ec4ed","seed":"qui9al","startedAt":"2026-07-14T14:26:11.097Z","finishedAt":"2026-07-14T14:28:03.458Z","initialDeckOrder":[44,4,24,50,23,49,16,27,35,51,45,47,8,15,39,25,38,7,1,20,5,0,36,18,11,40,48,43,58,28,33,31,2,29,13,17,57,6,59,46,32,56,41,9,54,14,21,52,10,55,22,53,3,19,34,30,12,37,26,42],"moves":[{"ply":1,"player":"human","action":12,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[4,16,23,24,27,44,49,50],"ai":[8,15,25,35,39,45,47,51]},"scoresAfter":[-17,0]},{"ply":2,"player":"ai","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[4,23,24,27,38,44,49,50],"ai":[8,15,25,35,39,45,47,51]},"scoresAfter":[-17,-13]},{"ply":3,"player":"human","action":48,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[4,23,24,27,38,44,49,50],"ai":[7,15,25,35,39,45,47,51]},"scoresAfter":[-57,-13]},{"ply":4,"player":"ai","action":84,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[1,4,23,24,27,44,49,50],"ai":[7,15,25,35,39,45,47,51]},"scoresAfter":[-57,-31]},{"ply":5,"player":"human","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[1,4,23,24,27,44,49,50],"ai":[7,15,20,25,35,39,45,47]},"scoresAfter":[-57,-31]},{"ply":6,"player":"ai","action":60,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[4,5,23,24,27,44,49,50],"ai":[7,15,20,25,35,39,45,47]},"scoresAfter":[-57,-49]},{"ply":7,"player":"human","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[4,5,23,24,27,44,49,50],"ai":[0,7,15,20,25,35,45,47]},"scoresAfter":[-74,-49]},{"ply":8,"player":"ai","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[5,23,24,27,36,44,49,50],"ai":[0,7,15,20,25,35,45,47]},"scoresAfter":[-74,-49]},{"ply":9,"player":"human","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[5,23,24,27,36,44,49,50],"ai":[7,15,18,20,25,35,45,47]},"scoresAfter":[-70,-49]},{"ply":10,"player":"ai","action":6,"playedCard":7,"placeType":"discard","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[11,23,24,27,36,44,49,50],"ai":[7,15,18,20,25,35,45,47]},"scoresAfter":[-70,-49]},{"ply":11,"player":"human","action":43,"playedCard":27,"placeType":"discard","drawSource":"discard_0","drawnCard":7,"handsBefore":{"human":[11,23,24,27,36,44,49,50],"ai":[15,18,20,25,35,40,45,47]},"scoresAfter":[-70,-49]},{"ply":12,"player":"ai","action":0,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[7,11,23,24,36,44,49,50],"ai":[15,18,20,25,35,40,45,47]},"scoresAfter":[-70,-67]},{"ply":13,"player":"human","action":78,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[7,11,23,24,36,44,49,50],"ai":[18,20,25,35,40,45,47,48]},"scoresAfter":[-70,-67]},{"ply":14,"player":"ai","action":0,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[7,11,23,24,36,43,44,50],"ai":[18,20,25,35,40,45,47,48]},"scoresAfter":[-70,-62]},{"ply":15,"player":"human","action":90,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[7,11,23,24,36,43,44,50],"ai":[20,25,35,40,45,47,48,58]},"scoresAfter":[-70,-62]},{"ply":16,"player":"ai","action":36,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[7,11,23,24,28,36,43,44],"ai":[20,25,35,40,45,47,48,58]},"scoresAfter":[-70,-59]},{"ply":17,"player":"human","action":42,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[7,11,23,24,28,36,43,44],"ai":[20,25,33,35,45,47,48,58]},"scoresAfter":[-70,-59]},{"ply":18,"player":"ai","action":48,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[7,11,23,28,31,36,43,44],"ai":[20,25,33,35,45,47,48,58]},"scoresAfter":[-70,-51]},{"ply":19,"player":"human","action":42,"playedCard":28,"placeType":"discard","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[7,11,23,28,31,36,43,44],"ai":[2,20,25,33,35,47,48,58]},"scoresAfter":[-70,-51]},{"ply":20,"player":"ai","action":9,"playedCard":2,"placeType":"discard","drawSource":"discard_2","drawnCard":28,"handsBefore":{"human":[7,11,23,29,31,36,43,44],"ai":[2,20,25,33,35,47,48,58]},"scoresAfter":[-70,-51]},{"ply":21,"player":"human","action":60,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[7,11,23,29,31,36,43,44],"ai":[20,25,28,33,35,47,48,58]},"scoresAfter":[-90,-51]},{"ply":22,"player":"ai","action":87,"playedCard":58,"placeType":"play","drawSource":"discard_2","drawnCard":24,"handsBefore":{"human":[7,11,13,23,29,31,43,44],"ai":[20,25,28,33,35,47,48,58]},"scoresAfter":[-90,-42]},{"ply":23,"player":"human","action":30,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[7,11,13,23,29,31,43,44],"ai":[20,24,25,28,33,35,47,48]},"scoresAfter":[-90,-42]},{"ply":24,"player":"ai","action":12,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[7,11,17,23,29,31,43,44],"ai":[20,24,25,28,33,35,47,48]},"scoresAfter":[-90,-82]},{"ply":25,"player":"human","action":24,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[7,11,17,23,29,31,43,44],"ai":[20,25,28,33,35,47,48,57]},"scoresAfter":[-86,-82]},{"ply":26,"player":"ai","action":3,"playedCard":20,"placeType":"play","drawSource":"discard_2","drawnCard":27,"handsBefore":{"human":[6,7,11,23,29,31,43,44],"ai":[20,25,28,33,35,47,48,57]},"scoresAfter":[-86,-75]},{"ply":27,"player":"human","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[6,7,11,23,29,31,43,44],"ai":[25,27,28,33,35,47,48,57]},"scoresAfter":[-81,-75]},{"ply":28,"player":"ai","action":0,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[7,11,23,29,31,43,44,59],"ai":[25,27,28,33,35,47,48,57]},"scoresAfter":[-81,-95]},{"ply":29,"player":"human","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[7,11,23,29,31,43,44,59],"ai":[27,28,33,35,46,47,48,57]},"scoresAfter":[-75,-95]},{"ply":30,"player":"ai","action":48,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[11,23,29,31,32,43,44,59],"ai":[27,28,33,35,46,47,48,57]},"scoresAfter":[-75,-86]},{"ply":31,"player":"human","action":24,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[11,23,29,31,32,43,44,59],"ai":[27,28,33,35,47,48,56,57]},"scoresAfter":[-91,-86]},{"ply":32,"player":"ai","action":48,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[11,23,31,32,41,43,44,59],"ai":[27,28,33,35,47,48,56,57]},"scoresAfter":[-91,-76]},{"ply":33,"player":"human","action":48,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[11,23,31,32,41,43,44,59],"ai":[9,27,28,33,35,48,56,57]},"scoresAfter":[-79,-76]},{"ply":34,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[11,23,31,32,43,44,54,59],"ai":[9,27,28,33,35,48,56,57]},"scoresAfter":[-79,-68]},{"ply":35,"player":"human","action":48,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[11,23,31,32,43,44,54,59],"ai":[14,27,28,33,35,48,56,57]},"scoresAfter":[-61,-68]},{"ply":36,"player":"ai","action":78,"playedCard":56,"placeType":"discard","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[11,21,23,31,32,44,54,59],"ai":[14,27,28,33,35,48,56,57]},"scoresAfter":[-61,-68]},{"ply":37,"player":"human","action":60,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[11,21,23,31,32,44,54,59],"ai":[14,27,28,33,35,48,52,57]},"scoresAfter":[-40,-68]},{"ply":38,"player":"ai","action":12,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[10,11,21,23,31,32,54,59],"ai":[14,27,28,33,35,48,52,57]},"scoresAfter":[-40,-62]},{"ply":39,"player":"human","action":24,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[10,11,21,23,31,32,54,59],"ai":[14,28,33,35,48,52,55,57]},"scoresAfter":[-32,-62]},{"ply":40,"player":"ai","action":78,"playedCard":55,"placeType":"discard","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[10,11,22,23,31,32,54,59],"ai":[14,28,33,35,48,52,55,57]},"scoresAfter":[-32,-62]},{"ply":41,"player":"human","action":24,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[10,11,22,23,31,32,54,59],"ai":[14,28,33,35,48,52,53,57]},"scoresAfter":[-23,-62]},{"ply":42,"player":"ai","action":12,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[3,10,11,23,31,32,54,59],"ai":[14,28,33,35,48,52,53,57]},"scoresAfter":[-23,-53]},{"ply":43,"player":"human","action":41,"playedCard":23,"placeType":"play","drawSource":"discard_4","drawnCard":55,"handsBefore":{"human":[3,10,11,23,31,32,54,59],"ai":[14,19,33,35,48,52,53,57]},"scoresAfter":[-13,-53]},{"ply":44,"player":"ai","action":66,"playedCard":52,"placeType":"discard","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[3,10,11,31,32,54,55,59],"ai":[14,19,33,35,48,52,53,57]},"scoresAfter":[-13,-53]},{"ply":45,"player":"human","action":17,"playedCard":10,"placeType":"play","drawSource":"discard_4","drawnCard":52,"handsBefore":{"human":[3,10,11,31,32,54,55,59],"ai":[14,19,33,34,35,48,53,57]},"scoresAfter":[-4,-53]},{"ply":46,"player":"ai","action":25,"playedCard":33,"placeType":"play","drawSource":"discard_0","drawnCard":2,"handsBefore":{"human":[3,11,31,32,52,54,55,59],"ai":[14,19,33,34,35,48,53,57]},"scoresAfter":[-4,-29]},{"ply":47,"player":"human","action":24,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[3,11,31,32,52,54,55,59],"ai":[2,14,19,34,35,48,53,57]},"scoresAfter":[2,-29]},{"ply":48,"player":"ai","action":37,"playedCard":34,"placeType":"play","drawSource":"discard_0","drawnCard":0,"handsBefore":{"human":[3,11,30,32,52,54,55,59],"ai":[2,14,19,34,35,48,53,57]},"scoresAfter":[2,-2]},{"ply":49,"player":"human","action":41,"playedCard":32,"placeType":"play","drawSource":"discard_4","drawnCard":56,"handsBefore":{"human":[3,11,30,32,52,54,55,59],"ai":[0,2,14,19,35,48,53,57]},"scoresAfter":[9,-2]},{"ply":50,"player":"ai","action":18,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[3,11,30,52,54,55,56,59],"ai":[0,2,14,19,35,48,53,57]},"scoresAfter":[9,-2]},{"ply":51,"player":"human","action":65,"playedCard":55,"placeType":"play","drawSource":"discard_4","drawnCard":50,"handsBefore":{"human":[3,11,30,52,54,55,56,59],"ai":[0,12,14,19,35,48,53,57]},"scoresAfter":[-5,-2]},{"ply":52,"player":"ai","action":48,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[3,11,30,50,52,54,56,59],"ai":[0,12,14,19,35,48,53,57]},"scoresAfter":[-5,28]},{"ply":53,"player":"human","action":77,"playedCard":56,"placeType":"play","drawSource":"discard_4","drawnCard":49,"handsBefore":{"human":[3,11,30,50,52,54,56,59],"ai":[0,12,14,19,37,48,53,57]},"scoresAfter":[2,28]},{"ply":54,"player":"ai","action":42,"playedCard":19,"placeType":"discard","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[3,11,30,49,50,52,54,59],"ai":[0,12,14,19,37,48,53,57]},"scoresAfter":[2,28]},{"ply":55,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[3,11,30,49,50,52,54,59],"ai":[0,12,14,26,37,48,53,57]},"scoresAfter":[12,28]}],"finalScores":[12,28],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[44,4,24,50,23,49,16,27,35,51,45,47,8,15,39,25,38,7,1,20,5,0,36,18,11,40,48,43,58,28,33,31,2,29,13,17,57,6,59,46,32,56,41,9,54,14,21,52,10,55,22,53,3,19,34,30,12,37,26,42],"drawPtr":60,"cardLoc":[2,5,5,1,3,3,3,3,4,4,3,1,2,5,2,4,3,3,4,5,4,3,3,3,4,4,2,4,4,3,1,3,3,4,4,4,3,2,3,4,4,3,1,3,3,4,4,4,2,1,1,4,1,2,1,3,3,2,4,3],"handPublic":[true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,false,true,false,false,false,false,false,false,false],"colTop":[[9,10,7,7,10],[8,7,10,10,9]],"colHandshakes":[[0,0,0,2,0],[0,0,2,0,0]],"colLength":[[5,5,3,5,3],[2,3,7,5,2]],"piles":[[1,2],[13,19],[],[],[]],"toMove":1,"stepCount":55,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"113d4a74-5bce-4331-870e-87c976332e87","seed":"35ot4y","startedAt":"2026-07-14T14:28:04.523Z","finishedAt":"2026-07-14T14:30:36.645Z","initialDeckOrder":[33,10,54,37,26,47,38,21,34,45,20,31,22,53,12,13,6,17,30,58,46,8,35,11,18,7,36,24,3,0,42,1,16,48,39,49,19,25,5,50,14,41,52,29,51,2,59,23,55,56,4,15,44,40,9,43,28,57,32,27],"moves":[{"ply":1,"player":"human","action":48,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[10,21,26,33,37,38,47,54],"ai":[12,13,20,22,31,34,45,53]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":12,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[6,10,21,26,33,38,47,54],"ai":[12,13,20,22,31,34,45,53]},"scoresAfter":[-40,-40]},{"ply":3,"player":"human","action":60,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[6,10,21,26,33,38,47,54],"ai":[12,17,20,22,31,34,45,53]},"scoresAfter":[-60,-40]},{"ply":4,"player":"ai","action":84,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[6,10,21,26,30,33,47,54],"ai":[12,17,20,22,31,34,45,53]},"scoresAfter":[-60,-56]},{"ply":5,"player":"human","action":36,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[6,10,21,26,30,33,47,54],"ai":[12,17,20,22,31,34,45,58]},"scoresAfter":[-100,-56]},{"ply":6,"player":"ai","action":0,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[6,10,21,30,33,46,47,54],"ai":[12,17,20,22,31,34,45,58]},"scoresAfter":[-100,-76]},{"ply":7,"player":"human","action":36,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[6,10,21,30,33,46,47,54],"ai":[8,17,20,22,31,34,45,58]},"scoresAfter":[-90,-76]},{"ply":8,"player":"ai","action":48,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[6,10,21,33,35,46,47,54],"ai":[8,17,20,22,31,34,45,58]},"scoresAfter":[-90,-90]},{"ply":9,"player":"human","action":36,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[6,10,21,33,35,46,47,54],"ai":[8,11,17,20,22,34,45,58]},"scoresAfter":[-74,-90]},{"ply":10,"player":"ai","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[6,10,18,21,35,46,47,54],"ai":[8,11,17,20,22,34,45,58]},"scoresAfter":[-74,-103]},{"ply":11,"player":"human","action":48,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[6,10,18,21,35,46,47,54],"ai":[7,11,17,20,22,34,45,58]},"scoresAfter":[-54,-103]},{"ply":12,"player":"ai","action":60,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[6,10,18,21,36,46,47,54],"ai":[7,11,17,20,22,34,45,58]},"scoresAfter":[-54,-94]},{"ply":13,"player":"human","action":48,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[6,10,18,21,36,46,47,54],"ai":[7,11,17,20,22,24,45,58]},"scoresAfter":[-74,-94]},{"ply":14,"player":"ai","action":66,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[3,6,10,18,21,46,47,54],"ai":[7,11,17,20,22,24,45,58]},"scoresAfter":[-74,-94]},{"ply":15,"player":"human","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[3,6,10,18,21,46,47,54],"ai":[0,7,11,17,20,22,45,58]},"scoresAfter":[-92,-94]},{"ply":16,"player":"ai","action":18,"playedCard":7,"placeType":"discard","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[6,10,18,21,42,46,47,54],"ai":[0,7,11,17,20,22,45,58]},"scoresAfter":[-92,-94]},{"ply":17,"player":"human","action":1,"playedCard":6,"placeType":"play","drawSource":"discard_0","drawnCard":7,"handsBefore":{"human":[6,10,18,21,42,46,47,54],"ai":[0,1,11,17,20,22,45,58]},"scoresAfter":[-87,-94]},{"ply":18,"player":"ai","action":18,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[7,10,18,21,42,46,47,54],"ai":[0,1,11,17,20,22,45,58]},"scoresAfter":[-87,-94]},{"ply":19,"player":"human","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[7,10,18,21,42,46,47,54],"ai":[0,11,16,17,20,22,45,58]},"scoresAfter":[-81,-94]},{"ply":20,"player":"ai","action":12,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[10,18,21,42,46,47,48,54],"ai":[0,11,16,17,20,22,45,58]},"scoresAfter":[-81,-84]},{"ply":21,"player":"human","action":78,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[10,18,21,42,46,47,48,54],"ai":[0,16,17,20,22,39,45,58]},"scoresAfter":[-81,-84]},{"ply":22,"player":"ai","action":83,"playedCard":45,"placeType":"discard","drawSource":"discard_4","drawnCard":48,"handsBefore":{"human":[10,18,21,42,46,47,49,54],"ai":[0,16,17,20,22,39,45,58]},"scoresAfter":[-81,-84]},{"ply":23,"player":"human","action":78,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[10,18,21,42,46,47,49,54],"ai":[0,16,17,20,22,39,48,58]},"scoresAfter":[-81,-84]},{"ply":24,"player":"ai","action":22,"playedCard":16,"placeType":"discard","drawSource":"discard_3","drawnCard":45,"handsBefore":{"human":[10,18,19,21,42,46,47,54],"ai":[0,16,17,20,22,39,48,58]},"scoresAfter":[-81,-84]},{"ply":25,"player":"human","action":50,"playedCard":42,"placeType":"play","drawSource":"discard_1","drawnCard":16,"handsBefore":{"human":[10,18,19,21,42,46,47,54],"ai":[0,17,20,22,39,45,48,58]},"scoresAfter":[-61,-84]},{"ply":26,"player":"ai","action":54,"playedCard":39,"placeType":"discard","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[10,16,18,19,21,46,47,54],"ai":[0,17,20,22,39,45,48,58]},"scoresAfter":[-61,-84]},{"ply":27,"player":"human","action":12,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[10,16,18,19,21,46,47,54],"ai":[0,17,20,22,25,45,48,58]},"scoresAfter":[-78,-84]},{"ply":28,"player":"ai","action":60,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[5,10,18,19,21,46,47,54],"ai":[0,17,20,22,25,45,48,58]},"scoresAfter":[-78,-96]},{"ply":29,"player":"human","action":24,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[5,10,18,19,21,46,47,54],"ai":[0,17,20,22,25,48,50,58]},"scoresAfter":[-73,-96]},{"ply":30,"player":"ai","action":12,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[5,10,14,19,21,46,47,54],"ai":[0,17,20,22,25,48,50,58]},"scoresAfter":[-73,-84]},{"ply":31,"player":"human","action":36,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[5,10,14,19,21,46,47,54],"ai":[0,20,22,25,41,48,50,58]},"scoresAfter":[-67,-84]},{"ply":32,"player":"ai","action":66,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[5,10,14,21,46,47,52,54],"ai":[0,20,22,25,41,48,50,58]},"scoresAfter":[-67,-84]},{"ply":33,"player":"human","action":78,"playedCard":52,"placeType":"discard","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[5,10,14,21,46,47,52,54],"ai":[0,20,22,25,29,41,50,58]},"scoresAfter":[-67,-84]},{"ply":34,"player":"ai","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[5,10,14,21,46,47,51,54],"ai":[0,20,22,25,29,41,50,58]},"scoresAfter":[-67,-84]},{"ply":35,"player":"human","action":30,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[5,10,14,21,46,47,51,54],"ai":[2,20,22,25,29,41,50,58]},"scoresAfter":[-67,-84]},{"ply":36,"player":"ai","action":12,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[5,10,21,46,47,51,54,59],"ai":[2,20,22,25,29,41,50,58]},"scoresAfter":[-67,-63]},{"ply":37,"player":"human","action":24,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[5,10,21,46,47,51,54,59],"ai":[2,22,23,25,29,41,50,58]},"scoresAfter":[-59,-63]},{"ply":38,"player":"ai","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[5,10,46,47,51,54,55,59],"ai":[2,22,23,25,29,41,50,58]},"scoresAfter":[-59,-63]},{"ply":39,"player":"human","action":53,"playedCard":51,"placeType":"play","drawSource":"discard_4","drawnCard":52,"handsBefore":{"human":[5,10,46,47,51,54,55,59],"ai":[22,23,25,29,41,50,56,58]},"scoresAfter":[-77,-63]},{"ply":40,"player":"ai","action":72,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[5,10,46,47,52,54,55,59],"ai":[22,23,25,29,41,50,56,58]},"scoresAfter":[-77,-56]},{"ply":41,"player":"human","action":48,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[5,10,46,47,52,54,55,59],"ai":[4,22,23,25,29,41,50,58]},"scoresAfter":[-74,-56]},{"ply":42,"player":"ai","action":12,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[5,10,15,46,47,54,55,59],"ai":[4,22,23,25,29,41,50,58]},"scoresAfter":[-74,-29]},{"ply":43,"player":"human","action":64,"playedCard":54,"placeType":"play","drawSource":"discard_3","drawnCard":39,"handsBefore":{"human":[5,10,15,46,47,54,55,59],"ai":[4,23,25,29,41,44,50,58]},"scoresAfter":[-69,-29]},{"ply":44,"player":"ai","action":12,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[5,10,15,39,46,47,55,59],"ai":[4,23,25,29,41,44,50,58]},"scoresAfter":[-69,1]},{"ply":45,"player":"human","action":77,"playedCard":55,"placeType":"play","drawSource":"discard_4","drawnCard":48,"handsBefore":{"human":[5,10,15,39,46,47,55,59],"ai":[4,25,29,40,41,44,50,58]},"scoresAfter":[-63,1]},{"ply":46,"player":"ai","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[5,10,15,39,46,47,48,59],"ai":[4,25,29,40,41,44,50,58]},"scoresAfter":[-63,10]},{"ply":47,"player":"human","action":17,"playedCard":10,"placeType":"play","drawSource":"discard_4","drawnCard":49,"handsBefore":{"human":[5,10,15,39,46,47,48,59],"ai":[4,9,25,29,40,41,44,50]},"scoresAfter":[-54,10]},{"ply":48,"player":"ai","action":30,"playedCard":25,"placeType":"discard","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[5,15,39,46,47,48,49,59],"ai":[4,9,25,29,40,41,44,50]},"scoresAfter":[-54,10]},{"ply":49,"player":"human","action":36,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[5,15,39,46,47,48,49,59],"ai":[4,9,29,40,41,43,44,50]},"scoresAfter":[-18,10]},{"ply":50,"player":"ai","action":18,"playedCard":9,"placeType":"discard","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[5,15,28,39,47,48,49,59],"ai":[4,9,29,40,41,43,44,50]},"scoresAfter":[-18,10]},{"ply":51,"player":"human","action":49,"playedCard":47,"placeType":"play","drawSource":"discard_0","drawnCard":9,"handsBefore":{"human":[5,15,28,39,47,48,49,59],"ai":[4,29,40,41,43,44,50,57]},"scoresAfter":[22,10]},{"ply":52,"player":"ai","action":6,"playedCard":4,"placeType":"discard","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[5,9,15,28,39,48,49,59],"ai":[4,29,40,41,43,44,50,57]},"scoresAfter":[22,10]},{"ply":53,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[5,9,15,28,39,48,49,59],"ai":[29,32,40,41,43,44,50,57]},"scoresAfter":[32,10]}],"finalScores":[32,10],"outcome":"YOU WIN","finalState":{"deckOrder":[33,10,54,37,26,47,38,21,34,45,20,31,22,53,12,13,6,17,30,58,46,8,35,11,18,7,36,24,3,0,42,1,16,48,39,49,19,25,5,50,14,41,52,29,51,2,59,23,55,56,4,15,44,40,9,43,28,57,32,27],"drawPtr":60,"cardLoc":[5,5,5,3,5,1,3,3,4,1,3,4,4,4,5,1,3,4,3,3,4,3,4,4,5,5,3,1,1,2,3,4,2,3,4,3,3,3,3,1,2,2,3,2,2,4,3,3,1,1,2,3,3,4,3,3,4,2,4,3],"handPublic":[false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,true,true,false,false,false,false,false,false,false,false,false,false],"colTop":[[9,8,10,10,10],[10,10,9,8,9]],"colHandshakes":[[0,0,1,3,0],[0,2,0,0,0]],"colLength":[[4,4,4,6,5],[2,6,2,1,3]],"piles":[[1,0,2,4],[14],[24,25],[],[]],"toMove":1,"stepCount":53,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"49b9cce2-9a8a-4322-9da0-85501156f3f0","seed":"ggiakb","startedAt":"2026-07-14T14:30:37.618Z","finishedAt":"2026-07-14T14:32:28.736Z","initialDeckOrder":[40,51,25,59,0,15,55,45,56,57,11,54,41,10,7,37,32,34,30,58,14,24,23,6,2,52,48,38,28,4,1,44,5,12,31,19,18,9,53,16,50,29,22,3,8,46,36,42,43,21,39,20,17,35,13,47,27,33,26,49],"moves":[{"ply":1,"player":"human","action":60,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[0,15,25,40,45,51,55,59],"ai":[7,10,11,37,41,54,56,57]},"scoresAfter":[-18,0]},{"ply":2,"player":"ai","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[0,15,25,32,40,45,55,59],"ai":[7,10,11,37,41,54,56,57]},"scoresAfter":[-18,-14]},{"ply":3,"player":"human","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[0,15,25,32,40,45,55,59],"ai":[10,11,34,37,41,54,56,57]},"scoresAfter":[-18,-14]},{"ply":4,"player":"ai","action":60,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[15,25,30,32,40,45,55,59],"ai":[10,11,34,37,41,54,56,57]},"scoresAfter":[-18,-29]},{"ply":5,"player":"human","action":12,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[15,25,30,32,40,45,55,59],"ai":[10,11,34,37,41,56,57,58]},"scoresAfter":[-58,-29]},{"ply":6,"player":"ai","action":60,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[14,15,30,32,40,45,55,59],"ai":[10,11,34,37,41,56,57,58]},"scoresAfter":[-58,-22]},{"ply":7,"player":"human","action":6,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[14,15,30,32,40,45,55,59],"ai":[10,11,24,34,37,41,57,58]},"scoresAfter":[-58,-22]},{"ply":8,"player":"ai","action":72,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[15,23,30,32,40,45,55,59],"ai":[10,11,24,34,37,41,57,58]},"scoresAfter":[-58,-14]},{"ply":9,"player":"human","action":48,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[15,23,30,32,40,45,55,59],"ai":[6,10,11,24,34,37,41,58]},"scoresAfter":[-75,-14]},{"ply":10,"player":"ai","action":72,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[2,15,23,30,32,45,55,59],"ai":[6,10,11,24,34,37,41,58]},"scoresAfter":[-75,-30]},{"ply":11,"player":"human","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[2,15,23,30,32,45,55,59],"ai":[6,10,11,24,34,37,52,58]},"scoresAfter":[-75,-30]},{"ply":12,"player":"ai","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[15,23,30,32,45,48,55,59],"ai":[6,10,11,24,34,37,52,58]},"scoresAfter":[-75,-21]},{"ply":13,"player":"human","action":66,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[15,23,30,32,45,48,55,59],"ai":[6,10,11,24,34,37,38,52]},"scoresAfter":[-75,-21]},{"ply":14,"player":"ai","action":90,"playedCard":52,"placeType":"discard","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[15,23,28,30,32,45,55,59],"ai":[6,10,11,24,34,37,38,52]},"scoresAfter":[-75,-21]},{"ply":15,"player":"human","action":24,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[15,23,28,30,32,45,55,59],"ai":[4,6,10,11,24,34,37,38]},"scoresAfter":[-69,-21]},{"ply":16,"player":"ai","action":66,"playedCard":34,"placeType":"discard","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[1,15,23,30,32,45,55,59],"ai":[4,6,10,11,24,34,37,38]},"scoresAfter":[-69,-21]},{"ply":17,"player":"human","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[1,15,23,30,32,45,55,59],"ai":[4,6,10,11,24,37,38,44]},"scoresAfter":[-69,-21]},{"ply":18,"player":"ai","action":9,"playedCard":4,"placeType":"discard","drawSource":"discard_2","drawnCard":34,"handsBefore":{"human":[5,15,23,30,32,45,55,59],"ai":[4,6,10,11,24,37,38,44]},"scoresAfter":[-69,-21]},{"ply":19,"player":"human","action":6,"playedCard":5,"placeType":"discard","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[5,15,23,30,32,45,55,59],"ai":[6,10,11,24,34,37,38,44]},"scoresAfter":[-69,-21]},{"ply":20,"player":"ai","action":66,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[12,15,23,30,32,45,55,59],"ai":[6,10,11,24,34,37,38,44]},"scoresAfter":[-69,-21]},{"ply":21,"player":"human","action":36,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[12,15,23,30,32,45,55,59],"ai":[6,10,11,24,31,34,38,44]},"scoresAfter":[-59,-21]},{"ply":22,"player":"ai","action":36,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[12,15,19,23,32,45,55,59],"ai":[6,10,11,24,31,34,38,44]},"scoresAfter":[-59,-61]},{"ply":23,"player":"human","action":2,"playedCard":12,"placeType":"play","drawSource":"discard_1","drawnCard":14,"handsBefore":{"human":[12,15,19,23,32,45,55,59],"ai":[6,10,11,18,31,34,38,44]},"scoresAfter":[-99,-61]},{"ply":24,"player":"ai","action":12,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[14,15,19,23,32,45,55,59],"ai":[6,10,11,18,31,34,38,44]},"scoresAfter":[-99,-52]},{"ply":25,"player":"human","action":0,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[14,15,19,23,32,45,55,59],"ai":[6,9,11,18,31,34,38,44]},"scoresAfter":[-119,-52]},{"ply":26,"player":"ai","action":6,"playedCard":6,"placeType":"discard","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[15,19,23,32,45,53,55,59],"ai":[6,9,11,18,31,34,38,44]},"scoresAfter":[-119,-52]},{"ply":27,"player":"human","action":0,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[15,19,23,32,45,53,55,59],"ai":[9,11,16,18,31,34,38,44]},"scoresAfter":[-113,-52]},{"ply":28,"player":"ai","action":24,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[19,23,32,45,50,53,55,59],"ai":[9,11,16,18,31,34,38,44]},"scoresAfter":[-113,-69]},{"ply":29,"player":"human","action":29,"playedCard":32,"placeType":"play","drawSource":"discard_4","drawnCard":52,"handsBefore":{"human":[19,23,32,45,50,53,55,59],"ai":[9,11,18,29,31,34,38,44]},"scoresAfter":[-99,-69]},{"ply":30,"player":"ai","action":84,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[19,23,45,50,52,53,55,59],"ai":[9,11,18,29,31,34,38,44]},"scoresAfter":[-99,-62]},{"ply":31,"player":"human","action":48,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[19,23,45,50,52,53,55,59],"ai":[9,11,18,22,29,31,34,38]},"scoresAfter":[-96,-62]},{"ply":32,"player":"ai","action":12,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[3,19,23,45,50,53,55,59],"ai":[9,11,18,22,29,31,34,38]},"scoresAfter":[-96,-52]},{"ply":33,"player":"human","action":60,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[3,19,23,45,50,53,55,59],"ai":[8,9,18,22,29,31,34,38]},"scoresAfter":[-92,-52]},{"ply":34,"player":"ai","action":24,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[3,19,23,45,46,50,55,59],"ai":[8,9,18,22,29,31,34,38]},"scoresAfter":[-92,-47]},{"ply":35,"player":"human","action":72,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[3,19,23,45,46,50,55,59],"ai":[8,9,22,29,31,34,36,38]},"scoresAfter":[-86,-47]},{"ply":36,"player":"ai","action":24,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[3,19,23,42,45,46,50,59],"ai":[8,9,22,29,31,34,36,38]},"scoresAfter":[-86,-38]},{"ply":37,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[3,19,23,42,45,46,50,59],"ai":[8,9,29,31,34,36,38,43]},"scoresAfter":[-76,-38]},{"ply":38,"player":"ai","action":24,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[3,19,21,23,42,45,46,50],"ai":[8,9,29,31,34,36,38,43]},"scoresAfter":[-76,-30]},{"ply":39,"player":"human","action":48,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[3,19,21,23,42,45,46,50],"ai":[8,9,31,34,36,38,39,43]},"scoresAfter":[-71,-30]},{"ply":40,"player":"ai","action":66,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[3,19,20,21,23,45,46,50],"ai":[8,9,31,34,36,38,39,43]},"scoresAfter":[-71,-30]},{"ply":41,"player":"human","action":16,"playedCard":19,"placeType":"play","drawSource":"discard_3","drawnCard":38,"handsBefore":{"human":[3,19,20,21,23,45,46,50],"ai":[8,9,17,31,34,36,39,43]},"scoresAfter":[-53,-30]},{"ply":42,"player":"ai","action":6,"playedCard":8,"placeType":"discard","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[3,20,21,23,38,45,46,50],"ai":[8,9,17,31,34,36,39,43]},"scoresAfter":[-53,-30]},{"ply":43,"player":"human","action":13,"playedCard":20,"placeType":"play","drawSource":"discard_0","drawnCard":8,"handsBefore":{"human":[3,20,21,23,38,45,46,50],"ai":[9,17,31,34,35,36,39,43]},"scoresAfter":[-32,-30]},{"ply":44,"player":"ai","action":24,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[3,8,21,23,38,45,46,50],"ai":[9,17,31,34,35,36,39,43]},"scoresAfter":[-32,-18]},{"ply":45,"player":"human","action":24,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[3,8,21,23,38,45,46,50],"ai":[9,13,17,34,35,36,39,43]},"scoresAfter":[-8,-18]},{"ply":46,"player":"ai","action":36,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[3,8,23,38,45,46,47,50],"ai":[9,13,17,34,35,36,39,43]},"scoresAfter":[-8,0]},{"ply":47,"player":"human","action":29,"playedCard":23,"placeType":"play","drawSource":"discard_4","drawnCard":48,"handsBefore":{"human":[3,8,23,38,45,46,47,50],"ai":[9,13,17,27,35,36,39,43]},"scoresAfter":[22,0]},{"ply":48,"player":"ai","action":48,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[3,8,38,45,46,47,48,50],"ai":[9,13,17,27,35,36,39,43]},"scoresAfter":[22,20]},{"ply":49,"player":"human","action":37,"playedCard":45,"placeType":"play","drawSource":"discard_0","drawnCard":6,"handsBefore":{"human":[3,8,38,45,46,47,48,50],"ai":[9,13,17,27,33,36,39,43]},"scoresAfter":[30,20]},{"ply":50,"player":"ai","action":6,"playedCard":9,"placeType":"discard","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[3,6,8,38,46,47,48,50],"ai":[9,13,17,27,33,36,39,43]},"scoresAfter":[30,20]},{"ply":51,"player":"human","action":52,"playedCard":46,"placeType":"play","drawSource":"discard_3","drawnCard":37,"handsBefore":{"human":[3,6,8,38,46,47,48,50],"ai":[13,17,26,27,33,36,39,43]},"scoresAfter":[39,20]},{"ply":52,"player":"ai","action":6,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[3,6,8,37,38,47,48,50],"ai":[13,17,26,27,33,36,39,43]},"scoresAfter":[39,20]}],"finalScores":[39,20],"outcome":"YOU WIN","finalState":{"deckOrder":[40,51,25,59,0,15,55,45,56,57,11,54,41,10,7,37,32,34,30,58,14,24,23,6,2,52,48,38,28,4,1,44,5,12,31,19,18,9,53,16,50,29,22,3,8,46,36,42,43,21,39,20,17,35,13,47,27,33,26,49],"drawPtr":60,"cardLoc":[5,5,5,1,5,5,1,4,1,5,4,4,3,5,3,3,4,2,4,3,3,3,4,3,4,3,2,2,3,4,3,4,3,2,4,4,2,1,1,2,3,4,3,2,4,3,3,1,1,2,1,3,3,3,4,3,4,4,4,3],"handPublic":[false,false,false,false,false,false,true,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[0,10,7,9,10],[10,9,10,7,9]],"colHandshakes":[[0,2,1,0,0],[0,0,1,0,0]],"colLength":[[0,7,4,4,5],[3,3,5,2,4]],"piles":[[0,2,1,4,5,9],[13],[],[],[]],"toMove":0,"stepCount":52,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"7c4f45cf-5233-4f91-be25-574d947a2df0","seed":"nmjxc1","startedAt":"2026-07-14T14:32:29.588Z","finishedAt":"2026-07-14T14:34:33.607Z","initialDeckOrder":[56,42,10,20,4,2,19,8,47,16,3,29,40,36,22,55,46,57,41,17,52,7,18,27,31,45,58,34,9,39,48,59,24,54,13,51,49,15,12,25,23,26,43,30,37,35,14,28,33,32,38,1,5,53,11,44,21,6,0,50],"moves":[{"ply":1,"player":"human","action":0,"playedCard":2,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[2,4,8,10,19,20,42,56],"ai":[3,16,22,29,36,40,47,55]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":84,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[4,8,10,19,20,42,46,56],"ai":[3,16,22,29,36,40,47,55]},"scoresAfter":[-40,-14]},{"ply":3,"player":"human","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[4,8,10,19,20,42,46,56],"ai":[3,16,22,29,36,40,47,57]},"scoresAfter":[-34,-14]},{"ply":4,"player":"ai","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[8,10,19,20,41,42,46,56],"ai":[3,16,22,29,36,40,47,57]},"scoresAfter":[-34,-32]},{"ply":5,"player":"human","action":48,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[8,10,19,20,41,42,46,56],"ai":[16,17,22,29,36,40,47,57]},"scoresAfter":[-50,-32]},{"ply":6,"player":"ai","action":84,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[8,10,19,20,42,46,52,56],"ai":[16,17,22,29,36,40,47,57]},"scoresAfter":[-50,-24]},{"ply":7,"player":"human","action":48,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[8,10,19,20,42,46,52,56],"ai":[7,16,17,22,29,36,40,47]},"scoresAfter":[-45,-24]},{"ply":8,"player":"ai","action":60,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[8,10,18,19,20,46,52,56],"ai":[7,16,17,22,29,36,40,47]},"scoresAfter":[-45,-64]},{"ply":9,"player":"human","action":78,"playedCard":52,"placeType":"discard","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[8,10,18,19,20,46,52,56],"ai":[7,16,17,22,27,29,40,47]},"scoresAfter":[-45,-64]},{"ply":10,"player":"ai","action":48,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[8,10,18,19,20,31,46,56],"ai":[7,16,17,22,27,29,40,47]},"scoresAfter":[-45,-82]},{"ply":11,"player":"human","action":90,"playedCard":56,"placeType":"discard","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[8,10,18,19,20,31,46,56],"ai":[7,16,17,22,29,40,45,47]},"scoresAfter":[-45,-82]},{"ply":12,"player":"ai","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[8,10,18,19,20,31,46,58],"ai":[7,16,17,22,29,40,45,47]},"scoresAfter":[-45,-76]},{"ply":13,"player":"human","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[8,10,18,19,20,31,46,58],"ai":[16,17,22,29,34,40,45,47]},"scoresAfter":[-31,-76]},{"ply":14,"player":"ai","action":0,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[9,10,18,19,20,31,46,58],"ai":[16,17,22,29,34,40,45,47]},"scoresAfter":[-31,-93]},{"ply":15,"player":"human","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[9,10,18,19,20,31,46,58],"ai":[17,22,29,34,39,40,45,47]},"scoresAfter":[-15,-93]},{"ply":16,"player":"ai","action":0,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[10,18,19,20,31,46,48,58],"ai":[17,22,29,34,39,40,45,47]},"scoresAfter":[-15,-89]},{"ply":17,"player":"human","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[10,18,19,20,31,46,48,58],"ai":[22,29,34,39,40,45,47,59]},"scoresAfter":[3,-89]},{"ply":18,"player":"ai","action":0,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[18,19,20,24,31,46,48,58],"ai":[22,29,34,39,40,45,47,59]},"scoresAfter":[3,-80]},{"ply":19,"player":"human","action":78,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[18,19,20,24,31,46,48,58],"ai":[29,34,39,40,45,47,54,59]},"scoresAfter":[3,-80]},{"ply":20,"player":"ai","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[13,18,19,20,24,31,46,58],"ai":[29,34,39,40,45,47,54,59]},"scoresAfter":[3,-70]},{"ply":21,"player":"human","action":54,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[13,18,19,20,24,31,46,58],"ai":[29,34,39,40,45,47,51,54]},"scoresAfter":[3,-70]},{"ply":22,"player":"ai","action":78,"playedCard":51,"placeType":"discard","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[13,18,19,20,31,46,49,58],"ai":[29,34,39,40,45,47,51,54]},"scoresAfter":[3,-70]},{"ply":23,"player":"human","action":78,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[13,18,19,20,31,46,49,58],"ai":[15,29,34,39,40,45,47,54]},"scoresAfter":[3,-70]},{"ply":24,"player":"ai","action":36,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[12,13,18,19,20,31,46,58],"ai":[15,29,34,39,40,45,47,54]},"scoresAfter":[3,-66]},{"ply":25,"player":"human","action":90,"playedCard":58,"placeType":"discard","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[12,13,18,19,20,31,46,58],"ai":[15,25,29,34,40,45,47,54]},"scoresAfter":[3,-66]},{"ply":26,"player":"ai","action":6,"playedCard":15,"placeType":"discard","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[12,13,18,19,20,23,31,46],"ai":[15,25,29,34,40,45,47,54]},"scoresAfter":[3,-66]},{"ply":27,"player":"human","action":2,"playedCard":12,"placeType":"play","drawSource":"discard_1","drawnCard":15,"handsBefore":{"human":[12,13,18,19,20,23,31,46],"ai":[25,26,29,34,40,45,47,54]},"scoresAfter":[-37,-66]},{"ply":28,"player":"ai","action":24,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[13,15,18,19,20,23,31,46],"ai":[25,26,29,34,40,45,47,54]},"scoresAfter":[-37,-62]},{"ply":29,"player":"human","action":0,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[13,15,18,19,20,23,31,46],"ai":[25,26,34,40,43,45,47,54]},"scoresAfter":[-57,-62]},{"ply":30,"player":"ai","action":24,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[15,18,19,20,23,30,31,46],"ai":[25,26,34,40,43,45,47,54]},"scoresAfter":[-57,-53]},{"ply":31,"player":"human","action":0,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[15,18,19,20,23,30,31,46],"ai":[25,26,37,40,43,45,47,54]},"scoresAfter":[-51,-53]},{"ply":32,"player":"ai","action":18,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[18,19,20,23,30,31,35,46],"ai":[25,26,37,40,43,45,47,54]},"scoresAfter":[-51,-53]},{"ply":33,"player":"human","action":0,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[18,19,20,23,30,31,35,46],"ai":[14,25,37,40,43,45,47,54]},"scoresAfter":[-36,-53]},{"ply":34,"player":"ai","action":36,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[19,20,23,28,30,31,35,46],"ai":[14,25,37,40,43,45,47,54]},"scoresAfter":[-36,-47]},{"ply":35,"player":"human","action":0,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[19,20,23,28,30,31,35,46],"ai":[14,25,33,37,43,45,47,54]},"scoresAfter":[-18,-47]},{"ply":36,"player":"ai","action":30,"playedCard":33,"placeType":"discard","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[20,23,28,30,31,32,35,46],"ai":[14,25,33,37,43,45,47,54]},"scoresAfter":[-18,-47]},{"ply":37,"player":"human","action":3,"playedCard":20,"placeType":"play","drawSource":"discard_2","drawnCard":33,"handsBefore":{"human":[20,23,28,30,31,32,35,46],"ai":[14,25,37,38,43,45,47,54]},"scoresAfter":[3,-47]},{"ply":38,"player":"ai","action":30,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[23,28,30,31,32,33,35,46],"ai":[14,25,37,38,43,45,47,54]},"scoresAfter":[3,-47]},{"ply":39,"player":"human","action":3,"playedCard":23,"placeType":"play","drawSource":"discard_2","drawnCard":26,"handsBefore":{"human":[23,28,30,31,32,33,35,46],"ai":[1,14,25,38,43,45,47,54]},"scoresAfter":[33,-47]},{"ply":40,"player":"ai","action":48,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[26,28,30,31,32,33,35,46],"ai":[1,14,25,38,43,45,47,54]},"scoresAfter":[33,-35]},{"ply":41,"player":"human","action":5,"playedCard":26,"placeType":"play","drawSource":"discard_4","drawnCard":58,"handsBefore":{"human":[26,28,30,31,32,33,35,46],"ai":[1,5,14,25,38,45,47,54]},"scoresAfter":[-7,-35]},{"ply":42,"player":"ai","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[28,30,31,32,33,35,46,58],"ai":[1,5,14,25,38,45,47,54]},"scoresAfter":[-7,-35]},{"ply":43,"player":"human","action":5,"playedCard":28,"placeType":"play","drawSource":"discard_4","drawnCard":49,"handsBefore":{"human":[28,30,31,32,33,35,46,58],"ai":[5,14,25,38,45,47,53,54]},"scoresAfter":[-1,-35]},{"ply":44,"player":"ai","action":48,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[30,31,32,33,35,46,49,58],"ai":[5,14,25,38,45,47,53,54]},"scoresAfter":[-1,-19]},{"ply":45,"player":"human","action":5,"playedCard":30,"placeType":"play","drawSource":"discard_4","drawnCard":51,"handsBefore":{"human":[30,31,32,33,35,46,49,58],"ai":[5,11,14,25,38,47,53,54]},"scoresAfter":[9,-19]},{"ply":46,"player":"ai","action":12,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[31,32,33,35,46,49,51,58],"ai":[5,11,14,25,38,47,53,54]},"scoresAfter":[9,-9]},{"ply":47,"player":"human","action":5,"playedCard":31,"placeType":"play","drawSource":"discard_4","drawnCard":48,"handsBefore":{"human":[31,32,33,35,46,49,51,58],"ai":[5,14,25,38,44,47,53,54]},"scoresAfter":[21,-9]},{"ply":48,"player":"ai","action":60,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[32,33,35,46,48,49,51,58],"ai":[5,14,25,38,44,47,53,54]},"scoresAfter":[21,11]},{"ply":49,"player":"human","action":5,"playedCard":32,"placeType":"play","drawSource":"discard_4","drawnCard":56,"handsBefore":{"human":[32,33,35,46,48,49,51,58],"ai":[5,14,21,25,38,44,53,54]},"scoresAfter":[35,11]},{"ply":50,"player":"ai","action":30,"playedCard":21,"placeType":"discard","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[33,35,46,48,49,51,56,58],"ai":[5,14,21,25,38,44,53,54]},"scoresAfter":[35,11]},{"ply":51,"player":"human","action":5,"playedCard":33,"placeType":"play","drawSource":"discard_4","drawnCard":52,"handsBefore":{"human":[33,35,46,48,49,51,56,58],"ai":[5,6,14,25,38,44,53,54]},"scoresAfter":[51,11]},{"ply":52,"player":"ai","action":54,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[35,46,48,49,51,52,56,58],"ai":[5,6,14,25,38,44,53,54]},"scoresAfter":[51,11]},{"ply":53,"player":"human","action":0,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[35,46,48,49,51,52,56,58],"ai":[0,5,6,14,25,44,53,54]},"scoresAfter":[71,11]}],"finalScores":[71,11],"outcome":"YOU WIN","finalState":{"deckOrder":[56,42,10,20,4,2,19,8,47,16,3,29,40,36,22,55,46,57,41,17,52,7,18,27,31,45,58,34,9,39,48,59,24,54,13,51,49,15,12,25,23,26,43,30,37,35,14,28,33,32,38,1,5,53,11,44,21,6,0,50],"drawPtr":60,"cardLoc":[2,5,3,4,3,2,2,4,3,3,3,4,3,3,2,3,4,4,3,3,3,5,4,3,5,2,3,4,3,4,3,3,3,3,4,3,4,5,5,4,4,3,3,4,2,4,1,4,1,1,1,1,1,2,2,4,1,4,1,4],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,false,true,true,false,false,false,true,false,true,false],"colTop":[[9,10,10,5,0],[10,9,9,10,10]],"colHandshakes":[[1,2,1,0,0],[0,0,0,1,0]],"colLength":[[5,7,7,2,0],[3,3,3,6,3]],"piles":[[1],[21],[24],[37,38],[]],"toMove":1,"stepCount":53,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"1d3339ba-e3f6-4325-9124-e14cef67e55d","seed":"k1r2x1","startedAt":"2026-07-14T14:34:34.928Z","finishedAt":"2026-07-14T14:36:32.219Z","initialDeckOrder":[4,16,23,13,31,12,1,18,8,58,53,28,40,21,30,39,19,22,9,15,32,44,48,25,26,52,57,11,42,55,5,6,50,20,46,10,43,2,45,33,36,47,51,41,34,49,37,0,17,3,14,24,56,27,35,54,38,59,29,7],"moves":[{"ply":1,"player":"human","action":24,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[1,4,12,13,16,18,23,31],"ai":[8,21,28,30,39,40,53,58]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":54,"playedCard":39,"placeType":"discard","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[1,4,13,16,18,19,23,31],"ai":[8,21,28,30,39,40,53,58]},"scoresAfter":[-40,0]},{"ply":3,"player":"human","action":24,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[1,4,13,16,18,19,23,31],"ai":[8,21,22,28,30,40,53,58]},"scoresAfter":[-60,0]},{"ply":4,"player":"ai","action":60,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[1,4,9,16,18,19,23,31],"ai":[8,21,22,28,30,40,53,58]},"scoresAfter":[-60,-17]},{"ply":5,"player":"human","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[1,4,9,16,18,19,23,31],"ai":[8,15,21,22,28,30,53,58]},"scoresAfter":[-100,-17]},{"ply":6,"player":"ai","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[4,9,16,18,19,23,31,32],"ai":[8,15,21,22,28,30,53,58]},"scoresAfter":[-100,-30]},{"ply":7,"player":"human","action":24,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[4,9,16,18,19,23,31,32],"ai":[15,21,22,28,30,44,53,58]},"scoresAfter":[-91,-30]},{"ply":8,"player":"ai","action":0,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[4,9,18,19,23,31,32,48],"ai":[15,21,22,28,30,44,53,58]},"scoresAfter":[-91,-48]},{"ply":9,"player":"human","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[4,9,18,19,23,31,32,48],"ai":[21,22,25,28,30,44,53,58]},"scoresAfter":[-85,-48]},{"ply":10,"player":"ai","action":4,"playedCard":21,"placeType":"play","drawSource":"discard_3","drawnCard":39,"handsBefore":{"human":[9,18,19,23,26,31,32,48],"ai":[21,22,25,28,30,44,53,58]},"scoresAfter":[-85,-40]},{"ply":11,"player":"human","action":12,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[9,18,19,23,26,31,32,48],"ai":[22,25,28,30,39,44,53,58]},"scoresAfter":[-70,-40]},{"ply":12,"player":"ai","action":0,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[9,19,23,26,31,32,48,52],"ai":[22,25,28,30,39,44,53,58]},"scoresAfter":[-70,-31]},{"ply":13,"player":"human","action":36,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[9,19,23,26,31,32,48,52],"ai":[25,28,30,39,44,53,57,58]},"scoresAfter":[-110,-31]},{"ply":14,"player":"ai","action":0,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[9,11,19,23,31,32,48,52],"ai":[25,28,30,39,44,53,57,58]},"scoresAfter":[-110,-71]},{"ply":15,"player":"human","action":24,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[9,11,19,23,31,32,48,52],"ai":[28,30,39,42,44,53,57,58]},"scoresAfter":[-92,-71]},{"ply":16,"player":"ai","action":36,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[9,11,23,31,32,48,52,55],"ai":[28,30,39,42,44,53,57,58]},"scoresAfter":[-92,-66]},{"ply":17,"player":"human","action":60,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[9,11,23,31,32,48,52,55],"ai":[5,28,30,39,44,53,57,58]},"scoresAfter":[-132,-66]},{"ply":18,"player":"ai","action":48,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[6,9,11,23,31,32,52,55],"ai":[5,28,30,39,44,53,57,58]},"scoresAfter":[-132,-59]},{"ply":19,"player":"human","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[6,9,11,23,31,32,52,55],"ai":[5,28,30,39,50,53,57,58]},"scoresAfter":[-122,-59]},{"ply":20,"player":"ai","action":48,"playedCard":50,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[9,11,20,23,31,32,52,55],"ai":[5,28,30,39,50,53,57,58]},"scoresAfter":[-122,-99]},{"ply":21,"player":"human","action":24,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[9,11,20,23,31,32,52,55],"ai":[5,28,30,39,46,53,57,58]},"scoresAfter":[-101,-99]},{"ply":22,"player":"ai","action":48,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[9,10,11,23,31,32,52,55],"ai":[5,28,30,39,46,53,57,58]},"scoresAfter":[-101,-90]},{"ply":23,"player":"human","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[9,10,11,23,31,32,52,55],"ai":[5,28,30,39,43,53,57,58]},"scoresAfter":[-85,-90]},{"ply":24,"player":"ai","action":6,"playedCard":5,"placeType":"discard","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[2,10,11,23,31,32,52,55],"ai":[5,28,30,39,43,53,57,58]},"scoresAfter":[-85,-90]},{"ply":25,"player":"human","action":12,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[2,10,11,23,31,32,52,55],"ai":[28,30,39,43,45,53,57,58]},"scoresAfter":[-67,-90]},{"ply":26,"player":"ai","action":0,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[2,11,23,31,32,33,52,55],"ai":[28,30,39,43,45,53,57,58]},"scoresAfter":[-67,-84]},{"ply":27,"player":"human","action":12,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[2,11,23,31,32,33,52,55],"ai":[30,36,39,43,45,53,57,58]},"scoresAfter":[-47,-84]},{"ply":28,"player":"ai","action":0,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[2,23,31,32,33,47,52,55],"ai":[30,36,39,43,45,53,57,58]},"scoresAfter":[-47,-74]},{"ply":29,"player":"human","action":24,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[2,23,31,32,33,47,52,55],"ai":[36,39,43,45,51,53,57,58]},"scoresAfter":[-35,-74]},{"ply":30,"player":"ai","action":48,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[2,23,32,33,41,47,52,55],"ai":[36,39,43,45,51,53,57,58]},"scoresAfter":[-35,-70]},{"ply":31,"player":"human","action":24,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[2,23,32,33,41,47,52,55],"ai":[34,36,39,43,45,53,57,58]},"scoresAfter":[-21,-70]},{"ply":32,"player":"ai","action":0,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[2,23,33,41,47,49,52,55],"ai":[34,36,39,43,45,53,57,58]},"scoresAfter":[-21,-52]},{"ply":33,"player":"human","action":24,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[2,23,33,41,47,49,52,55],"ai":[36,37,39,43,45,53,57,58]},"scoresAfter":[-5,-52]},{"ply":34,"player":"ai","action":60,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[0,2,23,41,47,49,52,55],"ai":[36,37,39,43,45,53,57,58]},"scoresAfter":[-5,-44]},{"ply":35,"player":"human","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[0,2,23,41,47,49,52,55],"ai":[17,36,37,39,43,45,57,58]},"scoresAfter":[-5,-44]},{"ply":36,"player":"ai","action":30,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[2,3,23,41,47,49,52,55],"ai":[17,36,37,39,43,45,57,58]},"scoresAfter":[-5,-44]},{"ply":37,"player":"human","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[2,3,23,41,47,49,52,55],"ai":[14,17,36,39,43,45,57,58]},"scoresAfter":[-5,-44]},{"ply":38,"player":"ai","action":54,"playedCard":43,"placeType":"discard","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[3,23,24,41,47,49,52,55],"ai":[14,17,36,39,43,45,57,58]},"scoresAfter":[-5,-44]},{"ply":39,"player":"human","action":72,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[3,23,24,41,47,49,52,55],"ai":[14,17,36,39,45,56,57,58]},"scoresAfter":[1,-44]},{"ply":40,"player":"ai","action":60,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[3,23,24,27,41,47,49,55],"ai":[14,17,36,39,45,56,57,58]},"scoresAfter":[1,-30]},{"ply":41,"player":"human","action":12,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[3,23,24,27,41,47,49,55],"ai":[14,17,35,36,39,45,57,58]},"scoresAfter":[31,-30]},{"ply":42,"player":"ai","action":24,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[3,24,27,41,47,49,54,55],"ai":[14,17,35,36,39,45,57,58]},"scoresAfter":[31,-10]},{"ply":43,"player":"human","action":72,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[3,24,27,41,47,49,54,55],"ai":[14,17,36,38,39,45,57,58]},"scoresAfter":[41,-10]},{"ply":44,"player":"ai","action":73,"playedCard":57,"placeType":"play","drawSource":"discard_0","drawnCard":2,"handsBefore":{"human":[3,24,27,41,47,49,55,59],"ai":[14,17,36,38,39,45,57,58]},"scoresAfter":[41,6]},{"ply":45,"player":"human","action":76,"playedCard":55,"placeType":"play","drawSource":"discard_3","drawnCard":43,"handsBefore":{"human":[3,24,27,41,47,49,55,59],"ai":[2,14,17,36,38,39,45,58]},"scoresAfter":[53,6]},{"ply":46,"player":"ai","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[3,24,27,41,43,47,49,59],"ai":[2,14,17,36,38,39,45,58]},"scoresAfter":[53,24]},{"ply":47,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[3,24,27,41,43,47,49,59],"ai":[2,14,17,29,36,38,39,45]},"scoresAfter":[73,24]}],"finalScores":[73,24],"outcome":"YOU WIN","finalState":{"deckOrder":[4,16,23,13,31,12,1,18,8,58,53,28,40,21,30,39,19,22,9,15,32,44,48,25,26,52,57,11,42,55,5,6,50,20,46,10,43,2,45,33,36,47,51,41,34,49,37,0,17,3,14,24,56,27,35,54,38,59,29,7],"drawPtr":60,"cardLoc":[5,3,2,1,3,5,3,1,4,3,3,3,3,3,2,4,3,2,3,3,3,4,4,3,1,4,3,1,4,2,4,3,3,3,4,4,2,5,2,2,4,1,4,1,4,2,4,1,3,1,4,4,3,4,3,3,4,4,4,3],"handPublic":[false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,10,8,0,10],[7,9,10,9,9]],"colHandshakes":[[1,2,1,0,1],[0,0,1,0,1]],"colLength":[[6,7,4,0,5],[1,3,5,4,6]],"piles":[[5,0],[],[],[37],[]],"toMove":1,"stepCount":47,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"e364fb69-a2b3-4072-981e-b788b79c802e","seed":"mt2404","startedAt":"2026-07-14T14:36:33.437Z","finishedAt":"2026-07-14T14:39:11.657Z","initialDeckOrder":[7,4,57,2,14,49,19,55,37,18,16,48,27,38,36,13,44,17,35,6,31,5,41,26,46,54,11,8,0,15,58,20,59,39,34,21,51,23,12,50,42,32,24,33,56,29,43,30,25,10,22,47,9,40,28,1,52,53,45,3],"moves":[{"ply":1,"player":"human","action":60,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[2,4,7,14,19,49,55,57],"ai":[13,16,18,27,36,37,38,48]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":12,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[2,4,7,14,19,44,55,57],"ai":[13,16,18,27,36,37,38,48]},"scoresAfter":[-40,-17]},{"ply":3,"player":"human","action":0,"playedCard":2,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[2,4,7,14,19,44,55,57],"ai":[13,17,18,27,36,37,38,48]},"scoresAfter":[-80,-17]},{"ply":4,"player":"ai","action":12,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[4,7,14,19,35,44,55,57],"ai":[13,17,18,27,36,37,38,48]},"scoresAfter":[-80,-13]},{"ply":5,"player":"human","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[4,7,14,19,35,44,55,57],"ai":[6,13,18,27,36,37,38,48]},"scoresAfter":[-74,-13]},{"ply":6,"player":"ai","action":78,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[7,14,19,31,35,44,55,57],"ai":[6,13,18,27,36,37,38,48]},"scoresAfter":[-74,-13]},{"ply":7,"player":"human","action":18,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[7,14,19,31,35,44,55,57],"ai":[5,6,13,18,27,36,37,48]},"scoresAfter":[-74,-13]},{"ply":8,"player":"ai","action":78,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[7,19,31,35,41,44,55,57],"ai":[5,6,13,18,27,36,37,48]},"scoresAfter":[-74,-13]},{"ply":9,"player":"human","action":48,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[7,19,31,35,41,44,55,57],"ai":[5,6,13,18,26,27,36,48]},"scoresAfter":[-90,-13]},{"ply":10,"player":"ai","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[7,19,31,35,44,46,55,57],"ai":[5,6,13,18,26,27,36,48]},"scoresAfter":[-90,-29]},{"ply":11,"player":"human","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[7,19,31,35,44,46,55,57],"ai":[6,13,18,26,27,36,48,54]},"scoresAfter":[-78,-29]},{"ply":12,"player":"ai","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[11,19,31,35,44,46,55,57],"ai":[6,13,18,26,27,36,48,54]},"scoresAfter":[-78,-24]},{"ply":13,"player":"human","action":48,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[11,19,31,35,44,46,55,57],"ai":[8,13,18,26,27,36,48,54]},"scoresAfter":[-71,-24]},{"ply":14,"player":"ai","action":78,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[0,11,19,31,35,46,55,57],"ai":[8,13,18,26,27,36,48,54]},"scoresAfter":[-71,-24]},{"ply":15,"player":"human","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[0,11,19,31,35,46,55,57],"ai":[8,13,15,18,26,27,36,54]},"scoresAfter":[-71,-24]},{"ply":16,"player":"ai","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[11,19,31,35,46,55,57,58],"ai":[8,13,15,18,26,27,36,54]},"scoresAfter":[-71,-17]},{"ply":17,"player":"human","action":60,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[11,19,31,35,46,55,57,58],"ai":[13,15,18,20,26,27,36,54]},"scoresAfter":[-59,-17]},{"ply":18,"player":"ai","action":6,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[11,19,31,35,46,57,58,59],"ai":[13,15,18,20,26,27,36,54]},"scoresAfter":[-59,-17]},{"ply":19,"player":"human","action":60,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[11,19,31,35,46,57,58,59],"ai":[15,18,20,26,27,36,39,54]},"scoresAfter":[-43,-17]},{"ply":20,"player":"ai","action":12,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[11,19,31,34,35,46,58,59],"ai":[15,18,20,26,27,36,39,54]},"scoresAfter":[-43,-12]},{"ply":21,"player":"human","action":24,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[11,19,31,34,35,46,58,59],"ai":[15,20,21,26,27,36,39,54]},"scoresAfter":[-57,-12]},{"ply":22,"player":"ai","action":12,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[11,19,34,35,46,51,58,59],"ai":[15,20,21,26,27,36,39,54]},"scoresAfter":[-57,-5]},{"ply":23,"player":"human","action":72,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[11,19,34,35,46,51,58,59],"ai":[15,21,23,26,27,36,39,54]},"scoresAfter":[-39,-5]},{"ply":24,"player":"ai","action":12,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[11,12,19,34,35,46,51,59],"ai":[15,21,23,26,27,36,39,54]},"scoresAfter":[-39,3]},{"ply":25,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[11,12,19,34,35,46,51,59],"ai":[15,23,26,27,36,39,50,54]},"scoresAfter":[-19,3]},{"ply":26,"player":"ai","action":90,"playedCard":54,"placeType":"discard","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[11,12,19,34,35,42,46,51],"ai":[15,23,26,27,36,39,50,54]},"scoresAfter":[-19,3]},{"ply":27,"player":"human","action":36,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[11,12,19,34,35,42,46,51],"ai":[15,23,26,27,32,36,39,50]},"scoresAfter":[-10,3]},{"ply":28,"player":"ai","action":90,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[11,12,19,24,35,42,46,51],"ai":[15,23,26,27,32,36,39,50]},"scoresAfter":[-10,3]},{"ply":29,"player":"human","action":48,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[11,12,19,24,35,42,46,51],"ai":[15,23,26,27,32,33,36,39]},"scoresAfter":[0,3]},{"ply":30,"player":"ai","action":12,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[11,12,19,24,42,46,51,56],"ai":[15,23,26,27,32,33,36,39]},"scoresAfter":[0,13]},{"ply":31,"player":"human","action":30,"playedCard":19,"placeType":"discard","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[11,12,19,24,42,46,51,56],"ai":[15,26,27,29,32,33,36,39]},"scoresAfter":[0,13]},{"ply":32,"player":"ai","action":12,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[11,12,24,42,43,46,51,56],"ai":[15,26,27,29,32,33,36,39]},"scoresAfter":[0,-27]},{"ply":33,"player":"human","action":18,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[11,12,24,42,43,46,51,56],"ai":[15,27,29,30,32,33,36,39]},"scoresAfter":[0,-27]},{"ply":34,"player":"ai","action":12,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[11,24,25,42,43,46,51,56],"ai":[15,27,29,30,32,33,36,39]},"scoresAfter":[0,-23]},{"ply":35,"player":"human","action":30,"playedCard":25,"placeType":"discard","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[11,24,25,42,43,46,51,56],"ai":[10,15,29,30,32,33,36,39]},"scoresAfter":[0,-23]},{"ply":36,"player":"ai","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[11,22,24,42,43,46,51,56],"ai":[10,15,29,30,32,33,36,39]},"scoresAfter":[0,-14]},{"ply":37,"player":"human","action":30,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[11,22,24,42,43,46,51,56],"ai":[15,29,30,32,33,36,39,47]},"scoresAfter":[0,-14]},{"ply":38,"player":"ai","action":12,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[9,11,22,42,43,46,51,56],"ai":[15,29,30,32,33,36,39,47]},"scoresAfter":[0,-6]},{"ply":39,"player":"human","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[9,11,22,42,43,46,51,56],"ai":[15,30,32,33,36,39,40,47]},"scoresAfter":[16,-6]},{"ply":40,"player":"ai","action":13,"playedCard":30,"placeType":"play","drawSource":"discard_0","drawnCard":0,"handsBefore":{"human":[11,22,28,42,43,46,51,56],"ai":[15,30,32,33,36,39,40,47]},"scoresAfter":[16,4]},{"ply":41,"player":"human","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[11,22,28,42,43,46,51,56],"ai":[0,15,32,33,36,39,40,47]},"scoresAfter":[36,4]},{"ply":42,"player":"ai","action":29,"playedCard":32,"placeType":"play","drawSource":"discard_4","drawnCard":50,"handsBefore":{"human":[1,22,28,42,43,46,51,56],"ai":[0,15,32,33,36,39,40,47]},"scoresAfter":[36,18]},{"ply":43,"player":"human","action":30,"playedCard":28,"placeType":"discard","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[1,22,28,42,43,46,51,56],"ai":[0,15,33,36,39,40,47,50]},"scoresAfter":[36,18]},{"ply":44,"player":"ai","action":35,"playedCard":33,"placeType":"discard","drawSource":"discard_4","drawnCard":54,"handsBefore":{"human":[1,22,42,43,46,51,52,56],"ai":[0,15,33,36,39,40,47,50]},"scoresAfter":[36,18]},{"ply":45,"player":"human","action":66,"playedCard":51,"placeType":"discard","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[1,22,42,43,46,51,52,56],"ai":[0,15,36,39,40,47,50,54]},"scoresAfter":[36,18]},{"ply":46,"player":"ai","action":90,"playedCard":54,"placeType":"discard","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[1,22,42,43,46,52,53,56],"ai":[0,15,36,39,40,47,50,54]},"scoresAfter":[36,18]},{"ply":47,"player":"human","action":48,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[1,22,42,43,46,52,53,56],"ai":[0,15,36,39,40,45,47,50]},"scoresAfter":[45,18]}],"finalScores":[45,18],"outcome":"YOU WIN","finalState":{"deckOrder":[7,4,57,2,14,49,19,55,37,18,16,48,27,38,36,13,44,17,35,6,31,5,41,26,46,54,11,8,0,15,58,20,59,39,34,21,51,23,12,50,42,32,24,33,56,29,43,30,25,10,22,47,9,40,28,1,52,53,45,3],"drawPtr":60,"cardLoc":[2,1,3,1,3,4,4,3,4,3,4,3,5,5,5,2,4,4,4,5,4,4,1,4,5,5,4,4,5,4,4,3,4,5,3,3,2,5,5,2,2,3,1,1,3,2,3,2,5,3,2,5,1,1,5,3,1,3,3,3],"handPublic":[true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false],"colTop":[[10,0,10,9,10],[9,10,7,0,0]],"colHandshakes":[[1,0,0,0,1],[0,0,1,0,0]],"colLength":[[5,0,3,3,5],[4,6,5,0,0]],"piles":[[],[14,13,19,12],[25,24,28,33],[38,37],[48,51,54]],"toMove":1,"stepCount":47,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"209e9adb-2392-4ebb-b1d4-b21841a59b16","seed":"mjwfnz","startedAt":"2026-07-14T14:39:12.527Z","finishedAt":"2026-07-14T14:41:20.142Z","initialDeckOrder":[56,22,3,31,58,8,55,39,48,32,57,28,10,29,49,23,44,18,30,12,6,14,0,50,20,54,1,45,33,42,36,38,37,51,35,9,41,5,21,46,52,17,2,53,27,19,16,25,4,24,13,26,40,11,47,43,34,15,7,59],"moves":[{"ply":1,"player":"human","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[3,8,22,31,39,55,56,58],"ai":[10,23,28,29,32,48,49,57]},"scoresAfter":[-18,0]},{"ply":2,"player":"ai","action":24,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[8,22,31,39,44,55,56,58],"ai":[10,23,28,29,32,48,49,57]},"scoresAfter":[-18,-17]},{"ply":3,"player":"human","action":36,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[8,22,31,39,44,55,56,58],"ai":[10,18,23,29,32,48,49,57]},"scoresAfter":[-36,-17]},{"ply":4,"player":"ai","action":36,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[8,22,30,31,44,55,56,58],"ai":[10,18,23,29,32,48,49,57]},"scoresAfter":[-36,-13]},{"ply":5,"player":"human","action":60,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[8,22,30,31,44,55,56,58],"ai":[10,12,18,23,32,48,49,57]},"scoresAfter":[-50,-13]},{"ply":6,"player":"ai","action":48,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[6,8,22,30,31,44,56,58],"ai":[10,12,18,23,32,48,49,57]},"scoresAfter":[-50,-6]},{"ply":7,"player":"human","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[6,8,22,30,31,44,56,58],"ai":[10,12,14,18,23,48,49,57]},"scoresAfter":[-45,-6]},{"ply":8,"player":"ai","action":12,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[0,8,22,30,31,44,56,58],"ai":[10,12,14,18,23,48,49,57]},"scoresAfter":[-45,-46]},{"ply":9,"player":"human","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[0,8,22,30,31,44,56,58],"ai":[10,14,18,23,48,49,50,57]},"scoresAfter":[-45,-46]},{"ply":10,"player":"ai","action":12,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[8,20,22,30,31,44,56,58],"ai":[10,14,18,23,48,49,50,57]},"scoresAfter":[-45,-66]},{"ply":11,"player":"human","action":72,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[8,20,22,30,31,44,56,58],"ai":[10,18,23,48,49,50,54,57]},"scoresAfter":[-38,-66]},{"ply":12,"player":"ai","action":48,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[1,8,20,22,30,31,44,58],"ai":[10,18,23,48,49,50,54,57]},"scoresAfter":[-38,-106]},{"ply":13,"player":"human","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[1,8,20,22,30,31,44,58],"ai":[10,18,23,45,48,50,54,57]},"scoresAfter":[-38,-106]},{"ply":14,"player":"ai","action":48,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[8,20,22,30,31,33,44,58],"ai":[10,18,23,45,48,50,54,57]},"scoresAfter":[-38,-126]},{"ply":15,"player":"human","action":36,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[8,20,22,30,31,33,44,58],"ai":[10,18,23,42,45,50,54,57]},"scoresAfter":[-53,-126]},{"ply":16,"player":"ai","action":36,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[8,20,22,31,33,36,44,58],"ai":[10,18,23,42,45,50,54,57]},"scoresAfter":[-53,-141]},{"ply":17,"player":"human","action":66,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[8,20,22,31,33,36,44,58],"ai":[10,18,23,38,45,50,54,57]},"scoresAfter":[-53,-141]},{"ply":18,"player":"ai","action":48,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[8,20,22,31,33,37,44,58],"ai":[10,18,23,38,45,50,54,57]},"scoresAfter":[-53,-133]},{"ply":19,"player":"human","action":66,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[8,20,22,31,33,37,44,58],"ai":[10,18,23,38,50,51,54,57]},"scoresAfter":[-53,-133]},{"ply":20,"player":"ai","action":48,"playedCard":50,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[8,20,22,31,33,35,44,58],"ai":[10,18,23,38,50,51,54,57]},"scoresAfter":[-53,-153]},{"ply":21,"player":"human","action":36,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[8,20,22,31,33,35,44,58],"ai":[9,10,18,23,38,51,54,57]},"scoresAfter":[-47,-153]},{"ply":22,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[8,20,22,33,35,41,44,58],"ai":[9,10,18,23,38,51,54,57]},"scoresAfter":[-47,-165]},{"ply":23,"player":"human","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[8,20,22,33,35,41,44,58],"ai":[5,10,18,23,38,51,54,57]},"scoresAfter":[-40,-165]},{"ply":24,"player":"ai","action":60,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[20,21,22,33,35,41,44,58],"ai":[5,10,18,23,38,51,54,57]},"scoresAfter":[-40,-157]},{"ply":25,"player":"human","action":36,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[20,21,22,33,35,41,44,58],"ai":[5,10,18,23,38,46,54,57]},"scoresAfter":[-32,-157]},{"ply":26,"player":"ai","action":60,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[20,21,22,35,41,44,52,58],"ai":[5,10,18,23,38,46,54,57]},"scoresAfter":[-32,-148]},{"ply":27,"player":"human","action":48,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[20,21,22,35,41,44,52,58],"ai":[5,10,17,18,23,38,54,57]},"scoresAfter":[-28,-148]},{"ply":28,"player":"ai","action":12,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[2,20,21,22,35,44,52,58],"ai":[5,10,17,18,23,38,54,57]},"scoresAfter":[-28,-139]},{"ply":29,"player":"human","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[2,20,21,22,35,44,52,58],"ai":[5,17,18,23,38,53,54,57]},"scoresAfter":[-28,-139]},{"ply":30,"player":"ai","action":60,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[20,21,22,27,35,44,52,58],"ai":[5,17,18,23,38,53,54,57]},"scoresAfter":[-28,-123]},{"ply":31,"player":"human","action":0,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[20,21,22,27,35,44,52,58],"ai":[5,17,18,19,23,38,54,57]},"scoresAfter":[-41,-123]},{"ply":32,"player":"ai","action":72,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[16,21,22,27,35,44,52,58],"ai":[5,17,18,19,23,38,54,57]},"scoresAfter":[-41,-103]},{"ply":33,"player":"human","action":12,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[16,21,22,27,35,44,52,58],"ai":[5,17,18,19,23,25,38,57]},"scoresAfter":[-33,-103]},{"ply":34,"player":"ai","action":12,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[4,16,22,27,35,44,52,58],"ai":[5,17,18,19,23,25,38,57]},"scoresAfter":[-33,-91]},{"ply":35,"player":"human","action":24,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[4,16,22,27,35,44,52,58],"ai":[5,18,19,23,24,25,38,57]},"scoresAfter":[-24,-91]},{"ply":36,"player":"ai","action":12,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[4,13,16,27,35,44,52,58],"ai":[5,18,19,23,24,25,38,57]},"scoresAfter":[-24,-76]},{"ply":37,"player":"human","action":18,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[4,13,16,27,35,44,52,58],"ai":[5,19,23,24,25,26,38,57]},"scoresAfter":[-24,-76]},{"ply":38,"player":"ai","action":12,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[4,16,27,35,40,44,52,58],"ai":[5,19,23,24,25,26,38,57]},"scoresAfter":[-24,-58]},{"ply":39,"player":"human","action":60,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[4,16,27,35,40,44,52,58],"ai":[5,11,23,24,25,26,38,57]},"scoresAfter":[-17,-58]},{"ply":40,"player":"ai","action":12,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[4,16,27,35,40,47,52,58],"ai":[5,11,23,24,25,26,38,57]},"scoresAfter":[-17,-48]},{"ply":41,"player":"human","action":60,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[4,16,27,35,40,47,52,58],"ai":[5,23,24,25,26,38,43,57]},"scoresAfter":[-7,-48]},{"ply":42,"player":"ai","action":13,"playedCard":23,"placeType":"play","drawSource":"discard_0","drawnCard":2,"handsBefore":{"human":[4,16,27,34,35,40,52,58],"ai":[5,23,24,25,26,38,43,57]},"scoresAfter":[-7,-18]},{"ply":43,"player":"human","action":40,"playedCard":34,"placeType":"play","drawSource":"discard_3","drawnCard":37,"handsBefore":{"human":[4,16,27,34,35,40,52,58],"ai":[2,5,24,25,26,38,43,57]},"scoresAfter":[2,-18]},{"ply":44,"player":"ai","action":58,"playedCard":26,"placeType":"discard","drawSource":"discard_3","drawnCard":36,"handsBefore":{"human":[4,16,27,35,37,40,52,58],"ai":[2,5,24,25,26,38,43,57]},"scoresAfter":[2,-18]},{"ply":45,"player":"human","action":87,"playedCard":58,"placeType":"play","drawSource":"discard_2","drawnCard":26,"handsBefore":{"human":[4,16,27,35,37,40,52,58],"ai":[2,5,24,25,36,38,43,57]},"scoresAfter":[11,-18]},{"ply":46,"player":"ai","action":84,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[4,16,26,27,35,37,40,52],"ai":[2,5,24,25,36,38,43,57]},"scoresAfter":[11,14]},{"ply":47,"player":"human","action":48,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[4,16,26,27,35,37,40,52],"ai":[2,5,15,24,25,36,38,43]},"scoresAfter":[21,14]},{"ply":48,"player":"ai","action":18,"playedCard":5,"placeType":"discard","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[4,7,16,26,27,37,40,52],"ai":[2,5,15,24,25,36,38,43]},"scoresAfter":[21,14]}],"finalScores":[21,14],"outcome":"YOU WIN","finalState":{"deckOrder":[56,22,3,31,58,8,55,39,48,32,57,28,10,29,49,23,44,18,30,12,6,14,0,50,20,54,1,45,33,42,36,38,37,51,35,9,41,5,21,46,52,17,2,53,27,19,16,25,4,24,13,26,40,11,47,43,34,15,7,59],"drawPtr":60,"cardLoc":[5,5,2,3,1,5,3,1,3,4,4,4,4,5,4,2,1,4,4,4,3,3,3,4,2,2,1,1,4,4,3,3,4,3,3,3,2,1,2,3,1,3,4,2,3,4,4,3,4,4,4,4,1,4,4,3,3,4,3,2],"handPublic":[false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[7,9,10,10,9],[10,10,7,9,8]],"colHandshakes":[[0,0,0,0,0],[0,2,0,0,3]],"colLength":[[3,3,5,4,3],[3,6,3,3,7]],"piles":[[0,1,5],[13],[],[],[]],"toMove":0,"stepCount":48,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"eed79824-f17e-4152-b3c2-71427c1ba620","seed":"sv7l7x","startedAt":"2026-07-14T14:41:21.654Z","finishedAt":"2026-07-14T14:44:43.966Z","initialDeckOrder":[20,51,56,16,34,59,25,21,7,44,57,26,52,13,36,29,22,45,0,40,27,15,30,1,39,32,43,12,46,53,31,23,47,14,42,9,37,4,55,3,8,35,54,6,50,58,11,5,48,17,28,33,18,49,19,24,2,38,41,10],"moves":[{"ply":1,"player":"human","action":36,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[16,20,21,25,34,51,56,59],"ai":[7,13,26,29,36,44,52,57]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":24,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[16,20,21,22,34,51,56,59],"ai":[7,13,26,29,36,44,52,57]},"scoresAfter":[-40,-40]},{"ply":3,"player":"human","action":0,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[16,20,21,22,34,51,56,59],"ai":[7,13,29,36,44,45,52,57]},"scoresAfter":[-57,-40]},{"ply":4,"player":"ai","action":36,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[0,20,21,22,34,51,56,59],"ai":[7,13,29,36,44,45,52,57]},"scoresAfter":[-57,-80]},{"ply":5,"player":"human","action":60,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[0,20,21,22,34,51,56,59],"ai":[7,13,29,40,44,45,52,57]},"scoresAfter":[-75,-80]},{"ply":6,"player":"ai","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[0,20,21,22,27,34,56,59],"ai":[7,13,29,40,44,45,52,57]},"scoresAfter":[-75,-94]},{"ply":7,"player":"human","action":48,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[0,20,21,22,27,34,56,59],"ai":[13,15,29,40,44,45,52,57]},"scoresAfter":[-71,-94]},{"ply":8,"player":"ai","action":0,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[0,20,21,22,30,34,56,59],"ai":[13,15,29,40,44,45,52,57]},"scoresAfter":[-71,-134]},{"ply":9,"player":"human","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[0,20,21,22,30,34,56,59],"ai":[1,15,29,40,44,45,52,57]},"scoresAfter":[-71,-134]},{"ply":10,"player":"ai","action":72,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[20,21,22,30,34,39,56,59],"ai":[1,15,29,40,44,45,52,57]},"scoresAfter":[-71,-151]},{"ply":11,"player":"human","action":0,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[20,21,22,30,34,39,56,59],"ai":[1,15,29,32,40,44,45,57]},"scoresAfter":[-64,-151]},{"ply":12,"player":"ai","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[21,22,30,34,39,43,56,59],"ai":[1,15,29,32,40,44,45,57]},"scoresAfter":[-64,-151]},{"ply":13,"player":"human","action":0,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[21,22,30,34,39,43,56,59],"ai":[12,15,29,32,40,44,45,57]},"scoresAfter":[-56,-151]},{"ply":14,"player":"ai","action":84,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[22,30,34,39,43,46,56,59],"ai":[12,15,29,32,40,44,45,57]},"scoresAfter":[-56,-143]},{"ply":15,"player":"human","action":0,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[22,30,34,39,43,46,56,59],"ai":[12,15,29,32,40,44,45,53]},"scoresAfter":[-47,-143]},{"ply":16,"player":"ai","action":12,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[30,31,34,39,43,46,56,59],"ai":[12,15,29,32,40,44,45,53]},"scoresAfter":[-47,-139]},{"ply":17,"player":"human","action":36,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[30,31,34,39,43,46,56,59],"ai":[12,23,29,32,40,44,45,53]},"scoresAfter":[-65,-139]},{"ply":18,"player":"ai","action":12,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[30,31,34,43,46,47,56,59],"ai":[12,23,29,32,40,44,45,53]},"scoresAfter":[-65,-119]},{"ply":19,"player":"human","action":36,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[30,31,34,43,46,47,56,59],"ai":[12,14,29,32,40,44,45,53]},"scoresAfter":[-59,-119]},{"ply":20,"player":"ai","action":6,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[30,31,34,42,46,47,56,59],"ai":[12,14,29,32,40,44,45,53]},"scoresAfter":[-59,-119]},{"ply":21,"player":"human","action":0,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[30,31,34,42,46,47,56,59],"ai":[9,14,29,32,40,44,45,53]},"scoresAfter":[-49,-119]},{"ply":22,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[31,34,37,42,46,47,56,59],"ai":[9,14,29,32,40,44,45,53]},"scoresAfter":[-49,-111]},{"ply":23,"player":"human","action":0,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[31,34,37,42,46,47,56,59],"ai":[4,14,29,32,40,44,45,53]},"scoresAfter":[-37,-111]},{"ply":24,"player":"ai","action":24,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[34,37,42,46,47,55,56,59],"ai":[4,14,29,32,40,44,45,53]},"scoresAfter":[-37,-103]},{"ply":25,"player":"human","action":60,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[34,37,42,46,47,55,56,59],"ai":[3,4,14,32,40,44,45,53]},"scoresAfter":[-31,-103]},{"ply":26,"player":"ai","action":6,"playedCard":3,"placeType":"discard","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[8,34,37,42,46,47,56,59],"ai":[3,4,14,32,40,44,45,53]},"scoresAfter":[-31,-103]},{"ply":27,"player":"human","action":6,"playedCard":8,"placeType":"discard","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[8,34,37,42,46,47,56,59],"ai":[4,14,32,35,40,44,45,53]},"scoresAfter":[-31,-103]},{"ply":28,"player":"ai","action":24,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[34,37,42,46,47,54,56,59],"ai":[4,14,32,35,40,44,45,53]},"scoresAfter":[-31,-89]},{"ply":29,"player":"human","action":66,"playedCard":54,"placeType":"discard","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[34,37,42,46,47,54,56,59],"ai":[4,6,14,35,40,44,45,53]},"scoresAfter":[-31,-89]},{"ply":30,"player":"ai","action":18,"playedCard":6,"placeType":"discard","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[34,37,42,46,47,50,56,59],"ai":[4,6,14,35,40,44,45,53]},"scoresAfter":[-31,-89]},{"ply":31,"player":"human","action":66,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[34,37,42,46,47,50,56,59],"ai":[4,14,35,40,44,45,53,58]},"scoresAfter":[-31,-89]},{"ply":32,"player":"ai","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[11,34,37,42,46,47,56,59],"ai":[4,14,35,40,44,45,53,58]},"scoresAfter":[-31,-80]},{"ply":33,"player":"human","action":72,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[11,34,37,42,46,47,56,59],"ai":[4,5,14,35,40,44,45,53]},"scoresAfter":[-24,-80]},{"ply":34,"player":"ai","action":90,"playedCard":53,"placeType":"discard","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[11,34,37,42,46,47,48,59],"ai":[4,5,14,35,40,44,45,53]},"scoresAfter":[-24,-80]},{"ply":35,"player":"human","action":78,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[11,34,37,42,46,47,48,59],"ai":[4,5,14,17,35,40,44,45]},"scoresAfter":[-24,-80]},{"ply":36,"player":"ai","action":60,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[11,28,34,37,42,46,47,59],"ai":[4,5,14,17,35,40,44,45]},"scoresAfter":[-24,-74]},{"ply":37,"player":"human","action":60,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[11,28,34,37,42,46,47,59],"ai":[4,5,14,17,33,35,44,45]},"scoresAfter":[-15,-74]},{"ply":38,"player":"ai","action":48,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[11,18,28,34,37,42,47,59],"ai":[4,5,14,17,33,35,44,45]},"scoresAfter":[-15,-58]},{"ply":39,"player":"human","action":72,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[11,18,28,34,37,42,47,59],"ai":[4,5,14,17,35,44,45,49]},"scoresAfter":[-5,-58]},{"ply":40,"player":"ai","action":23,"playedCard":5,"placeType":"discard","drawSource":"discard_4","drawnCard":48,"handsBefore":{"human":[11,18,19,28,34,37,42,59],"ai":[4,5,14,17,35,44,45,49]},"scoresAfter":[-5,-58]},{"ply":41,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[11,18,19,28,34,37,42,59],"ai":[4,14,17,35,44,45,48,49]},"scoresAfter":[5,-58]},{"ply":42,"player":"ai","action":36,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[11,18,19,24,28,34,37,42],"ai":[4,14,17,35,44,45,48,49]},"scoresAfter":[5,-38]},{"ply":43,"player":"human","action":60,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[11,18,19,24,28,34,37,42],"ai":[2,4,14,17,44,45,48,49]},"scoresAfter":[23,-38]},{"ply":44,"player":"ai","action":53,"playedCard":44,"placeType":"play","drawSource":"discard_4","drawnCard":53,"handsBefore":{"human":[11,18,19,24,28,37,38,42],"ai":[2,4,14,17,44,45,48,49]},"scoresAfter":[23,-24]},{"ply":45,"player":"human","action":30,"playedCard":19,"placeType":"discard","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[11,18,19,24,28,37,38,42],"ai":[2,4,14,17,45,48,49,53]},"scoresAfter":[23,-24]},{"ply":46,"player":"ai","action":48,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[11,18,24,28,37,38,41,42],"ai":[2,4,14,17,45,48,49,53]},"scoresAfter":[23,-8]}],"finalScores":[23,-8],"outcome":"YOU WIN","finalState":{"deckOrder":[20,51,56,16,34,59,25,21,7,44,57,26,52,13,36,29,22,45,0,40,27,15,30,1,39,32,43,12,46,53,31,23,47,14,42,9,37,4,55,3,8,35,54,6,50,58,11,5,48,17,28,33,18,49,19,24,2,38,41,10],"drawPtr":60,"cardLoc":[5,5,2,5,2,5,5,4,5,4,2,1,5,4,2,4,3,2,1,5,3,3,3,4,1,3,4,3,1,4,3,3,4,4,3,4,4,1,1,3,4,1,1,3,4,4,3,3,2,2,5,3,4,2,5,3,3,4,4,3],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,true,false,false,false,false,false,false],"colTop":[[0,9,9,10,10],[8,10,10,8,9]],"colHandshakes":[[0,0,1,0,0],[0,1,1,1,0]],"colLength":[[0,4,5,4,4],[2,3,5,4,3]],"piles":[[0,1,3,8,6,5],[12,19],[],[],[54,50]],"toMove":0,"stepCount":46,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"fb65ec0f-9beb-4dad-b413-8757200fb423","seed":"qk51y1","startedAt":"2026-07-14T14:44:44.916Z","finishedAt":"2026-07-14T14:47:36.324Z","initialDeckOrder":[23,57,12,56,52,30,43,47,38,21,39,5,28,41,46,14,25,31,22,26,15,27,13,37,19,44,16,32,2,1,54,42,17,48,29,8,18,3,24,49,53,36,9,55,40,34,20,4,33,58,7,59,10,50,6,35,51,0,45,11],"moves":[{"ply":1,"player":"human","action":60,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[12,23,30,43,47,52,56,57],"ai":[5,14,21,28,38,39,41,46]},"scoresAfter":[-17,0]},{"ply":2,"player":"ai","action":18,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[12,23,25,30,43,47,56,57],"ai":[5,14,21,28,38,39,41,46]},"scoresAfter":[-17,0]},{"ply":3,"player":"human","action":0,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[12,23,25,30,43,47,56,57],"ai":[5,21,28,31,38,39,41,46]},"scoresAfter":[-57,0]},{"ply":4,"player":"ai","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[22,23,25,30,43,47,56,57],"ai":[5,21,28,31,38,39,41,46]},"scoresAfter":[-57,-16]},{"ply":5,"player":"human","action":30,"playedCard":25,"placeType":"discard","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[22,23,25,30,43,47,56,57],"ai":[21,26,28,31,38,39,41,46]},"scoresAfter":[-57,-16]},{"ply":6,"player":"ai","action":60,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[15,22,23,30,43,47,56,57],"ai":[21,26,28,31,38,39,41,46]},"scoresAfter":[-57,-34]},{"ply":7,"player":"human","action":42,"playedCard":30,"placeType":"discard","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[15,22,23,30,43,47,56,57],"ai":[21,26,27,28,31,38,41,46]},"scoresAfter":[-57,-34]},{"ply":8,"player":"ai","action":0,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[13,15,22,23,43,47,56,57],"ai":[21,26,27,28,31,38,41,46]},"scoresAfter":[-57,-46]},{"ply":9,"player":"human","action":2,"playedCard":13,"placeType":"play","drawSource":"discard_1","drawnCard":14,"handsBefore":{"human":[13,15,22,23,43,47,56,57],"ai":[26,27,28,31,37,38,41,46]},"scoresAfter":[-77,-46]},{"ply":10,"player":"ai","action":3,"playedCard":26,"placeType":"play","drawSource":"discard_2","drawnCard":30,"handsBefore":{"human":[14,15,22,23,43,47,56,57],"ai":[26,27,28,31,37,38,41,46]},"scoresAfter":[-77,-86]},{"ply":11,"player":"human","action":0,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[14,15,22,23,43,47,56,57],"ai":[27,28,30,31,37,38,41,46]},"scoresAfter":[-97,-86]},{"ply":12,"player":"ai","action":66,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[15,19,22,23,43,47,56,57],"ai":[27,28,30,31,37,38,41,46]},"scoresAfter":[-97,-86]},{"ply":13,"player":"human","action":0,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[15,19,22,23,43,47,56,57],"ai":[27,28,30,31,37,41,44,46]},"scoresAfter":[-89,-86]},{"ply":14,"player":"ai","action":60,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[16,19,22,23,43,47,56,57],"ai":[27,28,30,31,37,41,44,46]},"scoresAfter":[-89,-82]},{"ply":15,"player":"human","action":0,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[16,19,22,23,43,47,56,57],"ai":[27,28,30,31,32,37,44,46]},"scoresAfter":[-77,-82]},{"ply":16,"player":"ai","action":75,"playedCard":44,"placeType":"play","drawSource":"discard_2","drawnCard":25,"handsBefore":{"human":[2,19,22,23,43,47,56,57],"ai":[27,28,30,31,32,37,44,46]},"scoresAfter":[-77,-75]},{"ply":17,"player":"human","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[2,19,22,23,43,47,56,57],"ai":[25,27,28,30,31,32,37,46]},"scoresAfter":[-77,-75]},{"ply":18,"player":"ai","action":84,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[1,19,22,23,43,47,56,57],"ai":[25,27,28,30,31,32,37,46]},"scoresAfter":[-77,-66]},{"ply":19,"player":"human","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[1,19,22,23,43,47,56,57],"ai":[25,27,28,30,31,32,37,54]},"scoresAfter":[-77,-66]},{"ply":20,"player":"ai","action":78,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[19,22,23,42,43,47,56,57],"ai":[25,27,28,30,31,32,37,54]},"scoresAfter":[-77,-66]},{"ply":21,"player":"human","action":72,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[19,22,23,42,43,47,56,57],"ai":[17,25,27,28,30,31,32,54]},"scoresAfter":[-70,-66]},{"ply":22,"player":"ai","action":12,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[19,22,23,42,43,47,48,57],"ai":[17,25,27,28,30,31,32,54]},"scoresAfter":[-70,-86]},{"ply":23,"player":"human","action":78,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[19,22,23,42,43,47,48,57],"ai":[17,27,28,29,30,31,32,54]},"scoresAfter":[-70,-86]},{"ply":24,"player":"ai","action":90,"playedCard":54,"placeType":"discard","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[8,19,22,23,42,43,47,57],"ai":[17,27,28,29,30,31,32,54]},"scoresAfter":[-70,-86]},{"ply":25,"player":"human","action":84,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[8,19,22,23,42,43,47,57],"ai":[17,18,27,28,29,30,31,32]},"scoresAfter":[-62,-86]},{"ply":26,"player":"ai","action":6,"playedCard":17,"placeType":"discard","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[3,8,19,22,23,42,43,47],"ai":[17,18,27,28,29,30,31,32]},"scoresAfter":[-62,-86]},{"ply":27,"player":"human","action":6,"playedCard":3,"placeType":"discard","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[3,8,19,22,23,42,43,47],"ai":[18,24,27,28,29,30,31,32]},"scoresAfter":[-62,-86]},{"ply":28,"player":"ai","action":12,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[8,19,22,23,42,43,47,49],"ai":[18,24,27,28,29,30,31,32]},"scoresAfter":[-62,-106]},{"ply":29,"player":"human","action":90,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[8,19,22,23,42,43,47,49],"ai":[18,27,28,29,30,31,32,53]},"scoresAfter":[-62,-106]},{"ply":30,"player":"ai","action":12,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[8,19,22,23,36,42,43,47],"ai":[18,27,28,29,30,31,32,53]},"scoresAfter":[-62,-98]},{"ply":31,"player":"human","action":52,"playedCard":36,"placeType":"play","drawSource":"discard_3","drawnCard":37,"handsBefore":{"human":[8,19,22,23,36,42,43,47],"ai":[9,18,28,29,30,31,32,53]},"scoresAfter":[-102,-98]},{"ply":32,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[8,19,22,23,37,42,43,47],"ai":[9,18,28,29,30,31,32,53]},"scoresAfter":[-102,-90]},{"ply":33,"player":"human","action":52,"playedCard":37,"placeType":"play","drawSource":"discard_3","drawnCard":38,"handsBefore":{"human":[8,19,22,23,37,42,43,47],"ai":[18,28,29,30,31,32,53,55]},"scoresAfter":[-122,-90]},{"ply":34,"player":"ai","action":72,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[8,19,22,23,38,42,43,47],"ai":[18,28,29,30,31,32,53,55]},"scoresAfter":[-122,-106]},{"ply":35,"player":"human","action":48,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[8,19,22,23,38,42,43,47],"ai":[18,28,29,30,31,32,40,55]},"scoresAfter":[-142,-106]},{"ply":36,"player":"ai","action":12,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[8,19,22,23,34,42,43,47],"ai":[18,28,29,30,31,32,40,55]},"scoresAfter":[-142,-94]},{"ply":37,"player":"human","action":60,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[8,19,22,23,34,42,43,47],"ai":[18,20,29,30,31,32,40,55]},"scoresAfter":[-122,-94]},{"ply":38,"player":"ai","action":24,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[4,8,19,22,23,34,43,47],"ai":[18,20,29,30,31,32,40,55]},"scoresAfter":[-122,-78]},{"ply":39,"player":"human","action":72,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[4,8,19,22,23,34,43,47],"ai":[18,20,30,31,32,33,40,55]},"scoresAfter":[-98,-78]},{"ply":40,"player":"ai","action":84,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[4,8,19,22,23,34,47,58],"ai":[18,20,30,31,32,33,40,55]},"scoresAfter":[-98,-72]},{"ply":41,"player":"human","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[4,8,19,22,23,34,47,58],"ai":[7,18,20,30,31,32,33,40]},"scoresAfter":[-89,-72]},{"ply":42,"player":"ai","action":36,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[4,8,19,22,23,34,47,59],"ai":[7,18,20,30,31,32,33,40]},"scoresAfter":[-89,-52]},{"ply":43,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[4,8,19,22,23,34,47,59],"ai":[7,10,18,20,31,32,33,40]},"scoresAfter":[-79,-52]},{"ply":44,"player":"ai","action":12,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[4,8,19,22,23,34,47,50],"ai":[7,10,18,20,31,32,33,40]},"scoresAfter":[-79,-43]},{"ply":45,"player":"human","action":8,"playedCard":4,"placeType":"discard","drawSource":"discard_1","drawnCard":17,"handsBefore":{"human":[4,8,19,22,23,34,47,50],"ai":[6,7,18,20,31,32,33,40]},"scoresAfter":[-79,-43]},{"ply":46,"player":"ai","action":48,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[8,17,19,22,23,34,47,50],"ai":[6,7,18,20,31,32,33,40]},"scoresAfter":[-79,1]},{"ply":47,"player":"human","action":17,"playedCard":17,"placeType":"play","drawSource":"discard_4","drawnCard":49,"handsBefore":{"human":[8,17,19,22,23,34,47,50],"ai":[6,7,18,20,32,33,35,40]},"scoresAfter":[-63,1]},{"ply":48,"player":"ai","action":48,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[8,19,22,23,34,47,49,50],"ai":[6,7,18,20,32,33,35,40]},"scoresAfter":[-63,29]},{"ply":49,"player":"human","action":65,"playedCard":47,"placeType":"play","drawSource":"discard_4","drawnCard":54,"handsBefore":{"human":[8,19,22,23,34,47,49,50],"ai":[6,7,18,20,33,35,40,51]},"scoresAfter":[-23,29]},{"ply":50,"player":"ai","action":48,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[8,19,22,23,34,49,50,54],"ai":[6,7,18,20,33,35,40,51]},"scoresAfter":[-23,61]},{"ply":51,"player":"human","action":29,"playedCard":22,"placeType":"play","drawSource":"discard_4","drawnCard":48,"handsBefore":{"human":[8,19,22,23,34,49,50,54],"ai":[0,6,7,18,20,35,40,51]},"scoresAfter":[13,61]},{"ply":52,"player":"ai","action":60,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[8,19,23,34,48,49,50,54],"ai":[0,6,7,18,20,35,40,51]},"scoresAfter":[13,101]},{"ply":53,"player":"human","action":24,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[8,19,23,34,48,49,50,54],"ai":[0,6,7,18,20,40,45,51]},"scoresAfter":[73,101]}],"finalScores":[73,101],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[23,57,12,56,52,30,43,47,38,21,39,5,28,41,46,14,25,31,22,26,15,27,13,37,19,44,16,32,2,1,54,42,17,48,29,8,18,3,24,49,53,36,9,55,40,34,20,4,33,58,7,59,10,50,6,35,51,0,45,11],"drawPtr":60,"cardLoc":[2,5,5,5,5,4,2,2,1,4,4,1,3,3,3,3,3,3,2,1,2,4,3,3,4,4,4,4,4,4,4,4,4,4,1,4,3,3,3,4,2,4,3,3,4,2,4,3,1,1,1,2,3,4,1,4,3,3,3,3],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,false,false,false,false,true,false,false,false,false,false],"colTop":[[0,10,0,10,10],[9,8,10,9,6]],"colHandshakes":[[0,3,0,3,0],[0,0,3,0,0]],"colLength":[[0,8,0,6,5],[3,1,11,4,2]],"piles":[[2,1,3,4],[],[],[],[]],"toMove":1,"stepCount":53,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"82fb2b04-6eb2-4d9e-962a-2a08ac4ea190","seed":"t9x9d6","startedAt":"2026-07-14T14:47:37.672Z","finishedAt":"2026-07-14T14:50:26.264Z","initialDeckOrder":[44,29,45,20,53,51,55,2,12,6,37,49,4,35,9,7,33,25,24,15,57,14,46,36,3,34,58,8,59,5,47,21,19,27,26,10,16,54,1,11,17,43,41,42,13,22,0,52,32,40,23,50,39,31,30,38,18,56,48,28],"moves":[{"ply":1,"player":"human","action":60,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[2,20,29,44,45,51,53,55],"ai":[4,6,7,9,12,35,37,49]},"scoresAfter":[-18,0]},{"ply":2,"player":"ai","action":90,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[2,20,29,33,44,45,53,55],"ai":[4,6,7,9,12,35,37,49]},"scoresAfter":[-18,0]},{"ply":3,"player":"human","action":72,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[2,20,29,33,44,45,53,55],"ai":[4,6,7,9,12,25,35,37]},"scoresAfter":[-14,0]},{"ply":4,"player":"ai","action":90,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[2,20,24,29,33,44,45,55],"ai":[4,6,7,9,12,25,35,37]},"scoresAfter":[-14,0]},{"ply":5,"player":"human","action":34,"playedCard":24,"placeType":"discard","drawSource":"discard_3","drawnCard":37,"handsBefore":{"human":[2,20,24,29,33,44,45,55],"ai":[4,6,7,9,12,15,25,35]},"scoresAfter":[-14,0]},{"ply":6,"player":"ai","action":60,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[2,20,29,33,37,44,45,55],"ai":[4,6,7,9,12,15,25,35]},"scoresAfter":[-14,-18]},{"ply":7,"player":"human","action":48,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[2,20,29,33,37,44,45,55],"ai":[4,6,7,9,12,25,35,57]},"scoresAfter":[-54,-18]},{"ply":8,"player":"ai","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[2,14,20,29,33,44,45,55],"ai":[4,6,7,9,12,25,35,57]},"scoresAfter":[-54,-35]},{"ply":9,"player":"human","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[2,14,20,29,33,44,45,55],"ai":[6,7,9,12,25,35,46,57]},"scoresAfter":[-54,-35]},{"ply":10,"player":"ai","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[14,20,29,33,36,44,45,55],"ai":[6,7,9,12,25,35,46,57]},"scoresAfter":[-54,-30]},{"ply":11,"player":"human","action":48,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[14,20,29,33,36,44,45,55],"ai":[3,7,9,12,25,35,46,57]},"scoresAfter":[-74,-30]},{"ply":12,"player":"ai","action":12,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[14,20,29,33,34,44,45,55],"ai":[3,7,9,12,25,35,46,57]},"scoresAfter":[-74,-24]},{"ply":13,"player":"human","action":9,"playedCard":14,"placeType":"discard","drawSource":"discard_2","drawnCard":24,"handsBefore":{"human":[14,20,29,33,34,44,45,55],"ai":[3,9,12,25,35,46,57,58]},"scoresAfter":[-74,-24]},{"ply":14,"player":"ai","action":6,"playedCard":3,"placeType":"discard","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[20,24,29,33,34,44,45,55],"ai":[3,9,12,25,35,46,57,58]},"scoresAfter":[-74,-24]},{"ply":15,"player":"human","action":12,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[20,24,29,33,34,44,45,55],"ai":[8,9,12,25,35,46,57,58]},"scoresAfter":[-114,-24]},{"ply":16,"player":"ai","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[20,29,33,34,44,45,55,59],"ai":[8,9,12,25,35,46,57,58]},"scoresAfter":[-114,-17]},{"ply":17,"player":"human","action":12,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[20,29,33,34,44,45,55,59],"ai":[5,9,12,25,35,46,57,58]},"scoresAfter":[-106,-17]},{"ply":18,"player":"ai","action":72,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[20,33,34,44,45,47,55,59],"ai":[5,9,12,25,35,46,57,58]},"scoresAfter":[-106,-29]},{"ply":19,"player":"human","action":36,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[20,33,34,44,45,47,55,59],"ai":[5,9,12,21,25,35,46,58]},"scoresAfter":[-85,-29]},{"ply":20,"player":"ai","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[19,20,33,34,45,47,55,59],"ai":[5,9,12,21,25,35,46,58]},"scoresAfter":[-85,-20]},{"ply":21,"player":"human","action":48,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[19,20,33,34,45,47,55,59],"ai":[5,9,12,21,25,27,35,46]},"scoresAfter":[-61,-20]},{"ply":22,"player":"ai","action":60,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[19,20,26,33,34,47,55,59],"ai":[5,9,12,21,25,27,35,46]},"scoresAfter":[-61,-38]},{"ply":23,"player":"human","action":72,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[19,20,26,33,34,47,55,59],"ai":[5,9,10,12,21,25,35,46]},"scoresAfter":[-55,-38]},{"ply":24,"player":"ai","action":12,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[16,19,20,26,33,34,47,59],"ai":[5,9,10,12,21,25,35,46]},"scoresAfter":[-55,-30]},{"ply":25,"player":"human","action":42,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[16,19,20,26,33,34,47,59],"ai":[5,10,12,21,25,35,46,54]},"scoresAfter":[-55,-30]},{"ply":26,"player":"ai","action":6,"playedCard":5,"placeType":"discard","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[1,16,19,20,33,34,47,59],"ai":[5,10,12,21,25,35,46,54]},"scoresAfter":[-55,-30]},{"ply":27,"player":"human","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[1,16,19,20,33,34,47,59],"ai":[10,11,12,21,25,35,46,54]},"scoresAfter":[-55,-30]},{"ply":28,"player":"ai","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[16,17,19,20,33,34,47,59],"ai":[10,11,12,21,25,35,46,54]},"scoresAfter":[-55,-21]},{"ply":29,"player":"human","action":74,"playedCard":47,"placeType":"play","drawSource":"discard_1","drawnCard":14,"handsBefore":{"human":[16,17,19,20,33,34,47,59],"ai":[11,12,21,25,35,43,46,54]},"scoresAfter":[-25,-21]},{"ply":30,"player":"ai","action":90,"playedCard":54,"placeType":"discard","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[14,16,17,19,20,33,34,59],"ai":[11,12,21,25,35,43,46,54]},"scoresAfter":[-25,-21]},{"ply":31,"player":"human","action":0,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[14,16,17,19,20,33,34,59],"ai":[11,12,21,25,35,41,43,46]},"scoresAfter":[-65,-21]},{"ply":32,"player":"ai","action":60,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[16,17,19,20,33,34,42,59],"ai":[11,12,21,25,35,41,43,46]},"scoresAfter":[-65,-37]},{"ply":33,"player":"human","action":0,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[16,17,19,20,33,34,42,59],"ai":[11,12,13,21,25,35,43,46]},"scoresAfter":[-59,-37]},{"ply":34,"player":"ai","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[17,19,20,22,33,34,42,59],"ai":[11,12,13,21,25,35,43,46]},"scoresAfter":[-59,-27]},{"ply":35,"player":"human","action":0,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[17,19,20,22,33,34,42,59],"ai":[0,12,13,21,25,35,43,46]},"scoresAfter":[-51,-27]},{"ply":36,"player":"ai","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[19,20,22,33,34,42,52,59],"ai":[0,12,13,21,25,35,43,46]},"scoresAfter":[-51,-27]},{"ply":37,"player":"human","action":78,"playedCard":52,"placeType":"discard","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[19,20,22,33,34,42,52,59],"ai":[12,13,21,25,32,35,43,46]},"scoresAfter":[-51,-27]},{"ply":38,"player":"ai","action":24,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[19,20,22,33,34,40,42,59],"ai":[12,13,21,25,32,35,43,46]},"scoresAfter":[-51,-19]},{"ply":39,"player":"human","action":0,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[19,20,22,33,34,40,42,59],"ai":[12,13,23,25,32,35,43,46]},"scoresAfter":[-39,-19]},{"ply":40,"player":"ai","action":24,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[20,22,33,34,40,42,50,59],"ai":[12,13,23,25,32,35,43,46]},"scoresAfter":[-39,-9]},{"ply":41,"player":"human","action":0,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[20,22,33,34,40,42,50,59],"ai":[12,13,25,32,35,39,43,46]},"scoresAfter":[-25,-9]},{"ply":42,"player":"ai","action":36,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[22,31,33,34,40,42,50,59],"ai":[12,13,25,32,35,39,43,46]},"scoresAfter":[-25,-2]},{"ply":43,"player":"human","action":12,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[22,31,33,34,40,42,50,59],"ai":[12,13,25,30,35,39,43,46]},"scoresAfter":[-13,-2]},{"ply":44,"player":"ai","action":48,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[22,33,34,38,40,42,50,59],"ai":[12,13,25,30,35,39,43,46]},"scoresAfter":[-13,8]},{"ply":45,"player":"human","action":17,"playedCard":33,"placeType":"play","drawSource":"discard_4","drawnCard":52,"handsBefore":{"human":[22,33,34,38,40,42,50,59],"ai":[12,13,18,25,30,39,43,46]},"scoresAfter":[3,8]},{"ply":46,"player":"ai","action":72,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[22,34,38,40,42,50,52,59],"ai":[12,13,18,25,30,39,43,46]},"scoresAfter":[3,14]},{"ply":47,"player":"human","action":17,"playedCard":34,"placeType":"play","drawSource":"discard_4","drawnCard":54,"handsBefore":{"human":[22,34,38,40,42,50,52,59],"ai":[12,13,18,25,30,39,46,56]},"scoresAfter":[21,14]},{"ply":48,"player":"ai","action":72,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[22,38,40,42,50,52,54,59],"ai":[12,13,18,25,30,39,46,56]},"scoresAfter":[21,23]},{"ply":49,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[22,38,40,42,50,52,54,59],"ai":[12,13,18,25,30,39,48,56]},"scoresAfter":[31,23]}],"finalScores":[31,23],"outcome":"YOU WIN","finalState":{"deckOrder":[44,29,45,20,53,51,55,2,12,6,37,49,4,35,9,7,33,25,24,15,57,14,46,36,3,34,58,8,59,5,47,21,19,27,26,10,16,54,1,11,17,43,41,42,13,22,0,52,32,40,23,50,39,31,30,38,18,56,48,28],"drawPtr":60,"cardLoc":[5,5,5,5,4,5,4,4,4,4,4,4,2,2,3,4,3,3,2,3,3,4,1,4,3,2,5,4,1,3,2,3,4,3,3,4,3,3,1,2,1,4,1,4,3,3,4,3,2,5,1,3,1,3,1,3,2,4,4,3],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,true,false,false,false,false,false],"colTop":[[0,7,9,10,10],[10,10,10,9,9]],"colHandshakes":[[0,1,1,2,0],[0,0,0,0,0]],"colLength":[[0,5,5,5,4],[7,3,3,3,2]],"piles":[[2,3,5,1,0],[],[26],[],[49]],"toMove":1,"stepCount":49,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"13a137ed-367a-4b3e-8a8d-70be7102111b","seed":"k5dbkb","startedAt":"2026-07-14T14:50:26.941Z","finishedAt":"2026-07-14T14:54:42.311Z","initialDeckOrder":[21,52,6,19,10,25,41,33,9,42,4,11,49,18,22,3,55,44,26,59,46,30,1,14,5,34,50,7,47,16,32,56,29,15,36,28,8,2,48,53,58,38,17,27,37,39,20,35,31,23,0,54,40,45,51,12,57,13,24,43],"moves":[{"ply":1,"player":"human","action":54,"playedCard":25,"placeType":"discard","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[6,10,19,21,25,33,41,52],"ai":[3,4,9,11,18,22,42,49]},"scoresAfter":[0,0]},{"ply":2,"player":"ai","action":78,"playedCard":42,"placeType":"discard","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[6,10,19,21,33,41,52,55],"ai":[3,4,9,11,18,22,42,49]},"scoresAfter":[0,0]},{"ply":3,"player":"human","action":64,"playedCard":41,"placeType":"play","drawSource":"discard_3","drawnCard":42,"handsBefore":{"human":[6,10,19,21,33,41,52,55],"ai":[3,4,9,11,18,22,44,49]},"scoresAfter":[-16,0]},{"ply":4,"player":"ai","action":90,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[6,10,19,21,33,42,52,55],"ai":[3,4,9,11,18,22,44,49]},"scoresAfter":[-16,0]},{"ply":5,"player":"human","action":60,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[6,10,19,21,33,42,52,55],"ai":[3,4,9,11,18,22,26,44]},"scoresAfter":[-11,0]},{"ply":6,"player":"ai","action":78,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[6,10,19,21,33,52,55,59],"ai":[3,4,9,11,18,22,26,44]},"scoresAfter":[-11,0]},{"ply":7,"player":"human","action":5,"playedCard":6,"placeType":"play","drawSource":"discard_4","drawnCard":49,"handsBefore":{"human":[6,10,19,21,33,52,55,59],"ai":[3,4,9,11,18,22,44,46]},"scoresAfter":[-26,0]},{"ply":8,"player":"ai","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[10,19,21,33,49,52,55,59],"ai":[3,4,9,11,18,22,44,46]},"scoresAfter":[-26,-18]},{"ply":9,"player":"human","action":48,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[10,19,21,33,49,52,55,59],"ai":[4,9,11,18,22,30,44,46]},"scoresAfter":[-66,-18]},{"ply":10,"player":"ai","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[1,10,19,21,33,52,55,59],"ai":[4,9,11,18,22,30,44,46]},"scoresAfter":[-66,-15]},{"ply":11,"player":"human","action":60,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[1,10,19,21,33,52,55,59],"ai":[9,11,14,18,22,30,44,46]},"scoresAfter":[-60,-15]},{"ply":12,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[1,5,10,19,21,33,55,59],"ai":[9,11,14,18,22,30,44,46]},"scoresAfter":[-60,-7]},{"ply":13,"player":"human","action":18,"playedCard":5,"placeType":"discard","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[1,5,10,19,21,33,55,59],"ai":[11,14,18,22,30,34,44,46]},"scoresAfter":[-60,-7]},{"ply":14,"player":"ai","action":48,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[1,10,19,21,33,50,55,59],"ai":[11,14,18,22,30,34,44,46]},"scoresAfter":[-60,-22]},{"ply":15,"player":"human","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[1,10,19,21,33,50,55,59],"ai":[7,11,14,18,22,34,44,46]},"scoresAfter":[-60,-22]},{"ply":16,"player":"ai","action":6,"playedCard":7,"placeType":"discard","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[10,19,21,33,47,50,55,59],"ai":[7,11,14,18,22,34,44,46]},"scoresAfter":[-60,-22]},{"ply":17,"player":"human","action":67,"playedCard":50,"placeType":"discard","drawSource":"discard_0","drawnCard":7,"handsBefore":{"human":[10,19,21,33,47,50,55,59],"ai":[11,14,16,18,22,34,44,46]},"scoresAfter":[-60,-22]},{"ply":18,"player":"ai","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[7,10,19,21,33,47,55,59],"ai":[11,14,16,18,22,34,44,46]},"scoresAfter":[-60,-12]},{"ply":19,"player":"human","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[7,10,19,21,33,47,55,59],"ai":[14,16,18,22,32,34,44,46]},"scoresAfter":[-54,-12]},{"ply":20,"player":"ai","action":48,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[10,19,21,33,47,55,56,59],"ai":[14,16,18,22,32,34,44,46]},"scoresAfter":[-54,-5]},{"ply":21,"player":"human","action":60,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[10,19,21,33,47,55,56,59],"ai":[14,16,18,22,29,34,44,46]},"scoresAfter":[-42,-5]},{"ply":22,"player":"ai","action":60,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[10,15,19,21,33,47,56,59],"ai":[14,16,18,22,29,34,44,46]},"scoresAfter":[-42,4]},{"ply":23,"player":"human","action":72,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[10,15,19,21,33,47,56,59],"ai":[14,16,18,22,29,36,44,46]},"scoresAfter":[-28,4]},{"ply":24,"player":"ai","action":0,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[10,15,19,21,28,33,47,59],"ai":[14,16,18,22,29,36,44,46]},"scoresAfter":[-28,-36]},{"ply":25,"player":"human","action":54,"playedCard":28,"placeType":"discard","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[10,15,19,21,28,33,47,59],"ai":[8,16,18,22,29,36,44,46]},"scoresAfter":[-28,-36]},{"ply":26,"player":"ai","action":60,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[2,10,15,19,21,33,47,59],"ai":[8,16,18,22,29,36,44,46]},"scoresAfter":[-28,-76]},{"ply":27,"player":"human","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[2,10,15,19,21,33,47,59],"ai":[8,16,18,22,29,44,46,48]},"scoresAfter":[-28,-76]},{"ply":28,"player":"ai","action":54,"playedCard":29,"placeType":"discard","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[10,15,19,21,33,47,53,59],"ai":[8,16,18,22,29,44,46,48]},"scoresAfter":[-28,-76]},{"ply":29,"player":"human","action":12,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[10,15,19,21,33,47,53,59],"ai":[8,16,18,22,44,46,48,58]},"scoresAfter":[-46,-76]},{"ply":30,"player":"ai","action":78,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[10,19,21,33,38,47,53,59],"ai":[8,16,18,22,44,46,48,58]},"scoresAfter":[-46,-76]},{"ply":31,"player":"human","action":54,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[10,19,21,33,38,47,53,59],"ai":[8,16,17,18,22,44,46,58]},"scoresAfter":[-46,-76]},{"ply":32,"player":"ai","action":12,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[10,19,21,27,33,47,53,59],"ai":[8,16,17,18,22,44,46,58]},"scoresAfter":[-46,-70]},{"ply":33,"player":"human","action":42,"playedCard":27,"placeType":"discard","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[10,19,21,27,33,47,53,59],"ai":[8,17,18,22,37,44,46,58]},"scoresAfter":[-46,-70]},{"ply":34,"player":"ai","action":12,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[10,19,21,33,39,47,53,59],"ai":[8,17,18,22,37,44,46,58]},"scoresAfter":[-46,-62]},{"ply":35,"player":"human","action":54,"playedCard":39,"placeType":"discard","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[10,19,21,33,39,47,53,59],"ai":[8,18,20,22,37,44,46,58]},"scoresAfter":[-46,-62]},{"ply":36,"player":"ai","action":12,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[10,19,21,33,35,47,53,59],"ai":[8,18,20,22,37,44,46,58]},"scoresAfter":[-46,-52]},{"ply":37,"player":"human","action":12,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[10,19,21,33,35,47,53,59],"ai":[8,20,22,31,37,44,46,58]},"scoresAfter":[-40,-52]},{"ply":38,"player":"ai","action":48,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[10,21,23,33,35,47,53,59],"ai":[8,20,22,31,37,44,46,58]},"scoresAfter":[-40,-72]},{"ply":39,"player":"human","action":12,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[10,21,23,33,35,47,53,59],"ai":[0,8,20,22,31,44,46,58]},"scoresAfter":[-32,-72]},{"ply":40,"player":"ai","action":24,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[10,23,33,35,47,53,54,59],"ai":[0,8,20,22,31,44,46,58]},"scoresAfter":[-32,-58]},{"ply":41,"player":"human","action":12,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[10,23,33,35,47,53,54,59],"ai":[0,8,22,31,40,44,46,58]},"scoresAfter":[-22,-58]},{"ply":42,"player":"ai","action":28,"playedCard":22,"placeType":"play","drawSource":"discard_3","drawnCard":39,"handsBefore":{"human":[10,33,35,45,47,53,54,59],"ai":[0,8,22,31,40,44,46,58]},"scoresAfter":[-22,-40]},{"ply":43,"player":"human","action":36,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[10,33,35,45,47,53,54,59],"ai":[0,8,31,39,40,44,46,58]},"scoresAfter":[-14,-40]},{"ply":44,"player":"ai","action":40,"playedCard":39,"placeType":"play","drawSource":"discard_3","drawnCard":38,"handsBefore":{"human":[10,33,35,47,51,53,54,59],"ai":[0,8,31,39,40,44,46,58]},"scoresAfter":[-14,-34]},{"ply":45,"player":"human","action":36,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[10,33,35,47,51,53,54,59],"ai":[0,8,31,38,40,44,46,58]},"scoresAfter":[-4,-34]},{"ply":46,"player":"ai","action":53,"playedCard":40,"placeType":"play","drawSource":"discard_4","drawnCard":48,"handsBefore":{"human":[10,12,33,35,51,53,54,59],"ai":[0,8,31,38,40,44,46,58]},"scoresAfter":[-4,-25]},{"ply":47,"player":"human","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[10,12,33,35,51,53,54,59],"ai":[0,8,31,38,44,46,48,58]},"scoresAfter":[5,-25]},{"ply":48,"player":"ai","action":53,"playedCard":44,"placeType":"play","drawSource":"discard_4","drawnCard":50,"handsBefore":{"human":[12,33,35,51,53,54,57,59],"ai":[0,8,31,38,44,46,48,58]},"scoresAfter":[5,-4]},{"ply":49,"player":"human","action":75,"playedCard":57,"placeType":"play","drawSource":"discard_2","drawnCard":27,"handsBefore":{"human":[12,33,35,51,53,54,57,59],"ai":[0,8,31,38,46,48,50,58]},"scoresAfter":[21,-4]},{"ply":50,"player":"ai","action":48,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[12,27,33,35,51,53,54,59],"ai":[0,8,31,38,46,48,50,58]},"scoresAfter":[21,23]},{"ply":51,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[12,27,33,35,51,53,54,59],"ai":[0,8,13,31,38,48,50,58]},"scoresAfter":[41,23]},{"ply":52,"player":"ai","action":18,"playedCard":8,"placeType":"discard","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[12,24,27,33,35,51,53,54],"ai":[0,8,13,31,38,48,50,58]},"scoresAfter":[41,23]}],"finalScores":[41,23],"outcome":"YOU WIN","finalState":{"deckOrder":[21,52,6,19,10,25,41,33,9,42,4,11,49,18,22,3,55,44,26,59,46,30,1,14,5,34,50,7,47,16,32,56,29,15,36,28,8,2,48,53,58,38,17,27,37,39,20,35,31,23,0,54,40,45,51,12,57,13,24,43],"drawPtr":60,"cardLoc":[2,5,5,4,4,5,3,3,5,4,3,4,1,2,4,3,4,4,4,3,4,3,4,3,1,5,5,1,5,5,4,2,4,1,4,1,4,4,2,4,4,3,3,2,4,3,4,3,2,3,2,1,3,1,1,3,3,3,2,3],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,true,false,true,false,false,false,false,false,false,false,false,false],"colTop":[[9,10,0,10,10],[10,9,9,9,0]],"colHandshakes":[[0,0,0,0,1],[0,1,0,2,0]],"colLength":[[3,4,0,4,6],[4,6,3,6,0]],"piles":[[5,1,2,8],[],[25,26,28,29],[],[]],"toMove":0,"stepCount":52,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"481937c3-32f4-4dd8-ade4-b732049fc526","seed":"nsgth2","startedAt":"2026-07-14T14:54:44.416Z","finishedAt":"2026-07-14T14:57:40.010Z","initialDeckOrder":[43,38,1,53,55,17,21,5,3,18,27,54,56,0,41,14,25,45,30,46,35,42,23,40,24,12,16,10,36,4,13,6,7,57,48,8,50,59,39,2,34,28,26,58,47,51,33,37,22,49,29,9,19,32,11,52,15,20,31,44],"moves":[{"ply":1,"player":"human","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[1,5,17,21,38,43,53,55],"ai":[0,3,14,18,27,41,54,56]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[5,17,21,25,38,43,53,55],"ai":[0,3,14,18,27,41,54,56]},"scoresAfter":[-40,0]},{"ply":3,"player":"human","action":42,"playedCard":25,"placeType":"discard","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[5,17,21,25,38,43,53,55],"ai":[3,14,18,27,41,45,54,56]},"scoresAfter":[-40,0]},{"ply":4,"player":"ai","action":36,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[5,17,21,30,38,43,53,55],"ai":[3,14,18,27,41,45,54,56]},"scoresAfter":[-40,-18]},{"ply":5,"player":"human","action":12,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[5,17,21,30,38,43,53,55],"ai":[3,14,18,41,45,46,54,56]},"scoresAfter":[-56,-18]},{"ply":6,"player":"ai","action":12,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[5,21,30,35,38,43,53,55],"ai":[3,14,18,41,45,46,54,56]},"scoresAfter":[-56,-58]},{"ply":7,"player":"human","action":24,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[5,21,30,35,38,43,53,55],"ai":[3,18,41,42,45,46,54,56]},"scoresAfter":[-71,-58]},{"ply":8,"player":"ai","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[5,21,23,35,38,43,53,55],"ai":[3,18,41,42,45,46,54,56]},"scoresAfter":[-71,-76]},{"ply":9,"player":"human","action":12,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[5,21,23,35,38,43,53,55],"ai":[18,40,41,42,45,46,54,56]},"scoresAfter":[-63,-76]},{"ply":10,"player":"ai","action":0,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[5,23,24,35,38,43,53,55],"ai":[18,40,41,42,45,46,54,56]},"scoresAfter":[-63,-66]},{"ply":11,"player":"human","action":30,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[5,23,24,35,38,43,53,55],"ai":[12,40,41,42,45,46,54,56]},"scoresAfter":[-63,-66]},{"ply":12,"player":"ai","action":72,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[5,16,23,35,38,43,53,55],"ai":[12,40,41,42,45,46,54,56]},"scoresAfter":[-63,-81]},{"ply":13,"player":"human","action":18,"playedCard":16,"placeType":"discard","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[5,16,23,35,38,43,53,55],"ai":[10,12,40,41,42,45,46,56]},"scoresAfter":[-63,-81]},{"ply":14,"player":"ai","action":84,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[5,23,35,36,38,43,53,55],"ai":[10,12,40,41,42,45,46,56]},"scoresAfter":[-63,-74]},{"ply":15,"player":"human","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[5,23,35,36,38,43,53,55],"ai":[4,10,12,40,41,42,45,46]},"scoresAfter":[-55,-74]},{"ply":16,"player":"ai","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[13,23,35,36,38,43,53,55],"ai":[4,10,12,40,41,42,45,46]},"scoresAfter":[-55,-71]},{"ply":17,"player":"human","action":6,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[13,23,35,36,38,43,53,55],"ai":[6,10,12,40,41,42,45,46]},"scoresAfter":[-55,-71]},{"ply":18,"player":"ai","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[7,23,35,36,38,43,53,55],"ai":[6,10,12,40,41,42,45,46]},"scoresAfter":[-55,-66]},{"ply":19,"player":"human","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[7,23,35,36,38,43,53,55],"ai":[10,12,40,41,42,45,46,57]},"scoresAfter":[-43,-66]},{"ply":20,"player":"ai","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[23,35,36,38,43,48,53,55],"ai":[10,12,40,41,42,45,46,57]},"scoresAfter":[-43,-57]},{"ply":21,"player":"human","action":0,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[23,35,36,38,43,48,53,55],"ai":[8,12,40,41,42,45,46,57]},"scoresAfter":[-33,-57]},{"ply":22,"player":"ai","action":54,"playedCard":42,"placeType":"discard","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[35,36,38,43,48,50,53,55],"ai":[8,12,40,41,42,45,46,57]},"scoresAfter":[-33,-57]},{"ply":23,"player":"human","action":18,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[35,36,38,43,48,50,53,55],"ai":[8,12,40,41,45,46,57,59]},"scoresAfter":[-33,-57]},{"ply":24,"player":"ai","action":72,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[35,38,39,43,48,50,53,55],"ai":[8,12,40,41,45,46,57,59]},"scoresAfter":[-33,-49]},{"ply":25,"player":"human","action":18,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[35,38,39,43,48,50,53,55],"ai":[2,8,12,40,41,45,46,59]},"scoresAfter":[-33,-49]},{"ply":26,"player":"ai","action":88,"playedCard":59,"placeType":"play","drawSource":"discard_3","drawnCard":38,"handsBefore":{"human":[34,35,39,43,48,50,53,55],"ai":[2,8,12,40,41,45,46,59]},"scoresAfter":[-33,-39]},{"ply":27,"player":"human","action":54,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[34,35,39,43,48,50,53,55],"ai":[2,8,12,38,40,41,45,46]},"scoresAfter":[-33,-39]},{"ply":28,"player":"ai","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[28,34,35,39,43,50,53,55],"ai":[2,8,12,38,40,41,45,46]},"scoresAfter":[-33,-39]},{"ply":29,"player":"human","action":66,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[28,34,35,39,43,50,53,55],"ai":[8,12,26,38,40,41,45,46]},"scoresAfter":[-33,-39]},{"ply":30,"player":"ai","action":18,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[28,34,35,39,43,53,55,58],"ai":[8,12,26,38,40,41,45,46]},"scoresAfter":[-33,-39]},{"ply":31,"player":"human","action":60,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[28,34,35,39,43,53,55,58],"ai":[8,26,38,40,41,45,46,47]},"scoresAfter":[-49,-39]},{"ply":32,"player":"ai","action":10,"playedCard":8,"placeType":"discard","drawSource":"discard_3","drawnCard":36,"handsBefore":{"human":[28,34,35,39,43,51,55,58],"ai":[8,26,38,40,41,45,46,47]},"scoresAfter":[-49,-39]},{"ply":33,"player":"human","action":72,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[28,34,35,39,43,51,55,58],"ai":[26,36,38,40,41,45,46,47]},"scoresAfter":[-43,-39]},{"ply":34,"player":"ai","action":16,"playedCard":36,"placeType":"play","drawSource":"discard_3","drawnCard":42,"handsBefore":{"human":[28,33,34,35,39,43,51,58],"ai":[26,36,38,40,41,45,46,47]},"scoresAfter":[-43,-79]},{"ply":35,"player":"human","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[28,33,34,35,39,43,51,58],"ai":[26,38,40,41,42,45,46,47]},"scoresAfter":[-34,-79]},{"ply":36,"player":"ai","action":12,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[28,33,34,35,37,39,43,51],"ai":[26,38,40,41,42,45,46,47]},"scoresAfter":[-34,-99]},{"ply":37,"player":"human","action":12,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[28,33,34,35,37,39,43,51],"ai":[22,26,40,41,42,45,46,47]},"scoresAfter":[-26,-99]},{"ply":38,"player":"ai","action":1,"playedCard":22,"placeType":"play","drawSource":"discard_0","drawnCard":8,"handsBefore":{"human":[28,34,35,37,39,43,49,51],"ai":[22,26,40,41,42,45,46,47]},"scoresAfter":[-26,-81]},{"ply":39,"player":"human","action":12,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[28,34,35,37,39,43,49,51],"ai":[8,26,40,41,42,45,46,47]},"scoresAfter":[-17,-81]},{"ply":40,"player":"ai","action":24,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[28,29,35,37,39,43,49,51],"ai":[8,26,40,41,42,45,46,47]},"scoresAfter":[-17,-72]},{"ply":41,"player":"human","action":24,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[28,29,35,37,39,43,49,51],"ai":[8,9,26,41,42,45,46,47]},"scoresAfter":[-7,-72]},{"ply":42,"player":"ai","action":36,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[19,28,29,37,39,43,49,51],"ai":[8,9,26,41,42,45,46,47]},"scoresAfter":[-7,-60]},{"ply":43,"player":"human","action":42,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[19,28,29,37,39,43,49,51],"ai":[8,9,26,32,42,45,46,47]},"scoresAfter":[-7,-60]},{"ply":44,"player":"ai","action":40,"playedCard":32,"placeType":"play","drawSource":"discard_3","drawnCard":37,"handsBefore":{"human":[11,19,28,29,39,43,49,51],"ai":[8,9,26,32,42,45,46,47]},"scoresAfter":[-7,-53]},{"ply":45,"player":"human","action":18,"playedCard":19,"placeType":"discard","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[11,19,28,29,39,43,49,51],"ai":[8,9,26,37,42,45,46,47]},"scoresAfter":[-7,-53]},{"ply":46,"player":"ai","action":51,"playedCard":42,"placeType":"play","drawSource":"discard_2","drawnCard":24,"handsBefore":{"human":[11,28,29,39,43,49,51,52],"ai":[8,9,26,37,42,45,46,47]},"scoresAfter":[-7,-38]},{"ply":47,"player":"human","action":66,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[11,28,29,39,43,49,51,52],"ai":[8,9,24,26,37,45,46,47]},"scoresAfter":[-7,-38]},{"ply":48,"player":"ai","action":65,"playedCard":45,"placeType":"play","drawSource":"discard_4","drawnCard":49,"handsBefore":{"human":[11,15,28,29,39,43,51,52],"ai":[8,9,24,26,37,45,46,47]},"scoresAfter":[-7,-14]},{"ply":49,"player":"human","action":18,"playedCard":15,"placeType":"discard","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[11,15,28,29,39,43,51,52],"ai":[8,9,24,26,37,46,47,49]},"scoresAfter":[-7,-14]},{"ply":50,"player":"ai","action":65,"playedCard":46,"placeType":"play","drawSource":"discard_4","drawnCard":50,"handsBefore":{"human":[11,20,28,29,39,43,51,52],"ai":[8,9,24,26,37,46,47,49]},"scoresAfter":[-7,13]},{"ply":51,"player":"human","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[11,20,28,29,39,43,51,52],"ai":[8,9,24,26,37,47,49,50]},"scoresAfter":[13,13]},{"ply":52,"player":"ai","action":65,"playedCard":47,"placeType":"play","drawSource":"discard_4","drawnCard":48,"handsBefore":{"human":[20,28,29,31,39,43,51,52],"ai":[8,9,24,26,37,47,49,50]},"scoresAfter":[13,63]},{"ply":53,"player":"human","action":42,"playedCard":31,"placeType":"discard","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[20,28,29,31,39,43,51,52],"ai":[8,9,24,26,37,48,49,50]},"scoresAfter":[13,63]}],"finalScores":[13,63],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[43,38,1,53,55,17,21,5,3,18,27,54,56,0,41,14,25,45,30,46,35,42,23,40,24,12,16,10,36,4,13,6,7,57,48,8,50,59,39,2,34,28,26,58,47,51,33,37,22,49,29,9,19,32,11,52,15,20,31,44],"drawPtr":60,"cardLoc":[5,3,5,4,4,3,4,3,2,2,4,3,5,5,4,5,5,3,4,5,1,3,4,3,2,5,2,4,1,1,3,5,4,3,3,3,4,2,4,1,4,4,4,1,1,4,4,4,2,2,2,1,1,3,4,3,4,4,3,4],"handPublic":[false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,true,true,true,false,false,false,false,false,false,false,false,false],"colTop":[[10,10,10,0,9],[9,9,7,10,10]],"colHandshakes":[[1,0,0,0,0],[0,1,0,2,0]],"colLength":[[4,3,4,0,3],[4,3,2,8,4]],"piles":[[0,2],[16,13,12,19,15],[25,31],[],[]],"toMove":1,"stepCount":53,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"152e6b53-94ae-41d3-8e68-4f8707cde756","seed":"g9fphx","startedAt":"2026-07-14T14:57:40.991Z","finishedAt":"2026-07-14T15:00:17.508Z","initialDeckOrder":[56,9,43,35,53,18,12,19,51,14,54,38,25,41,26,31,57,33,34,17,40,8,27,22,2,52,45,1,13,44,28,4,50,49,10,3,55,7,16,37,58,48,47,59,6,46,20,23,30,36,21,11,42,24,29,5,15,39,32,0],"moves":[{"ply":1,"player":"human","action":12,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[9,12,18,19,35,43,53,56],"ai":[14,25,26,31,38,41,51,54]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":78,"playedCard":51,"placeType":"discard","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[9,18,19,35,43,53,56,57],"ai":[14,25,26,31,38,41,51,54]},"scoresAfter":[-40,0]},{"ply":3,"player":"human","action":17,"playedCard":18,"placeType":"play","drawSource":"discard_4","drawnCard":51,"handsBefore":{"human":[9,18,19,35,43,53,56,57],"ai":[14,25,26,31,33,38,41,54]},"scoresAfter":[-30,0]},{"ply":4,"player":"ai","action":66,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[9,19,35,43,51,53,56,57],"ai":[14,25,26,31,33,38,41,54]},"scoresAfter":[-30,0]},{"ply":5,"player":"human","action":48,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[9,19,35,43,51,53,56,57],"ai":[14,25,26,31,33,34,41,54]},"scoresAfter":[-48,0]},{"ply":6,"player":"ai","action":12,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[9,17,19,35,43,53,56,57],"ai":[14,25,26,31,33,34,41,54]},"scoresAfter":[-48,-40]},{"ply":7,"player":"human","action":60,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[9,17,19,35,43,53,56,57],"ai":[14,26,31,33,34,40,41,54]},"scoresAfter":[-44,-40]},{"ply":8,"player":"ai","action":6,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[8,9,17,19,35,43,56,57],"ai":[14,26,31,33,34,40,41,54]},"scoresAfter":[-44,-40]},{"ply":9,"player":"human","action":36,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[8,9,17,19,35,43,56,57],"ai":[26,27,31,33,34,40,41,54]},"scoresAfter":[-32,-40]},{"ply":10,"player":"ai","action":90,"playedCard":54,"placeType":"discard","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[8,9,17,22,35,43,56,57],"ai":[26,27,31,33,34,40,41,54]},"scoresAfter":[-32,-40]},{"ply":11,"player":"human","action":35,"playedCard":17,"placeType":"discard","drawSource":"discard_4","drawnCard":54,"handsBefore":{"human":[8,9,17,22,35,43,56,57],"ai":[2,26,27,31,33,34,40,41]},"scoresAfter":[-32,-40]},{"ply":12,"player":"ai","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[8,9,22,35,43,54,56,57],"ai":[2,26,27,31,33,34,40,41]},"scoresAfter":[-32,-40]},{"ply":13,"player":"human","action":60,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[8,9,22,35,43,54,56,57],"ai":[26,27,31,33,34,40,41,52]},"scoresAfter":[-27,-40]},{"ply":14,"player":"ai","action":90,"playedCard":52,"placeType":"discard","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[8,9,22,35,43,45,56,57],"ai":[26,27,31,33,34,40,41,52]},"scoresAfter":[-27,-40]},{"ply":15,"player":"human","action":72,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[8,9,22,35,43,45,56,57],"ai":[1,26,27,31,33,34,40,41]},"scoresAfter":[-20,-40]},{"ply":16,"player":"ai","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[8,9,13,22,35,43,45,57],"ai":[1,26,27,31,33,34,40,41]},"scoresAfter":[-20,-40]},{"ply":17,"player":"human","action":30,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[8,9,13,22,35,43,45,57],"ai":[26,27,31,33,34,40,41,44]},"scoresAfter":[-20,-40]},{"ply":18,"player":"ai","action":0,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[8,9,22,28,35,43,45,57],"ai":[26,27,31,33,34,40,41,44]},"scoresAfter":[-20,-60]},{"ply":19,"player":"human","action":84,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[8,9,22,28,35,43,45,57],"ai":[4,27,31,33,34,40,41,44]},"scoresAfter":[-12,-60]},{"ply":20,"player":"ai","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[8,9,22,28,35,43,45,50],"ai":[4,27,31,33,34,40,41,44]},"scoresAfter":[-12,-77]},{"ply":21,"player":"human","action":90,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[8,9,22,28,35,43,45,50],"ai":[27,31,33,34,40,41,44,49]},"scoresAfter":[-12,-77]},{"ply":22,"player":"ai","action":90,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[8,9,10,22,28,35,43,45],"ai":[27,31,33,34,40,41,44,49]},"scoresAfter":[-12,-77]},{"ply":23,"player":"human","action":37,"playedCard":22,"placeType":"play","drawSource":"discard_0","drawnCard":1,"handsBefore":{"human":[8,9,10,22,28,35,43,45],"ai":[3,27,31,33,34,40,41,44]},"scoresAfter":[6,-77]},{"ply":24,"player":"ai","action":60,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[1,8,9,10,28,35,43,45],"ai":[3,27,31,33,34,40,41,44]},"scoresAfter":[6,-94]},{"ply":25,"player":"human","action":1,"playedCard":1,"placeType":"play","drawSource":"discard_0","drawnCard":2,"handsBefore":{"human":[1,8,9,10,28,35,43,45],"ai":[3,27,31,33,34,41,44,55]},"scoresAfter":[-34,-94]},{"ply":26,"player":"ai","action":60,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[2,8,9,10,28,35,43,45],"ai":[3,27,31,33,34,41,44,55]},"scoresAfter":[-34,-90]},{"ply":27,"player":"human","action":0,"playedCard":2,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[2,8,9,10,28,35,43,45],"ai":[3,7,27,31,33,34,44,55]},"scoresAfter":[-54,-90]},{"ply":28,"player":"ai","action":30,"playedCard":27,"placeType":"discard","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[8,9,10,16,28,35,43,45],"ai":[3,7,27,31,33,34,44,55]},"scoresAfter":[-54,-90]},{"ply":29,"player":"human","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[8,9,10,16,28,35,43,45],"ai":[3,7,31,33,34,37,44,55]},"scoresAfter":[-33,-90]},{"ply":30,"player":"ai","action":81,"playedCard":44,"placeType":"discard","drawSource":"discard_2","drawnCard":27,"handsBefore":{"human":[9,10,16,28,35,43,45,58],"ai":[3,7,31,33,34,37,44,55]},"scoresAfter":[-33,-90]},{"ply":31,"player":"human","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[9,10,16,28,35,43,45,58],"ai":[3,7,27,31,33,34,37,55]},"scoresAfter":[-24,-90]},{"ply":32,"player":"ai","action":90,"playedCard":55,"placeType":"discard","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[9,10,16,28,35,43,45,48],"ai":[3,7,27,31,33,34,37,55]},"scoresAfter":[-24,-90]},{"ply":33,"player":"human","action":90,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[9,10,16,28,35,43,45,48],"ai":[3,7,27,31,33,34,37,47]},"scoresAfter":[-24,-90]},{"ply":34,"player":"ai","action":12,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[9,10,16,28,35,43,45,59],"ai":[3,7,27,31,33,34,37,47]},"scoresAfter":[-24,-84]},{"ply":35,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[9,10,16,28,35,43,45,59],"ai":[3,6,27,31,33,34,37,47]},"scoresAfter":[-14,-84]},{"ply":36,"player":"ai","action":24,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[9,10,16,28,35,43,45,46],"ai":[3,6,27,31,33,34,37,47]},"scoresAfter":[-14,-78]},{"ply":37,"player":"human","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[9,10,16,28,35,43,45,46],"ai":[3,6,20,31,33,34,37,47]},"scoresAfter":[10,-78]},{"ply":38,"player":"ai","action":24,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[10,16,23,28,35,43,45,46],"ai":[3,6,20,31,33,34,37,47]},"scoresAfter":[10,-91]},{"ply":39,"player":"human","action":24,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[10,16,23,28,35,43,45,46],"ai":[3,6,30,31,33,34,37,47]},"scoresAfter":[30,-91]},{"ply":40,"player":"ai","action":24,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[10,16,28,35,36,43,45,46],"ai":[3,6,30,31,33,34,37,47]},"scoresAfter":[30,-76]},{"ply":41,"player":"human","action":52,"playedCard":36,"placeType":"play","drawSource":"discard_3","drawnCard":44,"handsBefore":{"human":[10,16,28,35,36,43,45,46],"ai":[3,6,21,31,33,34,37,47]},"scoresAfter":[-10,-76]},{"ply":42,"player":"ai","action":24,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[10,16,28,35,43,44,45,46],"ai":[3,6,21,31,33,34,37,47]},"scoresAfter":[-10,-68]},{"ply":43,"player":"human","action":48,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[10,16,28,35,43,44,45,46],"ai":[3,6,11,31,33,34,37,47]},"scoresAfter":[2,-68]},{"ply":44,"player":"ai","action":24,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[10,16,28,35,42,44,45,46],"ai":[3,6,11,31,33,34,37,47]},"scoresAfter":[2,-58]},{"ply":45,"player":"human","action":60,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[10,16,28,35,42,44,45,46],"ai":[3,6,24,31,33,34,37,47]},"scoresAfter":[16,-58]},{"ply":46,"player":"ai","action":41,"playedCard":31,"placeType":"play","drawSource":"discard_4","drawnCard":48,"handsBefore":{"human":[10,16,28,29,35,42,45,46],"ai":[3,6,24,31,33,34,37,47]},"scoresAfter":[16,-40]},{"ply":47,"player":"human","action":72,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[10,16,28,29,35,42,45,46],"ai":[3,6,24,33,34,37,47,48]},"scoresAfter":[32,-40]},{"ply":48,"player":"ai","action":41,"playedCard":33,"placeType":"play","drawSource":"discard_4","drawnCard":55,"handsBefore":{"human":[5,10,16,28,29,35,42,46],"ai":[3,6,24,33,34,37,47,48]},"scoresAfter":[32,-16]},{"ply":49,"player":"human","action":84,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[5,10,16,28,29,35,42,46],"ai":[3,6,24,34,37,47,48,55]},"scoresAfter":[50,-16]},{"ply":50,"player":"ai","action":41,"playedCard":34,"placeType":"play","drawSource":"discard_4","drawnCard":49,"handsBefore":{"human":[5,10,15,16,28,29,35,42],"ai":[3,6,24,34,37,47,48,55]},"scoresAfter":[50,11]},{"ply":51,"player":"human","action":12,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[5,10,15,16,28,29,35,42],"ai":[3,6,24,37,47,48,49,55]},"scoresAfter":[77,11]},{"ply":52,"player":"ai","action":48,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[5,15,16,28,29,35,39,42],"ai":[3,6,24,37,47,48,49,55]},"scoresAfter":[77,21]},{"ply":53,"player":"human","action":78,"playedCard":39,"placeType":"discard","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[5,15,16,28,29,35,39,42],"ai":[3,6,24,32,37,48,49,55]},"scoresAfter":[77,21]}],"finalScores":[77,21],"outcome":"YOU WIN","finalState":{"deckOrder":[56,9,43,35,53,18,12,19,51,14,54,38,25,41,26,31,57,33,34,17,40,8,27,22,2,52,45,1,13,44,28,4,50,49,10,3,55,7,16,37,58,48,47,59,6,46,20,23,30,36,21,11,42,24,29,5,15,39,32,0],"drawPtr":60,"cardLoc":[1,3,3,2,4,1,2,4,3,3,3,4,3,5,5,1,1,5,3,3,4,4,3,3,2,4,4,4,1,1,4,4,2,4,4,1,3,2,5,5,4,4,1,3,3,3,3,4,2,2,5,3,5,3,3,2,3,3,3,3],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,false,false,false,false,false,true,false,false,false,false],"colTop":[[9,10,0,9,10],[10,8,9,10,0]],"colHandshakes":[[2,1,0,1,0],[0,0,2,0,0]],"colLength":[[5,5,0,5,7],[3,2,7,3,0]],"piles":[[],[14,17,13],[],[38,39],[52,50]],"toMove":1,"stepCount":53,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"2e8f5634-ac14-4798-b879-df0ae9c587ab","seed":"13foau","startedAt":"2026-07-14T15:00:18.486Z","finishedAt":"2026-07-14T15:03:14.286Z","initialDeckOrder":[11,12,33,6,54,0,57,9,58,27,3,23,31,41,16,18,14,17,10,29,35,48,43,5,20,34,56,39,45,40,59,47,21,22,13,19,1,51,55,4,42,28,44,15,50,38,24,2,32,26,37,7,30,52,25,46,49,53,8,36],"moves":[{"ply":1,"player":"human","action":0,"playedCard":0,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[0,6,9,11,12,33,54,57],"ai":[3,16,18,23,27,31,41,58]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[6,9,11,12,14,33,54,57],"ai":[3,16,18,23,27,31,41,58]},"scoresAfter":[-40,-18]},{"ply":3,"player":"human","action":42,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[6,9,11,12,14,33,54,57],"ai":[16,17,18,23,27,31,41,58]},"scoresAfter":[-40,-18]},{"ply":4,"player":"ai","action":74,"playedCard":41,"placeType":"play","drawSource":"discard_1","drawnCard":12,"handsBefore":{"human":[6,9,10,11,14,33,54,57],"ai":[16,17,18,23,27,31,41,58]},"scoresAfter":[-40,-34]},{"ply":5,"player":"human","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[6,9,10,11,14,33,54,57],"ai":[12,16,17,18,23,27,31,58]},"scoresAfter":[-30,-34]},{"ply":6,"player":"ai","action":0,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[9,10,11,14,29,33,54,57],"ai":[12,16,17,18,23,27,31,58]},"scoresAfter":[-30,-74]},{"ply":7,"player":"human","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[9,10,11,14,29,33,54,57],"ai":[16,17,18,23,27,31,35,58]},"scoresAfter":[-14,-74]},{"ply":8,"player":"ai","action":0,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[10,11,14,29,33,48,54,57],"ai":[16,17,18,23,27,31,35,58]},"scoresAfter":[-14,-68]},{"ply":9,"player":"human","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[10,11,14,29,33,48,54,57],"ai":[17,18,23,27,31,35,43,58]},"scoresAfter":[4,-68]},{"ply":10,"player":"ai","action":0,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[5,11,14,29,33,48,54,57],"ai":[17,18,23,27,31,35,43,58]},"scoresAfter":[4,-60]},{"ply":11,"player":"human","action":12,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[5,11,14,29,33,48,54,57],"ai":[18,20,23,27,31,35,43,58]},"scoresAfter":[24,-60]},{"ply":12,"player":"ai","action":0,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[5,14,29,33,34,48,54,57],"ai":[18,20,23,27,31,35,43,58]},"scoresAfter":[24,-50]},{"ply":13,"player":"human","action":18,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[5,14,29,33,34,48,54,57],"ai":[20,23,27,31,35,43,56,58]},"scoresAfter":[24,-50]},{"ply":14,"player":"ai","action":60,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[5,29,33,34,39,48,54,57],"ai":[20,23,27,31,35,43,56,58]},"scoresAfter":[24,-44]},{"ply":15,"player":"human","action":54,"playedCard":39,"placeType":"discard","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[5,29,33,34,39,48,54,57],"ai":[20,23,27,31,35,45,56,58]},"scoresAfter":[24,-44]},{"ply":16,"player":"ai","action":60,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[5,29,33,34,40,48,54,57],"ai":[20,23,27,31,35,45,56,58]},"scoresAfter":[24,-36]},{"ply":17,"player":"human","action":54,"playedCard":40,"placeType":"discard","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[5,29,33,34,40,48,54,57],"ai":[20,23,27,31,35,56,58,59]},"scoresAfter":[24,-36]},{"ply":18,"player":"ai","action":0,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[5,29,33,34,47,48,54,57],"ai":[20,23,27,31,35,56,58,59]},"scoresAfter":[24,-22]},{"ply":19,"player":"human","action":60,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[5,29,33,34,47,48,54,57],"ai":[21,23,27,31,35,56,58,59]},"scoresAfter":[-16,-22]},{"ply":20,"player":"ai","action":0,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[5,22,29,33,34,47,54,57],"ai":[21,23,27,31,35,56,58,59]},"scoresAfter":[-16,-6]},{"ply":21,"player":"human","action":72,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[5,22,29,33,34,47,54,57],"ai":[13,23,27,31,35,56,58,59]},"scoresAfter":[-6,-6]},{"ply":22,"player":"ai","action":12,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[5,19,22,29,33,34,47,57],"ai":[13,23,27,31,35,56,58,59]},"scoresAfter":[-6,14]},{"ply":23,"player":"human","action":18,"playedCard":19,"placeType":"discard","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[5,19,22,29,33,34,47,57],"ai":[1,13,27,31,35,56,58,59]},"scoresAfter":[-6,14]},{"ply":24,"player":"ai","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[5,22,29,33,34,47,51,57],"ai":[1,13,27,31,35,56,58,59]},"scoresAfter":[-6,14]},{"ply":25,"player":"human","action":18,"playedCard":22,"placeType":"discard","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[5,22,29,33,34,47,51,57],"ai":[13,27,31,35,55,56,58,59]},"scoresAfter":[-6,14]},{"ply":26,"player":"ai","action":14,"playedCard":27,"placeType":"play","drawSource":"discard_1","drawnCard":22,"handsBefore":{"human":[4,5,29,33,34,47,51,57],"ai":[13,27,31,35,55,56,58,59]},"scoresAfter":[-6,-4]},{"ply":27,"player":"human","action":24,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[4,5,29,33,34,47,51,57],"ai":[13,22,31,35,55,56,58,59]},"scoresAfter":[-22,-4]},{"ply":28,"player":"ai","action":10,"playedCard":13,"placeType":"discard","drawSource":"discard_3","drawnCard":40,"handsBefore":{"human":[4,5,33,34,42,47,51,57],"ai":[13,22,31,35,55,56,58,59]},"scoresAfter":[-22,-4]},{"ply":29,"player":"human","action":28,"playedCard":33,"placeType":"play","drawSource":"discard_3","drawnCard":39,"handsBefore":{"human":[4,5,33,34,42,47,51,57],"ai":[22,31,35,40,55,56,58,59]},"scoresAfter":[-14,-4]},{"ply":30,"player":"ai","action":12,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[4,5,34,39,42,47,51,57],"ai":[22,31,35,40,55,56,58,59]},"scoresAfter":[-14,2]},{"ply":31,"player":"human","action":36,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[4,5,34,39,42,47,51,57],"ai":[22,28,35,40,55,56,58,59]},"scoresAfter":[-32,2]},{"ply":32,"player":"ai","action":6,"playedCard":22,"placeType":"discard","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[4,5,34,42,44,47,51,57],"ai":[22,28,35,40,55,56,58,59]},"scoresAfter":[-32,2]},{"ply":33,"player":"human","action":36,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[4,5,34,42,44,47,51,57],"ai":[15,28,35,40,55,56,58,59]},"scoresAfter":[-27,2]},{"ply":34,"player":"ai","action":26,"playedCard":35,"placeType":"play","drawSource":"discard_1","drawnCard":22,"handsBefore":{"human":[4,5,34,44,47,50,51,57],"ai":[15,28,35,40,55,56,58,59]},"scoresAfter":[-27,12]},{"ply":35,"player":"human","action":36,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[4,5,34,44,47,50,51,57],"ai":[15,22,28,40,55,56,58,59]},"scoresAfter":[-20,12]},{"ply":36,"player":"ai","action":18,"playedCard":22,"placeType":"discard","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[4,5,34,38,47,50,51,57],"ai":[15,22,28,40,55,56,58,59]},"scoresAfter":[-20,12]},{"ply":37,"player":"human","action":42,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[4,5,34,38,47,50,51,57],"ai":[15,24,28,40,55,56,58,59]},"scoresAfter":[-20,12]},{"ply":38,"player":"ai","action":20,"playedCard":24,"placeType":"discard","drawSource":"discard_1","drawnCard":22,"handsBefore":{"human":[2,4,5,34,47,50,51,57],"ai":[15,24,28,40,55,56,58,59]},"scoresAfter":[-20,12]},{"ply":39,"player":"human","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[2,4,5,34,47,50,51,57],"ai":[15,22,28,40,55,56,58,59]},"scoresAfter":[-20,12]},{"ply":40,"player":"ai","action":18,"playedCard":22,"placeType":"discard","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[4,5,32,34,47,50,51,57],"ai":[15,22,28,40,55,56,58,59]},"scoresAfter":[-20,12]},{"ply":41,"player":"human","action":36,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[4,5,32,34,47,50,51,57],"ai":[15,26,28,40,55,56,58,59]},"scoresAfter":[-11,12]},{"ply":42,"player":"ai","action":20,"playedCard":26,"placeType":"discard","drawSource":"discard_1","drawnCard":22,"handsBefore":{"human":[4,5,32,37,47,50,51,57],"ai":[15,26,28,40,55,56,58,59]},"scoresAfter":[-11,12]},{"ply":43,"player":"human","action":42,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[4,5,32,37,47,50,51,57],"ai":[15,22,28,40,55,56,58,59]},"scoresAfter":[-11,12]},{"ply":44,"player":"ai","action":48,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[4,5,7,32,47,50,51,57],"ai":[15,22,28,40,55,56,58,59]},"scoresAfter":[-11,-2]},{"ply":45,"player":"human","action":48,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[4,5,7,32,47,50,51,57],"ai":[15,22,28,30,40,56,58,59]},"scoresAfter":[-1,-2]},{"ply":46,"player":"ai","action":60,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[4,5,7,32,50,51,52,57],"ai":[15,22,28,30,40,56,58,59]},"scoresAfter":[-1,5]},{"ply":47,"player":"human","action":84,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[4,5,7,32,50,51,52,57],"ai":[15,22,25,28,30,40,58,59]},"scoresAfter":[15,5]},{"ply":48,"player":"ai","action":76,"playedCard":58,"placeType":"play","drawSource":"discard_3","drawnCard":37,"handsBefore":{"human":[4,5,7,32,46,50,51,52],"ai":[15,22,25,28,30,40,58,59]},"scoresAfter":[15,14]},{"ply":49,"player":"human","action":66,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[4,5,7,32,46,50,51,52],"ai":[15,22,25,28,30,37,40,59]},"scoresAfter":[15,14]},{"ply":50,"player":"ai","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[4,5,7,32,46,49,51,52],"ai":[15,22,25,28,30,37,40,59]},"scoresAfter":[15,24]},{"ply":51,"player":"human","action":66,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[4,5,7,32,46,49,51,52],"ai":[15,22,25,28,30,37,40,53]},"scoresAfter":[15,24]},{"ply":52,"player":"ai","action":90,"playedCard":53,"placeType":"discard","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[4,5,7,8,32,46,51,52],"ai":[15,22,25,28,30,37,40,53]},"scoresAfter":[15,24]}],"finalScores":[15,24],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[11,12,33,6,54,0,57,9,58,27,3,23,31,41,16,18,14,17,10,29,35,48,43,5,20,34,56,39,45,40,59,47,21,22,13,19,1,51,55,4,42,28,44,15,50,38,24,2,32,26,37,7,30,52,25,46,49,53,8,36],"drawPtr":60,"cardLoc":[3,5,5,4,1,1,3,1,1,3,3,3,4,5,5,2,4,4,4,5,4,4,2,4,5,2,5,4,2,3,2,4,1,3,3,4,2,2,5,3,2,4,3,4,3,4,1,3,3,5,5,1,1,5,3,4,4,3,4,4],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,0,9,10,8],[2,10,10,8,10]],"colHandshakes":[[1,0,0,0,1],[0,1,0,0,0]],"colLength":[[5,0,3,4,3],[1,7,3,3,4]],"piles":[[1,2],[14,19,13],[24,26],[38],[50,49,53]],"toMove":0,"stepCount":52,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"cd0dc0f9-11f4-420f-9fba-0226b23d3f79","seed":"txl22r","startedAt":"2026-07-14T15:03:15.595Z","finishedAt":"2026-07-14T15:06:21.632Z","initialDeckOrder":[25,46,44,19,54,55,45,14,58,1,57,34,28,8,36,18,37,6,43,23,20,3,51,41,22,4,42,21,9,39,12,17,38,29,33,59,49,13,30,56,0,32,40,48,27,24,5,31,11,7,35,47,26,15,50,16,10,2,53,52],"moves":[{"ply":1,"player":"human","action":6,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[14,19,25,44,45,46,54,55],"ai":[1,8,18,28,34,36,57,58]},"scoresAfter":[0,0]},{"ply":2,"player":"ai","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[19,25,37,44,45,46,54,55],"ai":[1,8,18,28,34,36,57,58]},"scoresAfter":[0,-40]},{"ply":3,"player":"human","action":24,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[19,25,37,44,45,46,54,55],"ai":[6,8,18,28,34,36,57,58]},"scoresAfter":[-40,-40]},{"ply":4,"player":"ai","action":24,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[19,25,43,44,45,46,54,55],"ai":[6,8,18,28,34,36,57,58]},"scoresAfter":[-40,-55]},{"ply":5,"player":"human","action":18,"playedCard":25,"placeType":"discard","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[19,25,43,44,45,46,54,55],"ai":[6,8,23,28,34,36,57,58]},"scoresAfter":[-40,-55]},{"ply":6,"player":"ai","action":3,"playedCard":6,"placeType":"play","drawSource":"discard_2","drawnCard":25,"handsBefore":{"human":[19,20,43,44,45,46,54,55],"ai":[6,8,23,28,34,36,57,58]},"scoresAfter":[-40,-45]},{"ply":7,"player":"human","action":72,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[19,20,43,44,45,46,54,55],"ai":[8,23,25,28,34,36,57,58]},"scoresAfter":[-55,-45]},{"ply":8,"player":"ai","action":24,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[3,19,20,43,44,45,46,55],"ai":[8,23,25,28,34,36,57,58]},"scoresAfter":[-55,-85]},{"ply":9,"player":"human","action":6,"playedCard":3,"placeType":"discard","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[3,19,20,43,44,45,46,55],"ai":[8,23,28,34,36,51,57,58]},"scoresAfter":[-55,-85]},{"ply":10,"player":"ai","action":60,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[19,20,41,43,44,45,46,55],"ai":[8,23,28,34,36,51,57,58]},"scoresAfter":[-55,-103]},{"ply":11,"player":"human","action":84,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[19,20,41,43,44,45,46,55],"ai":[8,22,23,28,34,36,57,58]},"scoresAfter":[-49,-103]},{"ply":12,"player":"ai","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[4,19,20,41,43,44,45,46],"ai":[8,22,23,28,34,36,57,58]},"scoresAfter":[-49,-89]},{"ply":13,"player":"human","action":6,"playedCard":4,"placeType":"discard","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[4,19,20,41,43,44,45,46],"ai":[22,23,28,34,36,42,57,58]},"scoresAfter":[-49,-89]},{"ply":14,"player":"ai","action":72,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[19,20,21,41,43,44,45,46],"ai":[22,23,28,34,36,42,57,58]},"scoresAfter":[-49,-81]},{"ply":15,"player":"human","action":38,"playedCard":41,"placeType":"play","drawSource":"discard_1","drawnCard":14,"handsBefore":{"human":[19,20,21,41,43,44,45,46],"ai":[9,22,23,28,34,36,42,58]},"scoresAfter":[-41,-81]},{"ply":16,"player":"ai","action":60,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[14,19,20,21,43,44,45,46],"ai":[9,22,23,28,34,36,42,58]},"scoresAfter":[-41,-121]},{"ply":17,"player":"human","action":0,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[14,19,20,21,43,44,45,46],"ai":[9,22,23,28,34,39,42,58]},"scoresAfter":[-81,-121]},{"ply":18,"player":"ai","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[12,19,20,21,43,44,45,46],"ai":[9,22,23,28,34,39,42,58]},"scoresAfter":[-81,-112]},{"ply":19,"player":"human","action":0,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[12,19,20,21,43,44,45,46],"ai":[9,17,22,23,28,34,39,42]},"scoresAfter":[-101,-112]},{"ply":20,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[19,20,21,38,43,44,45,46],"ai":[9,17,22,23,28,34,39,42]},"scoresAfter":[-101,-96]},{"ply":21,"player":"human","action":48,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[19,20,21,38,43,44,45,46],"ai":[17,22,23,28,29,34,39,42]},"scoresAfter":[-89,-96]},{"ply":22,"player":"ai","action":72,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[19,20,21,33,38,44,45,46],"ai":[17,22,23,28,29,34,39,42]},"scoresAfter":[-89,-92]},{"ply":23,"player":"human","action":60,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[19,20,21,33,38,44,45,46],"ai":[17,22,23,28,29,34,42,59]},"scoresAfter":[-75,-92]},{"ply":24,"player":"ai","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[19,20,21,33,38,45,46,49],"ai":[17,22,23,28,29,34,42,59]},"scoresAfter":[-75,-82]},{"ply":25,"player":"human","action":60,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[19,20,21,33,38,45,46,49],"ai":[13,17,22,23,28,29,34,42]},"scoresAfter":[-59,-82]},{"ply":26,"player":"ai","action":84,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[19,20,21,30,33,38,46,49],"ai":[13,17,22,23,28,29,34,42]},"scoresAfter":[-59,-72]},{"ply":27,"player":"human","action":72,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[19,20,21,30,33,38,46,49],"ai":[13,17,22,23,28,29,34,56]},"scoresAfter":[-41,-72]},{"ply":28,"player":"ai","action":7,"playedCard":13,"placeType":"discard","drawSource":"discard_0","drawnCard":4,"handsBefore":{"human":[0,19,20,21,30,33,38,49],"ai":[13,17,22,23,28,29,34,56]},"scoresAfter":[-41,-72]},{"ply":29,"player":"human","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[0,19,20,21,30,33,38,49],"ai":[4,17,22,23,28,29,34,56]},"scoresAfter":[-41,-72]},{"ply":30,"player":"ai","action":6,"playedCard":4,"placeType":"discard","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[19,20,21,30,32,33,38,49],"ai":[4,17,22,23,28,29,34,56]},"scoresAfter":[-41,-72]},{"ply":31,"player":"human","action":78,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[19,20,21,30,32,33,38,49],"ai":[17,22,23,28,29,34,40,56]},"scoresAfter":[-41,-72]},{"ply":32,"player":"ai","action":78,"playedCard":40,"placeType":"discard","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[19,20,21,30,32,33,48,49],"ai":[17,22,23,28,29,34,40,56]},"scoresAfter":[-41,-72]},{"ply":33,"player":"human","action":78,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[19,20,21,30,32,33,48,49],"ai":[17,22,23,27,28,29,34,56]},"scoresAfter":[-41,-72]},{"ply":34,"player":"ai","action":13,"playedCard":22,"placeType":"play","drawSource":"discard_0","drawnCard":4,"handsBefore":{"human":[19,20,21,24,30,32,33,49],"ai":[17,22,23,27,28,29,34,56]},"scoresAfter":[-41,-63]},{"ply":35,"player":"human","action":90,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[19,20,21,24,30,32,33,49],"ai":[4,17,23,27,28,29,34,56]},"scoresAfter":[-41,-63]},{"ply":36,"player":"ai","action":36,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[5,19,20,21,24,30,32,33],"ai":[4,17,23,27,28,29,34,56]},"scoresAfter":[-41,-59]},{"ply":37,"player":"human","action":6,"playedCard":5,"placeType":"discard","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[5,19,20,21,24,30,32,33],"ai":[4,17,23,28,29,31,34,56]},"scoresAfter":[-41,-59]},{"ply":38,"player":"ai","action":24,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[11,19,20,21,24,30,32,33],"ai":[4,17,23,28,29,31,34,56]},"scoresAfter":[-41,-49]},{"ply":39,"player":"human","action":48,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[11,19,20,21,24,30,32,33],"ai":[4,7,17,28,29,31,34,56]},"scoresAfter":[-81,-49]},{"ply":40,"player":"ai","action":36,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[11,19,20,21,30,32,33,35],"ai":[4,7,17,28,29,31,34,56]},"scoresAfter":[-81,-43]},{"ply":41,"player":"human","action":52,"playedCard":30,"placeType":"play","drawSource":"discard_3","drawnCard":40,"handsBefore":{"human":[11,19,20,21,30,32,33,35],"ai":[4,7,17,29,31,34,47,56]},"scoresAfter":[-71,-43]},{"ply":42,"player":"ai","action":72,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[11,19,20,21,32,33,35,40],"ai":[4,7,17,29,31,34,47,56]},"scoresAfter":[-71,-23]},{"ply":43,"player":"human","action":53,"playedCard":32,"placeType":"play","drawSource":"discard_4","drawnCard":49,"handsBefore":{"human":[11,19,20,21,32,33,35,40],"ai":[4,7,17,26,29,31,34,56]},"scoresAfter":[-57,-23]},{"ply":44,"player":"ai","action":48,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[11,19,20,21,33,35,40,49],"ai":[4,7,17,26,29,31,34,56]},"scoresAfter":[-57,-15]},{"ply":45,"player":"human","action":53,"playedCard":33,"placeType":"play","drawSource":"discard_4","drawnCard":48,"handsBefore":{"human":[11,19,20,21,33,35,40,49],"ai":[4,7,15,17,26,31,34,56]},"scoresAfter":[-41,-15]},{"ply":46,"player":"ai","action":60,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[11,19,20,21,35,40,48,49],"ai":[4,7,15,17,26,31,34,56]},"scoresAfter":[-41,-3]},{"ply":47,"player":"human","action":49,"playedCard":35,"placeType":"play","drawSource":"discard_0","drawnCard":5,"handsBefore":{"human":[11,19,20,21,35,40,48,49],"ai":[4,7,15,17,26,34,50,56]},"scoresAfter":[-21,-3]},{"ply":48,"player":"ai","action":60,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[5,11,19,20,21,40,48,49],"ai":[4,7,15,17,26,34,50,56]},"scoresAfter":[-21,15]},{"ply":49,"player":"human","action":25,"playedCard":19,"placeType":"play","drawSource":"discard_0","drawnCard":0,"handsBefore":{"human":[5,11,19,20,21,40,48,49],"ai":[4,7,15,16,17,26,50,56]},"scoresAfter":[-3,15]},{"ply":50,"player":"ai","action":6,"playedCard":4,"placeType":"discard","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[0,5,11,20,21,40,48,49],"ai":[4,7,15,16,17,26,50,56]},"scoresAfter":[-3,15]},{"ply":51,"player":"human","action":36,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[0,5,11,20,21,40,48,49],"ai":[7,10,15,16,17,26,50,56]},"scoresAfter":[18,15]},{"ply":52,"player":"ai","action":12,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[0,2,5,11,21,40,48,49],"ai":[7,10,15,16,17,26,50,56]},"scoresAfter":[18,33]},{"ply":53,"player":"human","action":48,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[0,2,5,11,21,40,48,49],"ai":[7,15,16,17,26,50,53,56]},"scoresAfter":[42,33]}],"finalScores":[42,33],"outcome":"YOU WIN","finalState":{"deckOrder":[25,46,44,19,54,55,45,14,58,1,57,34,28,8,36,18,37,6,43,23,20,3,51,41,22,4,42,21,9,39,12,17,38,29,33,59,49,13,30,56,0,32,40,48,27,24,5,31,11,7,35,47,26,15,50,16,10,2,53,52],"drawPtr":60,"cardLoc":[1,4,1,5,5,1,4,2,4,4,4,1,3,5,3,2,2,2,4,3,3,3,4,4,3,4,2,4,4,4,3,4,3,3,4,3,4,3,5,4,1,3,4,3,3,3,3,4,1,1,2,4,1,2,3,3,2,4,4,4],"handPublic":[true,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,true,true,false,false,false,false,false,false,false,false,false,false],"colTop":[[0,8,10,9,6],[9,10,9,10,10]],"colHandshakes":[[0,2,1,1,0],[1,0,1,1,0]],"colLength":[[0,5,5,6,2],[5,3,6,4,4]],"piles":[[3,4],[13],[],[38],[]],"toMove":1,"stepCount":53,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"2f6c62fb-9954-4d05-a252-0034effdbdd7","seed":"yq9dxo","startedAt":"2026-07-14T15:06:22.472Z","finishedAt":"2026-07-14T15:08:57.332Z","initialDeckOrder":[43,19,42,6,49,30,20,18,4,3,46,15,1,48,45,53,11,39,13,9,35,32,34,44,21,24,14,47,59,52,37,17,38,23,55,12,26,58,16,27,36,33,50,5,51,31,57,25,54,28,8,56,2,7,0,29,10,40,41,22],"moves":[{"ply":1,"player":"human","action":90,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[6,18,19,20,30,42,43,49],"ai":[1,3,4,15,45,46,48,53]},"scoresAfter":[0,0]},{"ply":2,"player":"ai","action":90,"playedCard":53,"placeType":"discard","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[6,11,18,19,20,30,42,43],"ai":[1,3,4,15,45,46,48,53]},"scoresAfter":[0,0]},{"ply":3,"player":"human","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[6,11,18,19,20,30,42,43],"ai":[1,3,4,15,39,45,46,48]},"scoresAfter":[-15,0]},{"ply":4,"player":"ai","action":54,"playedCard":39,"placeType":"discard","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[11,13,18,19,20,30,42,43],"ai":[1,3,4,15,39,45,46,48]},"scoresAfter":[-15,0]},{"ply":5,"player":"human","action":12,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[11,13,18,19,20,30,42,43],"ai":[1,3,4,9,15,45,46,48]},"scoresAfter":[-55,0]},{"ply":6,"player":"ai","action":90,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[11,18,19,20,30,35,42,43],"ai":[1,3,4,9,15,45,46,48]},"scoresAfter":[-55,0]},{"ply":7,"player":"human","action":16,"playedCard":18,"placeType":"play","drawSource":"discard_3","drawnCard":39,"handsBefore":{"human":[11,18,19,20,30,35,42,43],"ai":[1,3,4,9,15,32,45,46]},"scoresAfter":[-45,0]},{"ply":8,"player":"ai","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[11,19,20,30,35,39,42,43],"ai":[1,3,4,9,15,32,45,46]},"scoresAfter":[-45,-40]},{"ply":9,"player":"human","action":60,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[11,19,20,30,35,39,42,43],"ai":[3,4,9,15,32,34,45,46]},"scoresAfter":[-63,-40]},{"ply":10,"player":"ai","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[11,19,20,30,35,42,43,44],"ai":[3,4,9,15,32,34,45,46]},"scoresAfter":[-63,-36]},{"ply":11,"player":"human","action":60,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[11,19,20,30,35,42,43,44],"ai":[4,9,15,21,32,34,45,46]},"scoresAfter":[-58,-36]},{"ply":12,"player":"ai","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[11,19,20,24,30,35,43,44],"ai":[4,9,15,21,32,34,45,46]},"scoresAfter":[-58,-30]},{"ply":13,"player":"human","action":72,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[11,19,20,24,30,35,43,44],"ai":[9,14,15,21,32,34,45,46]},"scoresAfter":[-52,-30]},{"ply":14,"player":"ai","action":36,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[11,19,20,24,30,35,44,47],"ai":[9,14,15,21,32,34,45,46]},"scoresAfter":[-52,-42]},{"ply":15,"player":"human","action":72,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[11,19,20,24,30,35,44,47],"ai":[9,14,15,32,34,45,46,59]},"scoresAfter":[-45,-42]},{"ply":16,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[11,19,20,24,30,35,47,52],"ai":[9,14,15,32,34,45,46,59]},"scoresAfter":[-45,-26]},{"ply":17,"player":"human","action":12,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[11,19,20,24,30,35,47,52],"ai":[14,15,32,34,37,45,46,59]},"scoresAfter":[-33,-26]},{"ply":18,"player":"ai","action":48,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[11,17,20,24,30,35,47,52],"ai":[14,15,32,34,37,45,46,59]},"scoresAfter":[-33,-66]},{"ply":19,"player":"human","action":24,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[11,17,20,24,30,35,47,52],"ai":[14,15,32,34,38,45,46,59]},"scoresAfter":[-19,-66]},{"ply":20,"player":"ai","action":6,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[11,17,23,24,30,35,47,52],"ai":[14,15,32,34,38,45,46,59]},"scoresAfter":[-19,-66]},{"ply":21,"player":"human","action":18,"playedCard":17,"placeType":"discard","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[11,17,23,24,30,35,47,52],"ai":[15,32,34,38,45,46,55,59]},"scoresAfter":[-19,-66]},{"ply":22,"player":"ai","action":6,"playedCard":15,"placeType":"discard","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[11,12,23,24,30,35,47,52],"ai":[15,32,34,38,45,46,55,59]},"scoresAfter":[-19,-66]},{"ply":23,"player":"human","action":18,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[11,12,23,24,30,35,47,52],"ai":[26,32,34,38,45,46,55,59]},"scoresAfter":[-19,-66]},{"ply":24,"player":"ai","action":48,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[11,23,24,30,35,47,52,58],"ai":[26,32,34,38,45,46,55,59]},"scoresAfter":[-19,-50]},{"ply":25,"player":"human","action":78,"playedCard":52,"placeType":"discard","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[11,23,24,30,35,47,52,58],"ai":[16,26,32,34,38,46,55,59]},"scoresAfter":[-19,-50]},{"ply":26,"player":"ai","action":12,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[11,23,24,27,30,35,47,58],"ai":[16,26,32,34,38,46,55,59]},"scoresAfter":[-19,-90]},{"ply":27,"player":"human","action":12,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[11,23,24,27,30,35,47,58],"ai":[16,32,34,36,38,46,55,59]},"scoresAfter":[1,-90]},{"ply":28,"player":"ai","action":60,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[11,24,27,30,33,35,47,58],"ai":[16,32,34,36,38,46,55,59]},"scoresAfter":[1,-72]},{"ply":29,"player":"human","action":12,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[11,24,27,30,33,35,47,58],"ai":[16,32,34,36,38,50,55,59]},"scoresAfter":[-39,-72]},{"ply":30,"player":"ai","action":65,"playedCard":50,"placeType":"play","drawSource":"discard_4","drawnCard":52,"handsBefore":{"human":[5,11,27,30,33,35,47,58],"ai":[16,32,34,36,38,50,55,59]},"scoresAfter":[-39,-112]},{"ply":31,"player":"human","action":24,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[5,11,27,30,33,35,47,58],"ai":[16,32,34,36,38,52,55,59]},"scoresAfter":[-35,-112]},{"ply":32,"player":"ai","action":11,"playedCard":16,"placeType":"discard","drawSource":"discard_4","drawnCard":48,"handsBefore":{"human":[5,11,30,33,35,47,51,58],"ai":[16,32,34,36,38,52,55,59]},"scoresAfter":[-35,-112]},{"ply":33,"player":"human","action":24,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[5,11,30,33,35,47,51,58],"ai":[32,34,36,38,48,52,55,59]},"scoresAfter":[-25,-112]},{"ply":34,"player":"ai","action":48,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[5,11,31,33,35,47,51,58],"ai":[32,34,36,38,48,52,55,59]},"scoresAfter":[-25,-132]},{"ply":35,"player":"human","action":24,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[5,11,31,33,35,47,51,58],"ai":[32,34,36,38,52,55,57,59]},"scoresAfter":[-13,-132]},{"ply":36,"player":"ai","action":5,"playedCard":32,"placeType":"play","drawSource":"discard_4","drawnCard":53,"handsBefore":{"human":[5,11,25,33,35,47,51,58],"ai":[32,34,36,38,52,55,57,59]},"scoresAfter":[-13,-118]},{"ply":37,"player":"human","action":36,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[5,11,25,33,35,47,51,58],"ai":[34,36,38,52,53,55,57,59]},"scoresAfter":[3,-118]},{"ply":38,"player":"ai","action":5,"playedCard":34,"placeType":"play","drawSource":"discard_4","drawnCard":49,"handsBefore":{"human":[5,11,25,35,47,51,54,58],"ai":[34,36,38,52,53,55,57,59]},"scoresAfter":[3,-100]},{"ply":39,"player":"human","action":36,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[5,11,25,35,47,51,54,58],"ai":[36,38,49,52,53,55,57,59]},"scoresAfter":[23,-100]},{"ply":40,"player":"ai","action":24,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[5,11,25,28,47,51,54,58],"ai":[36,38,49,52,53,55,57,59]},"scoresAfter":[23,-120]},{"ply":41,"player":"human","action":48,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[5,11,25,28,47,51,54,58],"ai":[8,36,38,52,53,55,57,59]},"scoresAfter":[33,-120]},{"ply":42,"player":"ai","action":36,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[5,11,25,28,51,54,56,58],"ai":[8,36,38,52,53,55,57,59]},"scoresAfter":[33,-108]},{"ply":43,"player":"human","action":48,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[5,11,25,28,51,54,56,58],"ai":[2,8,36,38,53,55,57,59]},"scoresAfter":[15,-108]},{"ply":44,"player":"ai","action":50,"playedCard":53,"placeType":"play","drawSource":"discard_1","drawnCard":16,"handsBefore":{"human":[5,7,11,25,28,54,56,58],"ai":[2,8,36,38,53,55,57,59]},"scoresAfter":[15,-92]},{"ply":45,"player":"human","action":14,"playedCard":7,"placeType":"play","drawSource":"discard_1","drawnCard":12,"handsBefore":{"human":[5,7,11,25,28,54,56,58],"ai":[2,8,16,36,38,55,57,59]},"scoresAfter":[21,-92]},{"ply":46,"player":"ai","action":62,"playedCard":55,"placeType":"play","drawSource":"discard_1","drawnCard":15,"handsBefore":{"human":[5,11,12,25,28,54,56,58],"ai":[2,8,16,36,38,55,57,59]},"scoresAfter":[21,-68]},{"ply":47,"player":"human","action":60,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[5,11,12,25,28,54,56,58],"ai":[2,8,15,16,36,38,57,59]},"scoresAfter":[26,-68]},{"ply":48,"player":"ai","action":72,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[0,5,11,12,25,28,56,58],"ai":[2,8,15,16,36,38,57,59]},"scoresAfter":[26,-36]},{"ply":49,"player":"human","action":74,"playedCard":56,"placeType":"play","drawSource":"discard_1","drawnCard":17,"handsBefore":{"human":[0,5,11,12,25,28,56,58],"ai":[2,8,15,16,29,36,38,59]},"scoresAfter":[33,-36]},{"ply":50,"player":"ai","action":66,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[0,5,11,12,17,25,28,58],"ai":[2,8,15,16,29,36,38,59]},"scoresAfter":[33,-36]},{"ply":51,"player":"human","action":88,"playedCard":58,"placeType":"play","drawSource":"discard_3","drawnCard":36,"handsBefore":{"human":[0,5,11,12,17,25,28,58],"ai":[2,8,10,15,16,29,38,59]},"scoresAfter":[42,-36]},{"ply":52,"player":"ai","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[0,5,11,12,17,25,28,36],"ai":[2,8,10,15,16,29,38,59]},"scoresAfter":[42,24]},{"ply":53,"player":"human","action":24,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[0,5,11,12,17,25,28,36],"ai":[2,8,10,15,16,29,38,40]},"scoresAfter":[52,24]},{"ply":54,"player":"ai","action":24,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[0,5,12,17,25,28,36,41],"ai":[2,8,10,15,16,29,38,40]},"scoresAfter":[52,42]}],"finalScores":[52,42],"outcome":"YOU WIN","finalState":{"deckOrder":[43,19,42,6,49,30,20,18,4,3,46,15,1,48,45,53,11,39,13,9,35,32,34,44,21,24,14,47,59,52,37,17,38,23,55,12,26,58,16,27,36,33,50,5,51,31,57,25,54,28,8,56,2,7,0,29,10,40,41,22],"drawPtr":60,"cardLoc":[1,4,2,4,4,1,3,3,2,4,4,3,1,3,5,2,2,1,3,3,3,4,2,3,3,1,4,3,1,2,3,3,4,3,4,3,1,4,2,3,2,1,3,3,3,4,4,3,4,4,4,3,4,4,3,4,3,4,3,4],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,true,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,10,10,10,9],[9,8,9,9,10]],"colHandshakes":[[0,1,1,0,0],[1,0,1,1,3]],"colLength":[[3,5,6,5,4],[5,1,3,3,8]],"piles":[[],[14],[],[],[]],"toMove":0,"stepCount":54,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"b988170e-74b8-4423-a5d0-355b3869759c","seed":"f9a6ro","startedAt":"2026-07-14T15:08:58.144Z","finishedAt":"2026-07-14T15:12:42.922Z","initialDeckOrder":[4,59,34,44,8,27,35,24,38,5,30,55,33,49,57,50,1,36,17,16,10,53,23,12,31,47,32,7,26,15,0,25,6,39,14,40,37,3,20,18,41,11,9,46,56,52,42,29,43,22,28,51,48,19,58,45,21,2,13,54],"moves":[{"ply":1,"player":"human","action":24,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[4,8,24,27,34,35,44,59],"ai":[5,30,33,38,49,50,55,57]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":48,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[1,4,8,27,34,35,44,59],"ai":[5,30,33,38,49,50,55,57]},"scoresAfter":[-40,-40]},{"ply":3,"player":"human","action":36,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[1,4,8,27,34,35,44,59],"ai":[5,30,33,36,38,50,55,57]},"scoresAfter":[-36,-40]},{"ply":4,"player":"ai","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[1,4,8,17,34,35,44,59],"ai":[5,30,33,36,38,50,55,57]},"scoresAfter":[-36,-56]},{"ply":5,"player":"human","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[1,4,8,17,34,35,44,59],"ai":[16,30,33,36,38,50,55,57]},"scoresAfter":[-76,-56]},{"ply":6,"player":"ai","action":54,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[4,8,10,17,34,35,44,59],"ai":[16,30,33,36,38,50,55,57]},"scoresAfter":[-76,-56]},{"ply":7,"player":"human","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[4,8,10,17,34,35,44,59],"ai":[16,30,33,36,50,53,55,57]},"scoresAfter":[-70,-56]},{"ply":8,"player":"ai","action":48,"playedCard":50,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[8,10,17,23,34,35,44,59],"ai":[16,30,33,36,50,53,55,57]},"scoresAfter":[-70,-76]},{"ply":9,"player":"human","action":24,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[8,10,17,23,34,35,44,59],"ai":[12,16,30,33,36,53,55,57]},"scoresAfter":[-86,-76]},{"ply":10,"player":"ai","action":24,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[8,10,23,31,34,35,44,59],"ai":[12,16,30,33,36,53,55,57]},"scoresAfter":[-86,-91]},{"ply":11,"player":"human","action":36,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[8,10,23,31,34,35,44,59],"ai":[12,16,33,36,47,53,55,57]},"scoresAfter":[-74,-91]},{"ply":12,"player":"ai","action":0,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[8,10,23,32,34,35,44,59],"ai":[12,16,33,36,47,53,55,57]},"scoresAfter":[-74,-131]},{"ply":13,"player":"human","action":36,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[8,10,23,32,34,35,44,59],"ai":[7,16,33,36,47,53,55,57]},"scoresAfter":[-60,-131]},{"ply":14,"player":"ai","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[8,10,23,26,34,35,44,59],"ai":[7,16,33,36,47,53,55,57]},"scoresAfter":[-60,-125]},{"ply":15,"player":"human","action":42,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[8,10,23,26,34,35,44,59],"ai":[15,16,33,36,47,53,55,57]},"scoresAfter":[-60,-125]},{"ply":16,"player":"ai","action":0,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[0,8,10,23,34,35,44,59],"ai":[15,16,33,36,47,53,55,57]},"scoresAfter":[-60,-121]},{"ply":17,"player":"human","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[0,8,10,23,34,35,44,59],"ai":[16,25,33,36,47,53,55,57]},"scoresAfter":[-60,-121]},{"ply":18,"player":"ai","action":0,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[6,8,10,23,34,35,44,59],"ai":[16,25,33,36,47,53,55,57]},"scoresAfter":[-60,-115]},{"ply":19,"player":"human","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[6,8,10,23,34,35,44,59],"ai":[25,33,36,39,47,53,55,57]},"scoresAfter":[-50,-115]},{"ply":20,"player":"ai","action":24,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[8,10,14,23,34,35,44,59],"ai":[25,33,36,39,47,53,55,57]},"scoresAfter":[-50,-155]},{"ply":21,"player":"human","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[8,10,14,23,34,35,44,59],"ai":[25,33,39,40,47,53,55,57]},"scoresAfter":[-36,-155]},{"ply":22,"player":"ai","action":12,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[10,14,23,34,35,37,44,59],"ai":[25,33,39,40,47,53,55,57]},"scoresAfter":[-36,-147]},{"ply":23,"player":"human","action":66,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[10,14,23,34,35,37,44,59],"ai":[3,25,39,40,47,53,55,57]},"scoresAfter":[-36,-147]},{"ply":24,"player":"ai","action":24,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[10,14,20,23,34,35,44,59],"ai":[3,25,39,40,47,53,55,57]},"scoresAfter":[-36,-143]},{"ply":25,"player":"human","action":18,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[10,14,20,23,34,35,44,59],"ai":[3,18,25,40,47,53,55,57]},"scoresAfter":[-36,-143]},{"ply":26,"player":"ai","action":12,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[10,20,23,34,35,41,44,59],"ai":[3,18,25,40,47,53,55,57]},"scoresAfter":[-36,-133]},{"ply":27,"player":"human","action":60,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[10,20,23,34,35,41,44,59],"ai":[3,11,25,40,47,53,55,57]},"scoresAfter":[-52,-133]},{"ply":28,"player":"ai","action":12,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[9,10,20,23,34,35,44,59],"ai":[3,11,25,40,47,53,55,57]},"scoresAfter":[-52,-123]},{"ply":29,"player":"human","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[9,10,20,23,34,35,44,59],"ai":[3,25,40,46,47,53,55,57]},"scoresAfter":[-36,-123]},{"ply":30,"player":"ai","action":24,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[10,20,23,34,35,44,56,59],"ai":[3,25,40,46,47,53,55,57]},"scoresAfter":[-36,-117]},{"ply":31,"player":"human","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[10,20,23,34,35,44,56,59],"ai":[3,25,46,47,52,53,55,57]},"scoresAfter":[-18,-117]},{"ply":32,"player":"ai","action":24,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[20,23,34,35,42,44,56,59],"ai":[3,25,46,47,52,53,55,57]},"scoresAfter":[-18,-99]},{"ply":33,"player":"human","action":48,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[20,23,34,35,42,44,56,59],"ai":[3,25,29,47,52,53,55,57]},"scoresAfter":[-13,-99]},{"ply":34,"player":"ai","action":36,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[20,23,34,35,43,44,56,59],"ai":[3,25,29,47,52,53,55,57]},"scoresAfter":[-13,-79]},{"ply":35,"player":"human","action":48,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[20,23,34,35,43,44,56,59],"ai":[3,22,25,29,52,53,55,57]},"scoresAfter":[-7,-79]},{"ply":36,"player":"ai","action":12,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[20,23,28,34,35,44,56,59],"ai":[3,22,25,29,52,53,55,57]},"scoresAfter":[-7,-61]},{"ply":37,"player":"human","action":60,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[20,23,28,34,35,44,56,59],"ai":[3,25,29,51,52,53,55,57]},"scoresAfter":[0,-61]},{"ply":38,"player":"ai","action":36,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[20,23,28,34,35,48,56,59],"ai":[3,25,29,51,52,53,55,57]},"scoresAfter":[0,-55]},{"ply":39,"player":"human","action":36,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[20,23,28,34,35,48,56,59],"ai":[3,19,25,29,52,53,55,57]},"scoresAfter":[18,-55]},{"ply":40,"player":"ai","action":48,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[20,23,28,35,48,56,58,59],"ai":[3,19,25,29,52,53,55,57]},"scoresAfter":[18,-46]},{"ply":41,"player":"human","action":39,"playedCard":35,"placeType":"play","drawSource":"discard_2","drawnCard":26,"handsBefore":{"human":[20,23,28,35,48,56,58,59],"ai":[3,19,25,29,45,53,55,57]},"scoresAfter":[38,-46]},{"ply":42,"player":"ai","action":62,"playedCard":53,"placeType":"play","drawSource":"discard_1","drawnCard":14,"handsBefore":{"human":[20,23,26,28,48,56,58,59],"ai":[3,19,25,29,45,53,55,57]},"scoresAfter":[38,-34]},{"ply":43,"player":"human","action":64,"playedCard":56,"placeType":"play","drawSource":"discard_3","drawnCard":37,"handsBefore":{"human":[20,23,26,28,48,56,58,59],"ai":[3,14,19,25,29,45,55,57]},"scoresAfter":[25,-34]},{"ply":44,"player":"ai","action":72,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[20,23,26,28,37,48,58,59],"ai":[3,14,19,25,29,45,55,57]},"scoresAfter":[25,-16]},{"ply":45,"player":"human","action":76,"playedCard":58,"placeType":"play","drawSource":"discard_3","drawnCard":38,"handsBefore":{"human":[20,23,26,28,37,48,58,59],"ai":[3,14,19,21,25,29,45,57]},"scoresAfter":[34,-16]},{"ply":46,"player":"ai","action":84,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[20,23,26,28,37,38,48,59],"ai":[3,14,19,21,25,29,45,57]},"scoresAfter":[34,8]},{"ply":47,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[20,23,26,28,37,38,48,59],"ai":[2,3,14,19,21,25,29,45]},"scoresAfter":[44,8]},{"ply":48,"player":"ai","action":18,"playedCard":3,"placeType":"discard","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[13,20,23,26,28,37,38,48],"ai":[2,3,14,19,21,25,29,45]},"scoresAfter":[44,8]}],"finalScores":[44,8],"outcome":"YOU WIN","finalState":{"deckOrder":[4,59,34,44,8,27,35,24,38,5,30,55,33,49,57,50,1,36,17,16,10,53,23,12,31,47,32,7,26,15,0,25,6,39,14,40,37,3,20,18,41,11,9,46,56,52,42,29,43,22,28,51,48,19,58,45,21,2,13,54],"drawPtr":60,"cardLoc":[5,3,2,5,3,4,3,4,3,3,3,4,4,1,2,4,4,3,4,2,1,2,4,1,3,2,1,3,1,2,4,3,3,4,3,3,4,1,1,4,4,3,3,3,3,2,4,4,1,4,4,4,4,4,2,4,3,4,3,3],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[9,4,10,7,10],[10,9,8,10,8]],"colHandshakes":[[1,0,1,0,0],[0,1,0,1,2]],"colLength":[[6,1,6,4,3],[3,5,2,5,7]],"piles":[[0,3],[],[],[],[]],"toMove":0,"stepCount":48,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"dfeec9a4-6251-4932-8e1a-41dd1a30b790","seed":"m7afql","startedAt":"2026-07-14T15:12:43.953Z","finishedAt":"2026-07-14T15:15:12.340Z","initialDeckOrder":[35,17,14,57,7,11,31,5,28,30,54,39,49,37,12,55,0,2,43,10,58,51,27,48,53,33,23,3,6,34,21,22,46,41,19,26,59,40,8,24,52,25,15,18,13,50,32,4,38,56,42,44,45,16,20,47,29,36,9,1],"moves":[{"ply":1,"player":"human","action":42,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[5,7,11,14,17,31,35,57],"ai":[12,28,30,37,39,49,54,55]},"scoresAfter":[0,0]},{"ply":2,"player":"ai","action":72,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[0,5,7,11,17,31,35,57],"ai":[12,28,30,37,39,49,54,55]},"scoresAfter":[0,-15]},{"ply":3,"player":"human","action":0,"playedCard":0,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[0,5,7,11,17,31,35,57],"ai":[2,12,28,30,37,39,49,55]},"scoresAfter":[-40,-15]},{"ply":4,"player":"ai","action":84,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[5,7,11,17,31,35,43,57],"ai":[2,12,28,30,37,39,49,55]},"scoresAfter":[-40,-9]},{"ply":5,"player":"human","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[5,7,11,17,31,35,43,57],"ai":[2,10,12,28,30,37,39,49]},"scoresAfter":[-32,-9]},{"ply":6,"player":"ai","action":72,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[7,11,17,31,35,43,57,58],"ai":[2,10,12,28,30,37,39,49]},"scoresAfter":[-32,-27]},{"ply":7,"player":"human","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[7,11,17,31,35,43,57,58],"ai":[2,10,12,28,30,37,49,51]},"scoresAfter":[-20,-27]},{"ply":8,"player":"ai","action":78,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[11,17,27,31,35,43,57,58],"ai":[2,10,12,28,30,37,49,51]},"scoresAfter":[-20,-27]},{"ply":9,"player":"human","action":24,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[11,17,27,31,35,43,57,58],"ai":[2,10,12,28,30,37,48,51]},"scoresAfter":[-38,-27]},{"ply":10,"player":"ai","action":78,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[11,17,31,35,43,53,57,58],"ai":[2,10,12,28,30,37,48,51]},"scoresAfter":[-38,-27]},{"ply":11,"player":"human","action":23,"playedCard":17,"placeType":"discard","drawSource":"discard_4","drawnCard":48,"handsBefore":{"human":[11,17,31,35,43,53,57,58],"ai":[2,10,12,28,30,33,37,51]},"scoresAfter":[-38,-27]},{"ply":12,"player":"ai","action":12,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[11,31,35,43,48,53,57,58],"ai":[2,10,12,28,30,33,37,51]},"scoresAfter":[-38,-38]},{"ply":13,"player":"human","action":53,"playedCard":48,"placeType":"play","drawSource":"discard_4","drawnCard":49,"handsBefore":{"human":[11,31,35,43,48,53,57,58],"ai":[2,12,23,28,30,33,37,51]},"scoresAfter":[-78,-38]},{"ply":14,"player":"ai","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[11,31,35,43,49,53,57,58],"ai":[2,12,23,28,30,33,37,51]},"scoresAfter":[-78,-38]},{"ply":15,"player":"human","action":48,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[11,31,35,43,49,53,57,58],"ai":[3,12,23,28,30,33,37,51]},"scoresAfter":[-98,-38]},{"ply":16,"player":"ai","action":78,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[6,11,31,35,43,53,57,58],"ai":[3,12,23,28,30,33,37,51]},"scoresAfter":[-98,-38]},{"ply":17,"player":"human","action":6,"playedCard":6,"placeType":"discard","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[6,11,31,35,43,53,57,58],"ai":[3,12,23,28,30,33,34,51]},"scoresAfter":[-98,-38]},{"ply":18,"player":"ai","action":12,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[11,21,31,35,43,53,57,58],"ai":[3,12,23,28,30,33,34,51]},"scoresAfter":[-98,-78]},{"ply":19,"player":"human","action":60,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[11,21,31,35,43,53,57,58],"ai":[3,22,23,28,30,33,34,51]},"scoresAfter":[-86,-78]},{"ply":20,"player":"ai","action":38,"playedCard":28,"placeType":"play","drawSource":"discard_1","drawnCard":17,"handsBefore":{"human":[11,21,31,35,43,46,57,58],"ai":[3,22,23,28,30,33,34,51]},"scoresAfter":[-86,-95]},{"ply":21,"player":"human","action":72,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[11,21,31,35,43,46,57,58],"ai":[3,17,22,23,30,33,34,51]},"scoresAfter":[-62,-95]},{"ply":22,"player":"ai","action":50,"playedCard":30,"placeType":"play","drawSource":"discard_1","drawnCard":14,"handsBefore":{"human":[11,21,31,35,41,43,46,58],"ai":[3,17,22,23,30,33,34,51]},"scoresAfter":[-62,-90]},{"ply":23,"player":"human","action":88,"playedCard":58,"placeType":"play","drawSource":"discard_3","drawnCard":37,"handsBefore":{"human":[11,21,31,35,41,43,46,58],"ai":[3,14,17,22,23,33,34,51]},"scoresAfter":[-35,-90]},{"ply":24,"player":"ai","action":12,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[11,21,31,35,37,41,43,46],"ai":[3,14,17,22,23,33,34,51]},"scoresAfter":[-35,-110]},{"ply":25,"player":"human","action":48,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[11,21,31,35,37,41,43,46],"ai":[3,17,19,22,23,33,34,51]},"scoresAfter":[-75,-110]},{"ply":26,"player":"ai","action":60,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[11,21,26,31,35,41,43,46],"ai":[3,17,19,22,23,33,34,51]},"scoresAfter":[-75,-102]},{"ply":27,"player":"human","action":30,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[11,21,26,31,35,41,43,46],"ai":[3,17,19,22,23,34,51,59]},"scoresAfter":[-75,-102]},{"ply":28,"player":"ai","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[11,21,31,35,40,41,43,46],"ai":[3,17,19,22,23,34,51,59]},"scoresAfter":[-75,-92]},{"ply":29,"player":"human","action":48,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[11,21,31,35,40,41,43,46],"ai":[3,8,17,19,22,23,34,51]},"scoresAfter":[-69,-92]},{"ply":30,"player":"ai","action":6,"playedCard":3,"placeType":"discard","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[11,21,24,31,35,41,43,46],"ai":[3,8,17,19,22,23,34,51]},"scoresAfter":[-69,-92]},{"ply":31,"player":"human","action":30,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[11,21,24,31,35,41,43,46],"ai":[8,17,19,22,23,34,51,52]},"scoresAfter":[-69,-92]},{"ply":32,"player":"ai","action":90,"playedCard":52,"placeType":"discard","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[11,21,25,31,35,41,43,46],"ai":[8,17,19,22,23,34,51,52]},"scoresAfter":[-69,-92]},{"ply":33,"player":"human","action":30,"playedCard":25,"placeType":"discard","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[11,21,25,31,35,41,43,46],"ai":[8,15,17,19,22,23,34,51]},"scoresAfter":[-69,-92]},{"ply":34,"player":"ai","action":6,"playedCard":8,"placeType":"discard","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[11,18,21,31,35,41,43,46],"ai":[8,15,17,19,22,23,34,51]},"scoresAfter":[-69,-92]},{"ply":35,"player":"human","action":60,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[11,18,21,31,35,41,43,46],"ai":[13,15,17,19,22,23,34,51]},"scoresAfter":[-61,-92]},{"ply":36,"player":"ai","action":0,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[11,18,21,31,35,43,46,50],"ai":[13,15,17,19,22,23,34,51]},"scoresAfter":[-61,-112]},{"ply":37,"player":"human","action":60,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[11,18,21,31,35,43,46,50],"ai":[15,17,19,22,23,32,34,51]},"scoresAfter":[-49,-112]},{"ply":38,"player":"ai","action":0,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[4,11,18,21,31,35,46,50],"ai":[15,17,19,22,23,32,34,51]},"scoresAfter":[-49,-104]},{"ply":39,"player":"human","action":91,"playedCard":50,"placeType":"discard","drawSource":"discard_0","drawnCard":8,"handsBefore":{"human":[4,11,18,21,31,35,46,50],"ai":[17,19,22,23,32,34,38,51]},"scoresAfter":[-49,-104]},{"ply":40,"player":"ai","action":0,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[4,8,11,18,21,31,35,46],"ai":[17,19,22,23,32,34,38,51]},"scoresAfter":[-49,-88]},{"ply":41,"player":"human","action":12,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[4,8,11,18,21,31,35,46],"ai":[19,22,23,32,34,38,51,56]},"scoresAfter":[-35,-88]},{"ply":42,"player":"ai","action":48,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[4,11,18,21,31,35,42,46],"ai":[19,22,23,32,34,38,51,56]},"scoresAfter":[-35,-79]},{"ply":43,"player":"human","action":48,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[4,11,18,21,31,35,42,46],"ai":[19,22,23,32,38,44,51,56]},"scoresAfter":[-29,-79]},{"ply":44,"player":"ai","action":60,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[4,11,18,21,35,42,45,46],"ai":[19,22,23,32,38,44,51,56]},"scoresAfter":[-29,-72]},{"ply":45,"player":"human","action":48,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[4,11,18,21,35,42,45,46],"ai":[16,19,22,23,32,38,51,56]},"scoresAfter":[-19,-72]},{"ply":46,"player":"ai","action":12,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[4,11,18,20,21,42,45,46],"ai":[16,19,22,23,32,38,51,56]},"scoresAfter":[-19,-48]},{"ply":47,"player":"human","action":72,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[4,11,18,20,21,42,45,46],"ai":[16,22,23,32,38,47,51,56]},"scoresAfter":[-3,-48]},{"ply":48,"player":"ai","action":15,"playedCard":22,"placeType":"play","drawSource":"discard_2","drawnCard":25,"handsBefore":{"human":[4,11,18,20,21,29,42,46],"ai":[16,22,23,32,38,47,51,56]},"scoresAfter":[-3,-12]},{"ply":49,"player":"human","action":12,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[4,11,18,20,21,29,42,46],"ai":[16,23,25,32,38,47,51,56]},"scoresAfter":[17,-12]},{"ply":50,"player":"ai","action":15,"playedCard":23,"placeType":"play","drawSource":"discard_2","drawnCard":24,"handsBefore":{"human":[4,18,20,21,29,36,42,46],"ai":[16,23,25,32,38,47,51,56]},"scoresAfter":[17,48]},{"ply":51,"player":"human","action":84,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[4,18,20,21,29,36,42,46],"ai":[16,24,25,32,38,47,51,56]},"scoresAfter":[35,48]},{"ply":52,"player":"ai","action":60,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[4,9,18,20,21,29,36,42],"ai":[16,24,25,32,38,47,51,56]},"scoresAfter":[35,58]}],"finalScores":[35,58],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[35,17,14,57,7,11,31,5,28,30,54,39,49,37,12,55,0,2,43,10,58,51,27,48,53,33,23,3,6,34,21,22,46,41,19,26,59,40,8,24,52,25,15,18,13,50,32,4,38,56,42,44,45,16,20,47,29,36,9,1],"drawPtr":60,"cardLoc":[3,2,5,5,1,3,5,3,3,1,4,3,4,4,4,4,2,4,1,4,1,1,4,4,2,2,5,3,4,1,4,3,2,4,4,3,1,3,2,4,3,3,1,3,4,3,3,4,3,3,5,2,5,3,4,4,2,3,3,4],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,0,10,9,9],[9,10,9,10,10]],"colHandshakes":[[1,0,0,1,2],[0,3,0,0,0]],"colLength":[[5,0,3,6,5],[1,8,4,3,3]],"piles":[[2,6,3],[],[26],[],[52,50]],"toMove":0,"stepCount":52,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"57482daf-aca1-4ab0-8ce9-40dc25af3140","seed":"turhml","startedAt":"2026-07-14T15:15:13.718Z","finishedAt":"2026-07-14T15:17:54.452Z","initialDeckOrder":[0,23,37,54,12,47,34,7,4,29,44,57,36,41,10,50,2,17,25,35,49,42,20,16,21,3,43,5,18,51,11,59,8,33,9,31,30,38,22,58,32,15,24,28,53,56,55,19,14,40,46,6,52,13,48,26,45,1,39,27],"moves":[{"ply":1,"player":"human","action":24,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[0,7,12,23,34,37,47,54],"ai":[4,10,29,36,41,44,50,57]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":72,"playedCard":50,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[0,2,7,23,34,37,47,54],"ai":[4,10,29,36,41,44,50,57]},"scoresAfter":[-40,-40]},{"ply":3,"player":"human","action":60,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[0,2,7,23,34,37,47,54],"ai":[4,10,17,29,36,41,44,57]},"scoresAfter":[-80,-40]},{"ply":4,"player":"ai","action":36,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[0,2,7,23,25,34,47,54],"ai":[4,10,17,29,36,41,44,57]},"scoresAfter":[-80,-56]},{"ply":5,"player":"human","action":48,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[0,2,7,23,25,34,47,54],"ai":[4,10,17,35,36,41,44,57]},"scoresAfter":[-120,-56]},{"ply":6,"player":"ai","action":48,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[0,2,7,23,34,47,49,54],"ai":[4,10,17,35,36,41,44,57]},"scoresAfter":[-120,-96]},{"ply":7,"player":"human","action":78,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[0,2,7,23,34,47,49,54],"ai":[4,10,17,35,41,42,44,57]},"scoresAfter":[-120,-96]},{"ply":8,"player":"ai","action":48,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[0,2,7,20,23,34,47,54],"ai":[4,10,17,35,41,42,44,57]},"scoresAfter":[-120,-88]},{"ply":9,"player":"human","action":18,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[0,2,7,20,23,34,47,54],"ai":[4,10,16,17,35,42,44,57]},"scoresAfter":[-120,-88]},{"ply":10,"player":"ai","action":60,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[0,7,20,21,23,34,47,54],"ai":[4,10,16,17,35,42,44,57]},"scoresAfter":[-120,-78]},{"ply":11,"player":"human","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[0,7,20,21,23,34,47,54],"ai":[3,4,10,16,17,35,44,57]},"scoresAfter":[-120,-78]},{"ply":12,"player":"ai","action":5,"playedCard":3,"placeType":"play","drawSource":"discard_4","drawnCard":49,"handsBefore":{"human":[7,20,21,23,34,43,47,54],"ai":[3,4,10,16,17,35,44,57]},"scoresAfter":[-120,-96]},{"ply":13,"player":"human","action":12,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[7,20,21,23,34,43,47,54],"ai":[4,10,16,17,35,44,49,57]},"scoresAfter":[-106,-96]},{"ply":14,"player":"ai","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[5,7,21,23,34,43,47,54],"ai":[4,10,16,17,35,44,49,57]},"scoresAfter":[-106,-93]},{"ply":15,"player":"human","action":24,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[5,7,21,23,34,43,47,54],"ai":[10,16,17,18,35,44,49,57]},"scoresAfter":[-90,-93]},{"ply":16,"player":"ai","action":12,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[5,7,23,34,43,47,51,54],"ai":[10,16,17,18,35,44,49,57]},"scoresAfter":[-90,-110]},{"ply":17,"player":"human","action":24,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[5,7,23,34,43,47,51,54],"ai":[10,11,17,18,35,44,49,57]},"scoresAfter":[-70,-110]},{"ply":18,"player":"ai","action":48,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[5,7,34,43,47,51,54,59],"ai":[10,11,17,18,35,44,49,57]},"scoresAfter":[-70,-100]},{"ply":19,"player":"human","action":60,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[5,7,34,43,47,51,54,59],"ai":[8,10,11,17,18,44,49,57]},"scoresAfter":[-88,-100]},{"ply":20,"player":"ai","action":60,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[5,7,33,34,43,47,54,59],"ai":[8,10,11,17,18,44,49,57]},"scoresAfter":[-88,-86]},{"ply":21,"player":"human","action":72,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[5,7,33,34,43,47,54,59],"ai":[8,9,10,11,17,18,49,57]},"scoresAfter":[-83,-86]},{"ply":22,"player":"ai","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[5,7,31,33,34,43,47,59],"ai":[8,9,10,11,17,18,49,57]},"scoresAfter":[-83,-79]},{"ply":23,"player":"human","action":24,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[5,7,31,33,34,43,47,59],"ai":[9,10,11,17,18,30,49,57]},"scoresAfter":[-71,-79]},{"ply":24,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[5,7,33,34,38,43,47,59],"ai":[9,10,11,17,18,30,49,57]},"scoresAfter":[-71,-71]},{"ply":25,"player":"human","action":48,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[5,7,33,34,38,43,47,59],"ai":[10,11,17,18,22,30,49,57]},"scoresAfter":[-91,-71]},{"ply":26,"player":"ai","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[5,7,33,34,43,47,58,59],"ai":[10,11,17,18,22,30,49,57]},"scoresAfter":[-91,-62]},{"ply":27,"player":"human","action":72,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[5,7,33,34,43,47,58,59],"ai":[11,17,18,22,30,32,49,57]},"scoresAfter":[-82,-62]},{"ply":28,"player":"ai","action":78,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[5,7,15,33,34,43,47,59],"ai":[11,17,18,22,30,32,49,57]},"scoresAfter":[-82,-62]},{"ply":29,"player":"human","action":30,"playedCard":15,"placeType":"discard","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[5,7,15,33,34,43,47,59],"ai":[11,17,18,22,24,30,32,57]},"scoresAfter":[-82,-62]},{"ply":30,"player":"ai","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[5,7,28,33,34,43,47,59],"ai":[11,17,18,22,24,30,32,57]},"scoresAfter":[-82,-52]},{"ply":31,"player":"human","action":30,"playedCard":28,"placeType":"discard","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[5,7,28,33,34,43,47,59],"ai":[17,18,22,24,30,32,53,57]},"scoresAfter":[-82,-52]},{"ply":32,"player":"ai","action":0,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[5,7,33,34,43,47,56,59],"ai":[17,18,22,24,30,32,53,57]},"scoresAfter":[-82,-48]},{"ply":33,"player":"human","action":48,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[5,7,33,34,43,47,56,59],"ai":[18,22,24,30,32,53,55,57]},"scoresAfter":[-64,-48]},{"ply":34,"player":"ai","action":0,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[5,7,19,33,34,47,56,59],"ai":[18,22,24,30,32,53,55,57]},"scoresAfter":[-64,-43]},{"ply":35,"player":"human","action":6,"playedCard":5,"placeType":"discard","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[5,7,19,33,34,47,56,59],"ai":[14,22,24,30,32,53,55,57]},"scoresAfter":[-64,-43]},{"ply":36,"player":"ai","action":17,"playedCard":22,"placeType":"play","drawSource":"discard_4","drawnCard":49,"handsBefore":{"human":[7,19,33,34,40,47,56,59],"ai":[14,22,24,30,32,53,55,57]},"scoresAfter":[-64,-34]},{"ply":37,"player":"human","action":6,"playedCard":7,"placeType":"discard","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[7,19,33,34,40,47,56,59],"ai":[14,24,30,32,49,53,55,57]},"scoresAfter":[-64,-34]},{"ply":38,"player":"ai","action":48,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[19,33,34,40,46,47,56,59],"ai":[14,24,30,32,49,53,55,57]},"scoresAfter":[-64,-54]},{"ply":39,"player":"human","action":48,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[19,33,34,40,46,47,56,59],"ai":[6,14,24,30,32,53,55,57]},"scoresAfter":[-37,-54]},{"ply":40,"player":"ai","action":60,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[19,33,34,40,47,52,56,59],"ai":[6,14,24,30,32,53,55,57]},"scoresAfter":[-37,-42]},{"ply":41,"player":"human","action":48,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[19,33,34,40,47,52,56,59],"ai":[6,13,14,24,30,32,55,57]},"scoresAfter":[-7,-42]},{"ply":42,"player":"ai","action":72,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[19,33,34,40,48,52,56,59],"ai":[6,13,14,24,30,32,55,57]},"scoresAfter":[-7,-24]},{"ply":43,"player":"human","action":87,"playedCard":59,"placeType":"play","drawSource":"discard_2","drawnCard":28,"handsBefore":{"human":[19,33,34,40,48,52,56,59],"ai":[6,13,14,24,26,30,32,57]},"scoresAfter":[3,-24]},{"ply":44,"player":"ai","action":86,"playedCard":57,"placeType":"play","drawSource":"discard_1","drawnCard":15,"handsBefore":{"human":[19,28,33,34,40,48,52,56],"ai":[6,13,14,24,26,30,32,57]},"scoresAfter":[3,0]},{"ply":45,"player":"human","action":25,"playedCard":33,"placeType":"play","drawSource":"discard_0","drawnCard":7,"handsBefore":{"human":[19,28,33,34,40,48,52,56],"ai":[6,13,14,15,24,26,30,32]},"scoresAfter":[19,0]},{"ply":46,"player":"ai","action":54,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[7,19,28,34,40,48,52,56],"ai":[6,13,14,15,24,26,30,32]},"scoresAfter":[19,0]},{"ply":47,"player":"human","action":36,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[7,19,28,34,40,48,52,56],"ai":[6,13,14,15,26,30,32,45]},"scoresAfter":[37,0]},{"ply":48,"player":"ai","action":84,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[1,7,19,28,40,48,52,56],"ai":[6,13,14,15,26,30,32,45]},"scoresAfter":[37,16]},{"ply":49,"player":"human","action":18,"playedCard":7,"placeType":"discard","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[1,7,19,28,40,48,52,56],"ai":[6,13,14,15,26,30,32,39]},"scoresAfter":[37,16]}],"finalScores":[37,16],"outcome":"YOU WIN","finalState":{"deckOrder":[0,23,37,54,12,47,34,7,4,29,44,57,36,41,10,50,2,17,25,35,49,42,20,16,21,3,43,5,18,51,11,59,8,33,9,31,30,38,22,58,32,15,24,28,53,56,55,19,14,40,46,6,52,13,48,26,45,1,39,27],"drawPtr":60,"cardLoc":[5,1,5,4,4,5,2,5,4,4,4,4,3,2,2,2,4,4,4,1,3,3,4,3,5,3,2,1,1,4,2,3,2,3,3,4,4,3,3,2,1,4,4,3,4,4,3,3,1,4,4,3,1,4,3,4,1,4,3,3],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[0,10,9,10,10],[10,9,10,8,8]],"colHandshakes":[[0,1,1,2,0],[0,0,0,1,2]],"colLength":[[0,4,4,5,4],[6,4,2,5,5]],"piles":[[2,0,5,7],[],[24],[],[]],"toMove":1,"stepCount":49,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"d76eb23f-730d-4dea-821e-da17f55d2d60","seed":"1se2vk","startedAt":"2026-07-14T15:17:55.263Z","finishedAt":"2026-07-14T15:20:41.074Z","initialDeckOrder":[23,44,38,39,49,0,19,47,12,10,27,16,59,8,25,15,17,2,54,43,58,37,3,35,26,46,42,6,56,18,51,28,24,57,5,20,22,41,48,40,33,4,9,7,55,53,11,45,21,14,31,30,32,1,13,29,34,36,52,50],"moves":[{"ply":1,"player":"human","action":36,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[0,19,23,38,39,44,47,49],"ai":[8,10,12,15,16,25,27,59]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":54,"playedCard":16,"placeType":"discard","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[0,17,19,23,39,44,47,49],"ai":[8,10,12,15,16,25,27,59]},"scoresAfter":[-40,0]},{"ply":3,"player":"human","action":92,"playedCard":49,"placeType":"discard","drawSource":"discard_1","drawnCard":16,"handsBefore":{"human":[0,17,19,23,39,44,47,49],"ai":[2,8,10,12,15,25,27,59]},"scoresAfter":[-40,0]},{"ply":4,"player":"ai","action":0,"playedCard":2,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[0,16,17,19,23,39,44,47],"ai":[2,8,10,12,15,25,27,59]},"scoresAfter":[-40,-40]},{"ply":5,"player":"human","action":12,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[0,16,17,19,23,39,44,47],"ai":[8,10,12,15,25,27,54,59]},"scoresAfter":[-57,-40]},{"ply":6,"player":"ai","action":42,"playedCard":15,"placeType":"discard","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[0,17,19,23,39,43,44,47],"ai":[8,10,12,15,25,27,54,59]},"scoresAfter":[-57,-40]},{"ply":7,"player":"human","action":12,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[0,17,19,23,39,43,44,47],"ai":[8,10,12,25,27,54,58,59]},"scoresAfter":[-53,-40]},{"ply":8,"player":"ai","action":30,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[0,19,23,37,39,43,44,47],"ai":[8,10,12,25,27,54,58,59]},"scoresAfter":[-53,-40]},{"ply":9,"player":"human","action":36,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[0,19,23,37,39,43,44,47],"ai":[3,8,10,25,27,54,58,59]},"scoresAfter":[-73,-40]},{"ply":10,"player":"ai","action":5,"playedCard":3,"placeType":"play","drawSource":"discard_4","drawnCard":49,"handsBefore":{"human":[0,19,23,35,39,43,44,47],"ai":[3,8,10,25,27,54,58,59]},"scoresAfter":[-73,-36]},{"ply":11,"player":"human","action":48,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[0,19,23,35,39,43,44,47],"ai":[8,10,25,27,49,54,58,59]},"scoresAfter":[-67,-36]},{"ply":12,"player":"ai","action":48,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[0,19,23,26,35,43,44,47],"ai":[8,10,25,27,49,54,58,59]},"scoresAfter":[-67,-76]},{"ply":13,"player":"human","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[0,19,23,26,35,43,44,47],"ai":[8,10,25,27,46,54,58,59]},"scoresAfter":[-67,-76]},{"ply":14,"player":"ai","action":30,"playedCard":25,"placeType":"discard","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[19,23,26,35,42,43,44,47],"ai":[8,10,25,27,46,54,58,59]},"scoresAfter":[-67,-76]},{"ply":15,"player":"human","action":48,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[19,23,26,35,42,43,44,47],"ai":[6,8,10,27,46,54,58,59]},"scoresAfter":[-52,-76]},{"ply":16,"player":"ai","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[19,23,26,35,43,44,47,56],"ai":[6,8,10,27,46,54,58,59]},"scoresAfter":[-52,-66]},{"ply":17,"player":"human","action":48,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[19,23,26,35,43,44,47,56],"ai":[8,10,18,27,46,54,58,59]},"scoresAfter":[-34,-66]},{"ply":18,"player":"ai","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[19,23,26,35,44,47,51,56],"ai":[8,10,18,27,46,54,58,59]},"scoresAfter":[-34,-52]},{"ply":19,"player":"human","action":48,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[19,23,26,35,44,47,51,56],"ai":[10,18,27,28,46,54,58,59]},"scoresAfter":[-13,-52]},{"ply":20,"player":"ai","action":24,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[19,23,24,26,35,47,51,56],"ai":[10,18,27,28,46,54,58,59]},"scoresAfter":[-13,-70]},{"ply":21,"player":"human","action":0,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[19,23,24,26,35,47,51,56],"ai":[10,18,28,46,54,57,58,59]},"scoresAfter":[-7,-70]},{"ply":22,"player":"ai","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[5,23,24,26,35,47,51,56],"ai":[10,18,28,46,54,57,58,59]},"scoresAfter":[-7,-52]},{"ply":23,"player":"human","action":6,"playedCard":5,"placeType":"discard","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[5,23,24,26,35,47,51,56],"ai":[18,20,28,46,54,57,58,59]},"scoresAfter":[-7,-52]},{"ply":24,"player":"ai","action":24,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[22,23,24,26,35,47,51,56],"ai":[18,20,28,46,54,57,58,59]},"scoresAfter":[-7,-49]},{"ply":25,"player":"human","action":0,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[22,23,24,26,35,47,51,56],"ai":[18,20,41,46,54,57,58,59]},"scoresAfter":[2,-49]},{"ply":26,"player":"ai","action":0,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[23,24,26,35,47,48,51,56],"ai":[18,20,41,46,54,57,58,59]},"scoresAfter":[2,-64]},{"ply":27,"player":"human","action":66,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[23,24,26,35,47,48,51,56],"ai":[20,40,41,46,54,57,58,59]},"scoresAfter":[2,-64]},{"ply":28,"player":"ai","action":5,"playedCard":20,"placeType":"play","drawSource":"discard_4","drawnCard":48,"handsBefore":{"human":[23,24,26,33,35,47,51,56],"ai":[20,40,41,46,54,57,58,59]},"scoresAfter":[2,-57]},{"ply":29,"player":"human","action":15,"playedCard":24,"placeType":"play","drawSource":"discard_2","drawnCard":25,"handsBefore":{"human":[23,24,26,33,35,47,51,56],"ai":[40,41,46,48,54,57,58,59]},"scoresAfter":[-38,-57]},{"ply":30,"player":"ai","action":0,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[23,25,26,33,35,47,51,56],"ai":[40,41,46,48,54,57,58,59]},"scoresAfter":[-38,-74]},{"ply":31,"player":"human","action":12,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[23,25,26,33,35,47,51,56],"ai":[4,41,46,48,54,57,58,59]},"scoresAfter":[-58,-74]},{"ply":32,"player":"ai","action":12,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[9,23,26,33,35,47,51,56],"ai":[4,41,46,48,54,57,58,59]},"scoresAfter":[-58,-70]},{"ply":33,"player":"human","action":6,"playedCard":9,"placeType":"discard","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[9,23,26,33,35,47,51,56],"ai":[4,7,46,48,54,57,58,59]},"scoresAfter":[-58,-70]},{"ply":34,"player":"ai","action":25,"playedCard":46,"placeType":"play","drawSource":"discard_0","drawnCard":9,"handsBefore":{"human":[23,26,33,35,47,51,55,56],"ai":[4,7,46,48,54,57,58,59]},"scoresAfter":[-58,-61]},{"ply":35,"player":"human","action":0,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[23,26,33,35,47,51,55,56],"ai":[4,7,9,48,54,57,58,59]},"scoresAfter":[-48,-61]},{"ply":36,"player":"ai","action":30,"playedCard":9,"placeType":"discard","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[26,33,35,47,51,53,55,56],"ai":[4,7,9,48,54,57,58,59]},"scoresAfter":[-48,-61]},{"ply":37,"player":"human","action":48,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[26,33,35,47,51,53,55,56],"ai":[4,7,11,48,54,57,58,59]},"scoresAfter":[-66,-61]},{"ply":38,"player":"ai","action":36,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[26,33,35,45,47,53,55,56],"ai":[4,7,11,48,54,57,58,59]},"scoresAfter":[-66,-81]},{"ply":39,"player":"human","action":60,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[26,33,35,45,47,53,55,56],"ai":[4,7,11,21,54,57,58,59]},"scoresAfter":[-62,-81]},{"ply":40,"player":"ai","action":25,"playedCard":11,"placeType":"play","drawSource":"discard_0","drawnCard":9,"handsBefore":{"human":[14,26,33,35,45,47,55,56],"ai":[4,7,11,21,54,57,58,59]},"scoresAfter":[-62,-61]},{"ply":41,"player":"human","action":72,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[14,26,33,35,45,47,55,56],"ai":[4,7,9,21,54,57,58,59]},"scoresAfter":[-56,-61]},{"ply":42,"player":"ai","action":36,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[14,26,31,33,35,45,47,56],"ai":[4,7,9,21,54,57,58,59]},"scoresAfter":[-56,-53]},{"ply":43,"player":"human","action":14,"playedCard":26,"placeType":"play","drawSource":"discard_1","drawnCard":12,"handsBefore":{"human":[14,26,31,33,35,45,47,56],"ai":[4,7,9,30,54,57,58,59]},"scoresAfter":[-76,-53]},{"ply":44,"player":"ai","action":36,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[12,14,31,33,35,45,47,56],"ai":[4,7,9,30,54,57,58,59]},"scoresAfter":[-76,-48]},{"ply":45,"player":"human","action":26,"playedCard":31,"placeType":"play","drawSource":"discard_1","drawnCard":15,"handsBefore":{"human":[12,14,31,33,35,45,47,56],"ai":[4,7,9,32,54,57,58,59]},"scoresAfter":[-52,-48]},{"ply":46,"player":"ai","action":36,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[12,14,15,33,35,45,47,56],"ai":[4,7,9,32,54,57,58,59]},"scoresAfter":[-52,-41]},{"ply":47,"player":"human","action":61,"playedCard":45,"placeType":"play","drawSource":"discard_0","drawnCard":5,"handsBefore":{"human":[12,14,15,33,35,45,47,56],"ai":[1,4,7,9,54,57,58,59]},"scoresAfter":[-28,-41]},{"ply":48,"player":"ai","action":48,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[5,12,14,15,33,35,47,56],"ai":[1,4,7,9,54,57,58,59]},"scoresAfter":[-28,-26]},{"ply":49,"player":"human","action":73,"playedCard":47,"placeType":"play","drawSource":"discard_0","drawnCard":0,"handsBefore":{"human":[5,12,14,15,33,35,47,56],"ai":[1,4,7,9,13,57,58,59]},"scoresAfter":[22,-26]},{"ply":50,"player":"ai","action":60,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[0,5,12,14,15,33,35,56],"ai":[1,4,7,9,13,57,58,59]},"scoresAfter":[22,-2]},{"ply":51,"player":"human","action":84,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[0,5,12,14,15,33,35,56],"ai":[1,4,7,9,13,29,58,59]},"scoresAfter":[29,-2]},{"ply":52,"player":"ai","action":72,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[0,5,12,14,15,33,34,35],"ai":[1,4,7,9,13,29,58,59]},"scoresAfter":[29,25]},{"ply":53,"player":"human","action":84,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[0,5,12,14,15,33,34,35],"ai":[1,4,7,9,13,29,36,59]},"scoresAfter":[69,25]},{"ply":54,"player":"ai","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[0,5,12,14,15,33,34,52],"ai":[1,4,7,9,13,29,36,59]},"scoresAfter":[69,55]}],"finalScores":[69,55],"outcome":"YOU WIN","finalState":{"deckOrder":[23,44,38,39,49,0,19,47,12,10,27,16,59,8,25,15,17,2,54,43,58,37,3,35,26,46,42,6,56,18,51,28,24,57,5,20,22,41,48,40,33,4,9,7,55,53,11,45,21,14,31,30,32,1,13,29,34,36,52,50],"drawPtr":60,"cardLoc":[1,2,4,4,2,1,4,2,4,2,4,4,1,2,1,1,3,3,4,3,4,4,3,3,3,3,3,4,4,2,4,3,4,1,1,3,2,3,3,3,4,4,3,3,3,3,4,3,4,4,2,3,1,3,4,3,3,4,4,4],"handPublic":[true,false,false,false,false,true,false,false,false,true,false,false,true,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[0,10,10,10,7],[10,8,7,9,10]],"colHandshakes":[[0,0,3,2,0],[1,0,0,0,2]],"colLength":[[0,5,5,8,4],[6,3,4,3,6]],"piles":[[],[],[],[],[]],"toMove":0,"stepCount":54,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"15bfa03e-2d97-4293-b16d-1a20222755fd","seed":"9kt6rv","startedAt":"2026-07-14T15:20:41.975Z","finishedAt":"2026-07-14T15:23:09.940Z","initialDeckOrder":[57,20,29,12,53,52,6,24,17,36,1,27,56,7,42,46,45,47,18,41,26,43,48,11,4,25,55,5,32,38,58,2,3,35,59,37,22,21,19,34,0,50,16,54,40,15,8,30,14,23,33,28,44,13,31,51,49,9,10,39],"moves":[{"ply":1,"player":"human","action":60,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[6,12,20,24,29,52,53,57],"ai":[1,7,17,27,36,42,46,56]},"scoresAfter":[-17,0]},{"ply":2,"player":"ai","action":84,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[6,12,20,24,29,45,53,57],"ai":[1,7,17,27,36,42,46,56]},"scoresAfter":[-17,-13]},{"ply":3,"player":"human","action":72,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[6,12,20,24,29,45,53,57],"ai":[1,7,17,27,36,42,46,47]},"scoresAfter":[-13,-13]},{"ply":4,"player":"ai","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[6,12,18,20,24,29,45,57],"ai":[1,7,17,27,36,42,46,47]},"scoresAfter":[-13,-13]},{"ply":5,"player":"human","action":12,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[6,12,18,20,24,29,45,57],"ai":[7,17,27,36,41,42,46,47]},"scoresAfter":[-53,-13]},{"ply":6,"player":"ai","action":24,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[6,18,20,24,26,29,45,57],"ai":[7,17,27,36,41,42,46,47]},"scoresAfter":[-53,-31]},{"ply":7,"player":"human","action":42,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[6,18,20,24,26,29,45,57],"ai":[7,17,36,41,42,43,46,47]},"scoresAfter":[-53,-31]},{"ply":8,"player":"ai","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[6,18,20,26,29,45,48,57],"ai":[7,17,36,41,42,43,46,47]},"scoresAfter":[-53,-45]},{"ply":9,"player":"human","action":42,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[6,18,20,26,29,45,48,57],"ai":[11,17,36,41,42,43,46,47]},"scoresAfter":[-53,-45]},{"ply":10,"player":"ai","action":24,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[4,6,18,20,29,45,48,57],"ai":[11,17,36,41,42,43,46,47]},"scoresAfter":[-53,-85]},{"ply":11,"player":"human","action":78,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[4,6,18,20,29,45,48,57],"ai":[11,17,25,41,42,43,46,47]},"scoresAfter":[-53,-85]},{"ply":12,"player":"ai","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[4,6,18,20,29,45,55,57],"ai":[11,17,25,41,42,43,46,47]},"scoresAfter":[-53,-75]},{"ply":13,"player":"human","action":6,"playedCard":4,"placeType":"discard","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[4,6,18,20,29,45,55,57],"ai":[5,17,25,41,42,43,46,47]},"scoresAfter":[-53,-75]},{"ply":14,"player":"ai","action":6,"playedCard":5,"placeType":"discard","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[6,18,20,29,32,45,55,57],"ai":[5,17,25,41,42,43,46,47]},"scoresAfter":[-53,-75]},{"ply":15,"player":"human","action":6,"playedCard":6,"placeType":"discard","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[6,18,20,29,32,45,55,57],"ai":[17,25,38,41,42,43,46,47]},"scoresAfter":[-53,-75]},{"ply":16,"player":"ai","action":0,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[18,20,29,32,45,55,57,58],"ai":[17,25,38,41,42,43,46,47]},"scoresAfter":[-53,-91]},{"ply":17,"player":"human","action":60,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[18,20,29,32,45,55,57,58],"ai":[2,25,38,41,42,43,46,47]},"scoresAfter":[-47,-91]},{"ply":18,"player":"ai","action":18,"playedCard":25,"placeType":"discard","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[3,18,20,29,32,45,57,58],"ai":[2,25,38,41,42,43,46,47]},"scoresAfter":[-47,-91]},{"ply":19,"player":"human","action":72,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[3,18,20,29,32,45,57,58],"ai":[2,35,38,41,42,43,46,47]},"scoresAfter":[-39,-91]},{"ply":20,"player":"ai","action":12,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[3,18,20,29,32,45,58,59],"ai":[2,35,38,41,42,43,46,47]},"scoresAfter":[-39,-81]},{"ply":21,"player":"human","action":72,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[3,18,20,29,32,45,58,59],"ai":[2,37,38,41,42,43,46,47]},"scoresAfter":[-30,-81]},{"ply":22,"player":"ai","action":12,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[3,18,20,22,29,32,45,59],"ai":[2,37,38,41,42,43,46,47]},"scoresAfter":[-30,-101]},{"ply":23,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[3,18,20,22,29,32,45,59],"ai":[2,21,38,41,42,43,46,47]},"scoresAfter":[-20,-101]},{"ply":24,"player":"ai","action":12,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[3,18,19,20,22,29,32,45],"ai":[2,21,38,41,42,43,46,47]},"scoresAfter":[-20,-93]},{"ply":25,"player":"human","action":6,"playedCard":3,"placeType":"discard","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[3,18,19,20,22,29,32,45],"ai":[2,34,38,41,42,43,46,47]},"scoresAfter":[-20,-93]},{"ply":26,"player":"ai","action":24,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[0,18,19,20,22,29,32,45],"ai":[2,34,38,41,42,43,46,47]},"scoresAfter":[-20,-113]},{"ply":27,"player":"human","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[0,18,19,20,22,29,32,45],"ai":[2,34,41,42,43,46,47,50]},"scoresAfter":[-20,-113]},{"ply":28,"player":"ai","action":90,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[16,18,19,20,22,29,32,45],"ai":[2,34,41,42,43,46,47,50]},"scoresAfter":[-20,-113]},{"ply":29,"player":"human","action":66,"playedCard":29,"placeType":"discard","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[16,18,19,20,22,29,32,45],"ai":[2,34,41,42,43,46,47,54]},"scoresAfter":[-20,-113]},{"ply":30,"player":"ai","action":90,"playedCard":54,"placeType":"discard","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[16,18,19,20,22,32,40,45],"ai":[2,34,41,42,43,46,47,54]},"scoresAfter":[-20,-113]},{"ply":31,"player":"human","action":66,"playedCard":32,"placeType":"discard","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[16,18,19,20,22,32,40,45],"ai":[2,15,34,41,42,43,46,47]},"scoresAfter":[-20,-113]},{"ply":32,"player":"ai","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[8,16,18,19,20,22,40,45],"ai":[2,15,34,41,42,43,46,47]},"scoresAfter":[-20,-113]},{"ply":33,"player":"human","action":6,"playedCard":8,"placeType":"discard","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[8,16,18,19,20,22,40,45],"ai":[15,30,34,41,42,43,46,47]},"scoresAfter":[-20,-113]},{"ply":34,"player":"ai","action":6,"playedCard":15,"placeType":"discard","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[14,16,18,19,20,22,40,45],"ai":[15,30,34,41,42,43,46,47]},"scoresAfter":[-20,-113]},{"ply":35,"player":"human","action":2,"playedCard":14,"placeType":"play","drawSource":"discard_1","drawnCard":15,"handsBefore":{"human":[14,16,18,19,20,22,40,45],"ai":[23,30,34,41,42,43,46,47]},"scoresAfter":[-40,-113]},{"ply":36,"player":"ai","action":0,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[15,16,18,19,20,22,40,45],"ai":[23,30,34,41,42,43,46,47]},"scoresAfter":[-40,-103]},{"ply":37,"player":"human","action":0,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[15,16,18,19,20,22,40,45],"ai":[30,33,34,41,42,43,46,47]},"scoresAfter":[-34,-103]},{"ply":38,"player":"ai","action":36,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[16,18,19,20,22,28,40,45],"ai":[30,33,34,41,42,43,46,47]},"scoresAfter":[-34,-87]},{"ply":39,"player":"human","action":3,"playedCard":16,"placeType":"play","drawSource":"discard_2","drawnCard":32,"handsBefore":{"human":[16,18,19,20,22,28,40,45],"ai":[30,33,34,42,43,44,46,47]},"scoresAfter":[-25,-87]},{"ply":40,"player":"ai","action":36,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[18,19,20,22,28,32,40,45],"ai":[30,33,34,42,43,44,46,47]},"scoresAfter":[-25,-67]},{"ply":41,"player":"human","action":3,"playedCard":18,"placeType":"play","drawSource":"discard_2","drawnCard":29,"handsBefore":{"human":[18,19,20,22,28,32,40,45],"ai":[13,30,33,34,43,44,46,47]},"scoresAfter":[-10,-67]},{"ply":42,"player":"ai","action":48,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[19,20,22,28,29,32,40,45],"ai":[13,30,33,34,43,44,46,47]},"scoresAfter":[-10,-43]},{"ply":43,"player":"human","action":1,"playedCard":19,"placeType":"play","drawSource":"discard_0","drawnCard":8,"handsBefore":{"human":[19,20,22,28,29,32,40,45],"ai":[13,30,31,33,34,44,46,47]},"scoresAfter":[8,-43]},{"ply":44,"player":"ai","action":65,"playedCard":44,"placeType":"play","drawSource":"discard_4","drawnCard":54,"handsBefore":{"human":[8,20,22,28,29,32,40,45],"ai":[13,30,31,33,34,44,46,47]},"scoresAfter":[8,-15]},{"ply":45,"player":"human","action":13,"playedCard":20,"placeType":"play","drawSource":"discard_0","drawnCard":2,"handsBefore":{"human":[8,20,22,28,29,32,40,45],"ai":[13,30,31,33,34,46,47,54]},"scoresAfter":[29,-15]},{"ply":46,"player":"ai","action":60,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[2,8,22,28,29,32,40,45],"ai":[13,30,31,33,34,46,47,54]},"scoresAfter":[29,41]},{"ply":47,"player":"human","action":24,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[2,8,22,28,29,32,40,45],"ai":[13,30,31,33,34,47,51,54]},"scoresAfter":[76,41]},{"ply":48,"player":"ai","action":65,"playedCard":47,"placeType":"play","drawSource":"discard_4","drawnCard":50,"handsBefore":{"human":[2,8,28,29,32,40,45,49],"ai":[13,30,31,33,34,47,51,54]},"scoresAfter":[76,81]},{"ply":49,"player":"human","action":78,"playedCard":45,"placeType":"discard","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[2,8,28,29,32,40,45,49],"ai":[13,30,31,33,34,50,51,54]},"scoresAfter":[76,81]},{"ply":50,"player":"ai","action":91,"playedCard":54,"placeType":"discard","drawSource":"discard_0","drawnCard":0,"handsBefore":{"human":[2,8,9,28,29,32,40,49],"ai":[13,30,31,33,34,50,51,54]},"scoresAfter":[76,81]},{"ply":51,"player":"human","action":78,"playedCard":40,"placeType":"discard","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[2,8,9,28,29,32,40,49],"ai":[0,13,30,31,33,34,50,51]},"scoresAfter":[76,81]},{"ply":52,"player":"ai","action":78,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[2,8,9,10,28,29,32,49],"ai":[0,13,30,31,33,34,50,51]},"scoresAfter":[76,81]}],"finalScores":[76,81],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[57,20,29,12,53,52,6,24,17,36,1,27,56,7,42,46,45,47,18,41,26,43,48,11,4,25,55,5,32,38,58,2,3,35,59,37,22,21,19,34,0,50,16,54,40,15,8,30,14,23,33,28,44,13,31,51,49,9,10,39],"drawPtr":60,"cardLoc":[2,5,1,5,5,5,5,4,1,1,1,4,3,2,3,3,3,4,3,3,3,4,3,4,5,5,5,4,1,1,2,2,1,2,2,4,4,4,4,2,5,4,4,4,4,5,4,4,5,1,5,2,3,3,5,3,4,3,3,3],"handPublic":[true,false,true,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[0,9,0,0,10],[10,10,10,10,7]],"colHandshakes":[[0,2,0,0,0],[0,0,0,3,0]],"colLength":[[0,8,0,0,6],[2,3,2,9,1]],"piles":[[1,4,5,6,3],[],[24,26,25],[45,40],[48,54,50]],"toMove":0,"stepCount":52,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"c7fc43dc-9e19-4de9-86dc-7b7fc81ffa31","seed":"v3i80o","startedAt":"2026-07-14T15:23:11.266Z","finishedAt":"2026-07-14T15:27:53.112Z","initialDeckOrder":[12,20,17,53,55,26,56,11,22,42,27,16,41,7,28,9,1,39,24,13,6,47,30,15,31,0,37,48,51,43,46,10,2,18,44,32,52,40,3,33,4,36,49,35,59,23,45,34,29,8,25,14,54,57,58,5,50,21,19,38],"moves":[{"ply":1,"player":"human","action":12,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[11,12,17,20,26,53,55,56],"ai":[7,9,16,22,27,28,41,42]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":72,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[1,11,17,20,26,53,55,56],"ai":[7,9,16,22,27,28,41,42]},"scoresAfter":[-40,-16]},{"ply":3,"player":"human","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[1,11,17,20,26,53,55,56],"ai":[7,9,16,22,27,28,39,42]},"scoresAfter":[-80,-16]},{"ply":4,"player":"ai","action":84,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[11,17,20,24,26,53,55,56],"ai":[7,9,16,22,27,28,39,42]},"scoresAfter":[-80,-11]},{"ply":5,"player":"human","action":12,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[11,17,20,24,26,53,55,56],"ai":[7,9,13,16,22,27,28,39]},"scoresAfter":[-72,-11]},{"ply":6,"player":"ai","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[6,11,20,24,26,53,55,56],"ai":[7,9,13,16,22,27,28,39]},"scoresAfter":[-72,-25]},{"ply":7,"player":"human","action":42,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[6,11,20,24,26,53,55,56],"ai":[9,13,16,22,27,28,39,47]},"scoresAfter":[-72,-25]},{"ply":8,"player":"ai","action":12,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[6,11,20,26,30,53,55,56],"ai":[9,13,16,22,27,28,39,47]},"scoresAfter":[-72,-65]},{"ply":9,"player":"human","action":42,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[6,11,20,26,30,53,55,56],"ai":[9,15,16,22,27,28,39,47]},"scoresAfter":[-72,-65]},{"ply":10,"player":"ai","action":78,"playedCard":39,"placeType":"discard","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[6,11,20,30,31,53,55,56],"ai":[9,15,16,22,27,28,39,47]},"scoresAfter":[-72,-65]},{"ply":11,"player":"human","action":60,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[6,11,20,30,31,53,55,56],"ai":[0,9,15,16,22,27,28,47]},"scoresAfter":[-88,-65]},{"ply":12,"player":"ai","action":12,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[6,11,20,30,31,37,55,56],"ai":[0,9,15,16,22,27,28,47]},"scoresAfter":[-88,-57]},{"ply":13,"player":"human","action":66,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[6,11,20,30,31,37,55,56],"ai":[0,15,16,22,27,28,47,48]},"scoresAfter":[-88,-57]},{"ply":14,"player":"ai","action":90,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[6,11,20,30,31,51,55,56],"ai":[0,15,16,22,27,28,47,48]},"scoresAfter":[-88,-57]},{"ply":15,"player":"human","action":66,"playedCard":51,"placeType":"discard","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[6,11,20,30,31,51,55,56],"ai":[0,15,16,22,27,28,43,47]},"scoresAfter":[-88,-57]},{"ply":16,"player":"ai","action":72,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[6,11,20,30,31,46,55,56],"ai":[0,15,16,22,27,28,43,47]},"scoresAfter":[-88,-51]},{"ply":17,"player":"human","action":72,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[6,11,20,30,31,46,55,56],"ai":[0,10,15,16,22,27,28,47]},"scoresAfter":[-82,-51]},{"ply":18,"player":"ai","action":12,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[2,6,11,20,30,31,46,56],"ai":[0,10,15,16,22,27,28,47]},"scoresAfter":[-82,-42]},{"ply":19,"player":"human","action":0,"playedCard":2,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[2,6,11,20,30,31,46,56],"ai":[0,15,16,18,22,27,28,47]},"scoresAfter":[-102,-42]},{"ply":20,"player":"ai","action":12,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[6,11,20,30,31,44,46,56],"ai":[0,15,16,18,22,27,28,47]},"scoresAfter":[-102,-38]},{"ply":21,"player":"human","action":84,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[6,11,20,30,31,44,46,56],"ai":[0,16,18,22,27,28,32,47]},"scoresAfter":[-95,-38]},{"ply":22,"player":"ai","action":15,"playedCard":16,"placeType":"play","drawSource":"discard_2","drawnCard":26,"handsBefore":{"human":[6,11,20,30,31,44,46,52],"ai":[0,16,18,22,27,28,32,47]},"scoresAfter":[-95,-32]},{"ply":23,"player":"human","action":90,"playedCard":52,"placeType":"discard","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[6,11,20,30,31,44,46,52],"ai":[0,18,22,26,27,28,32,47]},"scoresAfter":[-95,-32]},{"ply":24,"player":"ai","action":15,"playedCard":18,"placeType":"play","drawSource":"discard_2","drawnCard":24,"handsBefore":{"human":[6,11,20,30,31,40,44,46],"ai":[0,18,22,26,27,28,32,47]},"scoresAfter":[-95,-22]},{"ply":25,"player":"human","action":60,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[6,11,20,30,31,40,44,46],"ai":[0,22,24,26,27,28,32,47]},"scoresAfter":[-112,-22]},{"ply":26,"player":"ai","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[3,6,11,20,30,31,44,46],"ai":[0,22,24,26,27,28,32,47]},"scoresAfter":[-112,-22]},{"ply":27,"player":"human","action":73,"playedCard":44,"placeType":"play","drawSource":"discard_0","drawnCard":0,"handsBefore":{"human":[3,6,11,20,30,31,44,46],"ai":[22,24,26,27,28,32,33,47]},"scoresAfter":[-105,-22]},{"ply":28,"player":"ai","action":24,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[0,3,6,11,20,30,31,46],"ai":[22,24,26,27,28,32,33,47]},"scoresAfter":[-105,-62]},{"ply":29,"player":"human","action":0,"playedCard":0,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[0,3,6,11,20,30,31,46],"ai":[4,22,24,27,28,32,33,47]},"scoresAfter":[-125,-62]},{"ply":30,"player":"ai","action":24,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[3,6,11,20,30,31,36,46],"ai":[4,22,24,27,28,32,33,47]},"scoresAfter":[-125,-82]},{"ply":31,"player":"human","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[3,6,11,20,30,31,36,46],"ai":[4,22,27,28,32,33,47,49]},"scoresAfter":[-117,-82]},{"ply":32,"player":"ai","action":78,"playedCard":47,"placeType":"discard","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[6,11,20,30,31,35,36,46],"ai":[4,22,27,28,32,33,47,49]},"scoresAfter":[-117,-82]},{"ply":33,"player":"human","action":88,"playedCard":46,"placeType":"play","drawSource":"discard_3","drawnCard":47,"handsBefore":{"human":[6,11,20,30,31,35,36,46],"ai":[4,22,27,28,32,33,49,59]},"scoresAfter":[-108,-82]},{"ply":34,"player":"ai","action":78,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[6,11,20,30,31,35,36,47],"ai":[4,22,27,28,32,33,49,59]},"scoresAfter":[-108,-82]},{"ply":35,"player":"human","action":84,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[6,11,20,30,31,35,36,47],"ai":[4,22,23,27,28,32,33,59]},"scoresAfter":[-98,-82]},{"ply":36,"player":"ai","action":36,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[6,11,20,30,31,35,36,45],"ai":[4,22,23,27,28,32,33,59]},"scoresAfter":[-98,-76]},{"ply":37,"player":"human","action":36,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[6,11,20,30,31,35,36,45],"ai":[4,22,23,28,32,33,34,59]},"scoresAfter":[-113,-76]},{"ply":38,"player":"ai","action":36,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[6,11,20,29,31,35,36,45],"ai":[4,22,23,28,32,33,34,59]},"scoresAfter":[-113,-67]},{"ply":39,"player":"human","action":48,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[6,11,20,29,31,35,36,45],"ai":[4,8,22,23,32,33,34,59]},"scoresAfter":[-107,-67]},{"ply":40,"player":"ai","action":48,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[6,11,20,25,29,35,36,45],"ai":[4,8,22,23,32,33,34,59]},"scoresAfter":[-107,-46]},{"ply":41,"player":"human","action":60,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[6,11,20,25,29,35,36,45],"ai":[4,8,14,22,23,33,34,59]},"scoresAfter":[-97,-46]},{"ply":42,"player":"ai","action":36,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[6,11,20,25,29,36,45,54],"ai":[4,8,14,22,23,33,34,59]},"scoresAfter":[-97,-28]},{"ply":43,"player":"human","action":42,"playedCard":25,"placeType":"discard","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[6,11,20,25,29,36,45,54],"ai":[4,8,14,23,33,34,57,59]},"scoresAfter":[-97,-28]},{"ply":44,"player":"ai","action":48,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[6,11,20,29,36,45,54,58],"ai":[4,8,14,23,33,34,57,59]},"scoresAfter":[-97,-4]},{"ply":45,"player":"human","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[6,11,20,29,36,45,54,58],"ai":[4,5,8,14,23,34,57,59]},"scoresAfter":[-77,-4]},{"ply":46,"player":"ai","action":48,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[11,20,29,36,45,50,54,58],"ai":[4,5,8,14,23,34,57,59]},"scoresAfter":[-77,16]},{"ply":47,"player":"human","action":89,"playedCard":58,"placeType":"play","drawSource":"discard_4","drawnCard":49,"handsBefore":{"human":[11,20,29,36,45,50,54,58],"ai":[4,5,8,14,21,34,57,59]},"scoresAfter":[-68,16]},{"ply":48,"player":"ai","action":60,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[11,20,29,36,45,49,50,54],"ai":[4,5,8,14,21,34,57,59]},"scoresAfter":[-68,43]},{"ply":49,"player":"human","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[11,20,29,36,45,49,50,54],"ai":[4,5,8,14,19,21,57,59]},"scoresAfter":[-28,43]}],"finalScores":[-28,43],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[12,20,17,53,55,26,56,11,22,42,27,16,41,7,28,9,1,39,24,13,6,47,30,15,31,0,37,48,51,43,46,10,2,18,44,32,52,40,3,33,4,36,49,35,59,23,45,34,29,8,25,14,54,57,58,5,50,21,19,38],"drawPtr":60,"cardLoc":[3,3,3,3,2,2,3,4,2,4,4,3,3,4,2,4,4,3,4,2,1,2,4,4,4,5,4,4,4,1,3,3,4,4,4,3,1,5,1,5,3,4,4,4,3,1,3,3,5,1,1,5,5,3,1,3,3,2,3,2],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,4,10,10,9],[9,10,9,6,0]],"colHandshakes":[[3,1,0,0,0],[0,1,2,0,0]],"colLength":[[6,2,3,4,4],[3,6,7,3,0]],"piles":[[],[],[25],[39,37],[48,51,52]],"toMove":1,"stepCount":49,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"5417d94e-e815-4b93-9906-9061114785d0","seed":"t49ofw","startedAt":"2026-07-14T15:27:54.085Z","finishedAt":"2026-07-14T15:32:14.576Z","initialDeckOrder":[31,18,8,32,12,13,38,45,58,51,6,3,34,9,29,15,56,44,7,53,40,27,20,57,46,35,0,17,36,37,52,54,47,43,42,16,14,21,49,22,59,4,2,10,55,30,11,50,23,26,48,33,41,24,1,28,39,25,19,5],"moves":[{"ply":1,"player":"human","action":72,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[8,12,13,18,31,32,38,45],"ai":[3,6,9,15,29,34,51,58]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":72,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[8,12,13,18,31,32,45,56],"ai":[3,6,9,15,29,34,51,58]},"scoresAfter":[-40,-18]},{"ply":3,"player":"human","action":12,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[8,12,13,18,31,32,45,56],"ai":[3,6,9,15,29,34,44,58]},"scoresAfter":[-80,-18]},{"ply":4,"player":"ai","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[7,8,13,18,31,32,45,56],"ai":[3,6,9,15,29,34,44,58]},"scoresAfter":[-80,-36]},{"ply":5,"player":"human","action":24,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[7,8,13,18,31,32,45,56],"ai":[6,9,15,29,34,44,53,58]},"scoresAfter":[-100,-36]},{"ply":6,"player":"ai","action":72,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[7,8,18,31,32,40,45,56],"ai":[6,9,15,29,34,44,53,58]},"scoresAfter":[-100,-32]},{"ply":7,"player":"human","action":60,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[7,8,18,31,32,40,45,56],"ai":[6,9,15,27,29,34,44,58]},"scoresAfter":[-94,-32]},{"ply":8,"player":"ai","action":72,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[7,8,18,20,31,32,45,56],"ai":[6,9,15,27,29,34,44,58]},"scoresAfter":[-94,-45]},{"ply":9,"player":"human","action":24,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[7,8,18,20,31,32,45,56],"ai":[6,9,15,27,29,34,57,58]},"scoresAfter":[-79,-45]},{"ply":10,"player":"ai","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[7,8,20,31,32,45,46,56],"ai":[6,9,15,27,29,34,57,58]},"scoresAfter":[-79,-40]},{"ply":11,"player":"human","action":60,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[7,8,20,31,32,45,46,56],"ai":[9,15,27,29,34,35,57,58]},"scoresAfter":[-63,-40]},{"ply":12,"player":"ai","action":72,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[0,7,8,20,31,32,46,56],"ai":[9,15,27,29,34,35,57,58]},"scoresAfter":[-63,-32]},{"ply":13,"player":"human","action":72,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[0,7,8,20,31,32,46,56],"ai":[9,15,17,27,29,34,35,58]},"scoresAfter":[-45,-32]},{"ply":14,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[0,7,8,20,31,32,36,56],"ai":[9,15,17,27,29,34,35,58]},"scoresAfter":[-45,-24]},{"ply":15,"player":"human","action":78,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[0,7,8,20,31,32,36,56],"ai":[15,17,27,29,34,35,37,58]},"scoresAfter":[-45,-24]},{"ply":16,"player":"ai","action":78,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[0,7,8,20,31,32,52,56],"ai":[15,17,27,29,34,35,37,58]},"scoresAfter":[-45,-24]},{"ply":17,"player":"human","action":78,"playedCard":52,"placeType":"discard","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[0,7,8,20,31,32,52,56],"ai":[15,17,27,29,34,35,54,58]},"scoresAfter":[-45,-24]},{"ply":18,"player":"ai","action":78,"playedCard":54,"placeType":"discard","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[0,7,8,20,31,32,47,56],"ai":[15,17,27,29,34,35,54,58]},"scoresAfter":[-45,-24]},{"ply":19,"player":"human","action":90,"playedCard":56,"placeType":"discard","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[0,7,8,20,31,32,47,56],"ai":[15,17,27,29,34,35,43,58]},"scoresAfter":[-45,-24]},{"ply":20,"player":"ai","action":0,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[0,7,8,20,31,32,42,47],"ai":[15,17,27,29,34,35,43,58]},"scoresAfter":[-45,-42]},{"ply":21,"player":"human","action":84,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[0,7,8,20,31,32,42,47],"ai":[16,17,27,29,34,35,43,58]},"scoresAfter":[-25,-42]},{"ply":22,"player":"ai","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[0,7,8,14,20,31,32,42],"ai":[16,17,27,29,34,35,43,58]},"scoresAfter":[-25,-33]},{"ply":23,"player":"human","action":42,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[0,7,8,14,20,31,32,42],"ai":[16,17,21,27,29,34,35,43]},"scoresAfter":[-25,-33]},{"ply":24,"player":"ai","action":0,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[0,7,8,20,31,32,42,49],"ai":[16,17,21,27,29,34,35,43]},"scoresAfter":[-25,-30]},{"ply":25,"player":"human","action":90,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[0,7,8,20,31,32,42,49],"ai":[17,21,22,27,29,34,35,43]},"scoresAfter":[-25,-30]},{"ply":26,"player":"ai","action":0,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[0,7,8,20,31,32,42,59],"ai":[17,21,22,27,29,34,35,43]},"scoresAfter":[-25,-26]},{"ply":27,"player":"human","action":78,"playedCard":42,"placeType":"discard","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[0,7,8,20,31,32,42,59],"ai":[4,21,22,27,29,34,35,43]},"scoresAfter":[-25,-26]},{"ply":28,"player":"ai","action":90,"playedCard":43,"placeType":"discard","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[0,2,7,8,20,31,32,59],"ai":[4,21,22,27,29,34,35,43]},"scoresAfter":[-25,-26]},{"ply":29,"player":"human","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[0,2,7,8,20,31,32,59],"ai":[4,10,21,22,27,29,34,35]},"scoresAfter":[-25,-26]},{"ply":30,"player":"ai","action":12,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[2,7,8,20,31,32,55,59],"ai":[4,10,21,22,27,29,34,35]},"scoresAfter":[-25,-17]},{"ply":31,"player":"human","action":0,"playedCard":2,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[2,7,8,20,31,32,55,59],"ai":[4,21,22,27,29,30,34,35]},"scoresAfter":[-65,-17]},{"ply":32,"player":"ai","action":12,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[7,8,11,20,31,32,55,59],"ai":[4,21,22,27,29,30,34,35]},"scoresAfter":[-65,-9]},{"ply":33,"player":"human","action":37,"playedCard":20,"placeType":"play","drawSource":"discard_0","drawnCard":0,"handsBefore":{"human":[7,8,11,20,31,32,55,59],"ai":[4,22,27,29,30,34,35,50]},"scoresAfter":[-44,-9]},{"ply":34,"player":"ai","action":90,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[0,7,8,11,31,32,55,59],"ai":[4,22,27,29,30,34,35,50]},"scoresAfter":[-44,-9]},{"ply":35,"player":"human","action":0,"playedCard":0,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[0,7,8,11,31,32,55,59],"ai":[4,22,23,27,29,30,34,35]},"scoresAfter":[-64,-9]},{"ply":36,"player":"ai","action":12,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[7,8,11,26,31,32,55,59],"ai":[4,22,23,27,29,30,34,35]},"scoresAfter":[-64,0]},{"ply":37,"player":"human","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[7,8,11,26,31,32,55,59],"ai":[4,23,27,29,30,34,35,48]},"scoresAfter":[-46,0]},{"ply":38,"player":"ai","action":12,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[8,11,26,31,32,33,55,59],"ai":[4,23,27,29,30,34,35,48]},"scoresAfter":[-46,10]},{"ply":39,"player":"human","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[8,11,26,31,32,33,55,59],"ai":[4,27,29,30,34,35,41,48]},"scoresAfter":[-25,10]},{"ply":40,"player":"ai","action":14,"playedCard":27,"placeType":"play","drawSource":"discard_1","drawnCard":14,"handsBefore":{"human":[11,24,26,31,32,33,55,59],"ai":[4,27,29,30,34,35,41,48]},"scoresAfter":[-25,-8]},{"ply":41,"player":"human","action":16,"playedCard":24,"placeType":"play","drawSource":"discard_3","drawnCard":43,"handsBefore":{"human":[11,24,26,31,32,33,55,59],"ai":[4,14,29,30,34,35,41,48]},"scoresAfter":[-65,-8]},{"ply":42,"player":"ai","action":24,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[11,26,31,32,33,43,55,59],"ai":[4,14,29,30,34,35,41,48]},"scoresAfter":[-65,-4]},{"ply":43,"player":"human","action":16,"playedCard":26,"placeType":"play","drawSource":"discard_3","drawnCard":42,"handsBefore":{"human":[11,26,31,32,33,43,55,59],"ai":[1,4,14,30,34,35,41,48]},"scoresAfter":[-85,-4]},{"ply":44,"player":"ai","action":36,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[11,31,32,33,42,43,55,59],"ai":[1,4,14,30,34,35,41,48]},"scoresAfter":[-85,1]},{"ply":45,"player":"human","action":4,"playedCard":11,"placeType":"play","drawSource":"discard_3","drawnCard":37,"handsBefore":{"human":[11,31,32,33,42,43,55,59],"ai":[1,4,14,28,34,35,41,48]},"scoresAfter":[-55,1]},{"ply":46,"player":"ai","action":78,"playedCard":41,"placeType":"discard","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[31,32,33,37,42,43,55,59],"ai":[1,4,14,28,34,35,41,48]},"scoresAfter":[-55,1]},{"ply":47,"player":"human","action":4,"playedCard":31,"placeType":"play","drawSource":"discard_3","drawnCard":41,"handsBefore":{"human":[31,32,33,37,42,43,55,59],"ai":[1,4,14,28,34,35,39,48]},"scoresAfter":[-37,1]},{"ply":48,"player":"ai","action":48,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[32,33,37,41,42,43,55,59],"ai":[1,4,14,28,34,35,39,48]},"scoresAfter":[-37,10]},{"ply":49,"player":"human","action":4,"playedCard":32,"placeType":"play","drawSource":"discard_3","drawnCard":36,"handsBefore":{"human":[32,33,37,41,42,43,55,59],"ai":[1,4,14,25,28,35,39,48]},"scoresAfter":[-16,10]},{"ply":50,"player":"ai","action":60,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[33,36,37,41,42,43,55,59],"ai":[1,4,14,25,28,35,39,48]},"scoresAfter":[-16,20]},{"ply":51,"player":"human","action":0,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[33,36,37,41,42,43,55,59],"ai":[1,4,14,19,25,28,39,48]},"scoresAfter":[8,20]}],"finalScores":[8,20],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[31,18,8,32,12,13,38,45,58,51,6,3,34,9,29,15,56,44,7,53,40,27,20,57,46,35,0,17,36,37,52,54,47,43,42,16,14,21,49,22,59,4,2,10,55,30,11,50,23,26,48,33,41,24,1,28,39,25,19,5],"drawPtr":60,"cardLoc":[3,2,3,4,2,1,4,3,3,4,4,3,3,3,2,4,4,4,3,2,3,4,4,4,3,2,3,4,2,4,4,3,3,3,4,4,1,1,3,2,3,1,1,1,4,3,3,3,2,5,5,4,5,4,5,1,5,4,4,1],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,false,false,false,true,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,7,8,10,0],[9,10,10,7,9]],"colHandshakes":[[2,2,2,1,0],[0,0,0,0,0]],"colLength":[[5,4,5,5,0],[4,6,5,1,4]],"piles":[[],[],[],[],[52,54,56,49,50]],"toMove":1,"stepCount":51,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"77e1cbf3-40d0-4213-91ae-f6e3501f549e","seed":"11qssr","startedAt":"2026-07-14T15:32:15.646Z","finishedAt":"2026-07-14T15:37:05.149Z","initialDeckOrder":[52,42,48,58,33,25,18,20,40,32,8,38,19,1,7,31,54,15,23,29,56,45,9,4,49,34,51,59,13,10,24,36,11,3,22,53,27,6,26,21,41,12,35,47,57,43,14,37,28,2,0,16,44,39,17,46,5,30,55,50],"moves":[{"ply":1,"player":"human","action":60,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[18,20,25,33,42,48,52,58],"ai":[1,7,8,19,31,32,38,40]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":84,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[18,20,25,33,42,52,54,58],"ai":[1,7,8,19,31,32,38,40]},"scoresAfter":[-40,-17]},{"ply":3,"player":"human","action":60,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[18,20,25,33,42,52,54,58],"ai":[1,7,8,15,19,31,32,38]},"scoresAfter":[-34,-17]},{"ply":4,"player":"ai","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[18,20,23,25,33,42,54,58],"ai":[1,7,8,15,19,31,32,38]},"scoresAfter":[-34,-57]},{"ply":5,"player":"human","action":72,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[18,20,23,25,33,42,54,58],"ai":[7,8,15,19,29,31,32,38]},"scoresAfter":[-24,-57]},{"ply":6,"player":"ai","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[18,20,23,25,33,42,56,58],"ai":[7,8,15,19,29,31,32,38]},"scoresAfter":[-24,-45]},{"ply":7,"player":"human","action":72,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[18,20,23,25,33,42,56,58],"ai":[8,15,19,29,31,32,38,45]},"scoresAfter":[-10,-45]},{"ply":8,"player":"ai","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[9,18,20,23,25,33,42,58],"ai":[8,15,19,29,31,32,38,45]},"scoresAfter":[-10,-31]},{"ply":9,"player":"human","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[9,18,20,23,25,33,42,58],"ai":[4,15,19,29,31,32,38,45]},"scoresAfter":[8,-31]},{"ply":10,"player":"ai","action":84,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[9,18,20,23,25,33,42,49],"ai":[4,15,19,29,31,32,38,45]},"scoresAfter":[8,-23]},{"ply":11,"player":"human","action":90,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[9,18,20,23,25,33,42,49],"ai":[4,15,19,29,31,32,34,38]},"scoresAfter":[8,-23]},{"ply":12,"player":"ai","action":6,"playedCard":4,"placeType":"discard","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[9,18,20,23,25,33,42,51],"ai":[4,15,19,29,31,32,34,38]},"scoresAfter":[8,-23]},{"ply":13,"player":"human","action":78,"playedCard":42,"placeType":"discard","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[9,18,20,23,25,33,42,51],"ai":[15,19,29,31,32,34,38,59]},"scoresAfter":[8,-23]},{"ply":14,"player":"ai","action":0,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[9,13,18,20,23,25,33,51],"ai":[15,19,29,31,32,34,38,59]},"scoresAfter":[8,-41]},{"ply":15,"player":"human","action":66,"playedCard":25,"placeType":"discard","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[9,13,18,20,23,25,33,51],"ai":[10,19,29,31,32,34,38,59]},"scoresAfter":[8,-41]},{"ply":16,"player":"ai","action":3,"playedCard":10,"placeType":"play","drawSource":"discard_2","drawnCard":25,"handsBefore":{"human":[9,13,18,20,23,24,33,51],"ai":[10,19,29,31,32,34,38,59]},"scoresAfter":[8,-23]},{"ply":17,"player":"human","action":66,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[9,13,18,20,23,24,33,51],"ai":[19,25,29,31,32,34,38,59]},"scoresAfter":[8,-23]},{"ply":18,"player":"ai","action":3,"playedCard":19,"placeType":"play","drawSource":"discard_2","drawnCard":24,"handsBefore":{"human":[9,13,18,20,23,33,36,51],"ai":[19,25,29,31,32,34,38,59]},"scoresAfter":[8,-17]},{"ply":19,"player":"human","action":12,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[9,13,18,20,23,33,36,51],"ai":[24,25,29,31,32,34,38,59]},"scoresAfter":[-32,-17]},{"ply":20,"player":"ai","action":0,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[9,11,18,20,23,33,36,51],"ai":[24,25,29,31,32,34,38,59]},"scoresAfter":[-32,-57]},{"ply":21,"player":"human","action":25,"playedCard":18,"placeType":"play","drawSource":"discard_0","drawnCard":4,"handsBefore":{"human":[9,11,18,20,23,33,36,51],"ai":[3,25,29,31,32,34,38,59]},"scoresAfter":[-22,-57]},{"ply":22,"player":"ai","action":6,"playedCard":3,"placeType":"discard","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[4,9,11,20,23,33,36,51],"ai":[3,25,29,31,32,34,38,59]},"scoresAfter":[-22,-57]},{"ply":23,"player":"human","action":37,"playedCard":20,"placeType":"play","drawSource":"discard_0","drawnCard":3,"handsBefore":{"human":[4,9,11,20,23,33,36,51],"ai":[22,25,29,31,32,34,38,59]},"scoresAfter":[-8,-57]},{"ply":24,"player":"ai","action":0,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[3,4,9,11,23,33,36,51],"ai":[22,25,29,31,32,34,38,59]},"scoresAfter":[-8,-48]},{"ply":25,"player":"human","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[3,4,9,11,23,33,36,51],"ai":[25,29,31,32,34,38,53,59]},"scoresAfter":[-26,-48]},{"ply":26,"player":"ai","action":72,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[4,9,11,23,27,33,36,51],"ai":[25,29,31,32,34,38,53,59]},"scoresAfter":[-26,-64]},{"ply":27,"player":"human","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[4,9,11,23,27,33,36,51],"ai":[6,25,29,31,32,34,38,59]},"scoresAfter":[-23,-64]},{"ply":28,"player":"ai","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[9,11,23,26,27,33,36,51],"ai":[6,25,29,31,32,34,38,59]},"scoresAfter":[-23,-54]},{"ply":29,"player":"human","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[9,11,23,26,27,33,36,51],"ai":[6,21,25,29,31,32,34,38]},"scoresAfter":[-15,-54]},{"ply":30,"player":"ai","action":18,"playedCard":21,"placeType":"discard","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[11,23,26,27,33,36,41,51],"ai":[6,21,25,29,31,32,34,38]},"scoresAfter":[-15,-54]},{"ply":31,"player":"human","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[11,23,26,27,33,36,41,51],"ai":[6,12,25,29,31,32,34,38]},"scoresAfter":[-5,-54]},{"ply":32,"player":"ai","action":8,"playedCard":6,"placeType":"discard","drawSource":"discard_1","drawnCard":21,"handsBefore":{"human":[23,26,27,33,35,36,41,51],"ai":[6,12,25,29,31,32,34,38]},"scoresAfter":[-5,-54]},{"ply":33,"player":"human","action":12,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[23,26,27,33,35,36,41,51],"ai":[12,21,25,29,31,32,34,38]},"scoresAfter":[-45,-54]},{"ply":34,"player":"ai","action":24,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[23,27,33,35,36,41,47,51],"ai":[12,21,25,29,31,32,34,38]},"scoresAfter":[-45,-74]},{"ply":35,"player":"human","action":0,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[23,27,33,35,36,41,47,51],"ai":[12,21,29,31,32,34,38,57]},"scoresAfter":[-25,-74]},{"ply":36,"player":"ai","action":18,"playedCard":21,"placeType":"discard","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[27,33,35,36,41,43,47,51],"ai":[12,21,29,31,32,34,38,57]},"scoresAfter":[-25,-74]},{"ply":37,"player":"human","action":36,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[27,33,35,36,41,43,47,51],"ai":[12,14,29,31,32,34,38,57]},"scoresAfter":[-65,-74]},{"ply":38,"player":"ai","action":24,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[27,33,35,37,41,43,47,51],"ai":[12,14,29,31,32,34,38,57]},"scoresAfter":[-65,-62]},{"ply":39,"player":"human","action":36,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[27,33,35,37,41,43,47,51],"ai":[12,14,28,31,32,34,38,57]},"scoresAfter":[-85,-62]},{"ply":40,"player":"ai","action":6,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[2,27,33,35,41,43,47,51],"ai":[12,14,28,31,32,34,38,57]},"scoresAfter":[-85,-62]},{"ply":41,"player":"human","action":12,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[2,27,33,35,41,43,47,51],"ai":[0,14,28,31,32,34,38,57]},"scoresAfter":[-81,-62]},{"ply":42,"player":"ai","action":18,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[2,16,33,35,41,43,47,51],"ai":[0,14,28,31,32,34,38,57]},"scoresAfter":[-81,-62]},{"ply":43,"player":"human","action":24,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[2,16,33,35,41,43,47,51],"ai":[0,28,31,32,34,38,44,57]},"scoresAfter":[-65,-62]},{"ply":44,"player":"ai","action":24,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[2,16,35,39,41,43,47,51],"ai":[0,28,31,32,34,38,44,57]},"scoresAfter":[-65,-44]},{"ply":45,"player":"human","action":24,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[2,16,35,39,41,43,47,51],"ai":[0,17,28,32,34,38,44,57]},"scoresAfter":[-45,-44]},{"ply":46,"player":"ai","action":37,"playedCard":32,"placeType":"play","drawSource":"discard_0","drawnCard":6,"handsBefore":{"human":[2,16,39,41,43,46,47,51],"ai":[0,17,28,32,34,38,44,57]},"scoresAfter":[-45,-23]},{"ply":47,"player":"human","action":40,"playedCard":41,"placeType":"play","drawSource":"discard_3","drawnCard":42,"handsBefore":{"human":[2,16,39,41,43,46,47,51],"ai":[0,6,17,28,34,38,44,57]},"scoresAfter":[-33,-23]},{"ply":48,"player":"ai","action":48,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[2,16,39,42,43,46,47,51],"ai":[0,6,17,28,34,38,44,57]},"scoresAfter":[-33,4]},{"ply":49,"player":"human","action":53,"playedCard":43,"placeType":"play","drawSource":"discard_4","drawnCard":49,"handsBefore":{"human":[2,16,39,42,43,46,47,51],"ai":[0,5,6,17,28,38,44,57]},"scoresAfter":[-15,4]},{"ply":50,"player":"ai","action":66,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[2,16,39,42,46,47,49,51],"ai":[0,5,6,17,28,38,44,57]},"scoresAfter":[-15,4]},{"ply":51,"player":"human","action":52,"playedCard":46,"placeType":"play","drawSource":"discard_3","drawnCard":38,"handsBefore":{"human":[2,16,39,42,46,47,49,51],"ai":[0,5,6,17,28,30,44,57]},"scoresAfter":[12,4]},{"ply":52,"player":"ai","action":78,"playedCard":44,"placeType":"discard","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[2,16,38,39,42,47,49,51],"ai":[0,5,6,17,28,30,44,57]},"scoresAfter":[12,4]},{"ply":53,"player":"human","action":60,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[2,16,38,39,42,47,49,51],"ai":[0,5,6,17,28,30,55,57]},"scoresAfter":[42,4]}],"finalScores":[42,4],"outcome":"YOU WIN","finalState":{"deckOrder":[52,42,48,58,33,25,18,20,40,32,8,38,19,1,7,31,54,15,23,29,56,45,9,4,49,34,51,59,13,10,24,36,11,3,22,53,27,6,26,21,41,12,35,47,57,43,14,37,28,2,0,16,44,39,17,46,5,30,55,50],"drawPtr":60,"cardLoc":[2,4,1,3,3,2,2,4,4,3,4,3,5,3,5,4,1,2,3,4,3,5,4,3,4,4,3,3,2,4,2,4,4,3,4,3,3,3,1,1,4,3,1,3,5,4,3,3,3,1,1,1,3,4,3,2,3,2,3,4],"handPublic":[false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,true,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,10,10,10,9],[9,9,9,8,10]],"colHandshakes":[[0,1,1,2,1],[1,0,2,0,0]],"colLength":[[4,4,4,6,5],[4,3,6,2,2]],"piles":[[],[21,12,14],[],[44],[]],"toMove":1,"stepCount":53,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"d9305001-a6bc-4d79-aeba-ae62c0cae6d4","seed":"ewnofs","startedAt":"2026-07-14T15:37:06.057Z","finishedAt":"2026-07-14T15:42:11.027Z","initialDeckOrder":[5,56,6,42,17,55,7,37,15,28,3,0,4,10,22,30,20,49,52,19,53,21,45,18,26,11,58,34,44,59,25,36,12,50,38,48,27,31,2,14,41,9,46,8,57,35,32,23,51,39,29,47,54,16,24,33,40,13,1,43],"moves":[{"ply":1,"player":"human","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[5,6,7,17,37,42,55,56],"ai":[0,3,4,10,15,22,28,30]},"scoresAfter":[-16,0]},{"ply":2,"player":"ai","action":0,"playedCard":0,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[6,7,17,20,37,42,55,56],"ai":[0,3,4,10,15,22,28,30]},"scoresAfter":[-16,-40]},{"ply":3,"player":"human","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[6,7,17,20,37,42,55,56],"ai":[3,4,10,15,22,28,30,49]},"scoresAfter":[-11,-40]},{"ply":4,"player":"ai","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[7,17,20,37,42,52,55,56],"ai":[3,4,10,15,22,28,30,49]},"scoresAfter":[-11,-36]},{"ply":5,"player":"human","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[7,17,20,37,42,52,55,56],"ai":[4,10,15,19,22,28,30,49]},"scoresAfter":[-5,-36]},{"ply":6,"player":"ai","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[17,20,37,42,52,53,55,56],"ai":[4,10,15,19,22,28,30,49]},"scoresAfter":[-5,-30]},{"ply":7,"player":"human","action":48,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[17,20,37,42,52,53,55,56],"ai":[10,15,19,21,22,28,30,49]},"scoresAfter":[-22,-30]},{"ply":8,"player":"ai","action":90,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[17,20,37,42,45,53,55,56],"ai":[10,15,19,21,22,28,30,49]},"scoresAfter":[-22,-30]},{"ply":9,"player":"human","action":60,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[17,20,37,42,45,53,55,56],"ai":[10,15,18,19,21,22,28,30]},"scoresAfter":[-18,-30]},{"ply":10,"player":"ai","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[17,20,26,37,42,45,55,56],"ai":[10,15,18,19,21,22,28,30]},"scoresAfter":[-18,-12]},{"ply":11,"player":"human","action":36,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[17,20,26,37,42,45,55,56],"ai":[11,15,18,19,21,22,28,30]},"scoresAfter":[-58,-12]},{"ply":12,"player":"ai","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[17,20,26,42,45,55,56,58],"ai":[11,15,18,19,21,22,28,30]},"scoresAfter":[-58,8]},{"ply":13,"player":"human","action":60,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[17,20,26,42,45,55,56,58],"ai":[15,18,19,21,22,28,30,34]},"scoresAfter":[-52,8]},{"ply":14,"player":"ai","action":0,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[17,20,26,42,44,45,56,58],"ai":[15,18,19,21,22,28,30,34]},"scoresAfter":[-52,-10]},{"ply":15,"player":"human","action":36,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[17,20,26,42,44,45,56,58],"ai":[18,19,21,22,28,30,34,59]},"scoresAfter":[-42,-10]},{"ply":16,"player":"ai","action":0,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[17,20,25,26,44,45,56,58],"ai":[18,19,21,22,28,30,34,59]},"scoresAfter":[-42,-5]},{"ply":17,"player":"human","action":30,"playedCard":25,"placeType":"discard","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[17,20,25,26,44,45,56,58],"ai":[19,21,22,28,30,34,36,59]},"scoresAfter":[-42,-5]},{"ply":18,"player":"ai","action":3,"playedCard":19,"placeType":"play","drawSource":"discard_2","drawnCard":25,"handsBefore":{"human":[12,17,20,26,44,45,56,58],"ai":[19,21,22,28,30,34,36,59]},"scoresAfter":[-42,1]},{"ply":19,"player":"human","action":42,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[12,17,20,26,44,45,56,58],"ai":[21,22,25,28,30,34,36,59]},"scoresAfter":[-42,1]},{"ply":20,"player":"ai","action":3,"playedCard":21,"placeType":"play","drawSource":"discard_2","drawnCard":26,"handsBefore":{"human":[12,17,20,44,45,50,56,58],"ai":[21,22,25,28,30,34,36,59]},"scoresAfter":[-42,9]},{"ply":21,"player":"human","action":72,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[12,17,20,44,45,50,56,58],"ai":[22,25,26,28,30,34,36,59]},"scoresAfter":[-35,9]},{"ply":22,"player":"ai","action":0,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[12,17,20,38,44,45,50,58],"ai":[22,25,26,28,30,34,36,59]},"scoresAfter":[-35,18]},{"ply":23,"player":"human","action":42,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[12,17,20,38,44,45,50,58],"ai":[25,26,28,30,34,36,48,59]},"scoresAfter":[-35,18]},{"ply":24,"player":"ai","action":0,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[12,17,20,27,44,45,50,58],"ai":[25,26,28,30,34,36,48,59]},"scoresAfter":[-35,-22]},{"ply":25,"player":"human","action":6,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[12,17,20,27,44,45,50,58],"ai":[26,28,30,31,34,36,48,59]},"scoresAfter":[-35,-22]},{"ply":26,"player":"ai","action":78,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[2,17,20,27,44,45,50,58],"ai":[26,28,30,31,34,36,48,59]},"scoresAfter":[-35,-22]},{"ply":27,"player":"human","action":18,"playedCard":17,"placeType":"discard","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[2,17,20,27,44,45,50,58],"ai":[14,26,28,30,31,34,36,59]},"scoresAfter":[-35,-22]},{"ply":28,"player":"ai","action":12,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[2,20,27,41,44,45,50,58],"ai":[14,26,28,30,31,34,36,59]},"scoresAfter":[-35,-42]},{"ply":29,"player":"human","action":18,"playedCard":20,"placeType":"discard","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[2,20,27,41,44,45,50,58],"ai":[9,14,28,30,31,34,36,59]},"scoresAfter":[-35,-42]},{"ply":30,"player":"ai","action":6,"playedCard":9,"placeType":"discard","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[2,27,41,44,45,46,50,58],"ai":[9,14,28,30,31,34,36,59]},"scoresAfter":[-35,-42]},{"ply":31,"player":"human","action":36,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[2,27,41,44,45,46,50,58],"ai":[8,14,28,30,31,34,36,59]},"scoresAfter":[-21,-42]},{"ply":32,"player":"ai","action":6,"playedCard":8,"placeType":"discard","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[2,27,41,45,46,50,57,58],"ai":[8,14,28,30,31,34,36,59]},"scoresAfter":[-21,-42]},{"ply":33,"player":"human","action":36,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[2,27,41,45,46,50,57,58],"ai":[14,28,30,31,34,35,36,59]},"scoresAfter":[-5,-42]},{"ply":34,"player":"ai","action":6,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[2,27,32,41,46,50,57,58],"ai":[14,28,30,31,34,35,36,59]},"scoresAfter":[-5,-42]},{"ply":35,"player":"human","action":48,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[2,27,32,41,46,50,57,58],"ai":[23,28,30,31,34,35,36,59]},"scoresAfter":[13,-42]},{"ply":36,"player":"ai","action":0,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[2,27,32,41,50,51,57,58],"ai":[23,28,30,31,34,35,36,59]},"scoresAfter":[13,-32]},{"ply":37,"player":"human","action":72,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[2,27,32,41,50,51,57,58],"ai":[28,30,31,34,35,36,39,59]},"scoresAfter":[21,-32]},{"ply":38,"player":"ai","action":0,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[2,27,29,32,41,50,51,58],"ai":[28,30,31,34,35,36,39,59]},"scoresAfter":[21,-23]},{"ply":39,"player":"human","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[2,27,29,32,41,50,51,58],"ai":[30,31,34,35,36,39,47,59]},"scoresAfter":[30,-23]},{"ply":40,"player":"ai","action":1,"playedCard":30,"placeType":"play","drawSource":"discard_0","drawnCard":8,"handsBefore":{"human":[2,27,29,32,41,50,51,54],"ai":[30,31,34,35,36,39,47,59]},"scoresAfter":[30,-8]},{"ply":41,"player":"human","action":55,"playedCard":41,"placeType":"discard","drawSource":"discard_0","drawnCard":9,"handsBefore":{"human":[2,27,29,32,41,50,51,54],"ai":[8,31,34,35,36,39,47,59]},"scoresAfter":[30,-8]},{"ply":42,"player":"ai","action":12,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[2,9,27,29,32,50,51,54],"ai":[8,31,34,35,36,39,47,59]},"scoresAfter":[30,10]},{"ply":43,"player":"human","action":12,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[2,9,27,29,32,50,51,54],"ai":[8,16,34,35,36,39,47,59]},"scoresAfter":[38,10]},{"ply":44,"player":"ai","action":26,"playedCard":34,"placeType":"play","drawSource":"discard_1","drawnCard":14,"handsBefore":{"human":[2,24,27,29,32,50,51,54],"ai":[8,16,34,35,36,39,47,59]},"scoresAfter":[38,37]},{"ply":45,"player":"human","action":18,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[2,24,27,29,32,50,51,54],"ai":[8,14,16,35,36,39,47,59]},"scoresAfter":[38,37]},{"ply":46,"player":"ai","action":78,"playedCard":47,"placeType":"discard","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[2,27,29,32,33,50,51,54],"ai":[8,14,16,35,36,39,47,59]},"scoresAfter":[38,37]},{"ply":47,"player":"human","action":22,"playedCard":27,"placeType":"discard","drawSource":"discard_3","drawnCard":47,"handsBefore":{"human":[2,27,29,32,33,50,51,54],"ai":[8,14,16,35,36,39,40,59]},"scoresAfter":[38,37]},{"ply":48,"player":"ai","action":36,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[2,29,32,33,47,50,51,54],"ai":[8,14,16,35,36,39,40,59]},"scoresAfter":[38,67]},{"ply":49,"player":"human","action":48,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[2,29,32,33,47,50,51,54],"ai":[8,13,14,16,36,39,40,59]},"scoresAfter":[58,67]},{"ply":50,"player":"ai","action":22,"playedCard":13,"placeType":"discard","drawSource":"discard_3","drawnCard":41,"handsBefore":{"human":[1,2,29,32,33,50,51,54],"ai":[8,13,14,16,36,39,40,59]},"scoresAfter":[58,67]},{"ply":51,"player":"human","action":54,"playedCard":33,"placeType":"discard","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[1,2,29,32,33,50,51,54],"ai":[8,14,16,36,39,40,41,59]},"scoresAfter":[58,67]}],"finalScores":[58,67],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[5,56,6,42,17,55,7,37,15,28,3,0,4,10,22,30,20,49,52,19,53,21,45,18,26,11,58,34,44,59,25,36,12,50,38,48,27,31,2,14,41,9,46,8,57,35,32,23,51,39,29,47,54,16,24,33,40,13,1,43],"drawPtr":60,"cardLoc":[4,1,1,4,4,3,3,3,2,3,4,4,5,5,2,4,2,5,4,4,5,4,4,4,5,4,4,5,4,1,4,4,1,5,4,4,2,3,5,2,2,2,3,1,3,3,3,3,5,5,1,1,3,3,1,3,3,3,3,2],"handPublic":[false,false,false,false,false,false,false,false,true,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[8,0,0,10,9],[10,10,10,0,0]],"colHandshakes":[[0,0,0,1,0],[1,0,2,0,0]],"colLength":[[4,0,0,6,6],[5,6,7,0,0]],"piles":[[],[12,17,20,13],[24,27,33],[38],[49,48]],"toMove":1,"stepCount":51,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"99bf2b12-4d8c-46dd-85ec-892e6e5ccfea","seed":"j5q99x","startedAt":"2026-07-14T15:42:12.198Z","finishedAt":"2026-07-14T15:46:27.347Z","initialDeckOrder":[41,6,9,49,1,32,44,21,8,38,50,17,34,25,15,26,20,7,33,57,27,55,45,58,13,40,46,18,37,11,22,16,43,19,5,4,30,31,51,48,28,12,42,0,29,47,36,2,56,52,10,23,53,3,59,35,24,54,14,39],"moves":[{"ply":1,"player":"human","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[1,6,9,21,32,41,44,49],"ai":[8,15,17,25,26,34,38,50]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":6,"playedCard":8,"placeType":"discard","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[6,9,20,21,32,41,44,49],"ai":[8,15,17,25,26,34,38,50]},"scoresAfter":[-40,0]},{"ply":3,"player":"human","action":1,"playedCard":6,"placeType":"play","drawSource":"discard_0","drawnCard":8,"handsBefore":{"human":[6,9,20,21,32,41,44,49],"ai":[7,15,17,25,26,34,38,50]},"scoresAfter":[-30,0]},{"ply":4,"player":"ai","action":6,"playedCard":7,"placeType":"discard","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[8,9,20,21,32,41,44,49],"ai":[7,15,17,25,26,34,38,50]},"scoresAfter":[-30,0]},{"ply":5,"player":"human","action":91,"playedCard":49,"placeType":"discard","drawSource":"discard_0","drawnCard":7,"handsBefore":{"human":[8,9,20,21,32,41,44,49],"ai":[15,17,25,26,33,34,38,50]},"scoresAfter":[-30,0]},{"ply":6,"player":"ai","action":0,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[7,8,9,20,21,32,41,44],"ai":[15,17,25,26,33,34,38,50]},"scoresAfter":[-30,-18]},{"ply":7,"player":"human","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[7,8,9,20,21,32,41,44],"ai":[17,25,26,33,34,38,50,57]},"scoresAfter":[-18,-18]},{"ply":8,"player":"ai","action":24,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[8,9,20,21,27,32,41,44],"ai":[17,25,26,33,34,38,50,57]},"scoresAfter":[-18,-58]},{"ply":9,"player":"human","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[8,9,20,21,27,32,41,44],"ai":[17,25,33,34,38,50,55,57]},"scoresAfter":[-4,-58]},{"ply":10,"player":"ai","action":65,"playedCard":50,"placeType":"play","drawSource":"discard_4","drawnCard":49,"handsBefore":{"human":[9,20,21,27,32,41,44,45],"ai":[17,25,33,34,38,50,55,57]},"scoresAfter":[-4,-98]},{"ply":11,"player":"human","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[9,20,21,27,32,41,44,45],"ai":[17,25,33,34,38,49,55,57]},"scoresAfter":[12,-98]},{"ply":12,"player":"ai","action":60,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[20,21,27,32,41,44,45,58],"ai":[17,25,33,34,38,49,55,57]},"scoresAfter":[12,-118]},{"ply":13,"player":"human","action":48,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[20,21,27,32,41,44,45,58],"ai":[13,17,25,33,34,38,55,57]},"scoresAfter":[-4,-118]},{"ply":14,"player":"ai","action":24,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[20,21,27,32,40,44,45,58],"ai":[13,17,25,33,34,38,55,57]},"scoresAfter":[-4,-138]},{"ply":15,"player":"human","action":54,"playedCard":40,"placeType":"discard","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[20,21,27,32,40,44,45,58],"ai":[13,17,33,34,38,46,55,57]},"scoresAfter":[-4,-138]},{"ply":16,"player":"ai","action":6,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[18,20,21,27,32,44,45,58],"ai":[13,17,33,34,38,46,55,57]},"scoresAfter":[-4,-138]},{"ply":17,"player":"human","action":62,"playedCard":44,"placeType":"play","drawSource":"discard_1","drawnCard":13,"handsBefore":{"human":[18,20,21,27,32,44,45,58],"ai":[17,33,34,37,38,46,55,57]},"scoresAfter":[3,-138]},{"ply":18,"player":"ai","action":36,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[13,18,20,21,27,32,45,58],"ai":[17,33,34,37,38,46,55,57]},"scoresAfter":[3,-178]},{"ply":19,"player":"human","action":0,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[13,18,20,21,27,32,45,58],"ai":[11,17,33,34,38,46,55,57]},"scoresAfter":[-37,-178]},{"ply":20,"player":"ai","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[18,20,21,22,27,32,45,58],"ai":[11,17,33,34,38,46,55,57]},"scoresAfter":[-37,-188]},{"ply":21,"player":"human","action":0,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[18,20,21,22,27,32,45,58],"ai":[16,17,33,34,38,46,55,57]},"scoresAfter":[-27,-188]},{"ply":22,"player":"ai","action":0,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[20,21,22,27,32,43,45,58],"ai":[16,17,33,34,38,46,55,57]},"scoresAfter":[-27,-185]},{"ply":23,"player":"human","action":0,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[20,21,22,27,32,43,45,58],"ai":[17,19,33,34,38,46,55,57]},"scoresAfter":[-13,-185]},{"ply":24,"player":"ai","action":0,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[5,21,22,27,32,43,45,58],"ai":[17,19,33,34,38,46,55,57]},"scoresAfter":[-13,-181]},{"ply":25,"player":"human","action":12,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[5,21,22,27,32,43,45,58],"ai":[4,19,33,34,38,46,55,57]},"scoresAfter":[3,-181]},{"ply":26,"player":"ai","action":6,"playedCard":4,"placeType":"discard","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[5,22,27,30,32,43,45,58],"ai":[4,19,33,34,38,46,55,57]},"scoresAfter":[3,-181]},{"ply":27,"player":"human","action":12,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[5,22,27,30,32,43,45,58],"ai":[19,31,33,34,38,46,55,57]},"scoresAfter":[21,-181]},{"ply":28,"player":"ai","action":48,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[5,27,30,32,43,45,51,58],"ai":[19,31,33,34,38,46,55,57]},"scoresAfter":[21,-201]},{"ply":29,"player":"human","action":6,"playedCard":5,"placeType":"discard","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[5,27,30,32,43,45,51,58],"ai":[19,31,33,34,46,48,55,57]},"scoresAfter":[21,-201]},{"ply":30,"player":"ai","action":48,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[27,28,30,32,43,45,51,58],"ai":[19,31,33,34,46,48,55,57]},"scoresAfter":[21,-174]},{"ply":31,"player":"human","action":0,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[27,28,30,32,43,45,51,58],"ai":[12,19,31,33,34,48,55,57]},"scoresAfter":[3,-174]},{"ply":32,"player":"ai","action":60,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[28,30,32,42,43,45,51,58],"ai":[12,19,31,33,34,48,55,57]},"scoresAfter":[3,-194]},{"ply":33,"player":"human","action":0,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[28,30,32,42,43,45,51,58],"ai":[0,12,19,31,33,34,55,57]},"scoresAfter":[6,-194]},{"ply":34,"player":"ai","action":24,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[29,30,32,42,43,45,51,58],"ai":[0,12,19,31,33,34,55,57]},"scoresAfter":[6,-188]},{"ply":35,"player":"human","action":0,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[29,30,32,42,43,45,51,58],"ai":[0,12,31,33,34,47,55,57]},"scoresAfter":[10,-188]},{"ply":36,"player":"ai","action":24,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[30,32,36,42,43,45,51,58],"ai":[0,12,31,33,34,47,55,57]},"scoresAfter":[10,-170]},{"ply":37,"player":"human","action":0,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[30,32,36,42,43,45,51,58],"ai":[0,2,12,33,34,47,55,57]},"scoresAfter":[15,-170]},{"ply":38,"player":"ai","action":36,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[32,36,42,43,45,51,56,58],"ai":[0,2,12,33,34,47,55,57]},"scoresAfter":[15,-146]},{"ply":39,"player":"human","action":0,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[32,36,42,43,45,51,56,58],"ai":[0,2,12,34,47,52,55,57]},"scoresAfter":[22,-146]},{"ply":40,"player":"ai","action":36,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[10,36,42,43,45,51,56,58],"ai":[0,2,12,34,47,52,55,57]},"scoresAfter":[22,-119]},{"ply":41,"player":"human","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[10,36,42,43,45,51,56,58],"ai":[0,2,12,23,47,52,55,57]},"scoresAfter":[40,-119]},{"ply":42,"player":"ai","action":48,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[36,42,43,45,51,53,56,58],"ai":[0,2,12,23,47,52,55,57]},"scoresAfter":[40,-89]},{"ply":43,"player":"human","action":36,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[36,42,43,45,51,53,56,58],"ai":[0,2,3,12,23,52,55,57]},"scoresAfter":[48,-89]},{"ply":44,"player":"ai","action":72,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[36,42,43,51,53,56,58,59],"ai":[0,2,3,12,23,52,55,57]},"scoresAfter":[48,-65]},{"ply":45,"player":"human","action":60,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[36,42,43,51,53,56,58,59],"ai":[0,2,3,12,23,35,52,57]},"scoresAfter":[35,-65]},{"ply":46,"player":"ai","action":52,"playedCard":23,"placeType":"play","drawSource":"discard_3","drawnCard":40,"handsBefore":{"human":[24,36,42,43,51,53,58,59],"ai":[0,2,3,12,23,35,52,57]},"scoresAfter":[35,-55]},{"ply":47,"player":"human","action":72,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[24,36,42,43,51,53,58,59],"ai":[0,2,3,12,35,40,52,57]},"scoresAfter":[44,-55]},{"ply":48,"player":"ai","action":49,"playedCard":35,"placeType":"play","drawSource":"discard_0","drawnCard":5,"handsBefore":{"human":[24,36,42,43,51,53,54,59],"ai":[0,2,3,12,35,40,52,57]},"scoresAfter":[44,-25]},{"ply":49,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[24,36,42,43,51,53,54,59],"ai":[0,2,3,5,12,40,52,57]},"scoresAfter":[54,-25]},{"ply":50,"player":"ai","action":84,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[14,24,36,42,43,51,53,54],"ai":[0,2,3,5,12,40,52,57]},"scoresAfter":[54,7]}],"finalScores":[54,7],"outcome":"YOU WIN","finalState":{"deckOrder":[41,6,9,49,1,32,44,21,8,38,50,17,34,25,15,26,20,7,33,57,27,55,45,58,13,40,46,18,37,11,22,16,43,19,5,4,30,31,51,48,28,12,42,0,29,47,36,2,56,52,10,23,53,3,59,35,24,54,14,39],"drawPtr":60,"cardLoc":[2,3,2,2,5,2,3,3,3,3,3,4,2,3,1,4,4,4,3,4,3,3,3,4,1,4,4,3,3,3,3,4,3,4,4,4,1,4,4,2,2,3,1,1,3,3,4,4,4,4,4,1,2,1,1,4,3,4,3,3],"handPublic":[false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[9,9,7,8,10],[10,10,10,10,8]],"colHandshakes":[[1,1,0,0,0],[0,0,2,2,3]],"colLength":[[6,5,5,3,3],[1,5,6,4,5]],"piles":[[4],[],[],[],[]],"toMove":0,"stepCount":50,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"6c091e19-42ee-4c38-bf34-ce17d5263bf4","seed":"84knyl","startedAt":"2026-07-14T15:46:28.209Z","finishedAt":"2026-07-14T15:49:25.921Z","initialDeckOrder":[0,36,2,45,47,16,46,11,10,21,41,20,24,19,48,54,55,52,51,25,50,1,7,53,26,5,15,31,49,9,35,30,27,40,34,28,8,18,59,32,17,33,23,43,38,29,22,6,44,56,14,39,57,3,58,12,13,42,4,37],"moves":[{"ply":1,"player":"human","action":48,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[0,2,11,16,36,45,46,47],"ai":[10,19,20,21,24,41,48,54]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":60,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[0,2,11,16,45,46,47,55],"ai":[10,19,20,21,24,41,48,54]},"scoresAfter":[-40,-16]},{"ply":3,"player":"human","action":0,"playedCard":0,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[0,2,11,16,45,46,47,55],"ai":[10,19,20,21,24,48,52,54]},"scoresAfter":[-80,-16]},{"ply":4,"player":"ai","action":60,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[2,11,16,45,46,47,51,55],"ai":[10,19,20,21,24,48,52,54]},"scoresAfter":[-80,-56]},{"ply":5,"player":"human","action":0,"playedCard":2,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[2,11,16,45,46,47,51,55],"ai":[10,19,20,21,24,25,52,54]},"scoresAfter":[-100,-56]},{"ply":6,"player":"ai","action":60,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[11,16,45,46,47,50,51,55],"ai":[10,19,20,21,24,25,52,54]},"scoresAfter":[-100,-96]},{"ply":7,"player":"human","action":60,"playedCard":50,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[11,16,45,46,47,50,51,55],"ai":[1,10,19,20,21,24,52,54]},"scoresAfter":[-140,-96]},{"ply":8,"player":"ai","action":72,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[7,11,16,45,46,47,51,55],"ai":[1,10,19,20,21,24,52,54]},"scoresAfter":[-140,-90]},{"ply":9,"player":"human","action":72,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[7,11,16,45,46,47,51,55],"ai":[1,10,19,20,21,24,53,54]},"scoresAfter":[-136,-90]},{"ply":10,"player":"ai","action":72,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[7,11,16,26,45,46,47,55],"ai":[1,10,19,20,21,24,53,54]},"scoresAfter":[-136,-82]},{"ply":11,"player":"human","action":42,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[7,11,16,26,45,46,47,55],"ai":[1,5,10,19,20,21,24,54]},"scoresAfter":[-136,-82]},{"ply":12,"player":"ai","action":84,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[7,11,15,16,45,46,47,55],"ai":[1,5,10,19,20,21,24,54]},"scoresAfter":[-136,-72]},{"ply":13,"player":"human","action":30,"playedCard":15,"placeType":"discard","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[7,11,15,16,45,46,47,55],"ai":[1,5,10,19,20,21,24,31]},"scoresAfter":[-136,-72]},{"ply":14,"player":"ai","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[7,11,16,45,46,47,49,55],"ai":[1,5,10,19,20,21,24,31]},"scoresAfter":[-136,-112]},{"ply":15,"player":"human","action":30,"playedCard":16,"placeType":"discard","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[7,11,16,45,46,47,49,55],"ai":[5,9,10,19,20,21,24,31]},"scoresAfter":[-136,-112]},{"ply":16,"player":"ai","action":2,"playedCard":5,"placeType":"play","drawSource":"discard_1","drawnCard":16,"handsBefore":{"human":[7,11,35,45,46,47,49,55],"ai":[5,9,10,19,20,21,24,31]},"scoresAfter":[-136,-104]},{"ply":17,"player":"human","action":78,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[7,11,35,45,46,47,49,55],"ai":[9,10,16,19,20,21,24,31]},"scoresAfter":[-136,-104]},{"ply":18,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[7,11,30,35,45,46,47,55],"ai":[9,10,16,19,20,21,24,31]},"scoresAfter":[-136,-88]},{"ply":19,"player":"human","action":51,"playedCard":45,"placeType":"play","drawSource":"discard_2","drawnCard":26,"handsBefore":{"human":[7,11,30,35,45,46,47,55],"ai":[10,16,19,20,21,24,27,31]},"scoresAfter":[-120,-88]},{"ply":20,"player":"ai","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[7,11,26,30,35,46,47,55],"ai":[10,16,19,20,21,24,27,31]},"scoresAfter":[-120,-70]},{"ply":21,"player":"human","action":60,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[7,11,26,30,35,46,47,55],"ai":[16,19,20,21,24,27,31,40]},"scoresAfter":[-102,-70]},{"ply":22,"player":"ai","action":60,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[7,11,26,30,34,35,47,55],"ai":[16,19,20,21,24,27,31,40]},"scoresAfter":[-102,-66]},{"ply":23,"player":"human","action":24,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[7,11,26,30,34,35,47,55],"ai":[16,19,20,21,24,28,31,40]},"scoresAfter":[-142,-66]},{"ply":24,"player":"ai","action":60,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[7,8,11,30,34,35,47,55],"ai":[16,19,20,21,24,28,31,40]},"scoresAfter":[-142,-60]},{"ply":25,"player":"human","action":72,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[7,8,11,30,34,35,47,55],"ai":[16,18,19,20,21,24,31,40]},"scoresAfter":[-122,-60]},{"ply":26,"player":"ai","action":74,"playedCard":31,"placeType":"play","drawSource":"discard_1","drawnCard":15,"handsBefore":{"human":[7,8,11,30,34,35,55,59],"ai":[16,18,19,20,21,24,31,40]},"scoresAfter":[-122,-48]},{"ply":27,"player":"human","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[7,8,11,30,34,35,55,59],"ai":[15,16,18,19,20,21,24,40]},"scoresAfter":[-104,-48]},{"ply":28,"player":"ai","action":0,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[8,11,30,32,34,35,55,59],"ai":[15,16,18,19,20,21,24,40]},"scoresAfter":[-104,-66]},{"ply":29,"player":"human","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[8,11,30,32,34,35,55,59],"ai":[16,17,18,19,20,21,24,40]},"scoresAfter":[-83,-66]},{"ply":30,"player":"ai","action":0,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[11,30,32,33,34,35,55,59],"ai":[16,17,18,19,20,21,24,40]},"scoresAfter":[-83,-63]},{"ply":31,"player":"human","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[11,30,32,33,34,35,55,59],"ai":[17,18,19,20,21,23,24,40]},"scoresAfter":[-53,-63]},{"ply":32,"player":"ai","action":0,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[30,32,33,34,35,43,55,59],"ai":[17,18,19,20,21,23,24,40]},"scoresAfter":[-53,-59]},{"ply":33,"player":"human","action":0,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[30,32,33,34,35,43,55,59],"ai":[18,19,20,21,23,24,38,40]},"scoresAfter":[-43,-59]},{"ply":34,"player":"ai","action":0,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[29,32,33,34,35,43,55,59],"ai":[18,19,20,21,23,24,38,40]},"scoresAfter":[-43,-54]},{"ply":35,"player":"human","action":12,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[29,32,33,34,35,43,55,59],"ai":[19,20,21,22,23,24,38,40]},"scoresAfter":[-29,-54]},{"ply":36,"player":"ai","action":0,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[6,29,33,34,35,43,55,59],"ai":[19,20,21,22,23,24,38,40]},"scoresAfter":[-29,-48]},{"ply":37,"player":"human","action":24,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[6,29,33,34,35,43,55,59],"ai":[20,21,22,23,24,38,40,44]},"scoresAfter":[-13,-48]},{"ply":38,"player":"ai","action":0,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[6,29,34,35,43,55,56,59],"ai":[20,21,22,23,24,38,40,44]},"scoresAfter":[-13,-41]},{"ply":39,"player":"human","action":24,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[6,29,34,35,43,55,56,59],"ai":[14,21,22,23,24,38,40,44]},"scoresAfter":[5,-41]},{"ply":40,"player":"ai","action":12,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[6,29,35,39,43,55,56,59],"ai":[14,21,22,23,24,38,40,44]},"scoresAfter":[5,-33]},{"ply":41,"player":"human","action":24,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[6,29,35,39,43,55,56,59],"ai":[14,22,23,24,38,40,44,57]},"scoresAfter":[25,-33]},{"ply":42,"player":"ai","action":12,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[3,6,29,39,43,55,56,59],"ai":[14,22,23,24,38,40,44,57]},"scoresAfter":[25,-4]},{"ply":43,"player":"human","action":60,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[3,6,29,39,43,55,56,59],"ai":[14,23,24,38,40,44,57,58]},"scoresAfter":[37,-4]},{"ply":44,"player":"ai","action":17,"playedCard":23,"placeType":"play","drawSource":"discard_4","drawnCard":49,"handsBefore":{"human":[3,6,12,29,39,43,56,59],"ai":[14,23,24,38,40,44,57,58]},"scoresAfter":[37,6]},{"ply":45,"player":"human","action":72,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[3,6,12,29,39,43,56,59],"ai":[14,24,38,40,44,49,57,58]},"scoresAfter":[51,6]},{"ply":46,"player":"ai","action":72,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[3,6,12,13,29,39,43,59],"ai":[14,24,38,40,44,49,57,58]},"scoresAfter":[51,22]},{"ply":47,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[3,6,12,13,29,39,43,59],"ai":[14,24,38,40,42,44,49,58]},"scoresAfter":[71,22]},{"ply":48,"player":"ai","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[3,4,6,12,13,29,39,43],"ai":[14,24,38,40,42,44,49,58]},"scoresAfter":[71,40]}],"finalScores":[71,40],"outcome":"YOU WIN","finalState":{"deckOrder":[0,36,2,45,47,16,46,11,10,21,41,20,24,19,48,54,55,52,51,25,50,1,7,53,26,5,15,31,49,9,35,30,27,40,34,28,8,18,59,32,17,33,23,43,38,29,22,6,44,56,14,39,57,3,58,12,13,42,4,37],"drawPtr":60,"cardLoc":[3,4,3,1,1,4,1,3,3,4,4,3,1,1,2,4,4,4,4,4,4,4,4,4,2,4,3,4,4,1,3,4,3,3,3,3,3,2,2,1,2,4,2,1,2,3,3,3,4,2,3,3,4,4,4,3,3,4,4,3],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,0,10,10,10],[9,10,6,4,9]],"colHandshakes":[[2,0,1,1,1],[1,0,1,0,1]],"colLength":[[5,0,6,4,5],[4,9,4,1,6]],"piles":[[],[],[],[],[]],"toMove":0,"stepCount":48,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"019cb61a-506a-4335-b149-0b8d8df5a4d0","seed":"4213ir","startedAt":"2026-07-14T15:49:26.954Z","finishedAt":"2026-07-14T15:52:27.148Z","initialDeckOrder":[59,25,30,4,34,13,38,26,3,31,27,19,2,11,23,36,45,58,0,33,1,42,6,29,44,56,14,53,46,43,51,32,12,52,55,54,7,16,37,20,50,21,57,9,5,10,28,22,39,8,15,35,41,24,49,40,17,48,47,18],"moves":[{"ply":1,"player":"human","action":24,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[4,13,25,26,30,34,38,59],"ai":[2,3,11,19,23,27,31,36]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":90,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[4,13,26,30,34,38,45,59],"ai":[2,3,11,19,23,27,31,36]},"scoresAfter":[-40,0]},{"ply":3,"player":"human","action":24,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[4,13,26,30,34,38,45,59],"ai":[2,3,11,19,23,27,31,58]},"scoresAfter":[-60,0]},{"ply":4,"player":"ai","action":0,"playedCard":2,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[0,4,13,30,34,38,45,59],"ai":[2,3,11,19,23,27,31,58]},"scoresAfter":[-60,-40]},{"ply":5,"player":"human","action":64,"playedCard":38,"placeType":"play","drawSource":"discard_3","drawnCard":36,"handsBefore":{"human":[0,4,13,30,34,38,45,59],"ai":[3,11,19,23,27,31,33,58]},"scoresAfter":[-100,-40]},{"ply":6,"player":"ai","action":48,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[0,4,13,30,34,36,45,59],"ai":[3,11,19,23,27,31,33,58]},"scoresAfter":[-100,-58]},{"ply":7,"player":"human","action":60,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[0,4,13,30,34,36,45,59],"ai":[1,3,11,19,23,31,33,58]},"scoresAfter":[-120,-58]},{"ply":8,"player":"ai","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[0,4,13,30,34,42,45,59],"ai":[1,3,11,19,23,31,33,58]},"scoresAfter":[-120,-78]},{"ply":9,"player":"human","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[0,4,13,30,34,42,45,59],"ai":[3,6,11,19,23,31,33,58]},"scoresAfter":[-120,-78]},{"ply":10,"player":"ai","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[4,13,29,30,34,42,45,59],"ai":[3,6,11,19,23,31,33,58]},"scoresAfter":[-120,-72]},{"ply":11,"player":"human","action":24,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[4,13,29,30,34,42,45,59],"ai":[6,11,19,23,31,33,44,58]},"scoresAfter":[-108,-72]},{"ply":12,"player":"ai","action":48,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[4,13,30,34,42,45,56,59],"ai":[6,11,19,23,31,33,44,58]},"scoresAfter":[-108,-66]},{"ply":13,"player":"human","action":24,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[4,13,30,34,42,45,56,59],"ai":[6,11,14,19,23,33,44,58]},"scoresAfter":[-93,-66]},{"ply":14,"player":"ai","action":24,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[4,13,34,42,45,53,56,59],"ai":[6,11,14,19,23,33,44,58]},"scoresAfter":[-93,-106]},{"ply":15,"player":"human","action":18,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[4,13,34,42,45,53,56,59],"ai":[6,11,19,23,33,44,46,58]},"scoresAfter":[-93,-106]},{"ply":16,"player":"ai","action":48,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[4,34,42,43,45,53,56,59],"ai":[6,11,19,23,33,44,46,58]},"scoresAfter":[-93,-98]},{"ply":17,"player":"human","action":24,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[4,34,42,43,45,53,56,59],"ai":[6,11,19,23,44,46,51,58]},"scoresAfter":[-78,-98]},{"ply":18,"player":"ai","action":73,"playedCard":51,"placeType":"play","drawSource":"discard_0","drawnCard":0,"handsBefore":{"human":[4,32,34,43,45,53,56,59],"ai":[6,11,19,23,44,46,51,58]},"scoresAfter":[-78,-116]},{"ply":19,"player":"human","action":12,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[4,32,34,43,45,53,56,59],"ai":[0,6,11,19,23,44,46,58]},"scoresAfter":[-57,-116]},{"ply":20,"player":"ai","action":62,"playedCard":44,"placeType":"play","drawSource":"discard_1","drawnCard":13,"handsBefore":{"human":[4,12,34,43,45,53,56,59],"ai":[0,6,11,19,23,44,46,58]},"scoresAfter":[-57,-129]},{"ply":21,"player":"human","action":18,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[4,12,34,43,45,53,56,59],"ai":[0,6,11,13,19,23,46,58]},"scoresAfter":[-57,-129]},{"ply":22,"player":"ai","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[4,34,43,45,52,53,56,59],"ai":[0,6,11,13,19,23,46,58]},"scoresAfter":[-57,-129]},{"ply":23,"player":"human","action":12,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[4,34,43,45,52,53,56,59],"ai":[6,11,13,19,23,46,55,58]},"scoresAfter":[-30,-129]},{"ply":24,"player":"ai","action":62,"playedCard":46,"placeType":"play","drawSource":"discard_1","drawnCard":12,"handsBefore":{"human":[4,43,45,52,53,54,56,59],"ai":[6,11,13,19,23,46,55,58]},"scoresAfter":[-30,-120]},{"ply":25,"player":"human","action":12,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[4,43,45,52,53,54,56,59],"ai":[6,11,12,13,19,23,55,58]},"scoresAfter":[-12,-120]},{"ply":26,"player":"ai","action":72,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[4,7,45,52,53,54,56,59],"ai":[6,11,12,13,19,23,55,58]},"scoresAfter":[-12,-114]},{"ply":27,"player":"human","action":24,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[4,7,45,52,53,54,56,59],"ai":[6,11,12,13,16,19,23,58]},"scoresAfter":[12,-114]},{"ply":28,"player":"ai","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[4,7,37,52,53,54,56,59],"ai":[6,11,12,13,16,19,23,58]},"scoresAfter":[12,-105]},{"ply":29,"player":"human","action":30,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[4,7,37,52,53,54,56,59],"ai":[6,11,12,13,16,19,20,23]},"scoresAfter":[12,-105]},{"ply":30,"player":"ai","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[4,7,50,52,53,54,56,59],"ai":[6,11,12,13,16,19,20,23]},"scoresAfter":[12,-90]},{"ply":31,"player":"human","action":24,"playedCard":50,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[4,7,50,52,53,54,56,59],"ai":[11,12,13,16,19,20,21,23]},"scoresAfter":[-28,-90]},{"ply":32,"player":"ai","action":12,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[4,7,52,53,54,56,57,59],"ai":[11,12,13,16,19,20,21,23]},"scoresAfter":[-28,-110]},{"ply":33,"player":"human","action":6,"playedCard":4,"placeType":"discard","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[4,7,52,53,54,56,57,59],"ai":[9,11,13,16,19,20,21,23]},"scoresAfter":[-28,-110]},{"ply":34,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[5,7,52,53,54,56,57,59],"ai":[9,11,13,16,19,20,21,23]},"scoresAfter":[-28,-86]},{"ply":35,"player":"human","action":6,"playedCard":5,"placeType":"discard","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[5,7,52,53,54,56,57,59],"ai":[10,11,13,16,19,20,21,23]},"scoresAfter":[-28,-86]},{"ply":36,"player":"ai","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[7,28,52,53,54,56,57,59],"ai":[10,11,13,16,19,20,21,23]},"scoresAfter":[-28,-59]},{"ply":37,"player":"human","action":24,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[7,28,52,53,54,56,57,59],"ai":[11,13,16,19,20,21,22,23]},"scoresAfter":[-22,-59]},{"ply":38,"player":"ai","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[7,28,39,53,54,56,57,59],"ai":[11,13,16,19,20,21,22,23]},"scoresAfter":[-22,-29]},{"ply":39,"player":"human","action":36,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[7,28,39,53,54,56,57,59],"ai":[8,13,16,19,20,21,22,23]},"scoresAfter":[-14,-29]},{"ply":40,"player":"ai","action":16,"playedCard":13,"placeType":"play","drawSource":"discard_3","drawnCard":37,"handsBefore":{"human":[7,15,28,39,54,56,57,59],"ai":[8,13,16,19,20,21,22,23]},"scoresAfter":[-14,-49]},{"ply":41,"player":"human","action":48,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[7,15,28,39,54,56,57,59],"ai":[8,16,19,20,21,22,23,37]},"scoresAfter":[-4,-49]},{"ply":42,"player":"ai","action":13,"playedCard":16,"placeType":"play","drawSource":"discard_0","drawnCard":5,"handsBefore":{"human":[7,15,28,35,39,56,57,59],"ai":[8,16,19,20,21,22,23,37]},"scoresAfter":[-4,-37]},{"ply":43,"player":"human","action":60,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[7,15,28,35,39,56,57,59],"ai":[5,8,19,20,21,22,23,37]},"scoresAfter":[10,-37]},{"ply":44,"player":"ai","action":25,"playedCard":19,"placeType":"play","drawSource":"discard_0","drawnCard":4,"handsBefore":{"human":[7,15,28,35,39,41,57,59],"ai":[5,8,19,20,21,22,23,37]},"scoresAfter":[10,-13]},{"ply":45,"player":"human","action":72,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[7,15,28,35,39,41,57,59],"ai":[4,5,8,20,21,22,23,37]},"scoresAfter":[26,-13]},{"ply":46,"player":"ai","action":36,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[7,15,24,28,35,39,41,59],"ai":[4,5,8,20,21,22,23,37]},"scoresAfter":[26,15]},{"ply":47,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[7,15,24,28,35,39,41,59],"ai":[4,5,8,21,22,23,37,49]},"scoresAfter":[46,15]},{"ply":48,"player":"ai","action":36,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[7,15,24,28,35,39,40,41],"ai":[4,5,8,21,22,23,37,49]},"scoresAfter":[46,47]},{"ply":49,"player":"human","action":48,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[7,15,24,28,35,39,40,41],"ai":[4,5,8,17,22,23,37,49]},"scoresAfter":[76,47]},{"ply":50,"player":"ai","action":79,"playedCard":37,"placeType":"discard","drawSource":"discard_0","drawnCard":0,"handsBefore":{"human":[7,15,24,28,39,40,41,48],"ai":[4,5,8,17,22,23,37,49]},"scoresAfter":[76,47]},{"ply":51,"player":"human","action":90,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[7,15,24,28,39,40,41,48],"ai":[0,4,5,8,17,22,23,49]},"scoresAfter":[76,47]},{"ply":52,"player":"ai","action":47,"playedCard":8,"placeType":"discard","drawSource":"discard_4","drawnCard":48,"handsBefore":{"human":[7,15,24,28,39,40,41,47],"ai":[0,4,5,8,17,22,23,49]},"scoresAfter":[76,47]},{"ply":53,"player":"human","action":84,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[7,15,24,28,39,40,41,47],"ai":[0,4,5,17,22,23,48,49]},"scoresAfter":[106,47]}],"finalScores":[106,47],"outcome":"YOU WIN","finalState":{"deckOrder":[59,25,30,4,34,13,38,26,3,31,27,19,2,11,23,36,45,58,0,33,1,42,6,29,44,56,14,53,46,43,51,32,12,52,55,54,7,16,37,20,50,21,57,9,5,10,28,22,39,8,15,35,41,24,49,40,17,48,47,18],"drawPtr":60,"cardLoc":[2,4,4,4,2,2,4,1,5,4,4,4,4,4,4,1,4,2,1,4,4,4,2,2,1,3,3,4,1,3,3,4,3,4,3,3,3,5,3,1,1,1,3,3,4,3,4,3,2,2,3,4,3,3,3,4,3,3,4,3],"handPublic":[true,false,false,false,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[0,0,10,10,10],[10,8,8,9,9]],"colHandshakes":[[0,0,2,2,1],[2,3,0,0,0]],"colLength":[[0,0,7,6,7],[7,7,3,2,3]],"piles":[[8],[],[],[37],[]],"toMove":1,"stepCount":53,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"431021db-ec29-482f-8931-21763342f1bb","seed":"djkogl","startedAt":"2026-07-14T15:52:28.139Z","finishedAt":"2026-07-14T15:56:30.660Z","initialDeckOrder":[39,2,54,5,57,41,24,48,9,35,23,44,51,52,25,53,27,28,58,10,42,49,46,40,19,16,3,37,31,56,43,6,12,59,45,38,22,21,4,8,55,17,0,7,15,33,13,18,29,1,50,32,36,34,14,30,11,47,26,20],"moves":[{"ply":1,"player":"human","action":60,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[2,5,24,39,41,48,54,57],"ai":[9,23,25,35,44,51,52,53]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":60,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[2,5,24,27,39,41,54,57],"ai":[9,23,25,35,44,51,52,53]},"scoresAfter":[-40,-18]},{"ply":3,"player":"human","action":30,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[2,5,24,27,39,41,54,57],"ai":[9,23,25,28,35,44,52,53]},"scoresAfter":[-40,-18]},{"ply":4,"player":"ai","action":72,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[2,5,27,39,41,54,57,58],"ai":[9,23,25,28,35,44,52,53]},"scoresAfter":[-40,-15]},{"ply":5,"player":"human","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[2,5,27,39,41,54,57,58],"ai":[9,10,23,25,28,35,44,53]},"scoresAfter":[-40,-15]},{"ply":6,"player":"ai","action":36,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[5,27,39,41,42,54,57,58],"ai":[9,10,23,25,28,35,44,53]},"scoresAfter":[-40,-55]},{"ply":7,"player":"human","action":60,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[5,27,39,41,42,54,57,58],"ai":[9,10,23,28,35,44,49,53]},"scoresAfter":[-30,-55]},{"ply":8,"player":"ai","action":84,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[5,27,39,41,42,46,57,58],"ai":[9,10,23,28,35,44,49,53]},"scoresAfter":[-30,-51]},{"ply":9,"player":"human","action":24,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[5,27,39,41,42,46,57,58],"ai":[9,10,23,28,35,40,44,49]},"scoresAfter":[-48,-51]},{"ply":10,"player":"ai","action":60,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[5,19,27,41,42,46,57,58],"ai":[9,10,23,28,35,40,44,49]},"scoresAfter":[-48,-68]},{"ply":11,"player":"human","action":36,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[5,19,27,41,42,46,57,58],"ai":[9,10,16,23,28,35,44,49]},"scoresAfter":[-44,-68]},{"ply":12,"player":"ai","action":78,"playedCard":44,"placeType":"discard","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[3,5,19,27,42,46,57,58],"ai":[9,10,16,23,28,35,44,49]},"scoresAfter":[-44,-68]},{"ply":13,"player":"human","action":46,"playedCard":27,"placeType":"discard","drawSource":"discard_3","drawnCard":44,"handsBefore":{"human":[3,5,19,27,42,46,57,58],"ai":[9,10,16,23,28,35,37,49]},"scoresAfter":[-44,-68]},{"ply":14,"player":"ai","action":78,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[3,5,19,42,44,46,57,58],"ai":[9,10,16,23,28,35,37,49]},"scoresAfter":[-44,-68]},{"ply":15,"player":"human","action":36,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[3,5,19,42,44,46,57,58],"ai":[9,10,16,23,28,31,35,49]},"scoresAfter":[-39,-68]},{"ply":16,"player":"ai","action":3,"playedCard":9,"placeType":"play","drawSource":"discard_2","drawnCard":27,"handsBefore":{"human":[3,5,19,44,46,56,57,58],"ai":[9,10,16,23,28,31,35,49]},"scoresAfter":[-39,-80]},{"ply":17,"player":"human","action":6,"playedCard":3,"placeType":"discard","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[3,5,19,44,46,56,57,58],"ai":[10,16,23,27,28,31,35,49]},"scoresAfter":[-39,-80]},{"ply":18,"player":"ai","action":3,"playedCard":10,"placeType":"play","drawSource":"discard_2","drawnCard":24,"handsBefore":{"human":[5,19,43,44,46,56,57,58],"ai":[10,16,23,27,28,31,35,49]},"scoresAfter":[-39,-71]},{"ply":19,"player":"human","action":6,"playedCard":5,"placeType":"discard","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[5,19,43,44,46,56,57,58],"ai":[16,23,24,27,28,31,35,49]},"scoresAfter":[-39,-71]},{"ply":20,"player":"ai","action":24,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[6,19,43,44,46,56,57,58],"ai":[16,23,24,27,28,31,35,49]},"scoresAfter":[-39,-91]},{"ply":21,"player":"human","action":24,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[6,19,43,44,46,56,57,58],"ai":[12,16,23,27,28,31,35,49]},"scoresAfter":[-33,-91]},{"ply":22,"player":"ai","action":0,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[6,19,44,46,56,57,58,59],"ai":[12,16,23,27,28,31,35,49]},"scoresAfter":[-33,-131]},{"ply":23,"player":"human","action":24,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[6,19,44,46,56,57,58,59],"ai":[16,23,27,28,31,35,45,49]},"scoresAfter":[-26,-131]},{"ply":24,"player":"ai","action":72,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[6,19,38,46,56,57,58,59],"ai":[16,23,27,28,31,35,45,49]},"scoresAfter":[-26,-123]},{"ply":25,"player":"human","action":30,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[6,19,38,46,56,57,58,59],"ai":[16,22,23,27,28,31,35,49]},"scoresAfter":[-26,-123]},{"ply":26,"player":"ai","action":36,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[6,19,21,46,56,57,58,59],"ai":[16,22,23,27,28,31,35,49]},"scoresAfter":[-26,-117]},{"ply":27,"player":"human","action":36,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[6,19,21,46,56,57,58,59],"ai":[4,16,22,23,28,31,35,49]},"scoresAfter":[-17,-117]},{"ply":28,"player":"ai","action":12,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[6,8,19,21,56,57,58,59],"ai":[4,16,22,23,28,31,35,49]},"scoresAfter":[-17,-111]},{"ply":29,"player":"human","action":48,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[6,8,19,21,56,57,58,59],"ai":[4,22,23,28,31,35,49,55]},"scoresAfter":[-3,-111]},{"ply":30,"player":"ai","action":78,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[6,8,17,19,21,57,58,59],"ai":[4,22,23,28,31,35,49,55]},"scoresAfter":[-3,-111]},{"ply":31,"player":"human","action":60,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[6,8,17,19,21,57,58,59],"ai":[0,4,22,23,28,31,35,55]},"scoresAfter":[13,-111]},{"ply":32,"player":"ai","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[6,7,8,17,19,21,58,59],"ai":[0,4,22,23,28,31,35,55]},"scoresAfter":[13,-111]},{"ply":33,"player":"human","action":72,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[6,7,8,17,19,21,58,59],"ai":[4,15,22,23,28,31,35,55]},"scoresAfter":[31,-111]},{"ply":34,"player":"ai","action":84,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[6,7,8,17,19,21,33,59],"ai":[4,15,22,23,28,31,35,55]},"scoresAfter":[31,-105]},{"ply":35,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[6,7,8,17,19,21,33,59],"ai":[4,13,15,22,23,28,31,35]},"scoresAfter":[51,-105]},{"ply":36,"player":"ai","action":6,"playedCard":4,"placeType":"discard","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[6,7,8,17,18,19,21,33],"ai":[4,13,15,22,23,28,31,35]},"scoresAfter":[51,-105]},{"ply":37,"player":"human","action":36,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[6,7,8,17,18,19,21,33],"ai":[13,15,22,23,28,29,31,35]},"scoresAfter":[35,-105]},{"ply":38,"player":"ai","action":24,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[1,6,7,8,18,19,21,33],"ai":[13,15,22,23,28,29,31,35]},"scoresAfter":[35,-87]},{"ply":39,"player":"human","action":1,"playedCard":1,"placeType":"play","drawSource":"discard_0","drawnCard":4,"handsBefore":{"human":[1,6,7,8,18,19,21,33],"ai":[13,15,23,28,29,31,35,50]},"scoresAfter":[-5,-87]},{"ply":40,"player":"ai","action":24,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[4,6,7,8,18,19,21,33],"ai":[13,15,23,28,29,31,35,50]},"scoresAfter":[-5,-67]},{"ply":41,"player":"human","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[4,6,7,8,18,19,21,33],"ai":[13,15,28,29,31,32,35,50]},"scoresAfter":[1,-67]},{"ply":42,"player":"ai","action":24,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[6,7,8,18,19,21,33,36],"ai":[13,15,28,29,31,32,35,50]},"scoresAfter":[1,-58]},{"ply":43,"player":"human","action":37,"playedCard":18,"placeType":"play","drawSource":"discard_0","drawnCard":0,"handsBefore":{"human":[6,7,8,18,19,21,33,36],"ai":[13,15,29,31,32,34,35,50]},"scoresAfter":[6,-58]},{"ply":44,"player":"ai","action":25,"playedCard":29,"placeType":"play","drawSource":"discard_0","drawnCard":5,"handsBefore":{"human":[0,6,7,8,19,21,33,36],"ai":[13,15,29,31,32,34,35,50]},"scoresAfter":[6,-46]},{"ply":45,"player":"human","action":12,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[0,6,7,8,19,21,33,36],"ai":[5,13,15,31,32,34,35,50]},"scoresAfter":[16,-46]},{"ply":46,"player":"ai","action":36,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[0,7,8,14,19,21,33,36],"ai":[5,13,15,31,32,34,35,50]},"scoresAfter":[16,-28]},{"ply":47,"player":"human","action":12,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[0,7,8,14,19,21,33,36],"ai":[5,13,15,30,32,34,35,50]},"scoresAfter":[28,-28]},{"ply":48,"player":"ai","action":53,"playedCard":32,"placeType":"play","drawSource":"discard_4","drawnCard":49,"handsBefore":{"human":[0,8,11,14,19,21,33,36],"ai":[5,13,15,30,32,34,35,50]},"scoresAfter":[28,-7]},{"ply":49,"player":"human","action":12,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[0,8,11,14,19,21,33,36],"ai":[5,13,15,30,34,35,49,50]},"scoresAfter":[42,-7]},{"ply":50,"player":"ai","action":52,"playedCard":34,"placeType":"play","drawSource":"discard_3","drawnCard":38,"handsBefore":{"human":[0,11,14,19,21,33,36,47],"ai":[5,13,15,30,34,35,49,50]},"scoresAfter":[42,40]},{"ply":51,"player":"human","action":12,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[0,11,14,19,21,33,36,47],"ai":[5,13,15,30,35,38,49,50]},"scoresAfter":[62,40]},{"ply":52,"player":"ai","action":48,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[0,14,19,21,26,33,36,47],"ai":[5,13,15,30,35,38,49,50]},"scoresAfter":[62,70]}],"finalScores":[62,70],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[39,2,54,5,57,41,24,48,9,35,23,44,51,52,25,53,27,28,58,10,42,49,46,40,19,16,3,37,31,56,43,6,12,59,45,38,22,21,4,8,55,17,0,7,15,33,13,18,29,1,50,32,36,34,14,30,11,47,26,20],"drawPtr":60,"cardLoc":[1,3,5,5,3,2,3,3,3,4,4,3,4,2,1,2,4,3,3,1,2,1,4,4,4,4,1,4,4,4,2,4,4,1,4,4,1,5,2,3,4,3,3,3,3,4,3,1,3,2,2,4,4,4,3,4,3,3,3,3],"handPublic":[true,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,5,0,9,10],[9,10,10,8,6]],"colHandshakes":[[1,0,0,0,1],[0,1,2,0,0]],"colLength":[[6,2,0,6,6],[2,4,9,2,4]],"piles":[[2,3],[],[],[37],[]],"toMove":0,"stepCount":52,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"780699c3-5ddc-4486-b6b1-ebe9e395fb89","seed":"oqjbml","startedAt":"2026-07-14T15:56:31.732Z","finishedAt":"2026-07-14T15:59:11.311Z","initialDeckOrder":[51,24,1,45,10,19,58,44,38,56,48,8,54,37,11,42,20,6,36,15,22,5,4,52,28,40,57,49,43,55,9,12,29,33,21,46,53,59,14,47,7,0,23,27,35,25,13,39,34,18,30,16,32,41,17,3,26,50,2,31],"moves":[{"ply":1,"player":"human","action":42,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[1,10,19,24,44,45,51,58],"ai":[8,11,37,38,42,48,54,56]},"scoresAfter":[0,0]},{"ply":2,"player":"ai","action":60,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[1,10,19,20,44,45,51,58],"ai":[8,11,37,38,42,48,54,56]},"scoresAfter":[0,-40]},{"ply":3,"player":"human","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[1,10,19,20,44,45,51,58],"ai":[6,8,11,37,38,42,54,56]},"scoresAfter":[-40,-40]},{"ply":4,"player":"ai","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[10,19,20,36,44,45,51,58],"ai":[6,8,11,37,38,42,54,56]},"scoresAfter":[-40,-55]},{"ply":5,"player":"human","action":36,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[10,19,20,36,44,45,51,58],"ai":[8,11,15,37,38,42,54,56]},"scoresAfter":[-80,-55]},{"ply":6,"player":"ai","action":60,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[10,19,20,22,44,45,51,58],"ai":[8,11,15,37,38,42,54,56]},"scoresAfter":[-80,-70]},{"ply":7,"player":"human","action":72,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[10,19,20,22,44,45,51,58],"ai":[5,8,11,15,37,38,54,56]},"scoresAfter":[-98,-70]},{"ply":8,"player":"ai","action":42,"playedCard":15,"placeType":"discard","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[4,10,19,20,22,44,45,58],"ai":[5,8,11,15,37,38,54,56]},"scoresAfter":[-98,-70]},{"ply":9,"player":"human","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[4,10,19,20,22,44,45,58],"ai":[5,8,11,37,38,52,54,56]},"scoresAfter":[-92,-70]},{"ply":10,"player":"ai","action":42,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[10,19,20,22,28,44,45,58],"ai":[5,8,11,37,38,52,54,56]},"scoresAfter":[-92,-70]},{"ply":11,"player":"human","action":54,"playedCard":28,"placeType":"discard","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[10,19,20,22,28,44,45,58],"ai":[5,8,11,38,40,52,54,56]},"scoresAfter":[-92,-70]},{"ply":12,"player":"ai","action":54,"playedCard":40,"placeType":"discard","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[10,19,20,22,44,45,57,58],"ai":[5,8,11,38,40,52,54,56]},"scoresAfter":[-92,-70]},{"ply":13,"player":"human","action":12,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[10,19,20,22,44,45,57,58],"ai":[5,8,11,38,49,52,54,56]},"scoresAfter":[-106,-70]},{"ply":14,"player":"ai","action":48,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[10,20,22,43,44,45,57,58],"ai":[5,8,11,38,49,52,54,56]},"scoresAfter":[-106,-90]},{"ply":15,"player":"human","action":12,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[10,20,22,43,44,45,57,58],"ai":[5,8,11,38,52,54,55,56]},"scoresAfter":[-99,-90]},{"ply":16,"player":"ai","action":6,"playedCard":5,"placeType":"discard","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[9,10,22,43,44,45,57,58],"ai":[5,8,11,38,52,54,55,56]},"scoresAfter":[-99,-90]},{"ply":17,"player":"human","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[9,10,22,43,44,45,57,58],"ai":[8,11,12,38,52,54,55,56]},"scoresAfter":[-83,-90]},{"ply":18,"player":"ai","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[10,22,29,43,44,45,57,58],"ai":[8,11,12,38,52,54,55,56]},"scoresAfter":[-83,-83]},{"ply":19,"player":"human","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[10,22,29,43,44,45,57,58],"ai":[11,12,33,38,52,54,55,56]},"scoresAfter":[-65,-83]},{"ply":20,"player":"ai","action":24,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[21,22,29,43,44,45,57,58],"ai":[11,12,33,38,52,54,55,56]},"scoresAfter":[-65,-95]},{"ply":21,"player":"human","action":0,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[21,22,29,43,44,45,57,58],"ai":[11,12,38,46,52,54,55,56]},"scoresAfter":[-57,-95]},{"ply":22,"player":"ai","action":36,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[22,29,43,44,45,53,57,58],"ai":[11,12,38,46,52,54,55,56]},"scoresAfter":[-57,-86]},{"ply":23,"player":"human","action":0,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[22,29,43,44,45,53,57,58],"ai":[11,12,38,52,54,55,56,59]},"scoresAfter":[-48,-86]},{"ply":24,"player":"ai","action":6,"playedCard":11,"placeType":"discard","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[14,29,43,44,45,53,57,58],"ai":[11,12,38,52,54,55,56,59]},"scoresAfter":[-48,-86]},{"ply":25,"player":"human","action":61,"playedCard":53,"placeType":"play","drawSource":"discard_0","drawnCard":11,"handsBefore":{"human":[14,29,43,44,45,53,57,58],"ai":[12,38,47,52,54,55,56,59]},"scoresAfter":[-44,-86]},{"ply":26,"player":"ai","action":6,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[11,14,29,43,44,45,57,58],"ai":[12,38,47,52,54,55,56,59]},"scoresAfter":[-44,-86]},{"ply":27,"player":"human","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[11,14,29,43,44,45,57,58],"ai":[7,38,47,52,54,55,56,59]},"scoresAfter":[-24,-86]},{"ply":28,"player":"ai","action":24,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[0,14,29,43,44,45,57,58],"ai":[7,38,47,52,54,55,56,59]},"scoresAfter":[-24,-76]},{"ply":29,"player":"human","action":34,"playedCard":29,"placeType":"discard","drawSource":"discard_3","drawnCard":40,"handsBefore":{"human":[0,14,29,43,44,45,57,58],"ai":[7,23,38,52,54,55,56,59]},"scoresAfter":[-24,-76]},{"ply":30,"player":"ai","action":36,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[0,14,40,43,44,45,57,58],"ai":[7,23,38,52,54,55,56,59]},"scoresAfter":[-24,-67]},{"ply":31,"player":"human","action":76,"playedCard":57,"placeType":"play","drawSource":"discard_3","drawnCard":37,"handsBefore":{"human":[0,14,40,43,44,45,57,58],"ai":[7,23,27,38,54,55,56,59]},"scoresAfter":[-16,-67]},{"ply":32,"player":"ai","action":48,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[0,14,37,40,43,44,45,58],"ai":[7,23,27,38,54,55,56,59]},"scoresAfter":[-16,-52]},{"ply":33,"player":"human","action":24,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[0,14,37,40,43,44,45,58],"ai":[7,23,27,35,38,55,56,59]},"scoresAfter":[-36,-52]},{"ply":34,"player":"ai","action":36,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[0,14,25,40,43,44,45,58],"ai":[7,23,27,35,38,55,56,59]},"scoresAfter":[-36,-42]},{"ply":35,"player":"human","action":36,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[0,14,25,40,43,44,45,58],"ai":[7,13,23,27,38,55,56,59]},"scoresAfter":[-27,-42]},{"ply":36,"player":"ai","action":24,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[0,14,25,39,43,44,45,58],"ai":[7,13,23,27,38,55,56,59]},"scoresAfter":[-27,-52]},{"ply":37,"player":"human","action":48,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[0,14,25,39,43,44,45,58],"ai":[7,13,27,34,38,55,56,59]},"scoresAfter":[-9,-52]},{"ply":38,"player":"ai","action":60,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[0,14,18,25,39,44,45,58],"ai":[7,13,27,34,38,55,56,59]},"scoresAfter":[-9,-34]},{"ply":39,"player":"human","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[0,14,18,25,39,44,45,58],"ai":[7,13,27,30,34,38,56,59]},"scoresAfter":[0,-34]},{"ply":40,"player":"ai","action":30,"playedCard":27,"placeType":"discard","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[0,14,16,18,25,39,44,45],"ai":[7,13,27,30,34,38,56,59]},"scoresAfter":[0,-34]},{"ply":41,"player":"human","action":72,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[0,14,16,18,25,39,44,45],"ai":[7,13,30,32,34,38,56,59]},"scoresAfter":[21,-34]},{"ply":42,"player":"ai","action":72,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[0,14,16,18,25,39,41,45],"ai":[7,13,30,32,34,38,56,59]},"scoresAfter":[21,-13]},{"ply":43,"player":"human","action":84,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[0,14,16,18,25,39,41,45],"ai":[7,13,17,30,32,34,38,59]},"scoresAfter":[45,-13]},{"ply":44,"player":"ai","action":33,"playedCard":17,"placeType":"discard","drawSource":"discard_2","drawnCard":27,"handsBefore":{"human":[0,3,14,16,18,25,39,41],"ai":[7,13,17,30,32,34,38,59]},"scoresAfter":[45,-13]},{"ply":45,"player":"human","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[0,3,14,16,18,25,39,41],"ai":[7,13,27,30,32,34,38,59]},"scoresAfter":[45,-13]},{"ply":46,"player":"ai","action":79,"playedCard":38,"placeType":"discard","drawSource":"discard_0","drawnCard":0,"handsBefore":{"human":[3,14,16,18,25,26,39,41],"ai":[7,13,27,30,32,34,38,59]},"scoresAfter":[45,-13]},{"ply":47,"player":"human","action":66,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[3,14,16,18,25,26,39,41],"ai":[0,7,13,27,30,32,34,59]},"scoresAfter":[45,-13]},{"ply":48,"player":"ai","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[3,14,16,18,25,39,41,50],"ai":[0,7,13,27,30,32,34,59]},"scoresAfter":[45,17]},{"ply":49,"player":"human","action":90,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[3,14,16,18,25,39,41,50],"ai":[0,2,7,13,27,30,32,34]},"scoresAfter":[45,17]}],"finalScores":[45,17],"outcome":"YOU WIN","finalState":{"deckOrder":[51,24,1,45,10,19,58,44,38,56,48,8,54,37,11,42,20,6,36,15,22,5,4,52,28,40,57,49,43,55,9,12,29,33,21,46,53,59,14,47,7,0,23,27,35,25,13,39,34,18,30,16,32,41,17,3,26,50,2,31],"drawPtr":60,"cardLoc":[2,3,2,1,3,5,4,2,4,3,3,3,5,2,1,5,1,5,1,3,3,3,3,4,5,1,5,2,5,5,2,1,2,4,2,4,3,3,5,1,3,1,4,3,3,3,4,4,4,4,5,3,4,3,4,4,4,3,3,4],"handPublic":[true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,9,0,8,9],[7,10,10,10,10]],"colHandshakes":[[1,0,0,2,0],[0,0,0,0,2]],"colLength":[[5,4,0,6,4],[2,1,2,3,7]],"piles":[[5],[15,12,17],[24,28,29,26],[38],[50]],"toMove":1,"stepCount":49,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"43b4b150-0713-41cf-85d9-fd2e1075b835","seed":"4wghwi","startedAt":"2026-07-14T15:59:12.155Z","finishedAt":"2026-07-14T16:02:06.385Z","initialDeckOrder":[47,23,13,46,6,10,36,51,55,27,50,42,57,15,38,3,26,31,24,49,12,17,1,25,54,40,44,58,53,4,34,43,9,28,8,37,16,11,52,33,19,18,22,7,5,20,29,35,59,14,30,45,39,21,32,2,41,48,56,0],"moves":[{"ply":1,"player":"human","action":48,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[6,10,13,23,36,46,47,51],"ai":[3,15,27,38,42,50,55,57]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":48,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[6,10,13,23,26,46,47,51],"ai":[3,15,27,38,42,50,55,57]},"scoresAfter":[-40,-15]},{"ply":3,"player":"human","action":24,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[6,10,13,23,26,46,47,51],"ai":[3,15,27,31,38,50,55,57]},"scoresAfter":[-80,-15]},{"ply":4,"player":"ai","action":12,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[6,10,23,24,26,46,47,51],"ai":[3,15,27,31,38,50,55,57]},"scoresAfter":[-80,-33]},{"ply":5,"player":"human","action":42,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[6,10,23,24,26,46,47,51],"ai":[3,27,31,38,49,50,55,57]},"scoresAfter":[-80,-33]},{"ply":6,"player":"ai","action":48,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[6,10,12,23,26,46,47,51],"ai":[3,27,31,38,49,50,55,57]},"scoresAfter":[-80,-73]},{"ply":7,"player":"human","action":54,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[6,10,12,23,26,46,47,51],"ai":[3,17,27,31,38,50,55,57]},"scoresAfter":[-80,-73]},{"ply":8,"player":"ai","action":60,"playedCard":50,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[1,6,10,12,23,46,47,51],"ai":[3,17,27,31,38,50,55,57]},"scoresAfter":[-80,-93]},{"ply":9,"player":"human","action":36,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[1,6,10,12,23,46,47,51],"ai":[3,17,25,27,31,38,55,57]},"scoresAfter":[-100,-93]},{"ply":10,"player":"ai","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[1,6,10,23,46,47,51,54],"ai":[3,17,25,27,31,38,55,57]},"scoresAfter":[-100,-111]},{"ply":11,"player":"human","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[1,6,10,23,46,47,51,54],"ai":[17,25,27,31,38,40,55,57]},"scoresAfter":[-140,-111]},{"ply":12,"player":"ai","action":12,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[6,10,23,44,46,47,51,54],"ai":[17,25,27,31,38,40,55,57]},"scoresAfter":[-140,-151]},{"ply":13,"player":"human","action":72,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[6,10,23,44,46,47,51,54],"ai":[17,27,31,38,40,55,57,58]},"scoresAfter":[-158,-151]},{"ply":14,"player":"ai","action":60,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[6,10,23,44,46,47,53,54],"ai":[17,27,31,38,40,55,57,58]},"scoresAfter":[-158,-133]},{"ply":15,"player":"human","action":72,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[6,10,23,44,46,47,53,54],"ai":[4,17,27,31,38,40,57,58]},"scoresAfter":[-154,-133]},{"ply":16,"player":"ai","action":72,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[6,10,23,34,44,46,47,54],"ai":[4,17,27,31,38,40,57,58]},"scoresAfter":[-154,-109]},{"ply":17,"player":"human","action":84,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[6,10,23,34,44,46,47,54],"ai":[4,17,27,31,38,40,43,58]},"scoresAfter":[-149,-109]},{"ply":18,"player":"ai","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[6,9,10,23,34,44,46,47],"ai":[4,17,27,31,38,40,43,58]},"scoresAfter":[-149,-82]},{"ply":19,"player":"human","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[6,9,10,23,34,44,46,47],"ai":[4,17,27,28,31,38,40,43]},"scoresAfter":[-139,-82]},{"ply":20,"player":"ai","action":3,"playedCard":4,"placeType":"play","drawSource":"discard_2","drawnCard":26,"handsBefore":{"human":[8,9,10,23,34,44,46,47],"ai":[4,17,27,28,31,38,40,43]},"scoresAfter":[-139,-79]},{"ply":21,"player":"human","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[8,9,10,23,34,44,46,47],"ai":[17,26,27,28,31,38,40,43]},"scoresAfter":[-125,-79]},{"ply":22,"player":"ai","action":3,"playedCard":17,"placeType":"play","drawSource":"discard_2","drawnCard":24,"handsBefore":{"human":[9,10,23,34,37,44,46,47],"ai":[17,26,27,28,31,38,40,43]},"scoresAfter":[-125,-75]},{"ply":23,"player":"human","action":48,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[9,10,23,34,37,44,46,47],"ai":[24,26,27,28,31,38,40,43]},"scoresAfter":[-145,-75]},{"ply":24,"player":"ai","action":84,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[9,10,16,23,34,44,46,47],"ai":[24,26,27,28,31,38,40,43]},"scoresAfter":[-145,-69]},{"ply":25,"player":"human","action":24,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[9,10,16,23,34,44,46,47],"ai":[11,24,26,27,28,31,38,40]},"scoresAfter":[-136,-69]},{"ply":26,"player":"ai","action":24,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[9,10,23,34,44,46,47,52],"ai":[11,24,26,27,28,31,38,40]},"scoresAfter":[-136,-89]},{"ply":27,"player":"human","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[9,10,23,34,44,46,47,52],"ai":[11,24,27,28,31,33,38,40]},"scoresAfter":[-120,-89]},{"ply":28,"player":"ai","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[10,19,23,34,44,46,47,52],"ai":[11,24,27,28,31,33,38,40]},"scoresAfter":[-120,-79]},{"ply":29,"player":"human","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[10,19,23,34,44,46,47,52],"ai":[18,24,27,28,31,33,38,40]},"scoresAfter":[-102,-79]},{"ply":30,"player":"ai","action":0,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[19,22,23,34,44,46,47,52],"ai":[18,24,27,28,31,33,38,40]},"scoresAfter":[-102,-74]},{"ply":31,"player":"human","action":0,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[19,22,23,34,44,46,47,52],"ai":[7,24,27,28,31,33,38,40]},"scoresAfter":[-84,-74]},{"ply":32,"player":"ai","action":12,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[5,22,23,34,44,46,47,52],"ai":[7,24,27,28,31,33,38,40]},"scoresAfter":[-84,-94]},{"ply":33,"player":"human","action":6,"playedCard":5,"placeType":"discard","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[5,22,23,34,44,46,47,52],"ai":[7,20,27,28,31,33,38,40]},"scoresAfter":[-84,-94]},{"ply":34,"player":"ai","action":12,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[22,23,29,34,44,46,47,52],"ai":[7,20,27,28,31,33,38,40]},"scoresAfter":[-84,-87]},{"ply":35,"player":"human","action":48,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[22,23,29,34,44,46,47,52],"ai":[7,27,28,31,33,35,38,40]},"scoresAfter":[-63,-87]},{"ply":36,"player":"ai","action":12,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[22,23,29,34,46,47,52,59],"ai":[7,27,28,31,33,35,38,40]},"scoresAfter":[-63,-79]},{"ply":37,"player":"human","action":0,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[22,23,29,34,46,47,52,59],"ai":[7,14,28,31,33,35,38,40]},"scoresAfter":[-36,-79]},{"ply":38,"player":"ai","action":24,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[23,29,30,34,46,47,52,59],"ai":[7,14,28,31,33,35,38,40]},"scoresAfter":[-36,-67]},{"ply":39,"player":"human","action":48,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[23,29,30,34,46,47,52,59],"ai":[7,14,31,33,35,38,40,45]},"scoresAfter":[-9,-67]},{"ply":40,"player":"ai","action":84,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[23,29,30,34,39,47,52,59],"ai":[7,14,31,33,35,38,40,45]},"scoresAfter":[-9,-59]},{"ply":41,"player":"human","action":0,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[23,29,30,34,39,47,52,59],"ai":[7,14,21,31,33,35,38,40]},"scoresAfter":[21,-59]},{"ply":42,"player":"ai","action":25,"playedCard":21,"placeType":"play","drawSource":"discard_0","drawnCard":5,"handsBefore":{"human":[29,30,32,34,39,47,52,59],"ai":[7,14,21,31,33,35,38,40]},"scoresAfter":[21,-51]},{"ply":43,"player":"human","action":60,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[29,30,32,34,39,47,52,59],"ai":[5,7,14,31,33,35,38,40]},"scoresAfter":[51,-51]},{"ply":44,"player":"ai","action":36,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[2,29,30,32,34,39,52,59],"ai":[5,7,14,31,33,35,38,40]},"scoresAfter":[51,-27]},{"ply":45,"player":"human","action":78,"playedCard":52,"placeType":"discard","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[2,29,30,32,34,39,52,59],"ai":[5,7,14,33,35,38,40,41]},"scoresAfter":[51,-27]},{"ply":46,"player":"ai","action":41,"playedCard":33,"placeType":"play","drawSource":"discard_4","drawnCard":52,"handsBefore":{"human":[2,29,30,32,34,39,48,59],"ai":[5,7,14,33,35,38,40,41]},"scoresAfter":[51,5]},{"ply":47,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[2,29,30,32,34,39,48,59],"ai":[5,7,14,35,38,40,41,52]},"scoresAfter":[61,5]},{"ply":48,"player":"ai","action":36,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[2,29,30,32,34,39,48,56],"ai":[5,7,14,35,38,40,41,52]},"scoresAfter":[61,65]}],"finalScores":[61,65],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[47,23,13,46,6,10,36,51,55,27,50,42,57,15,38,3,26,31,24,49,12,17,1,25,54,40,44,58,53,4,34,43,9,28,8,37,16,11,52,33,19,18,22,7,5,20,29,35,59,14,30,45,39,21,32,2,41,48,56,0],"drawPtr":60,"cardLoc":[2,3,1,4,4,2,3,2,3,3,3,4,3,3,2,4,3,4,4,3,4,4,3,3,4,4,4,4,4,1,1,4,1,4,1,4,3,3,2,1,2,2,4,4,3,4,3,3,1,4,4,3,2,3,3,4,1,4,4,3],"handPublic":[false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false],"colTop":[[9,10,0,10,10],[10,8,10,8,9]],"colHandshakes":[[1,2,0,2,0],[0,0,3,0,2]],"colLength":[[5,6,0,5,4],[3,5,8,3,5]],"piles":[[],[],[],[],[]],"toMove":0,"stepCount":48,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"71267abe-2d6d-4e7d-810c-f0fb205ade15","seed":"w6bbpc","startedAt":"2026-07-14T16:02:07.437Z","finishedAt":"2026-07-14T16:05:02.861Z","initialDeckOrder":[7,14,57,42,37,8,34,1,5,16,40,12,30,52,13,33,28,53,18,3,54,47,0,11,15,21,9,38,36,25,10,44,2,29,50,23,31,58,46,24,39,41,56,4,45,6,19,26,20,17,43,55,48,27,49,59,51,35,32,22],"moves":[{"ply":1,"player":"human","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[1,7,8,14,34,37,42,57],"ai":[5,12,13,16,30,33,40,52]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":6,"playedCard":5,"placeType":"discard","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[7,8,14,28,34,37,42,57],"ai":[5,12,13,16,30,33,40,52]},"scoresAfter":[-40,0]},{"ply":3,"player":"human","action":31,"playedCard":14,"placeType":"discard","drawSource":"discard_0","drawnCard":5,"handsBefore":{"human":[7,8,14,28,34,37,42,57],"ai":[12,13,16,30,33,40,52,53]},"scoresAfter":[-40,0]},{"ply":4,"player":"ai","action":24,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[5,7,8,28,34,37,42,57],"ai":[12,13,16,30,33,40,52,53]},"scoresAfter":[-40,-17]},{"ply":5,"player":"human","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[5,7,8,28,34,37,42,57],"ai":[12,13,18,30,33,40,52,53]},"scoresAfter":[-32,-17]},{"ply":6,"player":"ai","action":72,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[3,7,8,28,34,37,42,57],"ai":[12,13,18,30,33,40,52,53]},"scoresAfter":[-32,-34]},{"ply":7,"player":"human","action":66,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[3,7,8,28,34,37,42,57],"ai":[12,13,18,30,33,40,53,54]},"scoresAfter":[-32,-34]},{"ply":8,"player":"ai","action":6,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[3,7,8,28,34,42,47,57],"ai":[12,13,18,30,33,40,53,54]},"scoresAfter":[-32,-34]},{"ply":9,"player":"human","action":12,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[3,7,8,28,34,42,47,57],"ai":[0,13,18,30,33,40,53,54]},"scoresAfter":[-20,-34]},{"ply":10,"player":"ai","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[3,8,11,28,34,42,47,57],"ai":[0,13,18,30,33,40,53,54]},"scoresAfter":[-20,-34]},{"ply":11,"player":"human","action":12,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[3,8,11,28,34,42,47,57],"ai":[13,15,18,30,33,40,53,54]},"scoresAfter":[-6,-34]},{"ply":12,"player":"ai","action":24,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[3,11,21,28,34,42,47,57],"ai":[13,15,18,30,33,40,53,54]},"scoresAfter":[-6,-29]},{"ply":13,"player":"human","action":16,"playedCard":11,"placeType":"play","drawSource":"discard_3","drawnCard":37,"handsBefore":{"human":[3,11,21,28,34,42,47,57],"ai":[9,13,15,30,33,40,53,54]},"scoresAfter":[14,-29]},{"ply":14,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[3,21,28,34,37,42,47,57],"ai":[9,13,15,30,33,40,53,54]},"scoresAfter":[14,-41]},{"ply":15,"player":"human","action":48,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[3,21,28,34,37,42,47,57],"ai":[13,15,30,33,38,40,53,54]},"scoresAfter":[-26,-41]},{"ply":16,"player":"ai","action":48,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[3,21,28,34,36,42,47,57],"ai":[13,15,30,33,38,40,53,54]},"scoresAfter":[-26,-81]},{"ply":17,"player":"human","action":48,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[3,21,28,34,36,42,47,57],"ai":[13,15,25,30,33,40,53,54]},"scoresAfter":[-46,-81]},{"ply":18,"player":"ai","action":72,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[3,10,21,28,34,42,47,57],"ai":[13,15,25,30,33,40,53,54]},"scoresAfter":[-46,-77]},{"ply":19,"player":"human","action":6,"playedCard":3,"placeType":"discard","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[3,10,21,28,34,42,47,57],"ai":[13,15,25,30,33,40,44,54]},"scoresAfter":[-46,-77]},{"ply":20,"player":"ai","action":18,"playedCard":15,"placeType":"discard","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[2,10,21,28,34,42,47,57],"ai":[13,15,25,30,33,40,44,54]},"scoresAfter":[-46,-77]},{"ply":21,"player":"human","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[2,10,21,28,34,42,47,57],"ai":[13,25,29,30,33,40,44,54]},"scoresAfter":[-46,-77]},{"ply":22,"player":"ai","action":12,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[10,21,28,34,42,47,50,57],"ai":[13,25,29,30,33,40,44,54]},"scoresAfter":[-46,-117]},{"ply":23,"player":"human","action":78,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[10,21,28,34,42,47,50,57],"ai":[13,23,29,30,33,40,44,54]},"scoresAfter":[-46,-117]},{"ply":24,"player":"ai","action":6,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[10,21,28,31,34,42,47,57],"ai":[13,23,29,30,33,40,44,54]},"scoresAfter":[-46,-117]},{"ply":25,"player":"human","action":24,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[10,21,28,31,34,42,47,57],"ai":[23,29,30,33,40,44,54,58]},"scoresAfter":[-63,-117]},{"ply":26,"player":"ai","action":72,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[10,21,31,34,42,46,47,57],"ai":[23,29,30,33,40,44,54,58]},"scoresAfter":[-63,-112]},{"ply":27,"player":"human","action":48,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[10,21,31,34,42,46,47,57],"ai":[23,24,29,30,33,40,44,58]},"scoresAfter":[-48,-112]},{"ply":28,"player":"ai","action":60,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[10,21,31,34,39,46,47,57],"ai":[23,24,29,30,33,40,44,58]},"scoresAfter":[-48,-106]},{"ply":29,"player":"human","action":54,"playedCard":39,"placeType":"discard","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[10,21,31,34,39,46,47,57],"ai":[23,24,29,30,33,41,44,58]},"scoresAfter":[-48,-106]},{"ply":30,"player":"ai","action":60,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[10,21,31,34,46,47,56,57],"ai":[23,24,29,30,33,41,44,58]},"scoresAfter":[-48,-98]},{"ply":31,"player":"human","action":24,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[10,21,31,34,46,47,56,57],"ai":[4,23,24,29,30,33,44,58]},"scoresAfter":[-42,-98]},{"ply":32,"player":"ai","action":72,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[10,21,34,45,46,47,56,57],"ai":[4,23,24,29,30,33,44,58]},"scoresAfter":[-42,-84]},{"ply":33,"player":"human","action":36,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[10,21,34,45,46,47,56,57],"ai":[4,6,23,24,29,30,33,58]},"scoresAfter":[-18,-84]},{"ply":34,"player":"ai","action":48,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[10,19,21,34,46,47,56,57],"ai":[4,6,23,24,29,30,33,58]},"scoresAfter":[-18,-76]},{"ply":35,"player":"human","action":48,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[10,19,21,34,46,47,56,57],"ai":[4,6,23,24,26,30,33,58]},"scoresAfter":[9,-76]},{"ply":36,"player":"ai","action":60,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[10,19,20,21,34,47,56,57],"ai":[4,6,23,24,26,30,33,58]},"scoresAfter":[9,-66]},{"ply":37,"player":"human","action":60,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[10,19,20,21,34,47,56,57],"ai":[4,6,17,23,24,26,33,58]},"scoresAfter":[39,-66]},{"ply":38,"player":"ai","action":54,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[10,19,20,21,34,43,56,57],"ai":[4,6,17,23,24,26,33,58]},"scoresAfter":[39,-66]},{"ply":39,"player":"human","action":50,"playedCard":34,"placeType":"play","drawSource":"discard_1","drawnCard":13,"handsBefore":{"human":[10,19,20,21,34,43,56,57],"ai":[4,6,17,23,26,33,55,58]},"scoresAfter":[48,-66]},{"ply":40,"player":"ai","action":72,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[10,13,19,20,21,43,56,57],"ai":[4,6,17,23,26,33,55,58]},"scoresAfter":[48,-60]},{"ply":41,"player":"human","action":14,"playedCard":13,"placeType":"play","drawSource":"discard_1","drawnCard":15,"handsBefore":{"human":[10,13,19,20,21,43,56,57],"ai":[4,6,17,23,26,33,48,58]},"scoresAfter":[8,-60]},{"ply":42,"player":"ai","action":36,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[10,15,19,20,21,43,56,57],"ai":[4,6,17,23,26,33,48,58]},"scoresAfter":[8,-50]},{"ply":43,"player":"human","action":12,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[10,15,19,20,21,43,56,57],"ai":[4,6,17,26,27,33,48,58]},"scoresAfter":[12,-50]},{"ply":44,"player":"ai","action":60,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[10,19,20,21,43,49,56,57],"ai":[4,6,17,26,27,33,48,58]},"scoresAfter":[12,-34]},{"ply":45,"player":"human","action":14,"playedCard":19,"placeType":"play","drawSource":"discard_1","drawnCard":12,"handsBefore":{"human":[10,19,20,21,43,49,56,57],"ai":[4,6,17,26,27,48,58,59]},"scoresAfter":[24,-34]},{"ply":46,"player":"ai","action":72,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[10,12,20,21,43,49,56,57],"ai":[4,6,17,26,27,48,58,59]},"scoresAfter":[24,-25]},{"ply":47,"player":"human","action":26,"playedCard":20,"placeType":"play","drawSource":"discard_1","drawnCard":14,"handsBefore":{"human":[10,12,20,21,43,49,56,57],"ai":[4,6,17,26,27,48,51,59]},"scoresAfter":[38,-25]},{"ply":48,"player":"ai","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[10,12,14,21,43,49,56,57],"ai":[4,6,17,26,27,48,51,59]},"scoresAfter":[38,-15]},{"ply":49,"player":"human","action":36,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[10,12,14,21,43,49,56,57],"ai":[4,6,17,26,27,35,48,51]},"scoresAfter":[54,-15]},{"ply":50,"player":"ai","action":60,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[10,12,14,32,43,49,56,57],"ai":[4,6,17,26,27,35,48,51]},"scoresAfter":[54,5]}],"finalScores":[54,5],"outcome":"YOU WIN","finalState":{"deckOrder":[7,14,57,42,37,8,34,1,5,16,40,12,30,52,13,33,28,53,18,3,54,47,0,11,15,21,9,38,36,25,10,44,2,29,50,23,31,58,46,24,39,41,56,4,45,6,19,26,20,17,43,55,48,27,49,59,51,35,32,22],"drawPtr":60,"cardLoc":[5,3,5,5,2,3,2,3,3,4,1,3,1,3,1,3,4,2,4,3,3,3,2,4,5,4,2,2,3,4,4,3,1,4,3,4,3,3,4,5,4,4,3,1,4,3,3,3,2,1,5,2,4,4,4,4,1,1,4,4],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,true,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,8,9,10,0],[8,10,10,7,10]],"colHandshakes":[[1,1,0,2,0],[0,0,1,1,0]],"colLength":[[5,5,3,6,0],[1,3,5,4,6]],"piles":[[0,3,2],[],[24],[39],[50]],"toMove":0,"stepCount":50,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"64199479-c94d-4c80-bca3-8afede90b173","seed":"lomuvz","startedAt":"2026-07-14T16:05:04.082Z","finishedAt":"2026-07-14T16:07:00.893Z","initialDeckOrder":[17,38,1,3,23,22,35,28,29,15,13,52,44,21,33,18,45,6,50,24,43,34,26,48,59,20,7,5,12,36,8,46,55,57,31,11,51,42,19,40,9,27,53,54,16,14,0,58,41,25,39,49,4,37,10,56,32,30,2,47],"moves":[{"ply":1,"player":"human","action":90,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[1,3,17,22,23,28,35,38],"ai":[13,15,18,21,29,33,44,52]},"scoresAfter":[0,0]},{"ply":2,"player":"ai","action":0,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[1,3,17,22,23,28,35,45],"ai":[13,15,18,21,29,33,44,52]},"scoresAfter":[0,-40]},{"ply":3,"player":"human","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[1,3,17,22,23,28,35,45],"ai":[6,15,18,21,29,33,44,52]},"scoresAfter":[0,-40]},{"ply":4,"player":"ai","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[3,17,22,23,28,35,45,50],"ai":[6,15,18,21,29,33,44,52]},"scoresAfter":[0,-55]},{"ply":5,"player":"human","action":90,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[3,17,22,23,28,35,45,50],"ai":[15,18,21,24,29,33,44,52]},"scoresAfter":[0,-55]},{"ply":6,"player":"ai","action":84,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[3,17,22,23,28,35,43,45],"ai":[15,18,21,24,29,33,44,52]},"scoresAfter":[0,-72]},{"ply":7,"player":"human","action":10,"playedCard":3,"placeType":"discard","drawSource":"discard_3","drawnCard":38,"handsBefore":{"human":[3,17,22,23,28,35,43,45],"ai":[15,18,21,24,29,33,34,44]},"scoresAfter":[0,-72]},{"ply":8,"player":"ai","action":36,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[17,22,23,28,35,38,43,45],"ai":[15,18,21,24,29,33,34,44]},"scoresAfter":[0,-112]},{"ply":9,"player":"human","action":60,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[17,22,23,28,35,38,43,45],"ai":[15,18,21,26,29,33,34,44]},"scoresAfter":[-40,-112]},{"ply":10,"player":"ai","action":0,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[17,22,23,28,35,43,45,48],"ai":[15,18,21,26,29,33,34,44]},"scoresAfter":[-40,-108]},{"ply":11,"player":"human","action":60,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[17,22,23,28,35,43,45,48],"ai":[18,21,26,29,33,34,44,59]},"scoresAfter":[-28,-108]},{"ply":12,"player":"ai","action":24,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[17,20,22,23,28,35,45,48],"ai":[18,21,26,29,33,34,44,59]},"scoresAfter":[-28,-128]},{"ply":13,"player":"human","action":72,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[17,20,22,23,28,35,45,48],"ai":[7,18,21,29,33,34,44,59]},"scoresAfter":[-12,-128]},{"ply":14,"player":"ai","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[5,17,20,22,23,28,35,48],"ai":[7,18,21,29,33,34,44,59]},"scoresAfter":[-12,-122]},{"ply":15,"player":"human","action":6,"playedCard":5,"placeType":"discard","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[5,17,20,22,23,28,35,48],"ai":[12,18,21,29,33,34,44,59]},"scoresAfter":[-12,-122]},{"ply":16,"player":"ai","action":72,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[17,20,22,23,28,35,36,48],"ai":[12,18,21,29,33,34,44,59]},"scoresAfter":[-12,-135]},{"ply":17,"player":"human","action":78,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[17,20,22,23,28,35,36,48],"ai":[8,12,18,21,29,33,34,59]},"scoresAfter":[-12,-135]},{"ply":18,"player":"ai","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[17,20,22,23,28,35,46,48],"ai":[8,12,18,21,29,33,34,59]},"scoresAfter":[-12,-128]},{"ply":19,"player":"human","action":72,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[17,20,22,23,28,35,46,48],"ai":[12,18,21,29,33,34,55,59]},"scoresAfter":[6,-128]},{"ply":20,"player":"ai","action":72,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[17,20,22,23,28,35,48,57],"ai":[12,18,21,29,33,34,55,59]},"scoresAfter":[6,-122]},{"ply":21,"player":"human","action":77,"playedCard":48,"placeType":"play","drawSource":"discard_4","drawnCard":50,"handsBefore":{"human":[17,20,22,23,28,35,48,57],"ai":[12,18,21,29,31,33,34,59]},"scoresAfter":[-34,-122]},{"ply":22,"player":"ai","action":12,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[17,20,22,23,28,35,50,57],"ai":[12,18,21,29,31,33,34,59]},"scoresAfter":[-34,-112]},{"ply":23,"player":"human","action":72,"playedCard":50,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[17,20,22,23,28,35,50,57],"ai":[11,12,21,29,31,33,34,59]},"scoresAfter":[-54,-112]},{"ply":24,"player":"ai","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[17,20,22,23,28,35,51,57],"ai":[11,12,21,29,31,33,34,59]},"scoresAfter":[-54,-102]},{"ply":25,"player":"human","action":72,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[17,20,22,23,28,35,51,57],"ai":[12,21,29,31,33,34,42,59]},"scoresAfter":[-48,-102]},{"ply":26,"player":"ai","action":12,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[17,19,20,22,23,28,35,57],"ai":[12,21,29,31,33,34,42,59]},"scoresAfter":[-48,-86]},{"ply":27,"player":"human","action":60,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[17,19,20,22,23,28,35,57],"ai":[12,29,31,33,34,40,42,59]},"scoresAfter":[-65,-86]},{"ply":28,"player":"ai","action":66,"playedCard":40,"placeType":"discard","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[9,17,19,20,22,23,35,57],"ai":[12,29,31,33,34,40,42,59]},"scoresAfter":[-65,-86]},{"ply":29,"player":"human","action":6,"playedCard":9,"placeType":"discard","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[9,17,19,20,22,23,35,57],"ai":[12,27,29,31,33,34,42,59]},"scoresAfter":[-65,-86]},{"ply":30,"player":"ai","action":6,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[17,19,20,22,23,35,53,57],"ai":[12,27,29,31,33,34,42,59]},"scoresAfter":[-65,-86]},{"ply":31,"player":"human","action":72,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[17,19,20,22,23,35,53,57],"ai":[27,29,31,33,34,42,54,59]},"scoresAfter":[-53,-86]},{"ply":32,"player":"ai","action":66,"playedCard":42,"placeType":"discard","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[16,17,19,20,22,23,35,57],"ai":[27,29,31,33,34,42,54,59]},"scoresAfter":[-53,-86]},{"ply":33,"player":"human","action":86,"playedCard":57,"placeType":"play","drawSource":"discard_1","drawnCard":12,"handsBefore":{"human":[16,17,19,20,22,23,35,57],"ai":[14,27,29,31,33,34,54,59]},"scoresAfter":[-29,-86]},{"ply":34,"player":"ai","action":12,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[12,16,17,19,20,22,23,35],"ai":[14,27,29,31,33,34,54,59]},"scoresAfter":[-29,-80]},{"ply":35,"player":"human","action":0,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[12,16,17,19,20,22,23,35],"ai":[0,14,29,31,33,34,54,59]},"scoresAfter":[-69,-80]},{"ply":36,"player":"ai","action":24,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[16,17,19,20,22,23,35,58],"ai":[0,14,29,31,33,34,54,59]},"scoresAfter":[-69,-68]},{"ply":37,"player":"human","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[16,17,19,20,22,23,35,58],"ai":[0,14,31,33,34,41,54,59]},"scoresAfter":[-42,-68]},{"ply":38,"player":"ai","action":24,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[16,17,19,20,22,23,25,35],"ai":[0,14,31,33,34,41,54,59]},"scoresAfter":[-42,-50]},{"ply":39,"player":"human","action":0,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[16,17,19,20,22,23,25,35],"ai":[0,14,33,34,39,41,54,59]},"scoresAfter":[-36,-50]},{"ply":40,"player":"ai","action":24,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[17,19,20,22,23,25,35,49],"ai":[0,14,33,34,39,41,54,59]},"scoresAfter":[-36,-26]},{"ply":41,"player":"human","action":0,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[17,19,20,22,23,25,35,49],"ai":[0,4,14,34,39,41,54,59]},"scoresAfter":[-28,-26]},{"ply":42,"player":"ai","action":36,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[19,20,22,23,25,35,37,49],"ai":[0,4,14,34,39,41,54,59]},"scoresAfter":[-28,1]},{"ply":43,"player":"human","action":0,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[19,20,22,23,25,35,37,49],"ai":[0,4,10,14,39,41,54,59]},"scoresAfter":[-16,1]},{"ply":44,"player":"ai","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[20,22,23,25,35,37,49,56],"ai":[0,4,10,14,39,41,54,59]},"scoresAfter":[-16,11]},{"ply":45,"player":"human","action":1,"playedCard":20,"placeType":"play","drawSource":"discard_0","drawnCard":9,"handsBefore":{"human":[20,22,23,25,35,37,49,56],"ai":[0,4,10,14,32,39,41,54]},"scoresAfter":[-2,11]},{"ply":46,"player":"ai","action":30,"playedCard":10,"placeType":"discard","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[9,22,23,25,35,37,49,56],"ai":[0,4,10,14,32,39,41,54]},"scoresAfter":[-2,11]},{"ply":47,"player":"human","action":13,"playedCard":22,"placeType":"play","drawSource":"discard_0","drawnCard":10,"handsBefore":{"human":[9,22,23,25,35,37,49,56],"ai":[0,4,14,30,32,39,41,54]},"scoresAfter":[16,11]},{"ply":48,"player":"ai","action":66,"playedCard":39,"placeType":"discard","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[9,10,23,25,35,37,49,56],"ai":[0,4,14,30,32,39,41,54]},"scoresAfter":[16,11]},{"ply":49,"player":"human","action":24,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[9,10,23,25,35,37,49,56],"ai":[0,2,4,14,30,32,41,54]},"scoresAfter":[36,11]}],"finalScores":[36,11],"outcome":"YOU WIN","finalState":{"deckOrder":[17,38,1,3,23,22,35,28,29,15,13,52,44,21,33,18,45,6,50,24,43,34,26,48,59,20,7,5,12,36,8,46,55,57,31,11,51,42,19,40,9,27,53,54,16,14,0,58,41,25,39,49,4,37,10,56,32,30,2,47],"drawPtr":60,"cardLoc":[2,5,2,5,2,5,4,4,4,1,1,4,3,4,2,4,3,3,4,3,3,4,3,3,4,1,4,4,3,4,2,4,2,4,4,1,5,1,3,5,5,2,5,3,4,3,3,1,3,1,3,3,4,3,2,4,1,3,3,4],"handPublic":[false,false,false,false,false,false,false,false,false,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[0,10,3,9,9],[10,8,9,7,10]],"colHandshakes":[[0,1,0,1,2],[0,1,2,0,0]],"colLength":[[0,7,1,4,6],[4,4,7,1,3]],"piles":[[1,3,5],[],[],[36,40,42,39],[]],"toMove":1,"stepCount":49,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"c52837b5-e3bb-4642-9a2c-4eb9d15956d8","seed":"n8azk2","startedAt":"2026-07-14T16:07:01.770Z","finishedAt":"2026-07-14T16:11:23.282Z","initialDeckOrder":[20,43,8,55,14,18,26,11,23,2,40,22,5,25,58,19,38,44,54,9,21,36,52,41,51,35,29,12,50,30,0,3,33,49,24,53,34,56,16,28,47,45,59,1,7,37,48,10,27,42,15,32,6,57,31,46,13,4,17,39],"moves":[{"ply":1,"player":"human","action":24,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[8,11,14,18,20,26,43,55],"ai":[2,5,19,22,23,25,40,58]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[8,11,18,20,26,38,43,55],"ai":[2,5,19,22,23,25,40,58]},"scoresAfter":[-40,0]},{"ply":3,"player":"human","action":55,"playedCard":26,"placeType":"discard","drawSource":"discard_0","drawnCard":2,"handsBefore":{"human":[8,11,18,20,26,38,43,55],"ai":[5,19,22,23,25,40,44,58]},"scoresAfter":[-40,0]},{"ply":4,"player":"ai","action":60,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[2,8,11,18,20,38,43,55],"ai":[5,19,22,23,25,40,44,58]},"scoresAfter":[-40,-17]},{"ply":5,"player":"human","action":0,"playedCard":2,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[2,8,11,18,20,38,43,55],"ai":[5,19,22,23,25,44,54,58]},"scoresAfter":[-80,-17]},{"ply":6,"player":"ai","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[8,9,11,18,20,38,43,55],"ai":[5,19,22,23,25,44,54,58]},"scoresAfter":[-80,-33]},{"ply":7,"player":"human","action":66,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[8,9,11,18,20,38,43,55],"ai":[19,21,22,23,25,44,54,58]},"scoresAfter":[-80,-33]},{"ply":8,"player":"ai","action":60,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[8,9,11,18,20,36,43,55],"ai":[19,21,22,23,25,44,54,58]},"scoresAfter":[-80,-26]},{"ply":9,"player":"human","action":66,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[8,9,11,18,20,36,43,55],"ai":[19,21,22,23,25,52,54,58]},"scoresAfter":[-80,-26]},{"ply":10,"player":"ai","action":60,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[8,9,11,18,20,41,43,55],"ai":[19,21,22,23,25,52,54,58]},"scoresAfter":[-80,-43]},{"ply":11,"player":"human","action":66,"playedCard":41,"placeType":"discard","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[8,9,11,18,20,41,43,55],"ai":[19,21,22,23,25,51,54,58]},"scoresAfter":[-80,-43]},{"ply":12,"player":"ai","action":72,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[8,9,11,18,20,35,43,55],"ai":[19,21,22,23,25,51,54,58]},"scoresAfter":[-80,-38]},{"ply":13,"player":"human","action":78,"playedCard":43,"placeType":"discard","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[8,9,11,18,20,35,43,55],"ai":[19,21,22,23,25,29,51,58]},"scoresAfter":[-80,-38]},{"ply":14,"player":"ai","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[8,9,11,12,18,20,35,55],"ai":[19,21,22,23,25,29,51,58]},"scoresAfter":[-80,-29]},{"ply":15,"player":"human","action":36,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[8,9,11,12,18,20,35,55],"ai":[19,21,22,23,25,29,50,51]},"scoresAfter":[-100,-29]},{"ply":16,"player":"ai","action":90,"playedCard":51,"placeType":"discard","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[8,9,11,18,20,30,35,55],"ai":[19,21,22,23,25,29,50,51]},"scoresAfter":[-100,-29]},{"ply":17,"player":"human","action":90,"playedCard":55,"placeType":"discard","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[8,9,11,18,20,30,35,55],"ai":[0,19,21,22,23,25,29,50]},"scoresAfter":[-100,-29]},{"ply":18,"player":"ai","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[3,8,9,11,18,20,30,35],"ai":[0,19,21,22,23,25,29,50]},"scoresAfter":[-100,-29]},{"ply":19,"player":"human","action":73,"playedCard":30,"placeType":"play","drawSource":"discard_0","drawnCard":0,"handsBefore":{"human":[3,8,9,11,18,20,30,35],"ai":[19,21,22,23,25,29,33,50]},"scoresAfter":[-115,-29]},{"ply":20,"player":"ai","action":90,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[0,3,8,9,11,18,20,35],"ai":[19,21,22,23,25,29,33,50]},"scoresAfter":[-115,-29]},{"ply":21,"player":"human","action":0,"playedCard":0,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[0,3,8,9,11,18,20,35],"ai":[19,21,22,23,25,29,33,49]},"scoresAfter":[-135,-29]},{"ply":22,"player":"ai","action":90,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[3,8,9,11,18,20,24,35],"ai":[19,21,22,23,25,29,33,49]},"scoresAfter":[-135,-29]},{"ply":23,"player":"human","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[3,8,9,11,18,20,24,35],"ai":[19,21,22,23,25,29,33,53]},"scoresAfter":[-129,-29]},{"ply":24,"player":"ai","action":54,"playedCard":25,"placeType":"discard","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[8,9,11,18,20,24,34,35],"ai":[19,21,22,23,25,29,33,53]},"scoresAfter":[-129,-29]},{"ply":25,"player":"human","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[8,9,11,18,20,24,34,35],"ai":[19,21,22,23,29,33,53,56]},"scoresAfter":[-108,-29]},{"ply":26,"player":"ai","action":90,"playedCard":56,"placeType":"discard","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[9,11,16,18,20,24,34,35],"ai":[19,21,22,23,29,33,53,56]},"scoresAfter":[-108,-29]},{"ply":27,"player":"human","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[9,11,16,18,20,24,34,35],"ai":[19,21,22,23,28,29,33,53]},"scoresAfter":[-84,-29]},{"ply":28,"player":"ai","action":90,"playedCard":53,"placeType":"discard","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[11,16,18,20,24,34,35,47],"ai":[19,21,22,23,28,29,33,53]},"scoresAfter":[-84,-29]},{"ply":29,"player":"human","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[11,16,18,20,24,34,35,47],"ai":[19,21,22,23,28,29,33,45]},"scoresAfter":[-54,-29]},{"ply":30,"player":"ai","action":3,"playedCard":19,"placeType":"play","drawSource":"discard_2","drawnCard":25,"handsBefore":{"human":[16,18,20,24,34,35,47,59],"ai":[19,21,22,23,28,29,33,45]},"scoresAfter":[-54,-43]},{"ply":31,"player":"human","action":0,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[16,18,20,24,34,35,47,59],"ai":[21,22,23,25,28,29,33,45]},"scoresAfter":[-45,-43]},{"ply":32,"player":"ai","action":3,"playedCard":21,"placeType":"play","drawSource":"discard_2","drawnCard":26,"handsBefore":{"human":[1,18,20,24,34,35,47,59],"ai":[21,22,23,25,28,29,33,45]},"scoresAfter":[-45,-35]},{"ply":33,"player":"human","action":12,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[1,18,20,24,34,35,47,59],"ai":[22,23,25,26,28,29,33,45]},"scoresAfter":[-30,-35]},{"ply":34,"player":"ai","action":4,"playedCard":22,"placeType":"play","drawSource":"discard_3","drawnCard":43,"handsBefore":{"human":[1,7,20,24,34,35,47,59],"ai":[22,23,25,26,28,29,33,45]},"scoresAfter":[-30,-26]},{"ply":35,"player":"human","action":24,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[1,7,20,24,34,35,47,59],"ai":[23,25,26,28,29,33,43,45]},"scoresAfter":[-9,-26]},{"ply":36,"player":"ai","action":4,"playedCard":23,"placeType":"play","drawSource":"discard_3","drawnCard":41,"handsBefore":{"human":[1,7,24,34,35,37,47,59],"ai":[23,25,26,28,29,33,43,45]},"scoresAfter":[-9,-16]},{"ply":37,"player":"human","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[1,7,24,34,35,37,47,59],"ai":[25,26,28,29,33,41,43,45]},"scoresAfter":[-9,-16]},{"ply":38,"player":"ai","action":0,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[7,24,34,35,37,47,48,59],"ai":[25,26,28,29,33,41,43,45]},"scoresAfter":[-9,-56]},{"ply":39,"player":"human","action":6,"playedCard":7,"placeType":"discard","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[7,24,34,35,37,47,48,59],"ai":[10,26,28,29,33,41,43,45]},"scoresAfter":[-9,-56]},{"ply":40,"player":"ai","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[24,27,34,35,37,47,48,59],"ai":[10,26,28,29,33,41,43,45]},"scoresAfter":[-9,-47]},{"ply":41,"player":"human","action":6,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[24,27,34,35,37,47,48,59],"ai":[26,28,29,33,41,42,43,45]},"scoresAfter":[-9,-47]},{"ply":42,"player":"ai","action":15,"playedCard":28,"placeType":"play","drawSource":"discard_2","drawnCard":24,"handsBefore":{"human":[15,27,34,35,37,47,48,59],"ai":[26,28,29,33,41,42,43,45]},"scoresAfter":[-9,-41]},{"ply":43,"player":"human","action":77,"playedCard":48,"placeType":"play","drawSource":"discard_4","drawnCard":53,"handsBefore":{"human":[15,27,34,35,37,47,48,59],"ai":[24,26,29,33,41,42,43,45]},"scoresAfter":[-49,-41]},{"ply":44,"player":"ai","action":24,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[15,27,34,35,37,47,53,59],"ai":[24,26,29,33,41,42,43,45]},"scoresAfter":[-49,-33]},{"ply":45,"player":"human","action":77,"playedCard":53,"placeType":"play","drawSource":"discard_4","drawnCard":56,"handsBefore":{"human":[15,27,34,35,37,47,53,59],"ai":[24,26,32,33,41,42,43,45]},"scoresAfter":[-41,-33]},{"ply":46,"player":"ai","action":24,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[15,27,34,35,37,47,56,59],"ai":[24,26,32,33,41,42,43,45]},"scoresAfter":[-41,-19]},{"ply":47,"player":"human","action":72,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[15,27,34,35,37,47,56,59],"ai":[6,24,26,33,41,42,43,45]},"scoresAfter":[-27,-19]},{"ply":48,"player":"ai","action":36,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[15,27,34,35,37,47,57,59],"ai":[6,24,26,33,41,42,43,45]},"scoresAfter":[-27,-3]},{"ply":49,"player":"human","action":73,"playedCard":57,"placeType":"play","drawSource":"discard_0","drawnCard":7,"handsBefore":{"human":[15,27,34,35,37,47,57,59],"ai":[6,24,26,31,41,42,43,45]},"scoresAfter":[-11,-3]},{"ply":50,"player":"ai","action":84,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[7,15,27,34,35,37,47,59],"ai":[6,24,26,31,41,42,43,45]},"scoresAfter":[-11,5]},{"ply":51,"player":"human","action":37,"playedCard":34,"placeType":"play","drawSource":"discard_0","drawnCard":1,"handsBefore":{"human":[7,15,27,34,35,37,47,59],"ai":[6,24,26,31,41,42,43,46]},"scoresAfter":[-2,5]},{"ply":52,"player":"ai","action":84,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[1,7,15,27,35,37,47,59],"ai":[6,24,26,31,41,42,43,46]},"scoresAfter":[-2,14]},{"ply":53,"player":"human","action":48,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[1,7,15,27,35,37,47,59],"ai":[6,13,24,26,31,41,42,43]},"scoresAfter":[8,14]},{"ply":54,"player":"ai","action":30,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[1,4,7,15,27,37,47,59],"ai":[6,13,24,26,31,41,42,43]},"scoresAfter":[8,14]},{"ply":55,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[1,4,7,15,27,37,47,59],"ai":[6,13,17,26,31,41,42,43]},"scoresAfter":[28,14]}],"finalScores":[28,14],"outcome":"YOU WIN","finalState":{"deckOrder":[20,43,8,55,14,18,26,11,23,2,40,22,5,25,58,19,38,44,54,9,21,36,52,41,51,35,29,12,50,30,0,3,33,49,24,53,34,56,16,28,47,45,59,1,7,37,48,10,27,42,15,32,6,57,31,46,13,4,17,39],"drawPtr":60,"cardLoc":[3,1,3,3,1,4,2,1,3,3,4,3,3,2,3,1,3,2,3,4,3,4,4,4,5,4,2,1,4,4,3,2,4,4,3,3,5,1,5,1,4,2,2,2,4,4,4,1,3,5,5,5,4,3,4,5,3,3,4,3],"handPublic":[false,true,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,7,10,0,10],[9,10,8,9,9]],"colHandshakes":[[2,2,0,0,1],[0,0,1,0,0]],"colLength":[[6,5,3,0,5],[2,4,5,4,3]],"piles":[[],[],[24],[38,36],[51,55,50,49]],"toMove":1,"stepCount":55,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"db291042-c811-42db-bee6-7face2b96b2d","seed":"86x7l3","startedAt":"2026-07-14T16:11:24.396Z","finishedAt":"2026-07-14T16:14:18.888Z","initialDeckOrder":[12,14,26,32,10,2,0,17,35,56,49,8,37,28,57,42,27,33,25,9,11,19,16,3,29,23,52,24,59,38,6,36,1,39,54,21,47,4,58,45,15,40,43,31,18,13,41,5,44,22,51,46,53,48,30,34,7,20,50,55],"moves":[{"ply":1,"player":"human","action":0,"playedCard":0,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[0,2,10,12,14,17,26,32],"ai":[8,28,35,37,42,49,56,57]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":48,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[2,10,12,14,17,26,27,32],"ai":[8,28,35,37,42,49,56,57]},"scoresAfter":[-40,-15]},{"ply":3,"player":"human","action":0,"playedCard":2,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[2,10,12,14,17,26,27,32],"ai":[8,28,33,35,37,49,56,57]},"scoresAfter":[-60,-15]},{"ply":4,"player":"ai","action":60,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[10,12,14,17,25,26,27,32],"ai":[8,28,33,35,37,49,56,57]},"scoresAfter":[-60,-55]},{"ply":5,"player":"human","action":48,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[10,12,14,17,25,26,27,32],"ai":[8,9,28,33,35,37,56,57]},"scoresAfter":[-100,-55]},{"ply":6,"player":"ai","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[10,11,12,14,17,26,27,32],"ai":[8,9,28,33,35,37,56,57]},"scoresAfter":[-100,-68]},{"ply":7,"player":"human","action":60,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[10,11,12,14,17,26,27,32],"ai":[9,19,28,33,35,37,56,57]},"scoresAfter":[-120,-68]},{"ply":8,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[10,11,12,14,16,17,27,32],"ai":[9,19,28,33,35,37,56,57]},"scoresAfter":[-120,-60]},{"ply":9,"player":"human","action":72,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[10,11,12,14,16,17,27,32],"ai":[3,19,28,33,35,37,56,57]},"scoresAfter":[-114,-60]},{"ply":10,"player":"ai","action":12,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[10,11,12,14,16,17,29,32],"ai":[3,19,28,33,35,37,56,57]},"scoresAfter":[-114,-74]},{"ply":11,"player":"human","action":24,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[10,11,12,14,16,17,29,32],"ai":[3,23,28,33,35,37,56,57]},"scoresAfter":[-154,-74]},{"ply":12,"player":"ai","action":66,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[10,11,14,16,17,29,32,52],"ai":[3,23,28,33,35,37,56,57]},"scoresAfter":[-154,-74]},{"ply":13,"player":"human","action":24,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[10,11,14,16,17,29,32,52],"ai":[3,23,24,28,33,35,56,57]},"scoresAfter":[-174,-74]},{"ply":14,"player":"ai","action":24,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[10,11,16,17,29,32,52,59],"ai":[3,23,24,28,33,35,56,57]},"scoresAfter":[-174,-114]},{"ply":15,"player":"human","action":24,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[10,11,16,17,29,32,52,59],"ai":[3,23,28,33,35,38,56,57]},"scoresAfter":[-165,-114]},{"ply":16,"player":"ai","action":66,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[6,10,11,17,29,32,52,59],"ai":[3,23,28,33,35,38,56,57]},"scoresAfter":[-165,-114]},{"ply":17,"player":"human","action":36,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[6,10,11,17,29,32,52,59],"ai":[3,23,28,33,35,36,56,57]},"scoresAfter":[-153,-114]},{"ply":18,"player":"ai","action":66,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[1,6,10,11,29,32,52,59],"ai":[3,23,28,33,35,36,56,57]},"scoresAfter":[-153,-114]},{"ply":19,"player":"human","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[1,6,10,11,29,32,52,59],"ai":[3,23,28,33,35,39,56,57]},"scoresAfter":[-173,-114]},{"ply":20,"player":"ai","action":66,"playedCard":39,"placeType":"discard","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[6,10,11,29,32,52,54,59],"ai":[3,23,28,33,35,39,56,57]},"scoresAfter":[-173,-114]},{"ply":21,"player":"human","action":60,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[6,10,11,29,32,52,54,59],"ai":[3,21,23,28,33,35,56,57]},"scoresAfter":[-190,-114]},{"ply":22,"player":"ai","action":12,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[6,10,11,29,32,47,54,59],"ai":[3,21,23,28,33,35,56,57]},"scoresAfter":[-190,-106]},{"ply":23,"player":"human","action":72,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[6,10,11,29,32,47,54,59],"ai":[3,4,23,28,33,35,56,57]},"scoresAfter":[-185,-106]},{"ply":24,"player":"ai","action":6,"playedCard":3,"placeType":"discard","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[6,10,11,29,32,47,58,59],"ai":[3,4,23,28,33,35,56,57]},"scoresAfter":[-185,-106]},{"ply":25,"player":"human","action":36,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[6,10,11,29,32,47,58,59],"ai":[4,23,28,33,35,45,56,57]},"scoresAfter":[-173,-106]},{"ply":26,"player":"ai","action":60,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[6,10,11,15,32,47,58,59],"ai":[4,23,28,33,35,45,56,57]},"scoresAfter":[-173,-98]},{"ply":27,"player":"human","action":42,"playedCard":15,"placeType":"discard","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[6,10,11,15,32,47,58,59],"ai":[4,23,28,33,35,40,56,57]},"scoresAfter":[-173,-98]},{"ply":28,"player":"ai","action":72,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[6,10,11,32,43,47,58,59],"ai":[4,23,28,33,35,40,56,57]},"scoresAfter":[-173,-84]},{"ply":29,"player":"human","action":76,"playedCard":58,"placeType":"play","drawSource":"discard_3","drawnCard":39,"handsBefore":{"human":[6,10,11,32,43,47,58,59],"ai":[4,23,28,31,33,35,40,57]},"scoresAfter":[-164,-84]},{"ply":30,"player":"ai","action":84,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[6,10,11,32,39,43,47,59],"ai":[4,23,28,31,33,35,40,57]},"scoresAfter":[-164,-68]},{"ply":31,"player":"human","action":88,"playedCard":59,"placeType":"play","drawSource":"discard_3","drawnCard":36,"handsBefore":{"human":[6,10,11,32,39,43,47,59],"ai":[4,18,23,28,31,33,35,40]},"scoresAfter":[-154,-68]},{"ply":32,"player":"ai","action":24,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[6,10,11,32,36,39,43,47],"ai":[4,18,23,28,31,33,35,40]},"scoresAfter":[-154,-58]},{"ply":33,"player":"human","action":52,"playedCard":36,"placeType":"play","drawSource":"discard_3","drawnCard":38,"handsBefore":{"human":[6,10,11,32,36,39,43,47],"ai":[4,13,18,28,31,33,35,40]},"scoresAfter":[-194,-58]},{"ply":34,"player":"ai","action":36,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[6,10,11,32,38,39,43,47],"ai":[4,13,18,28,31,33,35,40]},"scoresAfter":[-194,-52]},{"ply":35,"player":"human","action":52,"playedCard":38,"placeType":"play","drawSource":"discard_3","drawnCard":37,"handsBefore":{"human":[6,10,11,32,38,39,43,47],"ai":[4,13,18,31,33,35,40,41]},"scoresAfter":[-214,-52]},{"ply":36,"player":"ai","action":6,"playedCard":4,"placeType":"discard","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[6,10,11,32,37,39,43,47],"ai":[4,13,18,31,33,35,40,41]},"scoresAfter":[-214,-52]},{"ply":37,"player":"human","action":48,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[6,10,11,32,37,39,43,47],"ai":[5,13,18,31,33,35,40,41]},"scoresAfter":[-234,-52]},{"ply":38,"player":"ai","action":36,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[6,10,11,32,39,43,44,47],"ai":[5,13,18,31,33,35,40,41]},"scoresAfter":[-234,-40]},{"ply":39,"player":"human","action":60,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[6,10,11,32,39,43,44,47],"ai":[5,13,18,22,33,35,40,41]},"scoresAfter":[-210,-40]},{"ply":40,"player":"ai","action":48,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[6,10,11,32,39,44,47,51],"ai":[5,13,18,22,33,35,40,41]},"scoresAfter":[-210,-24]},{"ply":41,"player":"human","action":60,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[6,10,11,32,39,44,47,51],"ai":[5,13,18,22,35,40,41,46]},"scoresAfter":[-182,-24]},{"ply":42,"player":"ai","action":84,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[6,10,11,32,39,47,51,53],"ai":[5,13,18,22,35,40,41,46]},"scoresAfter":[-182,-15]},{"ply":43,"player":"human","action":61,"playedCard":47,"placeType":"play","drawSource":"discard_0","drawnCard":4,"handsBefore":{"human":[6,10,11,32,39,47,51,53],"ai":[5,13,18,22,35,40,41,48]},"scoresAfter":[-142,-15]},{"ply":44,"player":"ai","action":48,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[4,6,10,11,32,39,51,53],"ai":[5,13,18,22,35,40,41,48]},"scoresAfter":[-142,5]},{"ply":45,"player":"human","action":1,"playedCard":4,"placeType":"play","drawSource":"discard_0","drawnCard":3,"handsBefore":{"human":[4,6,10,11,32,39,51,53],"ai":[5,13,18,22,30,40,41,48]},"scoresAfter":[-130,5]},{"ply":46,"player":"ai","action":90,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[3,6,10,11,32,39,51,53],"ai":[5,13,18,22,30,40,41,48]},"scoresAfter":[-130,5]},{"ply":47,"player":"human","action":14,"playedCard":6,"placeType":"play","drawSource":"discard_1","drawnCard":15,"handsBefore":{"human":[3,6,10,11,32,39,51,53],"ai":[5,13,18,22,30,34,40,41]},"scoresAfter":[-110,5]},{"ply":48,"player":"ai","action":54,"playedCard":30,"placeType":"discard","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[3,10,11,15,32,39,51,53],"ai":[5,13,18,22,30,34,40,41]},"scoresAfter":[-110,5]},{"ply":49,"player":"human","action":15,"playedCard":10,"placeType":"play","drawSource":"discard_2","drawnCard":30,"handsBefore":{"human":[3,10,11,15,32,39,51,53],"ai":[5,7,13,18,22,34,40,41]},"scoresAfter":[-74,5]},{"ply":50,"player":"ai","action":30,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[3,11,15,30,32,39,51,53],"ai":[5,7,13,18,22,34,40,41]},"scoresAfter":[-74,5]},{"ply":51,"player":"human","action":12,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[3,11,15,30,32,39,51,53],"ai":[5,7,18,20,22,34,40,41]},"scoresAfter":[-34,5]},{"ply":52,"player":"ai","action":78,"playedCard":40,"placeType":"discard","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[3,15,30,32,39,50,51,53],"ai":[5,7,18,20,22,34,40,41]},"scoresAfter":[-34,5]}],"finalScores":[-34,5],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[12,14,26,32,10,2,0,17,35,56,49,8,37,28,57,42,27,33,25,9,11,19,16,3,29,23,52,24,59,38,6,36,1,39,54,21,47,4,58,45,15,40,43,31,18,13,41,5,44,22,51,46,53,48,30,34,7,20,50,55],"drawPtr":60,"cardLoc":[3,3,3,1,3,2,3,2,4,4,3,3,3,5,3,1,3,3,2,4,2,4,2,4,4,3,3,3,4,3,1,4,1,4,2,4,3,3,3,1,5,2,4,3,3,4,4,3,5,4,1,1,3,1,3,2,4,4,3,3],"handPublic":[false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,4,4,10,10],[8,10,10,9,8]],"colHandshakes":[[3,2,2,3,0],[0,0,1,0,1]],"colLength":[[7,4,4,6,4],[2,3,5,3,3]],"piles":[[],[13],[],[40],[48]],"toMove":0,"stepCount":52,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"5c557589-0d3c-486a-897b-e9581540c2e5","seed":"43100p","startedAt":"2026-07-14T16:14:19.809Z","finishedAt":"2026-07-14T16:16:47.587Z","initialDeckOrder":[18,4,48,41,58,45,19,2,32,47,8,56,24,29,25,33,50,23,55,1,0,44,15,39,49,36,11,57,30,38,9,7,6,27,22,42,16,14,13,54,12,26,31,51,37,52,10,35,3,53,40,28,17,21,5,43,34,46,59,20],"moves":[{"ply":1,"player":"human","action":72,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[2,4,18,19,41,45,48,58],"ai":[8,24,25,29,32,33,47,56]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":12,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[2,4,18,19,41,45,50,58],"ai":[8,24,25,29,32,33,47,56]},"scoresAfter":[-40,-40]},{"ply":3,"player":"human","action":72,"playedCard":50,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[2,4,18,19,41,45,50,58],"ai":[8,23,25,29,32,33,47,56]},"scoresAfter":[-60,-40]},{"ply":4,"player":"ai","action":24,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[2,4,18,19,41,45,55,58],"ai":[8,23,25,29,32,33,47,56]},"scoresAfter":[-60,-60]},{"ply":5,"player":"human","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[2,4,18,19,41,45,55,58],"ai":[1,8,23,29,32,33,47,56]},"scoresAfter":[-60,-60]},{"ply":6,"player":"ai","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[0,4,18,19,41,45,55,58],"ai":[1,8,23,29,32,33,47,56]},"scoresAfter":[-60,-60]},{"ply":7,"player":"human","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[0,4,18,19,41,45,55,58],"ai":[8,23,29,32,33,44,47,56]},"scoresAfter":[-60,-60]},{"ply":8,"player":"ai","action":84,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[4,15,18,19,41,45,55,58],"ai":[8,23,29,32,33,44,47,56]},"scoresAfter":[-60,-73]},{"ply":9,"player":"human","action":12,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[4,15,18,19,41,45,55,58],"ai":[8,23,29,32,33,39,44,47]},"scoresAfter":[-78,-73]},{"ply":10,"player":"ai","action":60,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[4,18,19,41,45,49,55,58],"ai":[8,23,29,32,33,39,44,47]},"scoresAfter":[-78,-91]},{"ply":11,"player":"human","action":60,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[4,18,19,41,45,49,55,58],"ai":[8,23,29,32,33,36,44,47]},"scoresAfter":[-98,-91]},{"ply":12,"player":"ai","action":66,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[4,11,18,19,41,45,55,58],"ai":[8,23,29,32,33,36,44,47]},"scoresAfter":[-98,-91]},{"ply":13,"player":"human","action":24,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[4,11,18,19,41,45,55,58],"ai":[8,23,29,32,33,44,47,57]},"scoresAfter":[-93,-91]},{"ply":14,"player":"ai","action":24,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[4,11,19,30,41,45,55,58],"ai":[8,23,29,32,33,44,47,57]},"scoresAfter":[-93,-79]},{"ply":15,"player":"human","action":10,"playedCard":4,"placeType":"discard","drawSource":"discard_3","drawnCard":36,"handsBefore":{"human":[4,11,19,30,41,45,55,58],"ai":[8,23,32,33,38,44,47,57]},"scoresAfter":[-93,-79]},{"ply":16,"player":"ai","action":24,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[11,19,30,36,41,45,55,58],"ai":[8,23,32,33,38,44,47,57]},"scoresAfter":[-93,-58]},{"ply":17,"player":"human","action":36,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[11,19,30,36,41,45,55,58],"ai":[8,9,23,33,38,44,47,57]},"scoresAfter":[-133,-58]},{"ply":18,"player":"ai","action":36,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[7,11,19,30,41,45,55,58],"ai":[8,9,23,33,38,44,47,57]},"scoresAfter":[-133,-34]},{"ply":19,"player":"human","action":49,"playedCard":41,"placeType":"play","drawSource":"discard_0","drawnCard":4,"handsBefore":{"human":[7,11,19,30,41,45,55,58],"ai":[6,8,9,23,38,44,47,57]},"scoresAfter":[-125,-34]},{"ply":20,"player":"ai","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[4,7,11,19,30,45,55,58],"ai":[6,8,9,23,38,44,47,57]},"scoresAfter":[-125,-49]},{"ply":21,"player":"human","action":37,"playedCard":19,"placeType":"play","drawSource":"discard_0","drawnCard":0,"handsBefore":{"human":[4,7,11,19,30,45,55,58],"ai":[8,9,23,27,38,44,47,57]},"scoresAfter":[-119,-49]},{"ply":22,"player":"ai","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[0,4,7,11,30,45,55,58],"ai":[8,9,23,27,38,44,47,57]},"scoresAfter":[-119,-42]},{"ply":23,"player":"human","action":1,"playedCard":0,"placeType":"play","drawSource":"discard_0","drawnCard":1,"handsBefore":{"human":[0,4,7,11,30,45,55,58],"ai":[9,22,23,27,38,44,47,57]},"scoresAfter":[-159,-42]},{"ply":24,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[1,4,7,11,30,45,55,58],"ai":[9,22,23,27,38,44,47,57]},"scoresAfter":[-159,-34]},{"ply":25,"player":"human","action":1,"playedCard":1,"placeType":"play","drawSource":"discard_0","drawnCard":2,"handsBefore":{"human":[1,4,7,11,30,45,55,58],"ai":[22,23,27,38,42,44,47,57]},"scoresAfter":[-179,-34]},{"ply":26,"player":"ai","action":48,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[2,4,7,11,30,45,55,58],"ai":[22,23,27,38,42,44,47,57]},"scoresAfter":[-179,-29]},{"ply":27,"player":"human","action":0,"playedCard":2,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[2,4,7,11,30,45,55,58],"ai":[16,22,23,27,38,44,47,57]},"scoresAfter":[-199,-29]},{"ply":28,"player":"ai","action":72,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[4,7,11,14,30,45,55,58],"ai":[16,22,23,27,38,44,47,57]},"scoresAfter":[-199,-19]},{"ply":29,"player":"human","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[4,7,11,14,30,45,55,58],"ai":[13,16,22,23,27,38,44,57]},"scoresAfter":[-187,-19]},{"ply":30,"player":"ai","action":0,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[7,11,14,30,45,54,55,58],"ai":[13,16,22,23,27,38,44,57]},"scoresAfter":[-187,-59]},{"ply":31,"player":"human","action":30,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[7,11,14,30,45,54,55,58],"ai":[12,16,22,23,27,38,44,57]},"scoresAfter":[-187,-59]},{"ply":32,"player":"ai","action":0,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[7,11,26,30,45,54,55,58],"ai":[12,16,22,23,27,38,44,57]},"scoresAfter":[-187,-79]},{"ply":33,"player":"human","action":30,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[7,11,26,30,45,54,55,58],"ai":[16,22,23,27,31,38,44,57]},"scoresAfter":[-187,-79]},{"ply":34,"player":"ai","action":84,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[7,11,30,45,51,54,55,58],"ai":[16,22,23,27,31,38,44,57]},"scoresAfter":[-187,-71]},{"ply":35,"player":"human","action":30,"playedCard":30,"placeType":"discard","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[7,11,30,45,51,54,55,58],"ai":[16,22,23,27,31,37,38,44]},"scoresAfter":[-187,-71]},{"ply":36,"player":"ai","action":66,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[7,11,45,51,52,54,55,58],"ai":[16,22,23,27,31,37,38,44]},"scoresAfter":[-187,-71]},{"ply":37,"player":"human","action":36,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[7,11,45,51,52,54,55,58],"ai":[10,16,22,23,27,31,38,44]},"scoresAfter":[-179,-71]},{"ply":38,"player":"ai","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[7,11,35,45,52,54,55,58],"ai":[10,16,22,23,27,31,38,44]},"scoresAfter":[-179,-62]},{"ply":39,"player":"human","action":48,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[7,11,35,45,52,54,55,58],"ai":[3,16,22,23,27,31,38,44]},"scoresAfter":[-167,-62]},{"ply":40,"player":"ai","action":12,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[7,11,35,45,53,54,55,58],"ai":[3,16,22,23,27,31,38,44]},"scoresAfter":[-167,-53]},{"ply":41,"player":"human","action":48,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[7,11,35,45,53,54,55,58],"ai":[3,22,23,27,31,38,40,44]},"scoresAfter":[-151,-53]},{"ply":42,"player":"ai","action":12,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[7,11,28,35,45,54,55,58],"ai":[3,22,23,27,31,38,40,44]},"scoresAfter":[-151,-26]},{"ply":43,"player":"human","action":60,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[7,11,28,35,45,54,55,58],"ai":[3,17,23,27,31,38,40,44]},"scoresAfter":[-131,-26]},{"ply":44,"player":"ai","action":24,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[7,11,21,28,35,45,55,58],"ai":[3,17,23,27,31,38,40,44]},"scoresAfter":[-131,4]},{"ply":45,"player":"human","action":72,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[7,11,21,28,35,45,55,58],"ai":[3,5,17,27,31,38,40,44]},"scoresAfter":[-87,4]},{"ply":46,"player":"ai","action":30,"playedCard":17,"placeType":"discard","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[7,11,21,28,35,43,45,58],"ai":[3,5,17,27,31,38,40,44]},"scoresAfter":[-87,4]},{"ply":47,"player":"human","action":87,"playedCard":58,"placeType":"play","drawSource":"discard_2","drawnCard":30,"handsBefore":{"human":[7,11,21,28,35,43,45,58],"ai":[3,5,27,31,34,38,40,44]},"scoresAfter":[-51,4]},{"ply":48,"player":"ai","action":48,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[7,11,21,28,30,35,43,45],"ai":[3,5,27,31,34,38,40,44]},"scoresAfter":[-51,31]},{"ply":49,"player":"human","action":3,"playedCard":7,"placeType":"play","drawSource":"discard_2","drawnCard":26,"handsBefore":{"human":[7,11,21,28,30,35,43,45],"ai":[3,5,27,31,38,40,44,46]},"scoresAfter":[-27,31]},{"ply":50,"player":"ai","action":6,"playedCard":3,"placeType":"discard","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[11,21,26,28,30,35,43,45],"ai":[3,5,27,31,38,40,44,46]},"scoresAfter":[-27,31]},{"ply":51,"player":"human","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[11,21,26,28,30,35,43,45],"ai":[5,27,31,38,40,44,46,59]},"scoresAfter":[13,31]}],"finalScores":[13,31],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[18,4,48,41,58,45,19,2,32,47,8,56,24,29,25,33,50,23,55,1,0,44,15,39,49,36,11,57,30,38,9,7,6,27,22,42,16,14,13,54,12,26,31,51,37,52,10,35,3,53,40,28,17,21,5,43,34,46,59,20],"drawPtr":60,"cardLoc":[3,3,3,5,3,2,4,3,4,4,4,3,4,4,5,3,4,5,3,3,1,1,4,4,4,4,1,2,1,4,1,2,4,4,4,1,3,5,2,4,2,3,4,1,2,1,2,4,3,3,3,3,3,3,3,3,4,4,3,2],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,6,0,4,9],[9,10,9,10,8]],"colHandshakes":[[3,0,0,1,3],[0,2,2,0,0]],"colLength":[[6,3,0,2,9],[4,5,6,3,2]],"piles":[[3],[14,17],[],[37],[]],"toMove":1,"stepCount":51,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"32adbcb3-98a0-449f-aae8-041bd73bc521","seed":"kv82c8","startedAt":"2026-07-14T16:16:48.456Z","finishedAt":"2026-07-14T16:18:37.618Z","initialDeckOrder":[2,9,49,29,31,36,48,11,35,44,21,1,57,10,58,56,4,18,53,7,22,50,24,41,59,12,14,25,20,0,3,52,47,6,5,13,34,46,27,15,54,42,43,39,32,33,8,17,19,26,28,37,30,40,51,38,45,55,23,16],"moves":[{"ply":1,"player":"human","action":0,"playedCard":2,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[2,9,11,29,31,36,48,49],"ai":[1,10,21,35,44,56,57,58]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":60,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[4,9,11,29,31,36,48,49],"ai":[1,10,21,35,44,56,57,58]},"scoresAfter":[-40,-13]},{"ply":3,"player":"human","action":78,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[4,9,11,29,31,36,48,49],"ai":[1,10,18,21,35,44,57,58]},"scoresAfter":[-40,-13]},{"ply":4,"player":"ai","action":72,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[4,9,11,29,31,36,49,53],"ai":[1,10,18,21,35,44,57,58]},"scoresAfter":[-40,-5]},{"ply":5,"player":"human","action":78,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[4,9,11,29,31,36,49,53],"ai":[1,7,10,18,21,35,44,58]},"scoresAfter":[-40,-5]},{"ply":6,"player":"ai","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[4,9,11,22,29,31,36,53],"ai":[1,7,10,18,21,35,44,58]},"scoresAfter":[-40,4]},{"ply":7,"player":"human","action":78,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[4,9,11,22,29,31,36,53],"ai":[1,7,10,18,21,35,44,50]},"scoresAfter":[-40,4]},{"ply":8,"player":"ai","action":90,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[4,9,11,22,24,29,31,53],"ai":[1,7,10,18,21,35,44,50]},"scoresAfter":[-40,4]},{"ply":9,"player":"human","action":48,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[4,9,11,22,24,29,31,53],"ai":[1,7,10,18,21,35,41,44]},"scoresAfter":[-80,4]},{"ply":10,"player":"ai","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[4,9,11,22,29,31,53,59],"ai":[1,7,10,18,21,35,41,44]},"scoresAfter":[-80,-36]},{"ply":11,"player":"human","action":5,"playedCard":4,"placeType":"play","drawSource":"discard_4","drawnCard":50,"handsBefore":{"human":[4,9,11,22,29,31,53,59],"ai":[7,10,12,18,21,35,41,44]},"scoresAfter":[-74,-36]},{"ply":12,"player":"ai","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[9,11,22,29,31,50,53,59],"ai":[7,10,12,18,21,35,41,44]},"scoresAfter":[-74,-24]},{"ply":13,"player":"human","action":65,"playedCard":50,"placeType":"play","drawSource":"discard_4","drawnCard":49,"handsBefore":{"human":[9,11,22,29,31,50,53,59],"ai":[10,12,14,18,21,35,41,44]},"scoresAfter":[-114,-24]},{"ply":14,"player":"ai","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[9,11,22,29,31,49,53,59],"ai":[10,12,14,18,21,35,41,44]},"scoresAfter":[-114,-6]},{"ply":15,"player":"human","action":65,"playedCard":49,"placeType":"play","drawSource":"discard_4","drawnCard":48,"handsBefore":{"human":[9,11,22,29,31,49,53,59],"ai":[12,14,18,21,25,35,41,44]},"scoresAfter":[-134,-6]},{"ply":16,"player":"ai","action":0,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[9,11,22,29,31,48,53,59],"ai":[12,14,18,21,25,35,41,44]},"scoresAfter":[-134,-46]},{"ply":17,"player":"human","action":60,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[9,11,22,29,31,48,53,59],"ai":[14,18,20,21,25,35,41,44]},"scoresAfter":[-154,-46]},{"ply":18,"player":"ai","action":0,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[0,9,11,22,29,31,53,59],"ai":[14,18,20,21,25,35,41,44]},"scoresAfter":[-154,-66]},{"ply":19,"player":"human","action":72,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[0,9,11,22,29,31,53,59],"ai":[3,18,20,21,25,35,41,44]},"scoresAfter":[-138,-66]},{"ply":20,"player":"ai","action":72,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[0,9,11,22,29,31,52,59],"ai":[3,18,20,21,25,35,41,44]},"scoresAfter":[-138,-82]},{"ply":21,"player":"human","action":78,"playedCard":52,"placeType":"discard","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[0,9,11,22,29,31,52,59],"ai":[3,18,20,21,25,35,44,47]},"scoresAfter":[-138,-82]},{"ply":22,"player":"ai","action":72,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[0,6,9,11,22,29,31,59],"ai":[3,18,20,21,25,35,44,47]},"scoresAfter":[-138,-75]},{"ply":23,"player":"human","action":12,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[0,6,9,11,22,29,31,59],"ai":[3,5,18,20,21,25,35,47]},"scoresAfter":[-128,-75]},{"ply":24,"player":"ai","action":6,"playedCard":3,"placeType":"discard","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[0,9,11,13,22,29,31,59],"ai":[3,5,18,20,21,25,35,47]},"scoresAfter":[-128,-75]},{"ply":25,"player":"human","action":42,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[0,9,11,13,22,29,31,59],"ai":[5,18,20,21,25,34,35,47]},"scoresAfter":[-128,-75]},{"ply":26,"player":"ai","action":50,"playedCard":25,"placeType":"play","drawSource":"discard_1","drawnCard":13,"handsBefore":{"human":[0,9,11,22,29,31,46,59],"ai":[5,18,20,21,25,34,35,47]},"scoresAfter":[-128,-115]},{"ply":27,"player":"human","action":12,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[0,9,11,22,29,31,46,59],"ai":[5,13,18,20,21,34,35,47]},"scoresAfter":[-112,-115]},{"ply":28,"player":"ai","action":6,"playedCard":5,"placeType":"discard","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[0,11,22,27,29,31,46,59],"ai":[5,13,18,20,21,34,35,47]},"scoresAfter":[-112,-115]},{"ply":29,"player":"human","action":36,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[0,11,22,27,29,31,46,59],"ai":[13,15,18,20,21,34,35,47]},"scoresAfter":[-108,-115]},{"ply":30,"player":"ai","action":0,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[0,11,22,29,31,46,54,59],"ai":[13,15,18,20,21,34,35,47]},"scoresAfter":[-108,-135]},{"ply":31,"player":"human","action":72,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[0,11,22,29,31,46,54,59],"ai":[15,18,20,21,34,35,42,47]},"scoresAfter":[-88,-135]},{"ply":32,"player":"ai","action":84,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[0,11,22,29,31,43,46,59],"ai":[15,18,20,21,34,35,42,47]},"scoresAfter":[-88,-125]},{"ply":33,"player":"human","action":36,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[0,11,22,29,31,43,46,59],"ai":[15,18,20,21,34,35,39,42]},"scoresAfter":[-80,-125]},{"ply":34,"player":"ai","action":0,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[0,11,22,31,32,43,46,59],"ai":[15,18,20,21,34,35,39,42]},"scoresAfter":[-80,-117]},{"ply":35,"player":"human","action":36,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[0,11,22,31,32,43,46,59],"ai":[18,20,21,33,34,35,39,42]},"scoresAfter":[-68,-117]},{"ply":36,"player":"ai","action":0,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[0,8,11,22,32,43,46,59],"ai":[18,20,21,33,34,35,39,42]},"scoresAfter":[-68,-97]},{"ply":37,"player":"human","action":48,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[0,8,11,22,32,43,46,59],"ai":[17,20,21,33,34,35,39,42]},"scoresAfter":[-54,-97]},{"ply":38,"player":"ai","action":12,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[0,8,11,19,22,43,46,59],"ai":[17,20,21,33,34,35,39,42]},"scoresAfter":[-54,-69]},{"ply":39,"player":"human","action":24,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[0,8,11,19,22,43,46,59],"ai":[17,21,26,33,34,35,39,42]},"scoresAfter":[-34,-69]},{"ply":40,"player":"ai","action":36,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[0,8,19,22,28,43,46,59],"ai":[17,21,26,33,34,35,39,42]},"scoresAfter":[-34,-53]},{"ply":41,"player":"human","action":18,"playedCard":8,"placeType":"discard","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[0,8,19,22,28,43,46,59],"ai":[17,21,26,34,35,37,39,42]},"scoresAfter":[-34,-53]},{"ply":42,"player":"ai","action":36,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[0,19,22,28,30,43,46,59],"ai":[17,21,26,34,35,37,39,42]},"scoresAfter":[-34,-35]},{"ply":43,"player":"human","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[0,19,22,28,30,43,46,59],"ai":[17,21,26,35,37,39,40,42]},"scoresAfter":[-34,-35]},{"ply":44,"player":"ai","action":12,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[19,22,28,30,43,46,51,59],"ai":[17,21,26,35,37,39,40,42]},"scoresAfter":[-34,-3]},{"ply":45,"player":"human","action":6,"playedCard":19,"placeType":"discard","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[19,22,28,30,43,46,51,59],"ai":[17,26,35,37,38,39,40,42]},"scoresAfter":[-34,-3]},{"ply":46,"player":"ai","action":24,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[22,28,30,43,45,46,51,59],"ai":[17,26,35,37,38,39,40,42]},"scoresAfter":[-34,17]},{"ply":47,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[22,28,30,43,45,46,51,59],"ai":[17,26,37,38,39,40,42,55]},"scoresAfter":[6,17]},{"ply":48,"player":"ai","action":30,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[22,23,28,30,43,45,46,51],"ai":[17,26,37,38,39,40,42,55]},"scoresAfter":[6,17]}],"finalScores":[6,17],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[2,9,49,29,31,36,48,11,35,44,21,1,57,10,58,56,4,18,53,7,22,50,24,41,59,12,14,25,20,0,3,52,47,6,5,13,34,46,27,15,54,42,43,39,32,33,8,17,19,26,28,37,30,40,51,38,45,55,23,16],"drawPtr":60,"cardLoc":[5,4,3,5,3,5,3,4,5,3,4,3,4,4,4,4,2,2,4,5,4,4,1,1,3,4,2,3,1,3,1,3,3,4,4,4,5,5,2,2,2,4,2,1,4,1,1,4,3,3,3,1,5,3,3,2,4,4,4,3],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,0,7,0,10],[9,8,10,10,9]],"colHandshakes":[[1,0,1,0,3],[1,3,1,0,0]],"colLength":[[5,0,5,0,6],[3,7,4,3,3]],"piles":[[3,5,8,0],[19],[],[36,37],[52]],"toMove":0,"stepCount":48,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"b1483b11-1e1a-4fda-95f1-2c0db2fb8f3f","seed":"22glj2","startedAt":"2026-07-14T16:18:38.877Z","finishedAt":"2026-07-14T16:20:30.757Z","initialDeckOrder":[0,50,24,45,43,9,5,4,25,40,54,17,16,46,41,38,53,28,21,52,57,37,20,26,35,13,48,47,49,58,39,18,56,27,15,29,2,59,1,36,42,34,11,7,44,55,3,32,14,12,19,6,31,30,22,51,23,33,8,10],"moves":[{"ply":1,"player":"human","action":0,"playedCard":0,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[0,4,5,9,24,43,45,50],"ai":[16,17,25,38,40,41,46,54]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":0,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[4,5,9,24,43,45,50,53],"ai":[16,17,25,38,40,41,46,54]},"scoresAfter":[-40,-17]},{"ply":3,"player":"human","action":42,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[4,5,9,24,43,45,50,53],"ai":[17,25,28,38,40,41,46,54]},"scoresAfter":[-40,-17]},{"ply":4,"player":"ai","action":36,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[4,5,9,21,43,45,50,53],"ai":[17,25,28,38,40,41,46,54]},"scoresAfter":[-40,-57]},{"ply":5,"player":"human","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[4,5,9,21,43,45,50,53],"ai":[17,25,28,40,41,46,52,54]},"scoresAfter":[-34,-57]},{"ply":6,"player":"ai","action":72,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[5,9,21,43,45,50,53,57],"ai":[17,25,28,40,41,46,52,54]},"scoresAfter":[-34,-74]},{"ply":7,"player":"human","action":60,"playedCard":50,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[5,9,21,43,45,50,53,57],"ai":[17,25,28,37,40,41,46,54]},"scoresAfter":[-74,-74]},{"ply":8,"player":"ai","action":84,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[5,9,20,21,43,45,53,57],"ai":[17,25,28,37,40,41,46,54]},"scoresAfter":[-74,-69]},{"ply":9,"player":"human","action":72,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[5,9,20,21,43,45,53,57],"ai":[17,25,26,28,37,40,41,46]},"scoresAfter":[-66,-69]},{"ply":10,"player":"ai","action":48,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[5,9,20,21,35,43,45,57],"ai":[17,25,26,28,37,40,41,46]},"scoresAfter":[-66,-89]},{"ply":11,"player":"human","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[5,9,20,21,35,43,45,57],"ai":[13,17,25,26,28,40,41,46]},"scoresAfter":[-58,-89]},{"ply":12,"player":"ai","action":24,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[9,20,21,35,43,45,48,57],"ai":[13,17,25,26,28,40,41,46]},"scoresAfter":[-58,-129]},{"ply":13,"player":"human","action":78,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[9,20,21,35,43,45,48,57],"ai":[13,17,26,28,40,41,46,47]},"scoresAfter":[-58,-129]},{"ply":14,"player":"ai","action":12,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[9,20,21,35,43,45,49,57],"ai":[13,17,26,28,40,41,46,47]},"scoresAfter":[-58,-125]},{"ply":15,"player":"human","action":78,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[9,20,21,35,43,45,49,57],"ai":[13,26,28,40,41,46,47,58]},"scoresAfter":[-58,-125]},{"ply":16,"player":"ai","action":12,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[9,20,21,35,39,43,45,57],"ai":[13,26,28,40,41,46,47,58]},"scoresAfter":[-58,-145]},{"ply":17,"player":"human","action":48,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[9,20,21,35,39,43,45,57],"ai":[13,18,28,40,41,46,47,58]},"scoresAfter":[-76,-145]},{"ply":18,"player":"ai","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[9,20,21,35,43,45,56,57],"ai":[13,18,28,40,41,46,47,58]},"scoresAfter":[-76,-136]},{"ply":19,"player":"human","action":72,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[9,20,21,35,43,45,56,57],"ai":[13,18,27,28,40,41,46,47]},"scoresAfter":[-62,-136]},{"ply":20,"player":"ai","action":48,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[9,15,20,21,35,43,45,57],"ai":[13,18,27,28,40,41,46,47]},"scoresAfter":[-62,-127]},{"ply":21,"player":"human","action":12,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[9,15,20,21,35,43,45,57],"ai":[13,18,27,28,29,41,46,47]},"scoresAfter":[-80,-127]},{"ply":22,"player":"ai","action":60,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[2,9,20,21,35,43,45,57],"ai":[13,18,27,28,29,41,46,47]},"scoresAfter":[-80,-115]},{"ply":23,"player":"human","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[2,9,20,21,35,43,45,57],"ai":[13,18,27,28,29,46,47,59]},"scoresAfter":[-80,-115]},{"ply":24,"player":"ai","action":15,"playedCard":18,"placeType":"play","drawSource":"discard_2","drawnCard":24,"handsBefore":{"human":[1,9,20,21,35,43,45,57],"ai":[13,18,27,28,29,46,47,59]},"scoresAfter":[-80,-110]},{"ply":25,"player":"human","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[1,9,20,21,35,43,45,57],"ai":[13,24,27,28,29,46,47,59]},"scoresAfter":[-80,-110]},{"ply":26,"player":"ai","action":60,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[9,20,21,35,36,43,45,57],"ai":[13,24,27,28,29,46,47,59]},"scoresAfter":[-80,-83]},{"ply":27,"player":"human","action":54,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[9,20,21,35,36,43,45,57],"ai":[13,24,27,28,29,42,47,59]},"scoresAfter":[-80,-83]},{"ply":28,"player":"ai","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[9,20,21,34,35,43,45,57],"ai":[13,24,27,28,29,42,47,59]},"scoresAfter":[-80,-73]},{"ply":29,"player":"human","action":84,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[9,20,21,34,35,43,45,57],"ai":[11,13,24,27,28,29,42,47]},"scoresAfter":[-64,-73]},{"ply":30,"player":"ai","action":24,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[7,9,20,21,34,35,43,45],"ai":[11,13,24,27,28,29,42,47]},"scoresAfter":[-64,-93]},{"ply":31,"player":"human","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[7,9,20,21,34,35,43,45],"ai":[11,13,27,28,29,42,44,47]},"scoresAfter":[-52,-93]},{"ply":32,"player":"ai","action":24,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[9,20,21,34,35,43,45,55],"ai":[11,13,27,28,29,42,44,47]},"scoresAfter":[-52,-85]},{"ply":33,"player":"human","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[9,20,21,34,35,43,45,55],"ai":[3,11,13,28,29,42,44,47]},"scoresAfter":[-36,-85]},{"ply":34,"player":"ai","action":36,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[20,21,32,34,35,43,45,55],"ai":[3,11,13,28,29,42,44,47]},"scoresAfter":[-36,-73]},{"ply":35,"player":"human","action":60,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[20,21,32,34,35,43,45,55],"ai":[3,11,13,14,29,42,44,47]},"scoresAfter":[-30,-73]},{"ply":36,"player":"ai","action":6,"playedCard":3,"placeType":"discard","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[12,20,21,32,34,35,45,55],"ai":[3,11,13,14,29,42,44,47]},"scoresAfter":[-30,-73]},{"ply":37,"player":"human","action":12,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[12,20,21,32,34,35,45,55],"ai":[11,13,14,19,29,42,44,47]},"scoresAfter":[-23,-73]},{"ply":38,"player":"ai","action":36,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[6,12,21,32,34,35,45,55],"ai":[11,13,14,19,29,42,44,47]},"scoresAfter":[-23,-67]},{"ply":39,"player":"human","action":24,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[6,12,21,32,34,35,45,55],"ai":[11,13,14,29,31,42,44,47]},"scoresAfter":[-15,-67]},{"ply":40,"player":"ai","action":36,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[6,12,30,32,34,35,45,55],"ai":[11,13,14,29,31,42,44,47]},"scoresAfter":[-15,-51]},{"ply":41,"player":"human","action":24,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[6,12,30,32,34,35,45,55],"ai":[11,13,14,22,31,42,44,47]},"scoresAfter":[-30,-51]},{"ply":42,"player":"ai","action":36,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[6,12,32,34,35,45,51,55],"ai":[11,13,14,22,31,42,44,47]},"scoresAfter":[-30,-42]},{"ply":43,"player":"human","action":29,"playedCard":32,"placeType":"play","drawSource":"discard_4","drawnCard":49,"handsBefore":{"human":[6,12,32,34,35,45,51,55],"ai":[11,13,14,23,31,42,44,47]},"scoresAfter":[-23,-42]},{"ply":44,"player":"ai","action":40,"playedCard":23,"placeType":"play","drawSource":"discard_3","drawnCard":36,"handsBefore":{"human":[6,12,34,35,45,49,51,55],"ai":[11,13,14,23,31,42,44,47]},"scoresAfter":[-23,-32]},{"ply":45,"player":"human","action":29,"playedCard":34,"placeType":"play","drawSource":"discard_4","drawnCard":48,"handsBefore":{"human":[6,12,34,35,45,49,51,55],"ai":[11,13,14,31,36,42,44,47]},"scoresAfter":[-14,-32]},{"ply":46,"player":"ai","action":37,"playedCard":31,"placeType":"play","drawSource":"discard_0","drawnCard":3,"handsBefore":{"human":[6,12,35,45,48,49,51,55],"ai":[11,13,14,31,36,42,44,47]},"scoresAfter":[-14,-8]},{"ply":47,"player":"human","action":24,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[6,12,35,45,48,49,51,55],"ai":[3,11,13,14,36,42,44,47]},"scoresAfter":[-4,-8]},{"ply":48,"player":"ai","action":85,"playedCard":47,"placeType":"play","drawSource":"discard_0","drawnCard":1,"handsBefore":{"human":[6,12,33,45,48,49,51,55],"ai":[3,11,13,14,36,42,44,47]},"scoresAfter":[-4,22]},{"ply":49,"player":"human","action":36,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[6,12,33,45,48,49,51,55],"ai":[1,3,11,13,14,36,42,44]},"scoresAfter":[4,22]},{"ply":50,"player":"ai","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[6,8,12,33,48,49,51,55],"ai":[1,3,11,13,14,36,42,44]},"scoresAfter":[4,-18]}],"finalScores":[4,-18],"outcome":"YOU WIN","finalState":{"deckOrder":[0,50,24,45,43,9,5,4,25,40,54,17,16,46,41,38,53,28,21,52,57,37,20,26,35,13,48,47,49,58,39,18,56,27,15,29,2,59,1,36,42,34,11,7,44,55,3,32,14,12,19,6,31,30,22,51,23,33,8,10],"drawPtr":60,"cardLoc":[3,4,5,2,3,3,1,3,1,3,2,2,1,2,2,3,4,4,4,4,3,3,4,4,4,4,4,4,4,4,3,4,3,1,3,3,2,4,4,3,4,4,2,3,2,3,4,4,1,1,3,1,4,3,4,1,3,3,4,4],"handPublic":[false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,true,true,false,false,false,false,false,false,false,false,false,false],"colTop":[[8,8,10,8,8],[0,10,6,10,10]],"colHandshakes":[[1,0,0,0,1],[1,0,3,2,0]],"colLength":[[5,3,4,3,4],[1,6,7,6,4]],"piles":[[2],[],[],[],[]],"toMove":0,"stepCount":50,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"43dfa974-a87e-412b-b12b-fd0a06edbacc","seed":"bt8pmx","startedAt":"2026-07-14T16:20:31.655Z","finishedAt":"2026-07-14T16:22:45.519Z","initialDeckOrder":[8,51,15,44,19,28,12,37,36,39,55,29,27,30,3,34,5,20,58,1,31,2,45,6,13,41,9,14,25,59,21,52,43,17,42,24,10,18,40,49,22,50,4,0,35,33,57,46,47,26,11,54,53,16,38,23,7,56,48,32],"moves":[{"ply":1,"player":"human","action":12,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[8,12,15,19,28,37,44,51],"ai":[3,27,29,30,34,36,39,55]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":78,"playedCard":39,"placeType":"discard","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[5,8,15,19,28,37,44,51],"ai":[3,27,29,30,34,36,39,55]},"scoresAfter":[-40,0]},{"ply":3,"player":"human","action":24,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[5,8,15,19,28,37,44,51],"ai":[3,20,27,29,30,34,36,55]},"scoresAfter":[-36,0]},{"ply":4,"player":"ai","action":84,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[5,8,19,28,37,44,51,58],"ai":[3,20,27,29,30,34,36,55]},"scoresAfter":[-36,-14]},{"ply":5,"player":"human","action":52,"playedCard":37,"placeType":"play","drawSource":"discard_3","drawnCard":39,"handsBefore":{"human":[5,8,19,28,37,44,51,58],"ai":[1,3,20,27,29,30,34,36]},"scoresAfter":[-76,-14]},{"ply":6,"player":"ai","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[5,8,19,28,39,44,51,58],"ai":[1,3,20,27,29,30,34,36]},"scoresAfter":[-76,-14]},{"ply":7,"player":"human","action":48,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[5,8,19,28,39,44,51,58],"ai":[3,20,27,29,30,31,34,36]},"scoresAfter":[-72,-14]},{"ply":8,"player":"ai","action":90,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[2,5,8,19,28,44,51,58],"ai":[3,20,27,29,30,31,34,36]},"scoresAfter":[-72,-14]},{"ply":9,"player":"human","action":0,"playedCard":2,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[2,5,8,19,28,44,51,58],"ai":[3,20,27,29,30,31,34,45]},"scoresAfter":[-112,-14]},{"ply":10,"player":"ai","action":12,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[5,6,8,19,28,44,51,58],"ai":[3,20,27,29,30,31,34,45]},"scoresAfter":[-112,-27]},{"ply":11,"player":"human","action":79,"playedCard":51,"placeType":"discard","drawSource":"discard_0","drawnCard":1,"handsBefore":{"human":[5,6,8,19,28,44,51,58],"ai":[3,13,27,29,30,31,34,45]},"scoresAfter":[-112,-27]},{"ply":12,"player":"ai","action":18,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[1,5,6,8,19,28,44,58],"ai":[3,13,27,29,30,31,34,45]},"scoresAfter":[-112,-27]},{"ply":13,"player":"human","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[1,5,6,8,19,28,44,58],"ai":[3,27,29,30,31,34,41,45]},"scoresAfter":[-132,-27]},{"ply":14,"player":"ai","action":12,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[5,6,8,9,19,28,44,58],"ai":[3,27,29,30,31,34,41,45]},"scoresAfter":[-132,-45]},{"ply":15,"player":"human","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[5,6,8,9,19,28,44,58],"ai":[3,14,29,30,31,34,41,45]},"scoresAfter":[-120,-45]},{"ply":16,"player":"ai","action":18,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[6,8,9,19,25,28,44,58],"ai":[3,14,29,30,31,34,41,45]},"scoresAfter":[-120,-45]},{"ply":17,"player":"human","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[6,8,9,19,25,28,44,58],"ai":[3,29,30,31,34,41,45,59]},"scoresAfter":[-105,-45]},{"ply":18,"player":"ai","action":12,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[8,9,19,21,25,28,44,58],"ai":[3,29,30,31,34,41,45,59]},"scoresAfter":[-105,-41]},{"ply":19,"player":"human","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[8,9,19,21,25,28,44,58],"ai":[3,30,31,34,41,45,52,59]},"scoresAfter":[-84,-41]},{"ply":20,"player":"ai","action":6,"playedCard":3,"placeType":"discard","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[9,19,21,25,28,43,44,58],"ai":[3,30,31,34,41,45,52,59]},"scoresAfter":[-84,-41]},{"ply":21,"player":"human","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[9,19,21,25,28,43,44,58],"ai":[17,30,31,34,41,45,52,59]},"scoresAfter":[-60,-41]},{"ply":22,"player":"ai","action":12,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[19,21,25,28,42,43,44,58],"ai":[17,30,31,34,41,45,52,59]},"scoresAfter":[-60,-36]},{"ply":23,"player":"human","action":48,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[19,21,25,28,42,43,44,58],"ai":[17,24,31,34,41,45,52,59]},"scoresAfter":[-50,-36]},{"ply":24,"player":"ai","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[10,19,21,25,28,43,44,58],"ai":[17,24,31,34,41,45,52,59]},"scoresAfter":[-50,-26]},{"ply":25,"player":"human","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[10,19,21,25,28,43,44,58],"ai":[17,18,24,31,34,41,45,52]},"scoresAfter":[-23,-26]},{"ply":26,"player":"ai","action":60,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[19,21,25,28,40,43,44,58],"ai":[17,18,24,31,34,41,45,52]},"scoresAfter":[-23,-42]},{"ply":27,"player":"human","action":54,"playedCard":40,"placeType":"discard","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[19,21,25,28,40,43,44,58],"ai":[17,18,24,31,34,45,49,52]},"scoresAfter":[-23,-42]},{"ply":28,"player":"ai","action":36,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[19,21,22,25,28,43,44,58],"ai":[17,18,24,31,34,45,49,52]},"scoresAfter":[-23,-36]},{"ply":29,"player":"human","action":60,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[19,21,22,25,28,43,44,58],"ai":[17,18,24,34,45,49,50,52]},"scoresAfter":[-11,-36]},{"ply":30,"player":"ai","action":6,"playedCard":17,"placeType":"discard","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[4,19,21,22,25,28,44,58],"ai":[17,18,24,34,45,49,50,52]},"scoresAfter":[-11,-36]},{"ply":31,"player":"human","action":74,"playedCard":44,"placeType":"play","drawSource":"discard_1","drawnCard":17,"handsBefore":{"human":[4,19,21,22,25,28,44,58],"ai":[0,18,24,34,45,49,50,52]},"scoresAfter":[3,-36]},{"ply":32,"player":"ai","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[4,17,19,21,22,25,28,58],"ai":[0,18,24,34,45,49,50,52]},"scoresAfter":[3,-36]},{"ply":33,"player":"human","action":12,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[4,17,19,21,22,25,28,58],"ai":[18,24,34,35,45,49,50,52]},"scoresAfter":[11,-36]},{"ply":34,"player":"ai","action":78,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[4,19,21,22,25,28,33,58],"ai":[18,24,34,35,45,49,50,52]},"scoresAfter":[11,-36]},{"ply":35,"player":"human","action":12,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[4,19,21,22,25,28,33,58],"ai":[18,24,34,35,45,49,52,57]},"scoresAfter":[23,-36]},{"ply":36,"player":"ai","action":78,"playedCard":52,"placeType":"discard","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[4,21,22,25,28,33,46,58],"ai":[18,24,34,35,45,49,52,57]},"scoresAfter":[23,-36]},{"ply":37,"player":"human","action":6,"playedCard":4,"placeType":"discard","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[4,21,22,25,28,33,46,58],"ai":[18,24,34,35,45,47,49,57]},"scoresAfter":[23,-36]},{"ply":38,"player":"ai","action":90,"playedCard":57,"placeType":"discard","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[21,22,25,26,28,33,46,58],"ai":[18,24,34,35,45,47,49,57]},"scoresAfter":[23,-36]},{"ply":39,"player":"human","action":30,"playedCard":25,"placeType":"discard","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[21,22,25,26,28,33,46,58],"ai":[11,18,24,34,35,45,47,49]},"scoresAfter":[23,-36]},{"ply":40,"player":"ai","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[21,22,26,28,33,46,54,58],"ai":[11,18,24,34,35,45,47,49]},"scoresAfter":[23,-46]},{"ply":41,"player":"human","action":30,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[21,22,26,28,33,46,54,58],"ai":[18,24,34,35,45,47,49,53]},"scoresAfter":[23,-46]},{"ply":42,"player":"ai","action":24,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[16,21,22,28,33,46,54,58],"ai":[18,24,34,35,45,47,49,53]},"scoresAfter":[23,-37]},{"ply":43,"player":"human","action":17,"playedCard":21,"placeType":"play","drawSource":"discard_4","drawnCard":57,"handsBefore":{"human":[16,21,22,28,33,46,54,58],"ai":[18,24,35,38,45,47,49,53]},"scoresAfter":[39,-37]},{"ply":44,"player":"ai","action":24,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[16,22,28,33,46,54,57,58],"ai":[18,24,35,38,45,47,49,53]},"scoresAfter":[39,-27]},{"ply":45,"player":"human","action":48,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[16,22,28,33,46,54,57,58],"ai":[18,23,24,38,45,47,49,53]},"scoresAfter":[57,-27]},{"ply":46,"player":"ai","action":12,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[7,16,22,28,33,54,57,58],"ai":[18,23,24,38,45,47,49,53]},"scoresAfter":[57,-17]},{"ply":47,"player":"human","action":24,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[7,16,22,28,33,54,57,58],"ai":[18,24,38,45,47,49,53,56]},"scoresAfter":[75,-17]},{"ply":48,"player":"ai","action":48,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[7,16,28,33,48,54,57,58],"ai":[18,24,38,45,47,49,53,56]},"scoresAfter":[75,-7]}],"finalScores":[75,-7],"outcome":"YOU WIN","finalState":{"deckOrder":[8,51,15,44,19,28,12,37,36,39,55,29,27,30,3,34,5,20,58,1,31,2,45,6,13,41,9,14,25,59,21,52,43,17,42,24,10,18,40,49,22,50,4,0,35,33,57,46,47,26,11,54,53,16,38,23,7,56,48,32],"drawPtr":60,"cardLoc":[5,3,3,5,5,3,3,1,3,3,3,4,3,5,5,3,1,3,2,3,4,3,3,4,2,5,5,4,1,4,4,4,2,1,4,4,5,3,2,3,5,4,3,3,3,2,3,4,1,2,5,5,5,2,1,4,2,1,1,4],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false],"colTop":[[9,9,0,9,0],[10,10,10,10,10]],"colHandshakes":[[2,1,0,1,0],[0,0,0,0,0]],"colLength":[[7,6,0,6,0],[1,2,6,2,2]],"piles":[[3,0,4],[13,14],[25,26],[36,40],[51,50,52]],"toMove":0,"stepCount":48,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"d36bdd65-2dd7-426f-8edd-ddc10714fcb6","seed":"ge2iyt","startedAt":"2026-07-14T16:22:46.435Z","finishedAt":"2026-07-14T16:24:41.977Z","initialDeckOrder":[34,14,19,25,27,28,37,41,1,57,50,58,13,20,30,3,40,59,29,38,2,9,52,18,22,46,31,17,10,16,55,12,47,26,8,43,36,5,32,7,45,48,4,6,54,21,24,35,15,49,44,51,42,23,33,56,53,39,0,11],"moves":[{"ply":1,"player":"human","action":24,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[14,19,25,27,28,34,37,41],"ai":[1,3,13,20,30,50,57,58]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":60,"playedCard":50,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[14,19,27,28,34,37,40,41],"ai":[1,3,13,20,30,50,57,58]},"scoresAfter":[-40,-40]},{"ply":3,"player":"human","action":0,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[14,19,27,28,34,37,40,41],"ai":[1,3,13,20,30,57,58,59]},"scoresAfter":[-80,-40]},{"ply":4,"player":"ai","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[19,27,28,29,34,37,40,41],"ai":[1,3,13,20,30,57,58,59]},"scoresAfter":[-80,-40]},{"ply":5,"player":"human","action":12,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[19,27,28,29,34,37,40,41],"ai":[3,13,20,30,38,57,58,59]},"scoresAfter":[-76,-40]},{"ply":6,"player":"ai","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[2,19,28,29,34,37,40,41],"ai":[3,13,20,30,38,57,58,59]},"scoresAfter":[-76,-58]},{"ply":7,"player":"human","action":24,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[2,19,28,29,34,37,40,41],"ai":[9,13,20,30,38,57,58,59]},"scoresAfter":[-70,-58]},{"ply":8,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[2,19,29,34,37,40,41,52],"ai":[9,13,20,30,38,57,58,59]},"scoresAfter":[-70,-50]},{"ply":9,"player":"human","action":24,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[2,19,29,34,37,40,41,52],"ai":[13,18,20,30,38,57,58,59]},"scoresAfter":[-62,-50]},{"ply":10,"player":"ai","action":0,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[2,19,22,34,37,40,41,52],"ai":[13,18,20,30,38,57,58,59]},"scoresAfter":[-62,-90]},{"ply":11,"player":"human","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[2,19,22,34,37,40,41,52],"ai":[18,20,30,38,46,57,58,59]},"scoresAfter":[-62,-90]},{"ply":12,"player":"ai","action":24,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[19,22,31,34,37,40,41,52],"ai":[18,20,30,38,46,57,58,59]},"scoresAfter":[-62,-105]},{"ply":13,"player":"human","action":24,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[19,22,31,34,37,40,41,52],"ai":[17,18,20,38,46,57,58,59]},"scoresAfter":[-50,-105]},{"ply":14,"player":"ai","action":0,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[10,19,22,34,37,40,41,52],"ai":[17,18,20,38,46,57,58,59]},"scoresAfter":[-50,-97]},{"ply":15,"player":"human","action":48,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[10,19,22,34,37,40,41,52],"ai":[16,18,20,38,46,57,58,59]},"scoresAfter":[-90,-97]},{"ply":16,"player":"ai","action":12,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[10,19,22,34,40,41,52,55],"ai":[16,18,20,38,46,57,58,59]},"scoresAfter":[-90,-87]},{"ply":17,"player":"human","action":48,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[10,19,22,34,40,41,52,55],"ai":[12,16,20,38,46,57,58,59]},"scoresAfter":[-84,-87]},{"ply":18,"player":"ai","action":24,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[10,19,22,34,41,47,52,55],"ai":[12,16,20,38,46,57,58,59]},"scoresAfter":[-84,-73]},{"ply":19,"player":"human","action":48,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[10,19,22,34,41,47,52,55],"ai":[12,16,26,38,46,57,58,59]},"scoresAfter":[-76,-73]},{"ply":20,"player":"ai","action":6,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[8,10,19,22,34,47,52,55],"ai":[12,16,26,38,46,57,58,59]},"scoresAfter":[-76,-73]},{"ply":21,"player":"human","action":24,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[8,10,19,22,34,47,52,55],"ai":[16,26,38,43,46,57,58,59]},"scoresAfter":[-64,-73]},{"ply":22,"player":"ai","action":6,"playedCard":16,"placeType":"discard","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[8,10,22,34,36,47,52,55],"ai":[16,26,38,43,46,57,58,59]},"scoresAfter":[-64,-73]},{"ply":23,"player":"human","action":54,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[8,10,22,34,36,47,52,55],"ai":[5,26,38,43,46,57,58,59]},"scoresAfter":[-64,-73]},{"ply":24,"player":"ai","action":28,"playedCard":38,"placeType":"play","drawSource":"discard_3","drawnCard":36,"handsBefore":{"human":[8,10,22,32,34,47,52,55],"ai":[5,26,38,43,46,57,58,59]},"scoresAfter":[-64,-113]},{"ply":25,"player":"human","action":36,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[8,10,22,32,34,47,52,55],"ai":[5,26,36,43,46,57,58,59]},"scoresAfter":[-50,-113]},{"ply":26,"player":"ai","action":19,"playedCard":26,"placeType":"discard","drawSource":"discard_0","drawnCard":2,"handsBefore":{"human":[7,8,10,22,34,47,52,55],"ai":[5,26,36,43,46,57,58,59]},"scoresAfter":[-50,-113]},{"ply":27,"player":"human","action":48,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[7,8,10,22,34,47,52,55],"ai":[2,5,36,43,46,57,58,59]},"scoresAfter":[-32,-113]},{"ply":28,"player":"ai","action":24,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[7,8,10,22,45,47,52,55],"ai":[2,5,36,43,46,57,58,59]},"scoresAfter":[-32,-133]},{"ply":29,"player":"human","action":48,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[7,8,10,22,45,47,52,55],"ai":[2,5,43,46,48,57,58,59]},"scoresAfter":[-16,-133]},{"ply":30,"player":"ai","action":24,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[4,7,8,10,22,47,52,55],"ai":[2,5,43,46,48,57,58,59]},"scoresAfter":[-16,-115]},{"ply":31,"player":"human","action":61,"playedCard":47,"placeType":"play","drawSource":"discard_0","drawnCard":1,"handsBefore":{"human":[4,7,8,10,22,47,52,55],"ai":[2,5,6,46,48,57,58,59]},"scoresAfter":[4,-115]},{"ply":32,"player":"ai","action":36,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[1,4,7,8,10,22,52,55],"ai":[2,5,6,46,48,57,58,59]},"scoresAfter":[4,-88]},{"ply":33,"player":"human","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[1,4,7,8,10,22,52,55],"ai":[2,5,6,48,54,57,58,59]},"scoresAfter":[-36,-88]},{"ply":34,"player":"ai","action":36,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[4,7,8,10,21,22,52,55],"ai":[2,5,6,48,54,57,58,59]},"scoresAfter":[-36,-108]},{"ply":35,"player":"human","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[4,7,8,10,21,22,52,55],"ai":[2,5,6,24,54,57,58,59]},"scoresAfter":[-30,-108]},{"ply":36,"player":"ai","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[7,8,10,21,22,35,52,55],"ai":[2,5,6,24,54,57,58,59]},"scoresAfter":[-30,-108]},{"ply":37,"player":"human","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[7,8,10,21,22,35,52,55],"ai":[5,6,15,24,54,57,58,59]},"scoresAfter":[-18,-108]},{"ply":38,"player":"ai","action":48,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[8,10,21,22,35,49,52,55],"ai":[5,6,15,24,54,57,58,59]},"scoresAfter":[-18,-93]},{"ply":39,"player":"human","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[8,10,21,22,35,49,52,55],"ai":[5,6,15,24,44,57,58,59]},"scoresAfter":[-4,-93]},{"ply":40,"player":"ai","action":60,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[10,21,22,35,49,51,52,55],"ai":[5,6,15,24,44,57,58,59]},"scoresAfter":[-4,-69]},{"ply":41,"player":"human","action":36,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[10,21,22,35,49,51,52,55],"ai":[5,6,15,24,42,44,58,59]},"scoresAfter":[36,-69]},{"ply":42,"player":"ai","action":72,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[10,21,22,23,49,51,52,55],"ai":[5,6,15,24,42,44,58,59]},"scoresAfter":[36,-42]},{"ply":43,"player":"human","action":12,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[10,21,22,23,49,51,52,55],"ai":[5,6,15,24,33,42,44,59]},"scoresAfter":[52,-42]},{"ply":44,"player":"ai","action":48,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[10,22,23,49,51,52,55,56],"ai":[5,6,15,24,33,42,44,59]},"scoresAfter":[52,-34]},{"ply":45,"player":"human","action":12,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[10,22,23,49,51,52,55,56],"ai":[5,6,15,24,42,44,53,59]},"scoresAfter":[70,-34]},{"ply":46,"player":"ai","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[10,23,39,49,51,52,55,56],"ai":[5,6,15,24,42,44,53,59]},"scoresAfter":[70,-4]},{"ply":47,"player":"human","action":12,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[10,23,39,49,51,52,55,56],"ai":[0,5,6,15,24,42,44,53]},"scoresAfter":[90,-4]}],"finalScores":[90,-4],"outcome":"YOU WIN","finalState":{"deckOrder":[34,14,19,25,27,28,37,41,1,57,50,58,13,20,30,3,40,59,29,38,2,9,52,18,22,46,31,17,10,16,55,12,47,26,8,43,36,5,32,7,45,48,4,6,54,21,24,35,15,49,44,51,42,23,33,56,53,39,0,11],"drawPtr":60,"cardLoc":[2,3,5,4,3,2,2,3,3,4,1,1,5,4,3,2,5,4,4,3,4,3,3,3,2,3,5,3,3,3,4,3,3,4,3,3,4,3,4,1,3,3,2,4,2,3,4,3,4,1,4,1,1,2,4,1,1,4,4,4],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[7,10,10,10,0],[8,7,8,9,10]],"colHandshakes":[[1,1,1,1,0],[0,1,0,2,2]],"colLength":[[4,5,8,5,0],[2,4,2,4,6]],"piles":[[2],[12,16],[26],[],[]],"toMove":1,"stepCount":47,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"38b8875c-5a32-4211-b073-ea2cc3aaba7e","seed":"urze6h","startedAt":"2026-07-14T16:24:42.629Z","finishedAt":"2026-07-14T16:27:12.906Z","initialDeckOrder":[17,43,32,38,47,58,30,49,27,22,48,39,6,59,35,50,13,46,41,53,54,23,37,12,18,29,31,3,14,24,33,7,40,28,0,51,8,10,45,20,19,15,36,11,4,34,16,5,1,25,9,2,21,44,56,52,42,57,26,55],"moves":[{"ply":1,"player":"human","action":36,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[17,30,32,38,43,47,49,58],"ai":[6,22,27,35,39,48,50,59]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":48,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[13,17,30,32,43,47,49,58],"ai":[6,22,27,35,39,48,50,59]},"scoresAfter":[-40,-18]},{"ply":3,"player":"human","action":72,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[13,17,30,32,43,47,49,58],"ai":[6,22,27,35,46,48,50,59]},"scoresAfter":[-80,-18]},{"ply":4,"player":"ai","action":60,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[13,17,30,32,41,43,47,58],"ai":[6,22,27,35,46,48,50,59]},"scoresAfter":[-80,-58]},{"ply":5,"player":"human","action":6,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[13,17,30,32,41,43,47,58],"ai":[6,22,27,35,46,50,53,59]},"scoresAfter":[-80,-58]},{"ply":6,"player":"ai","action":60,"playedCard":50,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[17,30,32,41,43,47,54,58],"ai":[6,22,27,35,46,50,53,59]},"scoresAfter":[-80,-78]},{"ply":7,"player":"human","action":36,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[17,30,32,41,43,47,54,58],"ai":[6,22,23,27,35,46,53,59]},"scoresAfter":[-72,-78]},{"ply":8,"player":"ai","action":74,"playedCard":53,"placeType":"play","drawSource":"discard_1","drawnCard":13,"handsBefore":{"human":[17,30,32,37,43,47,54,58],"ai":[6,22,23,27,35,46,53,59]},"scoresAfter":[-72,-66]},{"ply":9,"player":"human","action":42,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[17,30,32,37,43,47,54,58],"ai":[6,13,22,23,27,35,46,59]},"scoresAfter":[-72,-66]},{"ply":10,"player":"ai","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[12,17,30,32,43,47,54,58],"ai":[6,13,22,23,27,35,46,59]},"scoresAfter":[-72,-81]},{"ply":11,"player":"human","action":6,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[12,17,30,32,43,47,54,58],"ai":[13,18,22,23,27,35,46,59]},"scoresAfter":[-72,-81]},{"ply":12,"player":"ai","action":2,"playedCard":13,"placeType":"play","drawSource":"discard_1","drawnCard":12,"handsBefore":{"human":[17,29,30,32,43,47,54,58],"ai":[13,18,22,23,27,35,46,59]},"scoresAfter":[-72,-121]},{"ply":13,"player":"human","action":12,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[17,29,30,32,43,47,54,58],"ai":[12,18,22,23,27,35,46,59]},"scoresAfter":[-88,-121]},{"ply":14,"player":"ai","action":0,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[17,30,31,32,43,47,54,58],"ai":[12,18,22,23,27,35,46,59]},"scoresAfter":[-88,-141]},{"ply":15,"player":"human","action":12,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[17,30,31,32,43,47,54,58],"ai":[3,18,22,23,27,35,46,59]},"scoresAfter":[-83,-141]},{"ply":16,"player":"ai","action":48,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[14,17,31,32,43,47,54,58],"ai":[3,18,22,23,27,35,46,59]},"scoresAfter":[-83,-159]},{"ply":17,"player":"human","action":24,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[14,17,31,32,43,47,54,58],"ai":[3,18,22,23,24,35,46,59]},"scoresAfter":[-77,-159]},{"ply":18,"player":"ai","action":60,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[14,17,32,33,43,47,54,58],"ai":[3,18,22,23,24,35,46,59]},"scoresAfter":[-77,-149]},{"ply":19,"player":"human","action":24,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[14,17,32,33,43,47,54,58],"ai":[3,7,18,22,23,24,46,59]},"scoresAfter":[-70,-149]},{"ply":20,"player":"ai","action":72,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[14,17,33,40,43,47,54,58],"ai":[3,7,18,22,23,24,46,59]},"scoresAfter":[-70,-140]},{"ply":21,"player":"human","action":24,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[14,17,33,40,43,47,54,58],"ai":[3,7,18,22,23,24,28,59]},"scoresAfter":[-62,-140]},{"ply":22,"player":"ai","action":66,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[0,14,17,40,43,47,54,58],"ai":[3,7,18,22,23,24,28,59]},"scoresAfter":[-62,-140]},{"ply":23,"player":"human","action":42,"playedCard":40,"placeType":"discard","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[0,14,17,40,43,47,54,58],"ai":[3,7,18,22,23,28,51,59]},"scoresAfter":[-62,-140]},{"ply":24,"player":"ai","action":6,"playedCard":3,"placeType":"discard","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[0,8,14,17,43,47,54,58],"ai":[3,7,18,22,23,28,51,59]},"scoresAfter":[-62,-140]},{"ply":25,"player":"human","action":30,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[0,8,14,17,43,47,54,58],"ai":[7,10,18,22,23,28,51,59]},"scoresAfter":[-62,-140]},{"ply":26,"player":"ai","action":2,"playedCard":7,"placeType":"play","drawSource":"discard_1","drawnCard":14,"handsBefore":{"human":[0,8,17,43,45,47,54,58],"ai":[7,10,18,22,23,28,51,59]},"scoresAfter":[-62,-134]},{"ply":27,"player":"human","action":36,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[0,8,17,43,45,47,54,58],"ai":[10,14,18,22,23,28,51,59]},"scoresAfter":[-50,-134]},{"ply":28,"player":"ai","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[0,8,17,20,45,47,54,58],"ai":[10,14,18,22,23,28,51,59]},"scoresAfter":[-50,-125]},{"ply":29,"player":"human","action":48,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[0,8,17,20,45,47,54,58],"ai":[14,18,19,22,23,28,51,59]},"scoresAfter":[-34,-125]},{"ply":30,"player":"ai","action":0,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[0,8,15,17,20,47,54,58],"ai":[14,18,19,22,23,28,51,59]},"scoresAfter":[-34,-145]},{"ply":31,"player":"human","action":60,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[0,8,15,17,20,47,54,58],"ai":[18,19,22,23,28,36,51,59]},"scoresAfter":[-14,-145]},{"ply":32,"player":"ai","action":66,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[0,8,11,15,17,20,54,58],"ai":[18,19,22,23,28,36,51,59]},"scoresAfter":[-14,-145]},{"ply":33,"player":"human","action":1,"playedCard":0,"placeType":"play","drawSource":"discard_0","drawnCard":3,"handsBefore":{"human":[0,8,11,15,17,20,54,58],"ai":[4,18,19,22,23,28,51,59]},"scoresAfter":[-54,-145]},{"ply":34,"player":"ai","action":78,"playedCard":51,"placeType":"discard","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[3,8,11,15,17,20,54,58],"ai":[4,18,19,22,23,28,51,59]},"scoresAfter":[-54,-145]},{"ply":35,"player":"human","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[3,8,11,15,17,20,54,58],"ai":[4,18,19,22,23,28,34,59]},"scoresAfter":[-50,-145]},{"ply":36,"player":"ai","action":78,"playedCard":34,"placeType":"discard","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[8,11,15,16,17,20,54,58],"ai":[4,18,19,22,23,28,34,59]},"scoresAfter":[-50,-145]},{"ply":37,"player":"human","action":5,"playedCard":8,"placeType":"play","drawSource":"discard_4","drawnCard":51,"handsBefore":{"human":[8,11,15,16,17,20,54,58],"ai":[4,5,18,19,22,23,28,59]},"scoresAfter":[-36,-145]},{"ply":38,"player":"ai","action":24,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[11,15,16,17,20,51,54,58],"ai":[4,5,18,19,22,23,28,59]},"scoresAfter":[-36,-125]},{"ply":39,"player":"human","action":60,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[11,15,16,17,20,51,54,58],"ai":[1,4,5,19,22,23,28,59]},"scoresAfter":[-32,-125]},{"ply":40,"player":"ai","action":33,"playedCard":5,"placeType":"discard","drawSource":"discard_2","drawnCard":34,"handsBefore":{"human":[11,15,16,17,20,25,54,58],"ai":[1,4,5,19,22,23,28,59]},"scoresAfter":[-32,-125]},{"ply":41,"player":"human","action":72,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[11,15,16,17,20,25,54,58],"ai":[1,4,19,22,23,28,34,59]},"scoresAfter":[-22,-125]},{"ply":42,"player":"ai","action":24,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[9,11,15,16,17,20,25,58],"ai":[1,4,19,22,23,28,34,59]},"scoresAfter":[-22,-101]},{"ply":43,"player":"human","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[9,11,15,16,17,20,25,58],"ai":[1,2,4,22,23,28,34,59]},"scoresAfter":[-6,-101]},{"ply":44,"player":"ai","action":36,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[11,15,16,17,20,21,25,58],"ai":[1,2,4,22,23,28,34,59]},"scoresAfter":[-6,-65]},{"ply":45,"player":"human","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[11,15,16,17,20,21,25,58],"ai":[1,2,4,23,28,34,44,59]},"scoresAfter":[14,-65]},{"ply":46,"player":"ai","action":36,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[15,16,17,20,21,25,56,58],"ai":[1,2,4,23,28,34,44,59]},"scoresAfter":[14,-25]},{"ply":47,"player":"human","action":72,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[15,16,17,20,21,25,56,58],"ai":[1,2,4,28,34,44,52,59]},"scoresAfter":[28,-25]},{"ply":48,"player":"ai","action":42,"playedCard":28,"placeType":"discard","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[15,16,17,20,21,25,42,58],"ai":[1,2,4,28,34,44,52,59]},"scoresAfter":[28,-25]},{"ply":49,"player":"human","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[15,16,17,20,21,25,42,58],"ai":[1,2,4,34,44,52,57,59]},"scoresAfter":[46,-25]},{"ply":50,"player":"ai","action":73,"playedCard":57,"placeType":"play","drawSource":"discard_0","drawnCard":5,"handsBefore":{"human":[15,16,17,20,21,25,26,42],"ai":[1,2,4,34,44,52,57,59]},"scoresAfter":[46,-1]},{"ply":51,"player":"human","action":78,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[15,16,17,20,21,25,26,42],"ai":[1,2,4,5,34,44,52,59]},"scoresAfter":[46,-1]}],"finalScores":[46,-1],"outcome":"YOU WIN","finalState":{"deckOrder":[17,43,32,38,47,58,30,49,27,22,48,39,6,59,35,50,13,46,41,53,54,23,37,12,18,29,31,3,14,24,33,7,40,28,0,51,8,10,45,20,19,15,36,11,4,34,16,5,1,25,9,2,21,44,56,52,42,57,26,55],"drawPtr":60,"cardLoc":[3,2,2,3,2,2,4,4,3,3,4,3,4,4,4,1,1,1,4,4,1,1,4,4,5,1,5,4,5,3,3,3,3,3,2,4,5,5,3,4,5,3,1,3,2,3,4,3,4,3,4,3,2,4,3,1,3,4,3,2],"handPublic":[false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,0,8,10,9],[9,10,10,9,8]],"colHandshakes":[[1,0,0,1,1],[0,3,0,0,2]],"colLength":[[5,0,5,5,5],[3,7,2,2,4]],"piles":[[],[],[24,28,26],[37,40,36],[]],"toMove":1,"stepCount":51,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"016b38ac-cead-494b-907a-a2d9bad637c2","seed":"6m04gh","startedAt":"2026-07-14T16:27:13.874Z","finishedAt":"2026-07-14T16:29:38.056Z","initialDeckOrder":[35,47,27,52,39,11,22,17,44,55,6,23,15,41,24,21,53,28,14,20,48,10,49,38,29,36,42,7,4,25,40,1,34,33,58,32,31,45,46,13,57,54,50,12,56,0,9,2,19,3,59,18,43,8,37,5,26,30,16,51],"moves":[{"ply":1,"player":"human","action":36,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[11,17,22,27,35,39,47,52],"ai":[6,15,21,23,24,41,44,55]},"scoresAfter":[-18,0]},{"ply":2,"player":"ai","action":78,"playedCard":44,"placeType":"discard","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[11,17,22,35,39,47,52,53],"ai":[6,15,21,23,24,41,44,55]},"scoresAfter":[-18,0]},{"ply":3,"player":"human","action":48,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[11,17,22,35,39,47,52,53],"ai":[6,15,21,23,24,28,41,55]},"scoresAfter":[-36,0]},{"ply":4,"player":"ai","action":84,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[11,14,17,22,35,47,52,53],"ai":[6,15,21,23,24,28,41,55]},"scoresAfter":[-36,-14]},{"ply":5,"player":"human","action":16,"playedCard":14,"placeType":"play","drawSource":"discard_3","drawnCard":44,"handsBefore":{"human":[11,14,17,22,35,47,52,53],"ai":[6,15,20,21,23,24,28,41]},"scoresAfter":[-76,-14]},{"ply":6,"player":"ai","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[11,17,22,35,44,47,52,53],"ai":[6,15,20,21,23,24,28,41]},"scoresAfter":[-76,-29]},{"ply":7,"player":"human","action":12,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[11,17,22,35,44,47,52,53],"ai":[15,20,21,23,24,28,41,48]},"scoresAfter":[-68,-29]},{"ply":8,"player":"ai","action":48,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[10,11,22,35,44,47,52,53],"ai":[15,20,21,23,24,28,41,48]},"scoresAfter":[-68,-69]},{"ply":9,"player":"human","action":78,"playedCard":52,"placeType":"discard","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[10,11,22,35,44,47,52,53],"ai":[15,20,21,23,28,41,48,49]},"scoresAfter":[-68,-69]},{"ply":10,"player":"ai","action":48,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[10,11,22,35,38,44,47,53],"ai":[15,20,21,23,28,41,48,49]},"scoresAfter":[-68,-63]},{"ply":11,"player":"human","action":90,"playedCard":53,"placeType":"discard","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[10,11,22,35,38,44,47,53],"ai":[15,20,21,23,29,41,48,49]},"scoresAfter":[-68,-63]},{"ply":12,"player":"ai","action":60,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[10,11,22,35,36,38,44,47],"ai":[15,20,21,23,29,41,48,49]},"scoresAfter":[-68,-79]},{"ply":13,"player":"human","action":54,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[10,11,22,35,36,38,44,47],"ai":[15,20,21,23,29,42,48,49]},"scoresAfter":[-68,-79]},{"ply":14,"player":"ai","action":60,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[7,10,11,22,35,38,44,47],"ai":[15,20,21,23,29,42,48,49]},"scoresAfter":[-68,-74]},{"ply":15,"player":"human","action":66,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[7,10,11,22,35,38,44,47],"ai":[4,15,20,21,23,29,48,49]},"scoresAfter":[-68,-74]},{"ply":16,"player":"ai","action":90,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[7,10,11,22,25,35,44,47],"ai":[4,15,20,21,23,29,48,49]},"scoresAfter":[-68,-74]},{"ply":17,"player":"human","action":54,"playedCard":25,"placeType":"discard","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[7,10,11,22,25,35,44,47],"ai":[4,15,20,21,23,29,40,48]},"scoresAfter":[-68,-74]},{"ply":18,"player":"ai","action":6,"playedCard":4,"placeType":"discard","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[1,7,10,11,22,35,44,47],"ai":[4,15,20,21,23,29,40,48]},"scoresAfter":[-68,-74]},{"ply":19,"player":"human","action":1,"playedCard":1,"placeType":"play","drawSource":"discard_0","drawnCard":4,"handsBefore":{"human":[1,7,10,11,22,35,44,47],"ai":[15,20,21,23,29,34,40,48]},"scoresAfter":[-108,-74]},{"ply":20,"player":"ai","action":90,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[4,7,10,11,22,35,44,47],"ai":[15,20,21,23,29,34,40,48]},"scoresAfter":[-108,-74]},{"ply":21,"player":"human","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[4,7,10,11,22,35,44,47],"ai":[15,20,21,23,29,33,34,40]},"scoresAfter":[-102,-74]},{"ply":22,"player":"ai","action":3,"playedCard":15,"placeType":"play","drawSource":"discard_2","drawnCard":25,"handsBefore":{"human":[7,10,11,22,35,44,47,58],"ai":[15,20,21,23,29,33,34,40]},"scoresAfter":[-102,-92]},{"ply":23,"player":"human","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[7,10,11,22,35,44,47,58],"ai":[20,21,23,25,29,33,34,40]},"scoresAfter":[-90,-92]},{"ply":24,"player":"ai","action":0,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[10,11,22,32,35,44,47,58],"ai":[20,21,23,25,29,33,34,40]},"scoresAfter":[-90,-85]},{"ply":25,"player":"human","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[10,11,22,32,35,44,47,58],"ai":[21,23,25,29,31,33,34,40]},"scoresAfter":[-72,-85]},{"ply":26,"player":"ai","action":0,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[11,22,32,35,44,45,47,58],"ai":[21,23,25,29,31,33,34,40]},"scoresAfter":[-72,-77]},{"ply":27,"player":"human","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[11,22,32,35,44,45,47,58],"ai":[23,25,29,31,33,34,40,46]},"scoresAfter":[-52,-77]},{"ply":28,"player":"ai","action":0,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[13,22,32,35,44,45,47,58],"ai":[23,25,29,31,33,34,40,46]},"scoresAfter":[-52,-67]},{"ply":29,"player":"human","action":6,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[13,22,32,35,44,45,47,58],"ai":[25,29,31,33,34,40,46,57]},"scoresAfter":[-52,-67]},{"ply":30,"player":"ai","action":6,"playedCard":25,"placeType":"discard","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[22,32,35,44,45,47,54,58],"ai":[25,29,31,33,34,40,46,57]},"scoresAfter":[-52,-67]},{"ply":31,"player":"human","action":0,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[22,32,35,44,45,47,54,58],"ai":[29,31,33,34,40,46,50,57]},"scoresAfter":[-34,-67]},{"ply":32,"player":"ai","action":81,"playedCard":50,"placeType":"discard","drawSource":"discard_2","drawnCard":25,"handsBefore":{"human":[12,32,35,44,45,47,54,58],"ai":[29,31,33,34,40,46,50,57]},"scoresAfter":[-34,-67]},{"ply":33,"player":"human","action":12,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[12,32,35,44,45,47,54,58],"ai":[25,29,31,33,34,40,46,57]},"scoresAfter":[-27,-67]},{"ply":34,"player":"ai","action":84,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[12,35,44,45,47,54,56,58],"ai":[25,29,31,33,34,40,46,57]},"scoresAfter":[-27,-59]},{"ply":35,"player":"human","action":60,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[12,35,44,45,47,54,56,58],"ai":[0,25,29,31,33,34,40,46]},"scoresAfter":[-42,-59]},{"ply":36,"player":"ai","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[9,12,35,44,45,47,56,58],"ai":[0,25,29,31,33,34,40,46]},"scoresAfter":[-42,-59]},{"ply":37,"player":"human","action":72,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[9,12,35,44,45,47,56,58],"ai":[2,25,29,31,33,34,40,46]},"scoresAfter":[-35,-59]},{"ply":38,"player":"ai","action":84,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[9,12,19,35,44,45,47,58],"ai":[2,25,29,31,33,34,40,46]},"scoresAfter":[-35,-50]},{"ply":39,"player":"human","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[9,12,19,35,44,45,47,58],"ai":[2,3,25,29,31,33,34,40]},"scoresAfter":[-26,-50]},{"ply":40,"player":"ai","action":36,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[9,12,19,35,44,45,47,59],"ai":[2,3,25,29,31,33,34,40]},"scoresAfter":[-26,-42]},{"ply":41,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[9,12,19,35,44,45,47,59],"ai":[2,3,18,25,31,33,34,40]},"scoresAfter":[-16,-42]},{"ply":42,"player":"ai","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[9,12,19,35,43,44,45,47],"ai":[2,3,18,25,31,33,34,40]},"scoresAfter":[-16,-42]},{"ply":43,"player":"human","action":36,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[9,12,19,35,43,44,45,47],"ai":[3,8,18,25,31,33,34,40]},"scoresAfter":[-6,-42]},{"ply":44,"player":"ai","action":17,"playedCard":8,"placeType":"play","drawSource":"discard_4","drawnCard":50,"handsBefore":{"human":[9,12,19,37,43,44,45,47],"ai":[3,8,18,25,31,33,34,40]},"scoresAfter":[-6,-35]},{"ply":45,"player":"human","action":48,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[9,12,19,37,43,44,45,47],"ai":[3,18,25,31,33,34,40,50]},"scoresAfter":[0,-35]},{"ply":46,"player":"ai","action":37,"playedCard":31,"placeType":"play","drawSource":"discard_0","drawnCard":2,"handsBefore":{"human":[5,9,12,19,37,44,45,47],"ai":[3,18,25,31,33,34,40,50]},"scoresAfter":[0,-23]},{"ply":47,"player":"human","action":60,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[5,9,12,19,37,44,45,47],"ai":[2,3,18,25,33,34,40,50]},"scoresAfter":[7,-23]},{"ply":48,"player":"ai","action":52,"playedCard":33,"placeType":"play","drawSource":"discard_3","drawnCard":38,"handsBefore":{"human":[5,9,12,19,26,37,45,47],"ai":[2,3,18,25,33,34,40,50]},"scoresAfter":[7,-7]},{"ply":49,"player":"human","action":72,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[5,9,12,19,26,37,45,47],"ai":[2,3,18,25,34,38,40,50]},"scoresAfter":[15,-7]},{"ply":50,"player":"ai","action":52,"playedCard":34,"placeType":"play","drawSource":"discard_3","drawnCard":36,"handsBefore":{"human":[5,9,12,19,26,30,37,47],"ai":[2,3,18,25,34,38,40,50]},"scoresAfter":[15,11]},{"ply":51,"player":"human","action":84,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[5,9,12,19,26,30,37,47],"ai":[2,3,18,25,36,38,40,50]},"scoresAfter":[25,11]},{"ply":52,"player":"ai","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[5,9,12,16,19,26,30,37],"ai":[2,3,18,25,36,38,40,50]},"scoresAfter":[25,11]}],"finalScores":[25,11],"outcome":"YOU WIN","finalState":{"deckOrder":[35,47,27,52,39,11,22,17,44,55,6,23,15,41,24,21,53,28,14,20,48,10,49,38,29,36,42,7,4,25,40,1,34,33,58,32,31,45,46,13,57,54,50,12,56,0,9,2,19,3,59,18,43,8,37,5,26,30,16,51],"drawPtr":60,"cardLoc":[5,3,5,2,3,1,4,3,4,1,3,3,1,5,3,4,1,3,2,1,4,4,3,4,4,2,1,3,4,4,1,4,3,4,4,3,2,1,2,3,2,4,4,3,3,3,4,3,5,5,2,2,5,5,3,4,3,4,3,3],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,true,false,true,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false],"colTop":[[10,9,10,10,10],[7,10,9,9,8]],"colHandshakes":[[1,1,0,0,0],[0,0,1,0,0]],"colLength":[[5,3,3,5,4],[2,4,6,3,2]],"piles":[[0,2],[13],[],[],[52,53,49,48]],"toMove":0,"stepCount":52,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"7964b026-d140-4049-8235-965f90d03c49","seed":"eksimd","startedAt":"2026-07-14T16:29:38.893Z","finishedAt":"2026-07-14T16:31:02.090Z","initialDeckOrder":[40,19,23,24,44,53,35,55,50,10,41,30,15,36,18,32,25,16,39,45,54,31,12,4,14,8,46,2,58,34,37,20,0,47,7,3,57,26,56,59,43,22,38,51,13,27,42,52,9,1,21,28,48,5,33,6,49,17,11,29],"moves":[{"ply":1,"player":"human","action":24,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[19,23,24,35,40,44,53,55],"ai":[10,15,18,30,32,36,41,50]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":12,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[19,23,25,35,40,44,53,55],"ai":[10,15,18,30,32,36,41,50]},"scoresAfter":[-40,-18]},{"ply":3,"player":"human","action":24,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[19,23,25,35,40,44,53,55],"ai":[10,16,18,30,32,36,41,50]},"scoresAfter":[-60,-18]},{"ply":4,"player":"ai","action":12,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[19,23,35,39,40,44,53,55],"ai":[10,16,18,30,32,36,41,50]},"scoresAfter":[-60,-15]},{"ply":5,"player":"human","action":36,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[19,23,35,39,40,44,53,55],"ai":[10,18,30,32,36,41,45,50]},"scoresAfter":[-78,-15]},{"ply":6,"player":"ai","action":48,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[19,23,35,40,44,53,54,55],"ai":[10,18,30,32,36,41,45,50]},"scoresAfter":[-78,-55]},{"ply":7,"player":"human","action":36,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[19,23,35,40,44,53,54,55],"ai":[10,18,30,31,32,41,45,50]},"scoresAfter":[-75,-55]},{"ply":8,"player":"ai","action":12,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[12,19,23,35,44,53,54,55],"ai":[10,18,30,31,32,41,45,50]},"scoresAfter":[-75,-50]},{"ply":9,"player":"human","action":60,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[12,19,23,35,44,53,54,55],"ai":[4,10,30,31,32,41,45,50]},"scoresAfter":[-91,-50]},{"ply":10,"player":"ai","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[12,14,19,23,35,44,54,55],"ai":[4,10,30,31,32,41,45,50]},"scoresAfter":[-91,-67]},{"ply":11,"player":"human","action":72,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[12,14,19,23,35,44,54,55],"ai":[8,10,30,31,32,41,45,50]},"scoresAfter":[-86,-67]},{"ply":12,"player":"ai","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[12,14,19,23,35,44,46,55],"ai":[8,10,30,31,32,41,45,50]},"scoresAfter":[-86,-60]},{"ply":13,"player":"human","action":84,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[12,14,19,23,35,44,46,55],"ai":[2,10,30,31,32,41,45,50]},"scoresAfter":[-80,-60]},{"ply":14,"player":"ai","action":12,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[12,14,19,23,35,44,46,58],"ai":[2,10,30,31,32,41,45,50]},"scoresAfter":[-80,-51]},{"ply":15,"player":"human","action":0,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[12,14,19,23,35,44,46,58],"ai":[2,30,31,32,34,41,45,50]},"scoresAfter":[-120,-51]},{"ply":16,"player":"ai","action":90,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[14,19,23,35,37,44,46,58],"ai":[2,30,31,32,34,41,45,50]},"scoresAfter":[-120,-51]},{"ply":17,"player":"human","action":0,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[14,19,23,35,37,44,46,58],"ai":[2,20,30,31,32,34,41,45]},"scoresAfter":[-140,-51]},{"ply":18,"player":"ai","action":12,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[0,19,23,35,37,44,46,58],"ai":[2,20,30,31,32,34,41,45]},"scoresAfter":[-140,-44]},{"ply":19,"player":"human","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[0,19,23,35,37,44,46,58],"ai":[2,30,31,32,34,41,45,47]},"scoresAfter":[-140,-44]},{"ply":20,"player":"ai","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[7,19,23,35,37,44,46,58],"ai":[2,30,31,32,34,41,45,47]},"scoresAfter":[-140,-44]},{"ply":21,"player":"human","action":6,"playedCard":7,"placeType":"discard","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[7,19,23,35,37,44,46,58],"ai":[3,30,31,32,34,41,45,47]},"scoresAfter":[-140,-44]},{"ply":22,"player":"ai","action":6,"playedCard":3,"placeType":"discard","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[19,23,35,37,44,46,57,58],"ai":[3,30,31,32,34,41,45,47]},"scoresAfter":[-140,-44]},{"ply":23,"player":"human","action":42,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[19,23,35,37,44,46,57,58],"ai":[26,30,31,32,34,41,45,47]},"scoresAfter":[-140,-44]},{"ply":24,"player":"ai","action":0,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[19,23,35,44,46,56,57,58],"ai":[26,30,31,32,34,41,45,47]},"scoresAfter":[-140,-84]},{"ply":25,"player":"human","action":60,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[19,23,35,44,46,56,57,58],"ai":[30,31,32,34,41,45,47,59]},"scoresAfter":[-133,-84]},{"ply":26,"player":"ai","action":0,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[19,23,35,43,44,46,57,58],"ai":[30,31,32,34,41,45,47,59]},"scoresAfter":[-133,-74]},{"ply":27,"player":"human","action":72,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[19,23,35,43,44,46,57,58],"ai":[22,31,32,34,41,45,47,59]},"scoresAfter":[-125,-74]},{"ply":28,"player":"ai","action":0,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[19,23,35,38,43,44,46,58],"ai":[22,31,32,34,41,45,47,59]},"scoresAfter":[-125,-65]},{"ply":29,"player":"human","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[19,23,35,38,43,44,46,58],"ai":[31,32,34,41,45,47,51,59]},"scoresAfter":[-116,-65]},{"ply":30,"player":"ai","action":0,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[13,19,23,35,38,43,44,46],"ai":[31,32,34,41,45,47,51,59]},"scoresAfter":[-116,-53]},{"ply":31,"player":"human","action":0,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[13,19,23,35,38,43,44,46],"ai":[27,32,34,41,45,47,51,59]},"scoresAfter":[-136,-53]},{"ply":32,"player":"ai","action":36,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[19,23,35,38,42,43,44,46],"ai":[27,32,34,41,45,47,51,59]},"scoresAfter":[-136,-45]},{"ply":33,"player":"human","action":48,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[19,23,35,38,42,43,44,46],"ai":[27,32,34,45,47,51,52,59]},"scoresAfter":[-131,-45]},{"ply":34,"player":"ai","action":12,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[9,19,23,35,38,43,44,46],"ai":[27,32,34,45,47,51,52,59]},"scoresAfter":[-131,-31]},{"ply":35,"player":"human","action":60,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[9,19,23,35,38,43,44,46],"ai":[1,27,34,45,47,51,52,59]},"scoresAfter":[-125,-31]},{"ply":36,"player":"ai","action":36,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[9,19,21,23,35,38,44,46],"ai":[1,27,34,45,47,51,52,59]},"scoresAfter":[-125,-15]},{"ply":37,"player":"human","action":72,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[9,19,21,23,35,38,44,46],"ai":[1,27,28,34,47,51,52,59]},"scoresAfter":[-118,-15]},{"ply":38,"player":"ai","action":36,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[9,19,21,23,35,38,46,48],"ai":[1,27,28,34,47,51,52,59]},"scoresAfter":[-118,3]},{"ply":39,"player":"human","action":12,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[9,19,21,23,35,38,46,48],"ai":[1,5,27,28,47,51,52,59]},"scoresAfter":[-94,3]},{"ply":40,"player":"ai","action":48,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[9,21,23,33,35,38,46,48],"ai":[1,5,27,28,47,51,52,59]},"scoresAfter":[-94,23]},{"ply":41,"player":"human","action":12,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[9,21,23,33,35,38,46,48],"ai":[1,5,6,27,28,51,52,59]},"scoresAfter":[-62,23]},{"ply":42,"player":"ai","action":54,"playedCard":28,"placeType":"discard","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[9,23,33,35,38,46,48,49],"ai":[1,5,6,27,28,51,52,59]},"scoresAfter":[-62,23]},{"ply":43,"player":"human","action":12,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[9,23,33,35,38,46,48,49],"ai":[1,5,6,17,27,51,52,59]},"scoresAfter":[-22,23]},{"ply":44,"player":"ai","action":78,"playedCard":52,"placeType":"discard","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[9,11,33,35,38,46,48,49],"ai":[1,5,6,17,27,51,52,59]},"scoresAfter":[-22,23]}],"finalScores":[-22,23],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[40,19,23,24,44,53,35,55,50,10,41,30,15,36,18,32,25,16,39,45,54,31,12,4,14,8,46,2,58,34,37,20,0,47,7,3,57,26,56,59,43,22,38,51,13,27,42,52,9,1,21,28,48,5,33,6,49,17,11,29],"drawPtr":60,"cardLoc":[5,2,5,5,4,2,2,5,4,1,4,1,3,3,3,4,4,2,4,3,4,3,4,3,3,3,4,2,5,2,4,4,4,1,4,1,4,5,1,3,3,4,3,3,3,4,1,4,1,1,5,2,5,3,3,3,3,3,3,2],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[0,10,0,7,9],[9,9,9,10,0]],"colHandshakes":[[0,3,2,0,0],[0,0,1,1,0]],"colLength":[[0,6,2,5,6],[3,5,5,4,0]],"piles":[[0,2,7,3],[],[28],[37],[50,52]],"toMove":0,"stepCount":44,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"ca4024bf-cfe7-486a-b4ea-7a2b0826b048","seed":"wum4dd","startedAt":"2026-07-14T16:31:03.222Z","finishedAt":"2026-07-14T16:33:27.124Z","initialDeckOrder":[27,2,57,18,24,50,44,25,5,58,13,37,15,36,38,48,14,11,56,52,23,46,17,45,19,47,55,6,51,9,10,33,43,41,26,39,53,29,31,22,34,30,7,59,49,4,16,54,40,8,28,1,20,3,0,21,35,42,32,12],"moves":[{"ply":1,"player":"human","action":72,"playedCard":50,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[2,18,24,25,27,44,50,57],"ai":[5,13,15,36,37,38,48,58]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[2,14,18,24,25,27,44,57],"ai":[5,13,15,36,37,38,48,58]},"scoresAfter":[-40,-16]},{"ply":3,"player":"human","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[2,14,18,24,25,27,44,57],"ai":[11,13,15,36,37,38,48,58]},"scoresAfter":[-40,-16]},{"ply":4,"player":"ai","action":12,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[14,18,24,25,27,44,56,57],"ai":[11,13,15,36,37,38,48,58]},"scoresAfter":[-40,-56]},{"ply":5,"player":"human","action":30,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[14,18,24,25,27,44,56,57],"ai":[11,15,36,37,38,48,52,58]},"scoresAfter":[-40,-56]},{"ply":6,"player":"ai","action":72,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[14,18,23,25,27,44,56,57],"ai":[11,15,36,37,38,48,52,58]},"scoresAfter":[-40,-73]},{"ply":7,"player":"human","action":42,"playedCard":25,"placeType":"discard","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[14,18,23,25,27,44,56,57],"ai":[11,15,36,37,38,46,48,58]},"scoresAfter":[-40,-73]},{"ply":8,"player":"ai","action":24,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[14,17,18,23,27,44,56,57],"ai":[11,15,36,37,38,46,48,58]},"scoresAfter":[-40,-113]},{"ply":9,"player":"human","action":0,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[14,17,18,23,27,44,56,57],"ai":[11,15,37,38,45,46,48,58]},"scoresAfter":[-80,-113]},{"ply":10,"player":"ai","action":24,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[17,18,19,23,27,44,56,57],"ai":[11,15,37,38,45,46,48,58]},"scoresAfter":[-80,-133]},{"ply":11,"player":"human","action":54,"playedCard":27,"placeType":"discard","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[17,18,19,23,27,44,56,57],"ai":[11,15,38,45,46,47,48,58]},"scoresAfter":[-80,-133]},{"ply":12,"player":"ai","action":78,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[17,18,19,23,44,55,56,57],"ai":[11,15,38,45,46,47,48,58]},"scoresAfter":[-80,-133]},{"ply":13,"player":"human","action":5,"playedCard":17,"placeType":"play","drawSource":"discard_4","drawnCard":48,"handsBefore":{"human":[17,18,19,23,44,55,56,57],"ai":[6,11,15,38,45,46,47,58]},"scoresAfter":[-72,-133]},{"ply":14,"player":"ai","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[18,19,23,44,48,55,56,57],"ai":[6,11,15,38,45,46,47,58]},"scoresAfter":[-72,-128]},{"ply":15,"player":"human","action":48,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[18,19,23,44,48,55,56,57],"ai":[11,15,38,45,46,47,51,58]},"scoresAfter":[-92,-128]},{"ply":16,"player":"ai","action":78,"playedCard":51,"placeType":"discard","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[9,18,19,23,44,55,56,57],"ai":[11,15,38,45,46,47,51,58]},"scoresAfter":[-92,-128]},{"ply":17,"player":"human","action":12,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[9,18,19,23,44,55,56,57],"ai":[10,11,15,38,45,46,47,58]},"scoresAfter":[-82,-128]},{"ply":18,"player":"ai","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[9,19,23,33,44,55,56,57],"ai":[10,11,15,38,45,46,47,58]},"scoresAfter":[-82,-119]},{"ply":19,"player":"human","action":12,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[9,19,23,33,44,55,56,57],"ai":[10,11,15,38,43,45,46,47]},"scoresAfter":[-70,-119]},{"ply":20,"player":"ai","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[9,23,33,41,44,55,56,57],"ai":[10,11,15,38,43,45,46,47]},"scoresAfter":[-70,-110]},{"ply":21,"player":"human","action":11,"playedCard":9,"placeType":"discard","drawSource":"discard_4","drawnCard":51,"handsBefore":{"human":[9,23,33,41,44,55,56,57],"ai":[11,15,26,38,43,45,46,47]},"scoresAfter":[-70,-110]},{"ply":22,"player":"ai","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[23,33,41,44,51,55,56,57],"ai":[11,15,26,38,43,45,46,47]},"scoresAfter":[-70,-100]},{"ply":23,"player":"human","action":48,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[23,33,41,44,51,55,56,57],"ai":[15,26,38,39,43,45,46,47]},"scoresAfter":[-64,-100]},{"ply":24,"player":"ai","action":12,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[23,33,41,44,53,55,56,57],"ai":[15,26,38,39,43,45,46,47]},"scoresAfter":[-64,-140]},{"ply":25,"player":"human","action":48,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[23,33,41,44,53,55,56,57],"ai":[15,29,38,39,43,45,46,47]},"scoresAfter":[-52,-140]},{"ply":26,"player":"ai","action":12,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[23,31,33,41,44,55,56,57],"ai":[15,29,38,39,43,45,46,47]},"scoresAfter":[-52,-132]},{"ply":27,"player":"human","action":63,"playedCard":55,"placeType":"play","drawSource":"discard_2","drawnCard":27,"handsBefore":{"human":[23,31,33,41,44,55,56,57],"ai":[15,22,38,39,43,45,46,47]},"scoresAfter":[-34,-132]},{"ply":28,"player":"ai","action":12,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[23,27,31,33,41,44,56,57],"ai":[15,22,38,39,43,45,46,47]},"scoresAfter":[-34,-114]},{"ply":29,"player":"human","action":75,"playedCard":56,"placeType":"play","drawSource":"discard_2","drawnCard":25,"handsBefore":{"human":[23,27,31,33,41,44,56,57],"ai":[15,34,38,39,43,45,46,47]},"scoresAfter":[-13,-114]},{"ply":30,"player":"ai","action":12,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[23,25,27,31,33,41,44,57],"ai":[15,34,38,39,43,45,46,47]},"scoresAfter":[-13,-96]},{"ply":31,"player":"human","action":87,"playedCard":57,"placeType":"play","drawSource":"discard_2","drawnCard":24,"handsBefore":{"human":[23,25,27,31,33,41,44,57],"ai":[15,30,38,39,43,45,46,47]},"scoresAfter":[11,-96]},{"ply":32,"player":"ai","action":24,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[23,24,25,27,31,33,41,44],"ai":[15,30,38,39,43,45,46,47]},"scoresAfter":[11,-116]},{"ply":33,"player":"human","action":12,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[23,24,25,27,31,33,41,44],"ai":[7,15,30,39,43,45,46,47]},"scoresAfter":[-29,-116]},{"ply":34,"player":"ai","action":36,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[23,25,27,31,33,41,44,59],"ai":[7,15,30,39,43,45,46,47]},"scoresAfter":[-29,-108]},{"ply":35,"player":"human","action":12,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[23,25,27,31,33,41,44,59],"ai":[7,15,30,43,45,46,47,49]},"scoresAfter":[-49,-108]},{"ply":36,"player":"ai","action":36,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[4,23,27,31,33,41,44,59],"ai":[7,15,30,43,45,46,47,49]},"scoresAfter":[-49,-84]},{"ply":37,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[4,23,27,31,33,41,44,59],"ai":[7,15,16,30,45,46,47,49]},"scoresAfter":[1,-84]},{"ply":38,"player":"ai","action":6,"playedCard":7,"placeType":"discard","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[4,23,27,31,33,41,44,54],"ai":[7,15,16,30,45,46,47,49]},"scoresAfter":[1,-84]},{"ply":39,"player":"human","action":24,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[4,23,27,31,33,41,44,54],"ai":[15,16,30,40,45,46,47,49]},"scoresAfter":[7,-84]},{"ply":40,"player":"ai","action":48,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[4,8,23,31,33,41,44,54],"ai":[15,16,30,40,45,46,47,49]},"scoresAfter":[7,-52]},{"ply":41,"player":"human","action":6,"playedCard":4,"placeType":"discard","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[4,8,23,31,33,41,44,54],"ai":[15,16,28,30,40,46,47,49]},"scoresAfter":[7,-52]},{"ply":42,"player":"ai","action":18,"playedCard":16,"placeType":"discard","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[1,8,23,31,33,41,44,54],"ai":[15,16,28,30,40,46,47,49]},"scoresAfter":[7,-52]},{"ply":43,"player":"human","action":18,"playedCard":8,"placeType":"discard","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[1,8,23,31,33,41,44,54],"ai":[15,20,28,30,40,46,47,49]},"scoresAfter":[7,-52]},{"ply":44,"player":"ai","action":30,"playedCard":28,"placeType":"discard","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[1,3,23,31,33,41,44,54],"ai":[15,20,28,30,40,46,47,49]},"scoresAfter":[7,-52]},{"ply":45,"player":"human","action":27,"playedCard":23,"placeType":"play","drawSource":"discard_2","drawnCard":28,"handsBefore":{"human":[1,3,23,31,33,41,44,54],"ai":[0,15,20,30,40,46,47,49]},"scoresAfter":[27,-52]},{"ply":46,"player":"ai","action":60,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[1,3,28,31,33,41,44,54],"ai":[0,15,20,30,40,46,47,49]},"scoresAfter":[27,-16]},{"ply":47,"player":"human","action":24,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[1,3,28,31,33,41,44,54],"ai":[0,15,20,21,30,40,47,49]},"scoresAfter":[36,-16]},{"ply":48,"player":"ai","action":72,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[1,3,31,33,35,41,44,54],"ai":[0,15,20,21,30,40,47,49]},"scoresAfter":[36,44]},{"ply":49,"player":"human","action":38,"playedCard":33,"placeType":"play","drawSource":"discard_1","drawnCard":16,"handsBefore":{"human":[1,3,31,33,35,41,44,54],"ai":[0,15,20,21,30,40,42,49]},"scoresAfter":[60,44]},{"ply":50,"player":"ai","action":78,"playedCard":42,"placeType":"discard","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[1,3,16,31,35,41,44,54],"ai":[0,15,20,21,30,40,42,49]},"scoresAfter":[60,44]},{"ply":51,"player":"human","action":48,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[1,3,16,31,35,41,44,54],"ai":[0,15,20,21,30,32,40,49]},"scoresAfter":[90,44]}],"finalScores":[90,44],"outcome":"YOU WIN","finalState":{"deckOrder":[27,2,57,18,24,50,44,25,5,58,13,37,15,36,38,48,14,11,56,52,23,46,17,45,19,47,55,6,51,9,10,33,43,41,26,39,53,29,31,22,34,30,7,59,49,4,16,54,40,8,28,1,20,3,0,21,35,42,32,12],"drawPtr":60,"cardLoc":[2,1,5,1,5,4,4,5,5,5,4,4,1,4,3,2,1,3,3,3,2,2,4,3,3,3,4,3,3,4,2,1,2,3,4,3,4,4,4,4,2,1,5,4,1,4,4,4,3,2,3,3,4,3,1,3,3,3,4,3],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[0,10,10,0,10],[10,9,9,10,9]],"colHandshakes":[[0,1,2,0,2],[0,1,1,3,0]],"colLength":[[0,5,6,0,8],[4,2,3,8,2]],"piles":[[2,9,7,4,8],[],[],[42],[]],"toMove":1,"stepCount":51,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"6325a07a-7789-4c94-a6cf-5902f241169b","seed":"yt36yr","startedAt":"2026-07-14T16:33:28.078Z","finishedAt":"2026-07-14T16:36:03.747Z","initialDeckOrder":[14,15,51,39,5,48,36,25,57,6,54,31,4,19,55,18,32,11,24,28,56,41,1,50,27,29,58,21,37,20,44,26,0,49,2,3,34,9,16,8,45,22,10,30,23,13,33,42,35,12,46,43,47,53,40,17,52,38,59,7],"moves":[{"ply":1,"player":"human","action":42,"playedCard":25,"placeType":"discard","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[5,14,15,25,36,39,48,51],"ai":[4,6,18,19,31,54,55,57]},"scoresAfter":[0,0]},{"ply":2,"player":"ai","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[5,14,15,32,36,39,48,51],"ai":[4,6,18,19,31,54,55,57]},"scoresAfter":[0,-17]},{"ply":3,"player":"human","action":57,"playedCard":36,"placeType":"discard","drawSource":"discard_2","drawnCard":25,"handsBefore":{"human":[5,14,15,32,36,39,48,51],"ai":[6,11,18,19,31,54,55,57]},"scoresAfter":[0,-17]},{"ply":4,"player":"ai","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[5,14,15,25,32,39,48,51],"ai":[6,11,18,19,31,54,55,57]},"scoresAfter":[0,-12]},{"ply":5,"player":"human","action":36,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[5,14,15,25,32,39,48,51],"ai":[11,18,19,24,31,54,55,57]},"scoresAfter":[-40,-12]},{"ply":6,"player":"ai","action":36,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[5,14,15,28,32,39,48,51],"ai":[11,18,19,24,31,54,55,57]},"scoresAfter":[-40,-52]},{"ply":7,"player":"human","action":36,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[5,14,15,28,32,39,48,51],"ai":[11,18,19,31,54,55,56,57]},"scoresAfter":[-34,-52]},{"ply":8,"player":"ai","action":48,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[5,14,15,32,39,41,48,51],"ai":[11,18,19,31,54,55,56,57]},"scoresAfter":[-34,-67]},{"ply":9,"player":"human","action":12,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[5,14,15,32,39,41,48,51],"ai":[1,11,18,19,31,55,56,57]},"scoresAfter":[-74,-67]},{"ply":10,"player":"ai","action":60,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[5,15,32,39,41,48,50,51],"ai":[1,11,18,19,31,55,56,57]},"scoresAfter":[-74,-61]},{"ply":11,"player":"human","action":66,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[5,15,32,39,41,48,50,51],"ai":[1,11,18,19,27,31,56,57]},"scoresAfter":[-74,-61]},{"ply":12,"player":"ai","action":72,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[5,15,29,32,39,41,50,51],"ai":[1,11,18,19,27,31,56,57]},"scoresAfter":[-74,-54]},{"ply":13,"player":"human","action":78,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[5,15,29,32,39,41,50,51],"ai":[1,11,18,19,27,31,57,58]},"scoresAfter":[-74,-54]},{"ply":14,"player":"ai","action":72,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[5,15,21,29,32,39,41,51],"ai":[1,11,18,19,27,31,57,58]},"scoresAfter":[-74,-46]},{"ply":15,"player":"human","action":90,"playedCard":51,"placeType":"discard","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[5,15,21,29,32,39,41,51],"ai":[1,11,18,19,27,31,37,58]},"scoresAfter":[-74,-46]},{"ply":16,"player":"ai","action":72,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[5,15,20,21,29,32,39,41],"ai":[1,11,18,19,27,31,37,58]},"scoresAfter":[-74,-86]},{"ply":17,"player":"human","action":48,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[5,15,20,21,29,32,39,41],"ai":[1,11,18,19,27,31,44,58]},"scoresAfter":[-66,-86]},{"ply":18,"player":"ai","action":72,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[5,15,20,21,26,32,39,41],"ai":[1,11,18,19,27,31,44,58]},"scoresAfter":[-66,-72]},{"ply":19,"player":"human","action":6,"playedCard":5,"placeType":"discard","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[5,15,20,21,26,32,39,41],"ai":[0,1,11,18,19,27,31,58]},"scoresAfter":[-66,-72]},{"ply":20,"player":"ai","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[15,20,21,26,32,39,41,49],"ai":[0,1,11,18,19,27,31,58]},"scoresAfter":[-66,-72]},{"ply":21,"player":"human","action":90,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[15,20,21,26,32,39,41,49],"ai":[1,2,11,18,19,27,31,58]},"scoresAfter":[-66,-72]},{"ply":22,"player":"ai","action":60,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[3,15,20,21,26,32,39,41],"ai":[1,2,11,18,19,27,31,58]},"scoresAfter":[-66,-68]},{"ply":23,"player":"human","action":6,"playedCard":3,"placeType":"discard","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[3,15,20,21,26,32,39,41],"ai":[1,2,11,18,19,31,34,58]},"scoresAfter":[-66,-68]},{"ply":24,"player":"ai","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[9,15,20,21,26,32,39,41],"ai":[1,2,11,18,19,31,34,58]},"scoresAfter":[-66,-68]},{"ply":25,"player":"human","action":12,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[9,15,20,21,26,32,39,41],"ai":[2,11,16,18,19,31,34,58]},"scoresAfter":[-62,-68]},{"ply":26,"player":"ai","action":48,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[8,9,20,21,26,32,39,41],"ai":[2,11,16,18,19,31,34,58]},"scoresAfter":[-62,-82]},{"ply":27,"player":"human","action":79,"playedCard":39,"placeType":"discard","drawSource":"discard_0","drawnCard":1,"handsBefore":{"human":[8,9,20,21,26,32,39,41],"ai":[2,11,16,18,31,34,45,58]},"scoresAfter":[-62,-82]},{"ply":28,"player":"ai","action":48,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[1,8,9,20,21,26,32,41],"ai":[2,11,16,18,31,34,45,58]},"scoresAfter":[-62,-70]},{"ply":29,"player":"human","action":1,"playedCard":1,"placeType":"play","drawSource":"discard_0","drawnCard":3,"handsBefore":{"human":[1,8,9,20,21,26,32,41],"ai":[2,11,16,18,22,34,45,58]},"scoresAfter":[-102,-70]},{"ply":30,"player":"ai","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[3,8,9,20,21,26,32,41],"ai":[2,11,16,18,22,34,45,58]},"scoresAfter":[-102,-70]},{"ply":31,"player":"human","action":91,"playedCard":41,"placeType":"discard","drawSource":"discard_0","drawnCard":2,"handsBefore":{"human":[3,8,9,20,21,26,32,41],"ai":[10,11,16,18,22,34,45,58]},"scoresAfter":[-102,-70]},{"ply":32,"player":"ai","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[2,3,8,9,20,21,26,32],"ai":[10,11,16,18,22,34,45,58]},"scoresAfter":[-102,-61]},{"ply":33,"player":"human","action":0,"playedCard":2,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[2,3,8,9,20,21,26,32],"ai":[11,16,18,22,30,34,45,58]},"scoresAfter":[-122,-61]},{"ply":34,"player":"ai","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[3,8,9,20,21,23,26,32],"ai":[11,16,18,22,30,34,45,58]},"scoresAfter":[-122,-51]},{"ply":35,"player":"human","action":37,"playedCard":20,"placeType":"play","drawSource":"discard_0","drawnCard":0,"handsBefore":{"human":[3,8,9,20,21,23,26,32],"ai":[13,16,18,22,30,34,45,58]},"scoresAfter":[-108,-51]},{"ply":36,"player":"ai","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[0,3,8,9,21,23,26,32],"ai":[13,16,18,22,30,34,45,58]},"scoresAfter":[-108,-42]},{"ply":37,"player":"human","action":1,"playedCard":0,"placeType":"play","drawSource":"discard_0","drawnCard":5,"handsBefore":{"human":[0,3,8,9,21,23,26,32],"ai":[13,16,18,22,30,33,34,45]},"scoresAfter":[-128,-42]},{"ply":38,"player":"ai","action":36,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[3,5,8,9,21,23,26,32],"ai":[13,16,18,22,30,33,34,45]},"scoresAfter":[-128,-33]},{"ply":39,"player":"human","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[3,5,8,9,21,23,26,32],"ai":[13,16,18,30,33,34,42,45]},"scoresAfter":[-120,-33]},{"ply":40,"player":"ai","action":84,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[5,8,9,21,23,26,32,35],"ai":[13,16,18,30,33,34,42,45]},"scoresAfter":[-120,-17]},{"ply":41,"player":"human","action":36,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[5,8,9,21,23,26,32,35],"ai":[12,13,16,18,30,33,34,42]},"scoresAfter":[-104,-17]},{"ply":42,"player":"ai","action":60,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[5,8,9,23,26,32,35,46],"ai":[12,13,16,18,30,33,34,42]},"scoresAfter":[-104,-1]},{"ply":43,"player":"human","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[5,8,9,23,26,32,35,46],"ai":[12,13,16,18,30,34,42,43]},"scoresAfter":[-88,-1]},{"ply":44,"player":"ai","action":60,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[8,9,23,26,32,35,46,47],"ai":[12,13,16,18,30,34,42,43]},"scoresAfter":[-88,17]},{"ply":45,"player":"human","action":4,"playedCard":8,"placeType":"play","drawSource":"discard_3","drawnCard":41,"handsBefore":{"human":[8,9,23,26,32,35,46,47],"ai":[12,13,16,18,30,42,43,53]},"scoresAfter":[-60,17]},{"ply":46,"player":"ai","action":6,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[9,23,26,32,35,41,46,47],"ai":[12,13,16,18,30,42,43,53]},"scoresAfter":[-60,17]},{"ply":47,"player":"human","action":4,"playedCard":9,"placeType":"play","drawSource":"discard_3","drawnCard":39,"handsBefore":{"human":[9,23,26,32,35,41,46,47],"ai":[13,16,18,30,40,42,43,53]},"scoresAfter":[-28,17]},{"ply":48,"player":"ai","action":6,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[23,26,32,35,39,41,46,47],"ai":[13,16,18,30,40,42,43,53]},"scoresAfter":[-28,17]},{"ply":49,"player":"human","action":24,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[23,26,32,35,39,41,46,47],"ai":[16,17,18,30,40,42,43,53]},"scoresAfter":[-14,17]},{"ply":50,"player":"ai","action":42,"playedCard":30,"placeType":"discard","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[23,26,35,39,41,46,47,52],"ai":[16,17,18,30,40,42,43,53]},"scoresAfter":[-14,17]},{"ply":51,"player":"human","action":27,"playedCard":35,"placeType":"play","drawSource":"discard_2","drawnCard":30,"handsBefore":{"human":[23,26,35,39,41,46,47,52],"ai":[16,17,18,38,40,42,43,53]},"scoresAfter":[6,17]},{"ply":52,"player":"ai","action":42,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[23,26,30,39,41,46,47,52],"ai":[16,17,18,38,40,42,43,53]},"scoresAfter":[6,17]},{"ply":53,"player":"human","action":0,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[23,26,30,39,41,46,47,52],"ai":[16,17,18,40,42,43,53,59]},"scoresAfter":[26,17]}],"finalScores":[26,17],"outcome":"YOU WIN","finalState":{"deckOrder":[14,15,51,39,5,48,36,25,57,6,54,31,4,19,55,18,32,11,24,28,56,41,1,50,27,29,58,21,37,20,44,26,0,49,2,3,34,9,16,8,45,22,10,30,23,13,33,42,35,12,46,43,47,53,40,17,52,38,59,7],"drawPtr":60,"cardLoc":[3,3,3,3,4,3,4,1,3,3,4,4,5,5,3,3,2,2,2,4,3,3,4,3,4,3,1,4,3,3,1,4,3,4,4,3,5,4,5,1,2,1,2,2,4,4,1,1,5,5,5,5,1,2,4,4,4,4,4,2],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,true,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[8,10,10,0,0],[10,9,9,8,9]],"colHandshakes":[[3,1,1,0,0],[0,0,1,1,0]],"colLength":[[7,5,5,0,0],[4,2,5,3,5]],"piles":[[],[12,13],[],[36,38],[48,50,51,49]],"toMove":1,"stepCount":53,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"d2185fb9-cf2f-4bcd-ad78-58b31abaa4f0","seed":"keniwn","startedAt":"2026-07-14T16:36:04.506Z","finishedAt":"2026-07-14T16:38:22.414Z","initialDeckOrder":[33,6,46,16,13,25,38,57,27,40,50,21,31,34,17,32,59,56,15,44,42,11,36,29,37,10,52,1,4,49,47,3,5,18,19,41,43,30,23,9,53,20,24,26,7,51,8,12,0,39,48,58,35,14,54,45,2,28,55,22],"moves":[{"ply":1,"player":"human","action":60,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[6,13,16,25,33,38,46,57],"ai":[17,21,27,31,32,34,40,50]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":84,"playedCard":50,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[6,13,16,25,33,46,57,59],"ai":[17,21,27,31,32,34,40,50]},"scoresAfter":[-40,-40]},{"ply":3,"player":"human","action":18,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[6,13,16,25,33,46,57,59],"ai":[17,21,27,31,32,34,40,56]},"scoresAfter":[-40,-40]},{"ply":4,"player":"ai","action":72,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[6,15,16,25,33,46,57,59],"ai":[17,21,27,31,32,34,40,56]},"scoresAfter":[-40,-57]},{"ply":5,"player":"human","action":18,"playedCard":15,"placeType":"discard","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[6,15,16,25,33,46,57,59],"ai":[17,21,27,31,32,34,44,56]},"scoresAfter":[-40,-57]},{"ply":6,"player":"ai","action":0,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[6,16,25,33,42,46,57,59],"ai":[17,21,27,31,32,34,44,56]},"scoresAfter":[-40,-73]},{"ply":7,"player":"human","action":18,"playedCard":16,"placeType":"discard","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[6,16,25,33,42,46,57,59],"ai":[11,21,27,31,32,34,44,56]},"scoresAfter":[-40,-73]},{"ply":8,"player":"ai","action":72,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[6,25,33,36,42,46,57,59],"ai":[11,21,27,31,32,34,44,56]},"scoresAfter":[-40,-66]},{"ply":9,"player":"human","action":36,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[6,25,33,36,42,46,57,59],"ai":[11,21,27,29,31,32,34,56]},"scoresAfter":[-60,-66]},{"ply":10,"player":"ai","action":12,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[6,25,33,37,42,46,57,59],"ai":[11,21,27,29,31,32,34,56]},"scoresAfter":[-60,-58]},{"ply":11,"player":"human","action":36,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[6,25,33,37,42,46,57,59],"ai":[10,11,27,29,31,32,34,56]},"scoresAfter":[-80,-58]},{"ply":12,"player":"ai","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[6,25,33,42,46,52,57,59],"ai":[10,11,27,29,31,32,34,56]},"scoresAfter":[-80,-69]},{"ply":13,"player":"human","action":18,"playedCard":25,"placeType":"discard","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[6,25,33,42,46,52,57,59],"ai":[1,11,27,29,31,32,34,56]},"scoresAfter":[-80,-69]},{"ply":14,"player":"ai","action":12,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[4,6,33,42,46,52,57,59],"ai":[1,11,27,29,31,32,34,56]},"scoresAfter":[-80,-59]},{"ply":15,"player":"human","action":36,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[4,6,33,42,46,52,57,59],"ai":[1,27,29,31,32,34,49,56]},"scoresAfter":[-60,-59]},{"ply":16,"player":"ai","action":12,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[4,6,33,46,47,52,57,59],"ai":[1,27,29,31,32,34,49,56]},"scoresAfter":[-60,-77]},{"ply":17,"player":"human","action":60,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[4,6,33,46,47,52,57,59],"ai":[1,3,29,31,32,34,49,56]},"scoresAfter":[-77,-77]},{"ply":18,"player":"ai","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[4,5,6,33,46,47,57,59],"ai":[1,3,29,31,32,34,49,56]},"scoresAfter":[-77,-77]},{"ply":19,"player":"human","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[4,5,6,33,46,47,57,59],"ai":[3,18,29,31,32,34,49,56]},"scoresAfter":[-94,-77]},{"ply":20,"player":"ai","action":6,"playedCard":3,"placeType":"discard","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[5,6,19,33,46,47,57,59],"ai":[3,18,29,31,32,34,49,56]},"scoresAfter":[-94,-77]},{"ply":21,"player":"human","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[5,6,19,33,46,47,57,59],"ai":[18,29,31,32,34,41,49,56]},"scoresAfter":[-90,-77]},{"ply":22,"player":"ai","action":12,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[6,19,33,43,46,47,57,59],"ai":[18,29,31,32,34,41,49,56]},"scoresAfter":[-90,-73]},{"ply":23,"player":"human","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[6,19,33,43,46,47,57,59],"ai":[18,30,31,32,34,41,49,56]},"scoresAfter":[-85,-73]},{"ply":24,"player":"ai","action":12,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[19,23,33,43,46,47,57,59],"ai":[18,30,31,32,34,41,49,56]},"scoresAfter":[-85,-68]},{"ply":25,"player":"human","action":36,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[19,23,33,43,46,47,57,59],"ai":[9,18,31,32,34,41,49,56]},"scoresAfter":[-61,-68]},{"ply":26,"player":"ai","action":24,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[19,23,33,46,47,53,57,59],"ai":[9,18,31,32,34,41,49,56]},"scoresAfter":[-61,-62]},{"ply":27,"player":"human","action":60,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[19,23,33,46,47,53,57,59],"ai":[9,18,20,32,34,41,49,56]},"scoresAfter":[-57,-62]},{"ply":28,"player":"ai","action":6,"playedCard":9,"placeType":"discard","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[19,23,24,33,46,47,57,59],"ai":[9,18,20,32,34,41,49,56]},"scoresAfter":[-57,-62]},{"ply":29,"player":"human","action":73,"playedCard":57,"placeType":"play","drawSource":"discard_0","drawnCard":9,"handsBefore":{"human":[19,23,24,33,46,47,57,59],"ai":[18,20,26,32,34,41,49,56]},"scoresAfter":[-49,-62]},{"ply":30,"player":"ai","action":72,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[9,19,23,24,33,46,47,59],"ai":[18,20,26,32,34,41,49,56]},"scoresAfter":[-49,-82]},{"ply":31,"player":"human","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[9,19,23,24,33,46,47,59],"ai":[7,18,20,26,32,34,41,56]},"scoresAfter":[-41,-82]},{"ply":32,"player":"ai","action":6,"playedCard":7,"placeType":"discard","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[19,23,24,33,46,47,51,59],"ai":[7,18,20,26,32,34,41,56]},"scoresAfter":[-41,-82]},{"ply":33,"player":"human","action":48,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[19,23,24,33,46,47,51,59],"ai":[8,18,20,26,32,34,41,56]},"scoresAfter":[-5,-82]},{"ply":34,"player":"ai","action":48,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[12,19,23,24,33,47,51,59],"ai":[8,18,20,26,32,34,41,56]},"scoresAfter":[-5,-75]},{"ply":35,"player":"human","action":60,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[12,19,23,24,33,47,51,59],"ai":[0,8,18,20,26,34,41,56]},"scoresAfter":[35,-75]},{"ply":36,"player":"ai","action":60,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[12,19,23,24,33,39,51,59],"ai":[0,8,18,20,26,34,41,56]},"scoresAfter":[35,-66]},{"ply":37,"player":"human","action":2,"playedCard":12,"placeType":"play","drawSource":"discard_1","drawnCard":16,"handsBefore":{"human":[12,19,23,24,33,39,51,59],"ai":[0,8,18,20,26,41,48,56]},"scoresAfter":[-5,-66]},{"ply":38,"player":"ai","action":72,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[16,19,23,24,33,39,51,59],"ai":[0,8,18,20,26,41,48,56]},"scoresAfter":[-5,-86]},{"ply":39,"player":"human","action":0,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[16,19,23,24,33,39,51,59],"ai":[0,8,18,20,26,41,56,58]},"scoresAfter":[1,-86]},{"ply":40,"player":"ai","action":54,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[19,23,24,33,35,39,51,59],"ai":[0,8,18,20,26,41,56,58]},"scoresAfter":[1,-86]},{"ply":41,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[19,23,24,33,35,39,51,59],"ai":[0,8,14,18,20,41,56,58]},"scoresAfter":[11,-86]},{"ply":42,"player":"ai","action":72,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[19,23,24,33,35,39,51,54],"ai":[0,8,14,18,20,41,56,58]},"scoresAfter":[11,-58]},{"ply":43,"player":"human","action":0,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[19,23,24,33,35,39,51,54],"ai":[0,8,14,18,20,41,45,58]},"scoresAfter":[23,-58]},{"ply":44,"player":"ai","action":72,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[2,23,24,33,35,39,51,54],"ai":[0,8,14,18,20,41,45,58]},"scoresAfter":[23,-50]},{"ply":45,"player":"human","action":12,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[2,23,24,33,35,39,51,54],"ai":[0,8,14,18,20,28,41,58]},"scoresAfter":[43,-50]},{"ply":46,"player":"ai","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[2,24,33,35,39,51,54,55],"ai":[0,8,14,18,20,28,41,58]},"scoresAfter":[43,-14]}],"finalScores":[43,-14],"outcome":"YOU WIN","finalState":{"deckOrder":[33,6,46,16,13,25,38,57,27,40,50,21,31,34,17,32,59,56,15,44,42,11,36,29,37,10,52,1,4,49,47,3,5,18,19,41,43,30,23,9,53,20,24,26,7,51,8,12,0,39,48,58,35,14,54,45,2,28,55,22],"drawPtr":60,"cardLoc":[2,5,1,5,3,3,3,5,2,3,4,4,3,5,2,5,3,4,2,3,2,4,2,3,1,5,5,4,2,4,4,4,4,1,4,1,3,3,3,1,4,2,3,3,4,4,3,3,4,4,4,1,3,3,1,1,4,3,4,3],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[8,10,0,10,10],[10,8,9,8,9]],"colHandshakes":[[0,1,0,3,0],[0,0,0,0,3]],"colLength":[[4,4,0,7,4],[2,2,6,3,5]],"piles":[[1,3,7],[13,15],[25,26],[],[]],"toMove":0,"stepCount":46,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"d8645b40-f54c-4044-b33d-1a1723722a62","seed":"1pobsh","startedAt":"2026-07-14T16:38:23.250Z","finishedAt":"2026-07-14T16:40:44.025Z","initialDeckOrder":[59,33,27,7,13,43,3,15,45,48,35,0,42,1,41,24,25,2,57,47,46,31,8,53,39,32,16,54,10,38,28,6,36,40,30,14,52,18,23,44,55,56,21,11,17,5,50,9,12,26,58,29,49,51,19,22,4,37,20,34],"moves":[{"ply":1,"player":"human","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[3,7,13,15,27,33,43,59],"ai":[0,1,24,35,41,42,45,48]},"scoresAfter":[-18,0]},{"ply":2,"player":"ai","action":48,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[7,13,15,25,27,33,43,59],"ai":[0,1,24,35,41,42,45,48]},"scoresAfter":[-18,-16]},{"ply":3,"player":"human","action":18,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[7,13,15,25,27,33,43,59],"ai":[0,1,2,24,35,42,45,48]},"scoresAfter":[-18,-16]},{"ply":4,"player":"ai","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[7,15,25,27,33,43,57,59],"ai":[0,1,2,24,35,42,45,48]},"scoresAfter":[-18,-16]},{"ply":5,"player":"human","action":24,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[7,15,25,27,33,43,57,59],"ai":[1,2,24,35,42,45,47,48]},"scoresAfter":[-58,-16]},{"ply":6,"player":"ai","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[7,15,27,33,43,46,57,59],"ai":[1,2,24,35,42,45,47,48]},"scoresAfter":[-58,-16]},{"ply":7,"player":"human","action":24,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[7,15,27,33,43,46,57,59],"ai":[2,24,31,35,42,45,47,48]},"scoresAfter":[-54,-16]},{"ply":8,"player":"ai","action":84,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[7,8,15,33,43,46,57,59],"ai":[2,24,31,35,42,45,47,48]},"scoresAfter":[-54,-56]},{"ply":9,"player":"human","action":30,"playedCard":15,"placeType":"discard","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[7,8,15,33,43,46,57,59],"ai":[2,24,31,35,42,45,47,53]},"scoresAfter":[-54,-56]},{"ply":10,"player":"ai","action":48,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[7,8,33,39,43,46,57,59],"ai":[2,24,31,35,42,45,47,53]},"scoresAfter":[-54,-51]},{"ply":11,"player":"human","action":36,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[7,8,33,39,43,46,57,59],"ai":[2,24,31,32,35,45,47,53]},"scoresAfter":[-72,-51]},{"ply":12,"player":"ai","action":60,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[7,8,16,33,43,46,57,59],"ai":[2,24,31,32,35,45,47,53]},"scoresAfter":[-72,-43]},{"ply":13,"player":"human","action":30,"playedCard":16,"placeType":"discard","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[7,8,16,33,43,46,57,59],"ai":[2,24,31,32,35,47,53,54]},"scoresAfter":[-72,-43]},{"ply":14,"player":"ai","action":60,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[7,8,10,33,43,46,57,59],"ai":[2,24,31,32,35,47,53,54]},"scoresAfter":[-72,-33]},{"ply":15,"player":"human","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[7,8,10,33,43,46,57,59],"ai":[2,24,31,32,35,38,53,54]},"scoresAfter":[-66,-33]},{"ply":16,"player":"ai","action":66,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[8,10,28,33,43,46,57,59],"ai":[2,24,31,32,35,38,53,54]},"scoresAfter":[-66,-33]},{"ply":17,"player":"human","action":24,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[8,10,28,33,43,46,57,59],"ai":[2,6,24,31,32,35,53,54]},"scoresAfter":[-60,-33]},{"ply":18,"player":"ai","action":0,"playedCard":2,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[8,10,33,36,43,46,57,59],"ai":[2,6,24,31,32,35,53,54]},"scoresAfter":[-60,-73]},{"ply":19,"player":"human","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[8,10,33,36,43,46,57,59],"ai":[6,24,31,32,35,40,53,54]},"scoresAfter":[-53,-73]},{"ply":20,"player":"ai","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[10,30,33,36,43,46,57,59],"ai":[6,24,31,32,35,40,53,54]},"scoresAfter":[-53,-63]},{"ply":21,"player":"human","action":12,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[10,30,33,36,43,46,57,59],"ai":[14,24,31,32,35,40,53,54]},"scoresAfter":[-43,-63]},{"ply":22,"player":"ai","action":12,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[10,33,36,43,46,52,57,59],"ai":[14,24,31,32,35,40,53,54]},"scoresAfter":[-43,-103]},{"ply":23,"player":"human","action":60,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[10,33,36,43,46,52,57,59],"ai":[14,18,31,32,35,40,53,54]},"scoresAfter":[-60,-103]},{"ply":24,"player":"ai","action":0,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[10,23,33,36,43,46,57,59],"ai":[14,18,31,32,35,40,53,54]},"scoresAfter":[-60,-143]},{"ply":25,"player":"human","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[10,23,33,36,43,46,57,59],"ai":[18,31,32,35,40,44,53,54]},"scoresAfter":[-51,-143]},{"ply":26,"player":"ai","action":72,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[23,33,36,43,46,55,57,59],"ai":[18,31,32,35,40,44,53,54]},"scoresAfter":[-51,-135]},{"ply":27,"player":"human","action":60,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[23,33,36,43,46,55,57,59],"ai":[18,31,32,35,40,44,54,56]},"scoresAfter":[-45,-135]},{"ply":28,"player":"ai","action":72,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[21,23,33,36,43,46,57,59],"ai":[18,31,32,35,40,44,54,56]},"scoresAfter":[-45,-125]},{"ply":29,"player":"human","action":74,"playedCard":57,"placeType":"play","drawSource":"discard_1","drawnCard":16,"handsBefore":{"human":[21,23,33,36,43,46,57,59],"ai":[11,18,31,32,35,40,44,56]},"scoresAfter":[-37,-125]},{"ply":30,"player":"ai","action":84,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[16,21,23,33,36,43,46,59],"ai":[11,18,31,32,35,40,44,56]},"scoresAfter":[-37,-111]},{"ply":31,"player":"human","action":56,"playedCard":36,"placeType":"discard","drawSource":"discard_1","drawnCard":15,"handsBefore":{"human":[16,21,23,33,36,43,46,59],"ai":[11,17,18,31,32,35,40,44]},"scoresAfter":[-37,-111]},{"ply":32,"player":"ai","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[15,16,21,23,33,43,46,59],"ai":[11,17,18,31,32,35,40,44]},"scoresAfter":[-37,-91]},{"ply":33,"player":"human","action":86,"playedCard":59,"placeType":"play","drawSource":"discard_1","drawnCard":13,"handsBefore":{"human":[15,16,21,23,33,43,46,59],"ai":[5,17,18,31,32,35,40,44]},"scoresAfter":[-27,-91]},{"ply":34,"player":"ai","action":12,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[13,15,16,21,23,33,43,46],"ai":[5,17,18,31,32,35,40,44]},"scoresAfter":[-27,-83]},{"ply":35,"player":"human","action":0,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[13,15,16,21,23,33,43,46],"ai":[5,18,31,32,35,40,44,50]},"scoresAfter":[-67,-83]},{"ply":36,"player":"ai","action":12,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[9,15,16,21,23,33,43,46],"ai":[5,18,31,32,35,40,44,50]},"scoresAfter":[-67,-73]},{"ply":37,"player":"human","action":12,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[9,15,16,21,23,33,43,46],"ai":[5,12,31,32,35,40,44,50]},"scoresAfter":[-63,-73]},{"ply":38,"player":"ai","action":24,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[9,16,21,23,26,33,43,46],"ai":[5,12,31,32,35,40,44,50]},"scoresAfter":[-63,-61]},{"ply":39,"player":"human","action":12,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[9,16,21,23,26,33,43,46],"ai":[5,12,32,35,40,44,50,58]},"scoresAfter":[-57,-61]},{"ply":40,"player":"ai","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[9,21,23,26,29,33,43,46],"ai":[5,12,32,35,40,44,50,58]},"scoresAfter":[-57,-43]},{"ply":41,"player":"human","action":72,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[9,21,23,26,29,33,43,46],"ai":[5,12,32,35,40,44,49,50]},"scoresAfter":[-51,-43]},{"ply":42,"player":"ai","action":24,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[9,21,23,26,29,33,46,51],"ai":[5,12,32,35,40,44,49,50]},"scoresAfter":[-51,-29]},{"ply":43,"player":"human","action":12,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[9,21,23,26,29,33,46,51],"ai":[5,12,19,35,40,44,49,50]},"scoresAfter":[-35,-29]},{"ply":44,"player":"ai","action":24,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[9,22,23,26,29,33,46,51],"ai":[5,12,19,35,40,44,49,50]},"scoresAfter":[-35,-17]},{"ply":45,"player":"human","action":61,"playedCard":33,"placeType":"play","drawSource":"discard_0","drawnCard":1,"handsBefore":{"human":[9,22,23,26,29,33,46,51],"ai":[4,5,12,35,40,44,49,50]},"scoresAfter":[-19,-17]},{"ply":46,"player":"ai","action":36,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[1,9,22,23,26,29,46,51],"ai":[4,5,12,35,40,44,49,50]},"scoresAfter":[-19,3]},{"ply":47,"player":"human","action":25,"playedCard":22,"placeType":"play","drawSource":"discard_0","drawnCard":0,"handsBefore":{"human":[1,9,22,23,26,29,46,51],"ai":[4,5,12,37,40,44,49,50]},"scoresAfter":[-1,3]},{"ply":48,"player":"ai","action":78,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[0,1,9,23,26,29,46,51],"ai":[4,5,12,37,40,44,49,50]},"scoresAfter":[-1,3]},{"ply":49,"player":"human","action":40,"playedCard":23,"placeType":"play","drawSource":"discard_3","drawnCard":36,"handsBefore":{"human":[0,1,9,23,26,29,46,51],"ai":[4,5,12,20,37,40,44,50]},"scoresAfter":[19,3]},{"ply":50,"player":"ai","action":36,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[0,1,9,26,29,36,46,51],"ai":[4,5,12,20,37,40,44,50]},"scoresAfter":[19,17]}],"finalScores":[19,17],"outcome":"YOU WIN","finalState":{"deckOrder":[59,33,27,7,13,43,3,15,45,48,35,0,42,1,41,24,25,2,57,47,46,31,8,53,39,32,16,54,10,38,28,6,36,40,30,14,52,18,23,44,55,56,21,11,17,5,50,9,12,26,58,29,49,51,19,22,4,37,20,34],"drawPtr":60,"cardLoc":[1,1,4,3,2,2,4,3,3,1,3,4,2,3,4,3,3,4,4,4,4,3,3,3,4,3,1,3,3,1,3,4,4,3,2,4,1,2,5,3,2,4,4,3,2,4,1,4,4,5,2,1,3,4,4,3,4,3,4,3],"handPublic":[true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[9,10,8,6,10],[10,7,10,10,9]],"colHandshakes":[[0,1,1,0,0],[1,1,1,0,1]],"colLength":[[4,6,5,2,4],[3,5,4,4,5]],"piles":[[],[],[],[38],[49]],"toMove":0,"stepCount":50,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"3404379e-f150-4d1c-b057-e0bd30107235","seed":"qgx3w2","startedAt":"2026-07-14T16:40:44.921Z","finishedAt":"2026-07-14T16:42:48.326Z","initialDeckOrder":[39,41,35,45,2,29,53,6,10,52,13,46,31,50,1,43,15,56,21,48,5,0,18,30,32,37,57,49,47,3,7,19,36,42,8,58,44,51,28,16,40,11,25,14,27,59,38,22,34,24,17,4,12,33,23,55,9,26,20,54],"moves":[{"ply":1,"player":"human","action":48,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[2,6,29,35,39,41,45,53],"ai":[1,10,13,31,43,46,50,52]},"scoresAfter":[-18,0]},{"ply":2,"player":"ai","action":90,"playedCard":52,"placeType":"discard","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[2,6,15,29,35,41,45,53],"ai":[1,10,13,31,43,46,50,52]},"scoresAfter":[-18,0]},{"ply":3,"player":"human","action":24,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[2,6,15,29,35,41,45,53],"ai":[1,10,13,31,43,46,50,56]},"scoresAfter":[-36,0]},{"ply":4,"player":"ai","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[2,6,21,29,35,41,45,53],"ai":[1,10,13,31,43,46,50,56]},"scoresAfter":[-36,-40]},{"ply":5,"player":"human","action":11,"playedCard":2,"placeType":"discard","drawSource":"discard_4","drawnCard":52,"handsBefore":{"human":[2,6,21,29,35,41,45,53],"ai":[10,13,31,43,46,48,50,56]},"scoresAfter":[-36,-40]},{"ply":6,"player":"ai","action":12,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[6,21,29,35,41,45,52,53],"ai":[10,13,31,43,46,48,50,56]},"scoresAfter":[-36,-80]},{"ply":7,"player":"human","action":72,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[6,21,29,35,41,45,52,53],"ai":[5,10,31,43,46,48,50,56]},"scoresAfter":[-53,-80]},{"ply":8,"player":"ai","action":60,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[0,6,21,29,35,41,45,53],"ai":[5,10,31,43,46,48,50,56]},"scoresAfter":[-53,-120]},{"ply":9,"player":"human","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[0,6,21,29,35,41,45,53],"ai":[5,10,18,31,43,46,50,56]},"scoresAfter":[-53,-120]},{"ply":10,"player":"ai","action":72,"playedCard":50,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[6,21,29,30,35,41,45,53],"ai":[5,10,18,31,43,46,50,56]},"scoresAfter":[-53,-140]},{"ply":11,"player":"human","action":84,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[6,21,29,30,35,41,45,53],"ai":[5,10,18,31,32,43,46,56]},"scoresAfter":[-49,-140]},{"ply":12,"player":"ai","action":24,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[6,21,29,30,35,37,41,45],"ai":[5,10,18,31,32,43,46,56]},"scoresAfter":[-49,-130]},{"ply":13,"player":"human","action":72,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[6,21,29,30,35,37,41,45],"ai":[5,10,31,32,43,46,56,57]},"scoresAfter":[-45,-130]},{"ply":14,"player":"ai","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[6,21,29,30,35,37,45,49],"ai":[5,10,31,32,43,46,56,57]},"scoresAfter":[-45,-122]},{"ply":15,"player":"human","action":90,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[6,21,29,30,35,37,45,49],"ai":[10,31,32,43,46,47,56,57]},"scoresAfter":[-45,-122]},{"ply":16,"player":"ai","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[3,6,21,29,30,35,37,45],"ai":[10,31,32,43,46,47,56,57]},"scoresAfter":[-45,-104]},{"ply":17,"player":"human","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[3,6,21,29,30,35,37,45],"ai":[7,31,32,43,46,47,56,57]},"scoresAfter":[-63,-104]},{"ply":18,"player":"ai","action":72,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[6,19,21,29,30,35,37,45],"ai":[7,31,32,43,46,47,56,57]},"scoresAfter":[-63,-83]},{"ply":19,"player":"human","action":12,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[6,19,21,29,30,35,37,45],"ai":[7,31,32,36,43,46,47,57]},"scoresAfter":[-57,-83]},{"ply":20,"player":"ai","action":84,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[6,21,29,30,35,37,42,45],"ai":[7,31,32,36,43,46,47,57]},"scoresAfter":[-57,-59]},{"ply":21,"player":"human","action":72,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[6,21,29,30,35,37,42,45],"ai":[7,8,31,32,36,43,46,47]},"scoresAfter":[-52,-59]},{"ply":22,"player":"ai","action":6,"playedCard":7,"placeType":"discard","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[6,21,29,30,35,37,45,58],"ai":[7,8,31,32,36,43,46,47]},"scoresAfter":[-52,-59]},{"ply":23,"player":"human","action":1,"playedCard":6,"placeType":"play","drawSource":"discard_0","drawnCard":7,"handsBefore":{"human":[6,21,29,30,35,37,45,58],"ai":[8,31,32,36,43,44,46,47]},"scoresAfter":[-47,-59]},{"ply":24,"player":"ai","action":36,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[7,21,29,30,35,37,45,58],"ai":[8,31,32,36,43,44,46,47]},"scoresAfter":[-47,-99]},{"ply":25,"player":"human","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[7,21,29,30,35,37,45,58],"ai":[8,31,32,43,44,46,47,51]},"scoresAfter":[-41,-99]},{"ply":26,"player":"ai","action":12,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[21,28,29,30,35,37,45,58],"ai":[8,31,32,43,44,46,47,51]},"scoresAfter":[-41,-113]},{"ply":27,"player":"human","action":12,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[21,28,29,30,35,37,45,58],"ai":[8,16,32,43,44,46,47,51]},"scoresAfter":[-58,-113]},{"ply":28,"player":"ai","action":24,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[21,29,30,35,37,40,45,58],"ai":[8,16,32,43,44,46,47,51]},"scoresAfter":[-58,-106]},{"ply":29,"player":"human","action":12,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[21,29,30,35,37,40,45,58],"ai":[8,11,16,43,44,46,47,51]},"scoresAfter":[-54,-106]},{"ply":30,"player":"ai","action":12,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[21,25,30,35,37,40,45,58],"ai":[8,11,16,43,44,46,47,51]},"scoresAfter":[-54,-86]},{"ply":31,"player":"human","action":24,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[21,25,30,35,37,40,45,58],"ai":[8,14,16,43,44,46,47,51]},"scoresAfter":[-49,-86]},{"ply":32,"player":"ai","action":18,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[21,25,27,35,37,40,45,58],"ai":[8,14,16,43,44,46,47,51]},"scoresAfter":[-49,-86]},{"ply":33,"player":"human","action":36,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[21,25,27,35,37,40,45,58],"ai":[8,16,43,44,46,47,51,59]},"scoresAfter":[-39,-86]},{"ply":34,"player":"ai","action":6,"playedCard":8,"placeType":"discard","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[21,25,27,37,38,40,45,58],"ai":[8,16,43,44,46,47,51,59]},"scoresAfter":[-39,-86]},{"ply":35,"player":"human","action":0,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[21,25,27,37,38,40,45,58],"ai":[16,22,43,44,46,47,51,59]},"scoresAfter":[-31,-86]},{"ply":36,"player":"ai","action":12,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[25,27,34,37,38,40,45,58],"ai":[16,22,43,44,46,47,51,59]},"scoresAfter":[-31,-68]},{"ply":37,"player":"human","action":85,"playedCard":58,"placeType":"play","drawSource":"discard_0","drawnCard":8,"handsBefore":{"human":[25,27,34,37,38,40,45,58],"ai":[16,24,43,44,46,47,51,59]},"scoresAfter":[-22,-68]},{"ply":38,"player":"ai","action":24,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[8,25,27,34,37,38,40,45],"ai":[16,24,43,44,46,47,51,59]},"scoresAfter":[-22,-56]},{"ply":39,"player":"human","action":84,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[8,25,27,34,37,38,40,45],"ai":[16,17,24,44,46,47,51,59]},"scoresAfter":[-14,-56]},{"ply":40,"player":"ai","action":36,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[4,8,25,27,34,37,38,40],"ai":[16,17,24,44,46,47,51,59]},"scoresAfter":[-14,-42]},{"ply":41,"player":"human","action":12,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[4,8,25,27,34,37,38,40],"ai":[12,16,17,24,46,47,51,59]},"scoresAfter":[-7,-42]},{"ply":42,"player":"ai","action":48,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[4,25,27,33,34,37,38,40],"ai":[12,16,17,24,46,47,51,59]},"scoresAfter":[-7,-24]},{"ply":43,"player":"human","action":78,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[4,25,27,33,34,37,38,40],"ai":[12,16,17,23,24,47,51,59]},"scoresAfter":[-7,-24]},{"ply":44,"player":"ai","action":41,"playedCard":23,"placeType":"play","drawSource":"discard_4","drawnCard":49,"handsBefore":{"human":[4,25,27,33,34,37,40,55],"ai":[12,16,17,23,24,47,51,59]},"scoresAfter":[-7,-4]},{"ply":45,"player":"human","action":66,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[4,25,27,33,34,37,40,55],"ai":[12,16,17,24,47,49,51,59]},"scoresAfter":[-7,-4]},{"ply":46,"player":"ai","action":50,"playedCard":47,"placeType":"play","drawSource":"discard_1","drawnCard":14,"handsBefore":{"human":[4,9,25,27,33,34,40,55],"ai":[12,16,17,24,47,49,51,59]},"scoresAfter":[-7,16]},{"ply":47,"player":"human","action":12,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[4,9,25,27,33,34,40,55],"ai":[12,14,16,17,24,49,51,59]},"scoresAfter":[1,16]},{"ply":48,"player":"ai","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[4,25,26,27,33,34,40,55],"ai":[12,14,16,17,24,49,51,59]},"scoresAfter":[1,46]},{"ply":49,"player":"human","action":30,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[4,25,26,27,33,34,40,55],"ai":[12,14,16,17,20,24,49,51]},"scoresAfter":[1,46]}],"finalScores":[1,46],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[39,41,35,45,2,29,53,6,10,52,13,46,31,50,1,43,15,56,21,48,5,0,18,30,32,37,57,49,47,3,7,19,36,42,8,58,44,51,28,16,40,11,25,14,27,59,38,22,34,24,17,4,12,33,23,55,9,26,20,54],"drawPtr":60,"cardLoc":[5,4,5,3,1,4,3,3,3,3,4,4,2,4,2,3,2,2,4,3,2,3,4,4,2,1,5,1,3,3,3,4,4,1,1,3,4,5,5,3,1,3,3,4,4,3,4,4,4,2,4,2,3,3,1,1,4,4,3,4],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false],"colTop":[[8,8,10,8,9],[10,10,7,10,10]],"colHandshakes":[[0,0,0,0,0],[1,1,0,1,2]],"colLength":[[5,3,4,4,3],[4,4,2,5,5]],"piles":[[2,0],[],[26],[38,37],[]],"toMove":1,"stepCount":49,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"68af0aef-a728-4d5e-8981-5000fb1e1bcf","seed":"hwjq99","startedAt":"2026-07-14T16:42:49.346Z","finishedAt":"2026-07-14T16:45:25.144Z","initialDeckOrder":[5,0,39,17,48,38,27,21,47,37,18,33,45,6,51,44,49,16,32,35,13,1,8,9,23,22,30,20,15,50,24,31,11,57,55,59,54,26,12,10,40,3,53,56,28,52,19,14,29,2,36,43,46,41,7,34,4,25,42,58],"moves":[{"ply":1,"player":"human","action":78,"playedCard":39,"placeType":"discard","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[0,5,17,21,27,38,39,48],"ai":[6,18,33,37,44,45,47,51]},"scoresAfter":[0,0]},{"ply":2,"player":"ai","action":40,"playedCard":37,"placeType":"play","drawSource":"discard_3","drawnCard":39,"handsBefore":{"human":[0,5,17,21,27,38,48,49],"ai":[6,18,33,37,44,45,47,51]},"scoresAfter":[0,-40]},{"ply":3,"player":"human","action":78,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[0,5,17,21,27,38,48,49],"ai":[6,18,33,39,44,45,47,51]},"scoresAfter":[0,-40]},{"ply":4,"player":"ai","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[0,5,16,17,21,27,38,49],"ai":[6,18,33,39,44,45,47,51]},"scoresAfter":[0,-55]},{"ply":5,"player":"human","action":90,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[0,5,16,17,21,27,38,49],"ai":[18,32,33,39,44,45,47,51]},"scoresAfter":[0,-55]},{"ply":6,"player":"ai","action":84,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[0,5,16,17,21,27,35,38],"ai":[18,32,33,39,44,45,47,51]},"scoresAfter":[0,-73]},{"ply":7,"player":"human","action":90,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[0,5,16,17,21,27,35,38],"ai":[13,18,32,33,39,44,45,47]},"scoresAfter":[0,-73]},{"ply":8,"player":"ai","action":4,"playedCard":13,"placeType":"play","drawSource":"discard_3","drawnCard":38,"handsBefore":{"human":[0,1,5,16,17,21,27,35],"ai":[13,18,32,33,39,44,45,47]},"scoresAfter":[0,-113]},{"ply":9,"player":"human","action":0,"playedCard":0,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[0,1,5,16,17,21,27,35],"ai":[18,32,33,38,39,44,45,47]},"scoresAfter":[-40,-113]},{"ply":10,"player":"ai","action":36,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[1,5,8,16,17,21,27,35],"ai":[18,32,33,38,39,44,45,47]},"scoresAfter":[-40,-133]},{"ply":11,"player":"human","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[1,5,8,16,17,21,27,35],"ai":[9,18,32,33,39,44,45,47]},"scoresAfter":[-60,-133]},{"ply":12,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[5,8,16,17,21,23,27,35],"ai":[9,18,32,33,39,44,45,47]},"scoresAfter":[-60,-125]},{"ply":13,"player":"human","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[5,8,16,17,21,23,27,35],"ai":[18,22,32,33,39,44,45,47]},"scoresAfter":[-48,-125]},{"ply":14,"player":"ai","action":24,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[8,16,17,21,23,27,30,35],"ai":[18,22,32,33,39,44,45,47]},"scoresAfter":[-48,-138]},{"ply":15,"player":"human","action":60,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[8,16,17,21,23,27,30,35],"ai":[18,20,22,33,39,44,45,47]},"scoresAfter":[-66,-138]},{"ply":16,"player":"ai","action":36,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[8,15,16,17,21,23,30,35],"ai":[18,20,22,33,39,44,45,47]},"scoresAfter":[-66,-130]},{"ply":17,"player":"human","action":12,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[8,15,16,17,21,23,30,35],"ai":[18,20,22,39,44,45,47,50]},"scoresAfter":[-84,-130]},{"ply":18,"player":"ai","action":5,"playedCard":18,"placeType":"play","drawSource":"discard_4","drawnCard":49,"handsBefore":{"human":[8,16,17,21,23,24,30,35],"ai":[18,20,22,39,44,45,47,50]},"scoresAfter":[-84,-120]},{"ply":19,"player":"human","action":12,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[8,16,17,21,23,24,30,35],"ai":[20,22,39,44,45,47,49,50]},"scoresAfter":[-81,-120]},{"ply":20,"player":"ai","action":90,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[8,17,21,23,24,30,31,35],"ai":[20,22,39,44,45,47,49,50]},"scoresAfter":[-81,-120]},{"ply":21,"player":"human","action":12,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[8,17,21,23,24,30,31,35],"ai":[11,20,22,39,44,45,47,49]},"scoresAfter":[-77,-120]},{"ply":22,"player":"ai","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[8,21,23,24,30,31,35,57],"ai":[11,20,22,39,44,45,47,49]},"scoresAfter":[-77,-110]},{"ply":23,"player":"human","action":48,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[8,21,23,24,30,31,35,57],"ai":[20,22,39,44,45,47,49,55]},"scoresAfter":[-72,-110]},{"ply":24,"player":"ai","action":84,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[8,21,23,24,31,35,57,59],"ai":[20,22,39,44,45,47,49,55]},"scoresAfter":[-72,-104]},{"ply":25,"player":"human","action":53,"playedCard":31,"placeType":"play","drawSource":"discard_4","drawnCard":50,"handsBefore":{"human":[8,21,23,24,31,35,57,59],"ai":[20,22,39,44,45,47,49,54]},"scoresAfter":[-66,-104]},{"ply":26,"player":"ai","action":90,"playedCard":54,"placeType":"discard","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[8,21,23,24,35,50,57,59],"ai":[20,22,39,44,45,47,49,54]},"scoresAfter":[-66,-104]},{"ply":27,"player":"human","action":65,"playedCard":50,"placeType":"play","drawSource":"discard_4","drawnCard":54,"handsBefore":{"human":[8,21,23,24,35,50,57,59],"ai":[20,22,26,39,44,45,47,49]},"scoresAfter":[-106,-104]},{"ply":28,"player":"ai","action":0,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[8,21,23,24,35,54,57,59],"ai":[20,22,26,39,44,45,47,49]},"scoresAfter":[-106,-90]},{"ply":29,"player":"human","action":42,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[8,21,23,24,35,54,57,59],"ai":[12,22,26,39,44,45,47,49]},"scoresAfter":[-106,-90]},{"ply":30,"player":"ai","action":12,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[8,10,21,23,35,54,57,59],"ai":[12,22,26,39,44,45,47,49]},"scoresAfter":[-106,-72]},{"ply":31,"player":"human","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[8,10,21,23,35,54,57,59],"ai":[12,26,39,40,44,45,47,49]},"scoresAfter":[-85,-72]},{"ply":32,"player":"ai","action":18,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[3,10,21,23,35,54,57,59],"ai":[12,26,39,40,44,45,47,49]},"scoresAfter":[-85,-72]},{"ply":33,"player":"human","action":17,"playedCard":10,"placeType":"play","drawSource":"discard_4","drawnCard":48,"handsBefore":{"human":[3,10,21,23,35,54,57,59],"ai":[12,39,40,44,45,47,49,53]},"scoresAfter":[-58,-72]},{"ply":34,"player":"ai","action":90,"playedCard":53,"placeType":"discard","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[3,21,23,35,48,54,57,59],"ai":[12,39,40,44,45,47,49,53]},"scoresAfter":[-58,-72]},{"ply":35,"player":"human","action":48,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[3,21,23,35,48,54,57,59],"ai":[12,39,40,44,45,47,49,56]},"scoresAfter":[-78,-72]},{"ply":36,"player":"ai","action":84,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[3,21,23,28,35,54,57,59],"ai":[12,39,40,44,45,47,49,56]},"scoresAfter":[-78,-65]},{"ply":37,"player":"human","action":47,"playedCard":28,"placeType":"discard","drawSource":"discard_4","drawnCard":53,"handsBefore":{"human":[3,21,23,28,35,54,57,59],"ai":[12,39,40,44,45,47,49,52]},"scoresAfter":[-78,-65]},{"ply":38,"player":"ai","action":90,"playedCard":52,"placeType":"discard","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[3,21,23,35,53,54,57,59],"ai":[12,39,40,44,45,47,49,52]},"scoresAfter":[-78,-65]},{"ply":39,"player":"human","action":17,"playedCard":21,"placeType":"play","drawSource":"discard_4","drawnCard":52,"handsBefore":{"human":[3,21,23,35,53,54,57,59],"ai":[12,19,39,40,44,45,47,49]},"scoresAfter":[-70,-65]},{"ply":40,"player":"ai","action":24,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[3,23,35,52,53,54,57,59],"ai":[12,19,39,40,44,45,47,49]},"scoresAfter":[-70,-59]},{"ply":41,"player":"human","action":36,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[3,23,35,52,53,54,57,59],"ai":[12,14,19,40,44,45,47,49]},"scoresAfter":[-61,-59]},{"ply":42,"player":"ai","action":36,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[3,23,29,35,53,54,57,59],"ai":[12,14,19,40,44,45,47,49]},"scoresAfter":[-61,-50]},{"ply":43,"player":"human","action":48,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[3,23,29,35,53,54,57,59],"ai":[2,12,14,19,44,45,47,49]},"scoresAfter":[-49,-50]},{"ply":44,"player":"ai","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[3,23,29,35,36,54,57,59],"ai":[2,12,14,19,44,45,47,49]},"scoresAfter":[-49,-50]},{"ply":45,"player":"human","action":60,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[3,23,29,35,36,54,57,59],"ai":[12,14,19,43,44,45,47,49]},"scoresAfter":[-34,-50]},{"ply":46,"player":"ai","action":36,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[3,23,29,35,36,46,57,59],"ai":[12,14,19,43,44,45,47,49]},"scoresAfter":[-34,-32]},{"ply":47,"player":"human","action":72,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[3,23,29,35,36,46,57,59],"ai":[12,14,19,41,44,45,47,49]},"scoresAfter":[-10,-32]},{"ply":48,"player":"ai","action":48,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[3,7,23,29,35,36,46,59],"ai":[12,14,19,41,44,45,47,49]},"scoresAfter":[-10,-11]},{"ply":49,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[3,7,23,29,35,36,46,59],"ai":[12,14,19,34,41,45,47,49]},"scoresAfter":[20,-11]},{"ply":50,"player":"ai","action":39,"playedCard":34,"placeType":"play","drawSource":"discard_2","drawnCard":28,"handsBefore":{"human":[3,4,7,23,29,35,36,46],"ai":[12,14,19,34,41,45,47,49]},"scoresAfter":[20,-2]},{"ply":51,"player":"human","action":60,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[3,4,7,23,29,35,36,46],"ai":[12,14,19,28,41,45,47,49]},"scoresAfter":[30,-2]},{"ply":52,"player":"ai","action":61,"playedCard":45,"placeType":"play","drawSource":"discard_0","drawnCard":2,"handsBefore":{"human":[3,4,7,23,25,29,36,46],"ai":[12,14,19,28,41,45,47,49]},"scoresAfter":[30,22]},{"ply":53,"player":"human","action":36,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[3,4,7,23,25,29,36,46],"ai":[2,12,14,19,28,41,47,49]},"scoresAfter":[40,22]},{"ply":54,"player":"ai","action":72,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[3,4,7,25,29,36,42,46],"ai":[2,12,14,19,28,41,47,49]},"scoresAfter":[40,72]}],"finalScores":[40,72],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[5,0,39,17,48,38,27,21,47,37,18,33,45,6,51,44,49,16,32,35,13,1,8,9,23,22,30,20,15,50,24,31,11,57,55,59,54,26,12,10,40,3,53,56,28,52,19,14,29,2,36,43,46,41,7,34,4,25,42,58],"drawPtr":60,"cardLoc":[3,3,2,1,1,3,4,1,3,4,3,4,2,4,2,3,3,3,4,2,4,3,4,3,5,1,5,3,2,1,3,3,4,4,4,3,1,4,4,4,4,2,1,4,4,4,1,4,3,2,3,4,3,3,3,4,4,3,2,3],"handPublic":[false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false],"colTop":[[9,10,10,0,10],[10,9,9,10,7]],"colHandshakes":[[2,0,0,0,2],[0,1,0,2,0]],"colLength":[[5,5,4,0,7],[3,4,3,8,3]],"piles":[[],[],[24,26],[],[]],"toMove":0,"stepCount":54,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"5c98e70e-c5ff-43c6-828c-6395936298d6","seed":"ure5l7","startedAt":"2026-07-14T16:45:27.154Z","finishedAt":"2026-07-14T16:47:23.228Z","initialDeckOrder":[1,32,21,2,16,52,36,39,11,6,26,44,9,55,38,15,53,50,28,17,4,54,42,45,13,7,51,27,31,56,34,59,14,43,49,47,46,12,23,41,20,29,57,24,25,19,5,3,18,33,10,30,8,40,22,35,48,58,0,37],"moves":[{"ply":1,"player":"human","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[1,2,16,21,32,36,39,52],"ai":[6,9,11,15,26,38,44,55]},"scoresAfter":[0,0]},{"ply":2,"player":"ai","action":43,"playedCard":15,"placeType":"discard","drawSource":"discard_0","drawnCard":1,"handsBefore":{"human":[2,16,21,32,36,39,52,53],"ai":[6,9,11,15,26,38,44,55]},"scoresAfter":[0,0]},{"ply":3,"player":"human","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[2,16,21,32,36,39,52,53],"ai":[1,6,9,11,26,38,44,55]},"scoresAfter":[0,0]},{"ply":4,"player":"ai","action":61,"playedCard":38,"placeType":"play","drawSource":"discard_0","drawnCard":2,"handsBefore":{"human":[16,21,32,36,39,50,52,53],"ai":[1,6,9,11,26,38,44,55]},"scoresAfter":[0,-40]},{"ply":5,"player":"human","action":42,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[16,21,32,36,39,50,52,53],"ai":[1,2,6,9,11,26,44,55]},"scoresAfter":[0,-40]},{"ply":6,"player":"ai","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[16,21,28,32,39,50,52,53],"ai":[1,2,6,9,11,26,44,55]},"scoresAfter":[0,-80]},{"ply":7,"player":"human","action":62,"playedCard":50,"placeType":"play","drawSource":"discard_1","drawnCard":15,"handsBefore":{"human":[16,21,28,32,39,50,52,53],"ai":[2,6,9,11,17,26,44,55]},"scoresAfter":[-40,-80]},{"ply":8,"player":"ai","action":0,"playedCard":2,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[15,16,21,28,32,39,52,53],"ai":[2,6,9,11,17,26,44,55]},"scoresAfter":[-40,-100]},{"ply":9,"player":"human","action":0,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[15,16,21,28,32,39,52,53],"ai":[4,6,9,11,17,26,44,55]},"scoresAfter":[-58,-100]},{"ply":10,"player":"ai","action":84,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[16,21,28,32,39,52,53,54],"ai":[4,6,9,11,17,26,44,55]},"scoresAfter":[-58,-114]},{"ply":11,"player":"human","action":0,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[16,21,28,32,39,52,53,54],"ai":[4,6,9,11,17,26,42,44]},"scoresAfter":[-55,-114]},{"ply":12,"player":"ai","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[21,28,32,39,45,52,53,54],"ai":[4,6,9,11,17,26,42,44]},"scoresAfter":[-55,-105]},{"ply":13,"player":"human","action":60,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[21,28,32,39,45,52,53,54],"ai":[6,9,11,13,17,26,42,44]},"scoresAfter":[-49,-105]},{"ply":14,"player":"ai","action":54,"playedCard":17,"placeType":"discard","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[7,21,28,32,39,45,53,54],"ai":[6,9,11,13,17,26,42,44]},"scoresAfter":[-49,-105]},{"ply":15,"player":"human","action":72,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[7,21,28,32,39,45,53,54],"ai":[6,9,11,13,26,42,44,51]},"scoresAfter":[-41,-105]},{"ply":16,"player":"ai","action":54,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[7,21,27,28,32,39,45,54],"ai":[6,9,11,13,26,42,44,51]},"scoresAfter":[-41,-105]},{"ply":17,"player":"human","action":86,"playedCard":54,"placeType":"play","drawSource":"discard_1","drawnCard":17,"handsBefore":{"human":[7,21,27,28,32,39,45,54],"ai":[6,9,11,13,31,42,44,51]},"scoresAfter":[-31,-105]},{"ply":18,"player":"ai","action":90,"playedCard":51,"placeType":"discard","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[7,17,21,27,28,32,39,45],"ai":[6,9,11,13,31,42,44,51]},"scoresAfter":[-31,-105]},{"ply":19,"player":"human","action":12,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[7,17,21,27,28,32,39,45],"ai":[6,9,11,13,31,42,44,56]},"scoresAfter":[-27,-105]},{"ply":20,"player":"ai","action":84,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[7,21,27,28,32,34,39,45],"ai":[6,9,11,13,31,42,44,56]},"scoresAfter":[-27,-98]},{"ply":21,"player":"human","action":81,"playedCard":39,"placeType":"discard","drawSource":"discard_2","drawnCard":26,"handsBefore":{"human":[7,21,27,28,32,34,39,45],"ai":[6,9,11,13,31,42,44,59]},"scoresAfter":[-27,-98]},{"ply":22,"player":"ai","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[7,21,26,27,28,32,34,45],"ai":[6,9,11,13,31,42,44,59]},"scoresAfter":[-27,-83]},{"ply":23,"player":"human","action":24,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[7,21,26,27,28,32,34,45],"ai":[9,11,13,14,31,42,44,59]},"scoresAfter":[-67,-83]},{"ply":24,"player":"ai","action":30,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[7,21,27,28,32,34,43,45],"ai":[9,11,13,14,31,42,44,59]},"scoresAfter":[-67,-83]},{"ply":25,"player":"human","action":24,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[7,21,27,28,32,34,43,45],"ai":[9,11,14,31,42,44,49,59]},"scoresAfter":[-63,-83]},{"ply":26,"player":"ai","action":30,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[7,21,28,32,34,43,45,47],"ai":[9,11,14,31,42,44,49,59]},"scoresAfter":[-63,-83]},{"ply":27,"player":"human","action":24,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[7,21,28,32,34,43,45,47],"ai":[9,11,31,42,44,46,49,59]},"scoresAfter":[-57,-83]},{"ply":28,"player":"ai","action":24,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[7,12,21,32,34,43,45,47],"ai":[9,11,31,42,44,46,49,59]},"scoresAfter":[-57,-97]},{"ply":29,"player":"human","action":22,"playedCard":12,"placeType":"discard","drawSource":"discard_3","drawnCard":39,"handsBefore":{"human":[7,12,21,32,34,43,45,47],"ai":[9,11,23,42,44,46,49,59]},"scoresAfter":[-57,-97]},{"ply":30,"player":"ai","action":78,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[7,21,32,34,39,43,45,47],"ai":[9,11,23,42,44,46,49,59]},"scoresAfter":[-57,-97]},{"ply":31,"player":"human","action":28,"playedCard":32,"placeType":"play","drawSource":"discard_3","drawnCard":36,"handsBefore":{"human":[7,21,32,34,39,43,45,47],"ai":[9,11,23,41,42,44,46,59]},"scoresAfter":[-43,-97]},{"ply":32,"player":"ai","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[7,21,34,36,39,43,45,47],"ai":[9,11,23,41,42,44,46,59]},"scoresAfter":[-43,-87]},{"ply":33,"player":"human","action":24,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[7,21,34,36,39,43,45,47],"ai":[9,11,20,23,41,42,44,46]},"scoresAfter":[-25,-87]},{"ply":34,"player":"ai","action":48,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[7,21,29,36,39,43,45,47],"ai":[9,11,20,23,41,42,44,46]},"scoresAfter":[-25,-79]},{"ply":35,"player":"human","action":36,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[7,21,29,36,39,43,45,47],"ai":[9,11,20,23,42,44,46,57]},"scoresAfter":[-65,-79]},{"ply":36,"player":"ai","action":60,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[7,21,24,29,39,43,45,47],"ai":[9,11,20,23,42,44,46,57]},"scoresAfter":[-65,-65]},{"ply":37,"player":"human","action":48,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[7,21,24,29,39,43,45,47],"ai":[9,11,20,23,25,42,46,57]},"scoresAfter":[-61,-65]},{"ply":38,"player":"ai","action":74,"playedCard":46,"placeType":"play","drawSource":"discard_1","drawnCard":12,"handsBefore":{"human":[7,19,21,24,29,43,45,47],"ai":[9,11,20,23,25,42,46,57]},"scoresAfter":[-61,-47]},{"ply":39,"player":"human","action":12,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[7,19,21,24,29,43,45,47],"ai":[9,11,12,20,23,25,42,57]},"scoresAfter":[-55,-47]},{"ply":40,"player":"ai","action":2,"playedCard":9,"placeType":"play","drawSource":"discard_1","drawnCard":14,"handsBefore":{"human":[5,7,21,24,29,43,45,47],"ai":[9,11,12,20,23,25,42,57]},"scoresAfter":[-55,-23]},{"ply":41,"player":"human","action":60,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[5,7,21,24,29,43,45,47],"ai":[11,12,14,20,23,25,42,57]},"scoresAfter":[-43,-23]},{"ply":42,"player":"ai","action":2,"playedCard":11,"placeType":"play","drawSource":"discard_1","drawnCard":13,"handsBefore":{"human":[3,5,7,21,24,29,45,47],"ai":[11,12,14,20,23,25,42,57]},"scoresAfter":[-43,7]},{"ply":43,"player":"human","action":72,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[3,5,7,21,24,29,45,47],"ai":[12,13,14,20,23,25,42,57]},"scoresAfter":[-27,7]},{"ply":44,"player":"ai","action":24,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[3,5,7,18,21,24,29,47],"ai":[12,13,14,20,23,25,42,57]},"scoresAfter":[-27,-33]},{"ply":45,"player":"human","action":84,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[3,5,7,18,21,24,29,47],"ai":[12,13,20,23,25,33,42,57]},"scoresAfter":[-7,-33]},{"ply":46,"player":"ai","action":0,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[3,5,7,10,18,21,24,29],"ai":[12,13,20,23,25,33,42,57]},"scoresAfter":[-7,-53]},{"ply":47,"player":"human","action":60,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[3,5,7,10,18,21,24,29],"ai":[13,20,23,25,30,33,42,57]},"scoresAfter":[1,-53]},{"ply":48,"player":"ai","action":0,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[3,5,7,8,10,18,24,29],"ai":[13,20,23,25,30,33,42,57]},"scoresAfter":[1,-73]},{"ply":49,"player":"human","action":24,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[3,5,7,8,10,18,24,29],"ai":[20,23,25,30,33,40,42,57]},"scoresAfter":[-13,-73]},{"ply":50,"player":"ai","action":0,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[3,5,8,10,18,22,24,29],"ai":[20,23,25,30,33,40,42,57]},"scoresAfter":[-13,-45]},{"ply":51,"player":"human","action":65,"playedCard":22,"placeType":"play","drawSource":"discard_4","drawnCard":49,"handsBefore":{"human":[3,5,8,10,18,22,24,29],"ai":[23,25,30,33,35,40,42,57]},"scoresAfter":[-4,-45]},{"ply":52,"player":"ai","action":5,"playedCard":23,"placeType":"play","drawSource":"discard_4","drawnCard":51,"handsBefore":{"human":[3,5,8,10,18,24,29,49],"ai":[23,25,30,33,35,40,42,57]},"scoresAfter":[-4,-5]},{"ply":53,"player":"human","action":24,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[3,5,8,10,18,24,29,49],"ai":[25,30,33,35,40,42,51,57]},"scoresAfter":[3,-5]},{"ply":54,"player":"ai","action":24,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[3,5,10,18,24,29,48,49],"ai":[25,30,33,35,40,42,51,57]},"scoresAfter":[3,3]},{"ply":55,"player":"human","action":24,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[3,5,10,18,24,29,48,49],"ai":[25,30,35,40,42,51,57,58]},"scoresAfter":[12,3]},{"ply":56,"player":"ai","action":24,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[0,3,5,18,24,29,48,49],"ai":[25,30,35,40,42,51,57,58]},"scoresAfter":[12,13]}],"finalScores":[12,13],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[1,32,21,2,16,52,36,39,11,6,26,44,9,55,38,15,53,50,28,17,4,54,42,45,13,7,51,27,31,56,34,59,14,43,49,47,46,12,23,41,20,29,57,24,25,19,5,3,18,33,10,30,8,40,22,35,48,58,0,37],"drawPtr":60,"cardLoc":[1,4,4,1,4,1,4,3,3,4,3,4,4,4,4,3,3,3,1,3,4,3,3,4,1,2,3,3,3,1,2,4,3,4,3,4,3,2,4,3,2,4,2,3,4,3,4,3,1,1,3,2,3,3,3,4,4,2,2,4],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,true,false,false,false,false,false,false,false,false],"colTop":[[9,9,9,10,5],[10,10,10,9,10]],"colHandshakes":[[0,0,1,1,1],[2,3,0,1,0]],"colLength":[[3,6,5,5,4],[6,5,3,4,3]],"piles":[[],[],[],[],[]],"toMove":0,"stepCount":56,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"46a16d0b-932e-4111-ad1a-f9d50a5198f4","seed":"vftnkz","startedAt":"2026-07-14T16:47:24.366Z","finishedAt":"2026-07-14T16:50:08.550Z","initialDeckOrder":[57,45,1,58,30,29,3,17,36,16,44,42,10,33,12,41,26,52,8,38,56,6,4,53,34,46,7,15,21,19,55,35,9,14,22,11,13,51,32,5,40,0,37,24,28,25,31,48,23,49,47,20,27,39,54,59,50,2,43,18],"moves":[{"ply":1,"player":"human","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[1,3,17,29,30,45,57,58],"ai":[10,12,16,33,36,41,42,44]},"scoresAfter":[0,0]},{"ply":2,"player":"ai","action":12,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[3,17,26,29,30,45,57,58],"ai":[10,12,16,33,36,41,42,44]},"scoresAfter":[0,-40]},{"ply":3,"player":"human","action":24,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[3,17,26,29,30,45,57,58],"ai":[10,16,33,36,41,42,44,52]},"scoresAfter":[-40,-40]},{"ply":4,"player":"ai","action":36,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[3,8,17,29,30,45,57,58],"ai":[10,16,33,36,41,42,44,52]},"scoresAfter":[-40,-80]},{"ply":5,"player":"human","action":36,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[3,8,17,29,30,45,57,58],"ai":[10,16,33,38,41,42,44,52]},"scoresAfter":[-32,-80]},{"ply":6,"player":"ai","action":12,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[3,8,17,30,45,56,57,58],"ai":[10,16,33,38,41,42,44,52]},"scoresAfter":[-32,-74]},{"ply":7,"player":"human","action":37,"playedCard":30,"placeType":"play","drawSource":"discard_0","drawnCard":1,"handsBefore":{"human":[3,8,17,30,45,56,57,58],"ai":[6,10,33,38,41,42,44,52]},"scoresAfter":[-22,-74]},{"ply":8,"player":"ai","action":12,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[1,3,8,17,45,56,57,58],"ai":[6,10,33,38,41,42,44,52]},"scoresAfter":[-22,-85]},{"ply":9,"player":"human","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[1,3,8,17,45,56,57,58],"ai":[4,6,33,38,41,42,44,52]},"scoresAfter":[-62,-85]},{"ply":10,"player":"ai","action":84,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[3,8,17,45,53,56,57,58],"ai":[4,6,33,38,41,42,44,52]},"scoresAfter":[-62,-102]},{"ply":11,"player":"human","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[3,8,17,45,53,56,57,58],"ai":[4,6,33,34,38,41,42,44]},"scoresAfter":[-58,-102]},{"ply":12,"player":"ai","action":48,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[8,17,45,46,53,56,57,58],"ai":[4,6,33,34,38,41,42,44]},"scoresAfter":[-58,-122]},{"ply":13,"player":"human","action":48,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[8,17,45,46,53,56,57,58],"ai":[4,6,7,33,34,41,42,44]},"scoresAfter":[-74,-122]},{"ply":14,"player":"ai","action":6,"playedCard":4,"placeType":"discard","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[8,15,17,45,46,56,57,58],"ai":[4,6,7,33,34,41,42,44]},"scoresAfter":[-74,-122]},{"ply":15,"player":"human","action":18,"playedCard":15,"placeType":"discard","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[8,15,17,45,46,56,57,58],"ai":[6,7,21,33,34,41,42,44]},"scoresAfter":[-74,-122]},{"ply":16,"player":"ai","action":6,"playedCard":6,"placeType":"discard","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[8,17,19,45,46,56,57,58],"ai":[6,7,21,33,34,41,42,44]},"scoresAfter":[-74,-122]},{"ply":17,"player":"human","action":61,"playedCard":56,"placeType":"play","drawSource":"discard_0","drawnCard":6,"handsBefore":{"human":[8,17,19,45,46,56,57,58],"ai":[7,21,33,34,41,42,44,55]},"scoresAfter":[-67,-122]},{"ply":18,"player":"ai","action":48,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[6,8,17,19,45,46,57,58],"ai":[7,21,33,34,41,42,44,55]},"scoresAfter":[-67,-110]},{"ply":19,"player":"human","action":73,"playedCard":57,"placeType":"play","drawSource":"discard_0","drawnCard":4,"handsBefore":{"human":[6,8,17,19,45,46,57,58],"ai":[7,21,33,34,35,42,44,55]},"scoresAfter":[-59,-110]},{"ply":20,"player":"ai","action":60,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[4,6,8,17,19,45,46,58],"ai":[7,21,33,34,35,42,44,55]},"scoresAfter":[-59,-95]},{"ply":21,"player":"human","action":86,"playedCard":58,"placeType":"play","drawSource":"discard_1","drawnCard":15,"handsBefore":{"human":[4,6,8,17,19,45,46,58],"ai":[7,9,21,33,34,35,44,55]},"scoresAfter":[-50,-95]},{"ply":22,"player":"ai","action":6,"playedCard":7,"placeType":"discard","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[4,6,8,15,17,19,45,46],"ai":[7,9,21,33,34,35,44,55]},"scoresAfter":[-50,-95]},{"ply":23,"player":"human","action":1,"playedCard":4,"placeType":"play","drawSource":"discard_0","drawnCard":7,"handsBefore":{"human":[4,6,8,15,17,19,45,46],"ai":[9,14,21,33,34,35,44,55]},"scoresAfter":[-44,-95]},{"ply":24,"player":"ai","action":84,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[6,7,8,15,17,19,45,46],"ai":[9,14,21,33,34,35,44,55]},"scoresAfter":[-44,-89]},{"ply":25,"player":"human","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[6,7,8,15,17,19,45,46],"ai":[9,14,21,22,33,34,35,44]},"scoresAfter":[-34,-89]},{"ply":26,"player":"ai","action":84,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[7,8,11,15,17,19,45,46],"ai":[9,14,21,22,33,34,35,44]},"scoresAfter":[-34,-68]},{"ply":27,"player":"human","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[7,8,11,15,17,19,45,46],"ai":[9,13,14,21,22,33,34,35]},"scoresAfter":[-22,-68]},{"ply":28,"player":"ai","action":6,"playedCard":9,"placeType":"discard","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[8,11,15,17,19,45,46,51],"ai":[9,13,14,21,22,33,34,35]},"scoresAfter":[-22,-68]},{"ply":29,"player":"human","action":1,"playedCard":8,"placeType":"play","drawSource":"discard_0","drawnCard":9,"handsBefore":{"human":[8,11,15,17,19,45,46,51],"ai":[13,14,21,22,32,33,34,35]},"scoresAfter":[-8,-68]},{"ply":30,"player":"ai","action":6,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[9,11,15,17,19,45,46,51],"ai":[13,14,21,22,32,33,34,35]},"scoresAfter":[-8,-68]},{"ply":31,"player":"human","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[9,11,15,17,19,45,46,51],"ai":[5,14,21,22,32,33,34,35]},"scoresAfter":[8,-68]},{"ply":32,"player":"ai","action":6,"playedCard":5,"placeType":"discard","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[11,15,17,19,40,45,46,51],"ai":[5,14,21,22,32,33,34,35]},"scoresAfter":[8,-68]},{"ply":33,"player":"human","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[11,15,17,19,40,45,46,51],"ai":[0,14,21,22,32,33,34,35]},"scoresAfter":[48,-68]},{"ply":34,"player":"ai","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[15,17,19,37,40,45,46,51],"ai":[0,14,21,22,32,33,34,35]},"scoresAfter":[48,-68]},{"ply":35,"player":"human","action":36,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[15,17,19,37,40,45,46,51],"ai":[14,21,22,24,32,33,34,35]},"scoresAfter":[8,-68]},{"ply":36,"player":"ai","action":36,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[15,17,19,28,40,45,46,51],"ai":[14,21,22,24,32,33,34,35]},"scoresAfter":[8,-108]},{"ply":37,"player":"human","action":48,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[15,17,19,28,40,45,46,51],"ai":[14,21,22,25,32,33,34,35]},"scoresAfter":[14,-108]},{"ply":38,"player":"ai","action":12,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[15,17,19,28,31,45,46,51],"ai":[14,21,22,25,32,33,34,35]},"scoresAfter":[14,-92]},{"ply":39,"player":"human","action":48,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[15,17,19,28,31,45,46,51],"ai":[14,22,25,32,33,34,35,48]},"scoresAfter":[26,-92]},{"ply":40,"player":"ai","action":36,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[15,17,19,23,28,45,46,51],"ai":[14,22,25,32,33,34,35,48]},"scoresAfter":[26,-78]},{"ply":41,"player":"human","action":60,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[15,17,19,23,28,45,46,51],"ai":[14,22,25,33,34,35,48,49]},"scoresAfter":[42,-78]},{"ply":42,"player":"ai","action":12,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[15,17,19,23,28,46,47,51],"ai":[14,22,25,33,34,35,48,49]},"scoresAfter":[42,-60]},{"ply":43,"player":"human","action":60,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[15,17,19,23,28,46,47,51],"ai":[14,20,25,33,34,35,48,49]},"scoresAfter":[60,-60]},{"ply":44,"player":"ai","action":36,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[15,17,19,23,27,28,47,51],"ai":[14,20,25,33,34,35,48,49]},"scoresAfter":[60,-44]},{"ply":45,"player":"human","action":74,"playedCard":47,"placeType":"play","drawSource":"discard_1","drawnCard":13,"handsBefore":{"human":[15,17,19,23,27,28,47,51],"ai":[14,20,25,34,35,39,48,49]},"scoresAfter":[80,-44]},{"ply":46,"player":"ai","action":36,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[13,15,17,19,23,27,28,51],"ai":[14,20,25,34,35,39,48,49]},"scoresAfter":[80,-26]},{"ply":47,"player":"human","action":6,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[13,15,17,19,23,27,28,51],"ai":[14,20,25,35,39,48,49,54]},"scoresAfter":[80,-26]},{"ply":48,"player":"ai","action":36,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[15,17,19,23,27,28,51,59],"ai":[14,20,25,35,39,48,49,54]},"scoresAfter":[80,-6]},{"ply":49,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[15,17,19,23,27,28,51,59],"ai":[14,20,25,39,48,49,50,54]},"scoresAfter":[90,-6]},{"ply":50,"player":"ai","action":30,"playedCard":25,"placeType":"discard","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[2,15,17,19,23,27,28,51],"ai":[14,20,25,39,48,49,50,54]},"scoresAfter":[90,-6]},{"ply":51,"player":"human","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[2,15,17,19,23,27,28,51],"ai":[14,20,39,43,48,49,50,54]},"scoresAfter":[90,-6]}],"finalScores":[90,-6],"outcome":"YOU WIN","finalState":{"deckOrder":[57,45,1,58,30,29,3,17,36,16,44,42,10,33,12,41,26,52,8,38,56,6,4,53,34,46,7,15,21,19,55,35,9,14,22,11,13,51,32,5,40,0,37,24,28,25,31,48,23,49,47,20,27,39,54,59,50,2,43,18],"drawPtr":60,"cardLoc":[5,3,5,3,3,5,3,3,3,3,4,3,4,5,2,1,4,1,1,1,2,4,4,1,4,5,3,1,1,3,3,3,4,4,4,4,4,3,4,2,3,4,4,2,4,3,3,3,2,2,2,1,4,3,2,4,3,3,3,3],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,0,6,10,10],[9,9,10,7,6]],"colHandshakes":[[1,0,1,1,0],[0,1,1,2,0]],"colLength":[[8,0,4,5,5],[1,4,5,5,2]],"piles":[[5,0,2],[13],[25],[],[]],"toMove":1,"stepCount":51,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"12445466-9867-41e0-b72a-05bbfef15c10","seed":"d1ka89","startedAt":"2026-07-14T16:50:09.524Z","finishedAt":"2026-07-14T16:51:26.338Z","initialDeckOrder":[6,24,11,3,0,32,29,57,54,59,55,18,7,45,25,28,56,43,2,26,30,40,14,5,48,19,41,12,23,17,9,50,8,38,53,52,4,10,58,33,31,37,49,35,13,22,36,16,15,39,44,1,21,27,34,47,20,46,42,51],"moves":[{"ply":1,"player":"human","action":0,"playedCard":0,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[0,3,6,11,24,29,32,57],"ai":[7,18,25,28,45,54,55,59]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":30,"playedCard":25,"placeType":"discard","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[3,6,11,24,29,32,56,57],"ai":[7,18,25,28,45,54,55,59]},"scoresAfter":[-40,0]},{"ply":3,"player":"human","action":36,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[3,6,11,24,29,32,56,57],"ai":[7,18,28,43,45,54,55,59]},"scoresAfter":[-80,0]},{"ply":4,"player":"ai","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[2,3,6,11,29,32,56,57],"ai":[7,18,28,43,45,54,55,59]},"scoresAfter":[-80,-14]},{"ply":5,"player":"human","action":0,"playedCard":2,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[2,3,6,11,29,32,56,57],"ai":[18,26,28,43,45,54,55,59]},"scoresAfter":[-100,-14]},{"ply":6,"player":"ai","action":60,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[3,6,11,29,30,32,56,57],"ai":[18,26,28,43,45,54,55,59]},"scoresAfter":[-100,-29]},{"ply":7,"player":"human","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[3,6,11,29,30,32,56,57],"ai":[18,26,28,40,43,45,55,59]},"scoresAfter":[-94,-29]},{"ply":8,"player":"ai","action":72,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[6,11,14,29,30,32,56,57],"ai":[18,26,28,40,43,45,55,59]},"scoresAfter":[-94,-23]},{"ply":9,"player":"human","action":33,"playedCard":14,"placeType":"discard","drawSource":"discard_2","drawnCard":25,"handsBefore":{"human":[6,11,14,29,30,32,56,57],"ai":[5,18,26,28,40,43,45,59]},"scoresAfter":[-94,-23]},{"ply":10,"player":"ai","action":30,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[6,11,25,29,30,32,56,57],"ai":[5,18,26,28,40,43,45,59]},"scoresAfter":[-94,-23]},{"ply":11,"player":"human","action":27,"playedCard":25,"placeType":"play","drawSource":"discard_2","drawnCard":26,"handsBefore":{"human":[6,11,25,29,30,32,56,57],"ai":[5,18,28,40,43,45,48,59]},"scoresAfter":[-114,-23]},{"ply":12,"player":"ai","action":78,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[6,11,26,29,30,32,56,57],"ai":[5,18,28,40,43,45,48,59]},"scoresAfter":[-114,-23]},{"ply":13,"player":"human","action":24,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[6,11,26,29,30,32,56,57],"ai":[5,18,19,28,40,43,45,59]},"scoresAfter":[-134,-23]},{"ply":14,"player":"ai","action":36,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[6,11,29,30,32,41,56,57],"ai":[5,18,19,28,40,43,45,59]},"scoresAfter":[-134,-40]},{"ply":15,"player":"human","action":24,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[6,11,29,30,32,41,56,57],"ai":[5,12,18,19,40,43,45,59]},"scoresAfter":[-118,-40]},{"ply":16,"player":"ai","action":12,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[6,11,23,30,32,41,56,57],"ai":[5,12,18,19,40,43,45,59]},"scoresAfter":[-118,-80]},{"ply":17,"player":"human","action":2,"playedCard":6,"placeType":"play","drawSource":"discard_1","drawnCard":14,"handsBefore":{"human":[6,11,23,30,32,41,56,57],"ai":[5,17,18,19,40,43,45,59]},"scoresAfter":[-103,-80]},{"ply":18,"player":"ai","action":36,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[11,14,23,30,32,41,56,57],"ai":[5,17,18,19,40,43,45,59]},"scoresAfter":[-103,-68]},{"ply":19,"player":"human","action":12,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[11,14,23,30,32,41,56,57],"ai":[5,9,17,18,40,43,45,59]},"scoresAfter":[-143,-68]},{"ply":20,"player":"ai","action":72,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[11,23,30,32,41,50,56,57],"ai":[5,9,17,18,40,43,45,59]},"scoresAfter":[-143,-80]},{"ply":21,"player":"human","action":65,"playedCard":50,"placeType":"play","drawSource":"discard_4","drawnCard":48,"handsBefore":{"human":[11,23,30,32,41,50,56,57],"ai":[5,8,9,17,18,40,43,59]},"scoresAfter":[-183,-80]},{"ply":22,"player":"ai","action":12,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[11,23,30,32,41,48,56,57],"ai":[5,8,9,17,18,40,43,59]},"scoresAfter":[-183,-73]},{"ply":23,"player":"human","action":60,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[11,23,30,32,41,48,56,57],"ai":[5,9,17,18,38,40,43,59]},"scoresAfter":[-203,-73]},{"ply":24,"player":"ai","action":66,"playedCard":40,"placeType":"discard","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[11,23,30,32,41,53,56,57],"ai":[5,9,17,18,38,40,43,59]},"scoresAfter":[-203,-73]},{"ply":25,"player":"human","action":60,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[11,23,30,32,41,53,56,57],"ai":[5,9,17,18,38,43,52,59]},"scoresAfter":[-191,-73]},{"ply":26,"player":"ai","action":66,"playedCard":43,"placeType":"discard","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[4,11,23,30,32,41,56,57],"ai":[5,9,17,18,38,43,52,59]},"scoresAfter":[-191,-73]},{"ply":27,"player":"human","action":72,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[4,11,23,30,32,41,56,57],"ai":[5,9,10,17,18,38,52,59]},"scoresAfter":[-170,-73]},{"ply":28,"player":"ai","action":78,"playedCard":52,"placeType":"discard","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[4,11,23,30,32,41,57,58],"ai":[5,9,10,17,18,38,52,59]},"scoresAfter":[-170,-73]},{"ply":29,"player":"human","action":72,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[4,11,23,30,32,41,57,58],"ai":[5,9,10,17,18,33,38,59]},"scoresAfter":[-146,-73]},{"ply":30,"player":"ai","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[4,11,23,30,31,32,41,58],"ai":[5,9,10,17,18,33,38,59]},"scoresAfter":[-146,-63]},{"ply":31,"player":"human","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[4,11,23,30,31,32,41,58],"ai":[5,9,10,17,18,33,37,38]},"scoresAfter":[-119,-63]},{"ply":32,"player":"ai","action":12,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[4,11,23,30,31,32,41,49],"ai":[5,9,10,17,18,33,37,38]},"scoresAfter":[-119,-55]},{"ply":33,"player":"human","action":36,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[4,11,23,30,31,32,41,49],"ai":[5,10,17,18,33,35,37,38]},"scoresAfter":[-99,-55]},{"ply":34,"player":"ai","action":12,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[4,11,13,23,31,32,41,49],"ai":[5,10,17,18,33,35,37,38]},"scoresAfter":[-99,-46]},{"ply":35,"player":"human","action":48,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[4,11,13,23,31,32,41,49],"ai":[5,17,18,22,33,35,37,38]},"scoresAfter":[-75,-46]},{"ply":36,"player":"ai","action":6,"playedCard":5,"placeType":"discard","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[4,11,13,23,32,36,41,49],"ai":[5,17,18,22,33,35,37,38]},"scoresAfter":[-75,-46]},{"ply":37,"player":"human","action":48,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[4,11,13,23,32,36,41,49],"ai":[16,17,18,22,33,35,37,38]},"scoresAfter":[-47,-46]},{"ply":38,"player":"ai","action":48,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[4,11,13,15,23,36,41,49],"ai":[16,17,18,22,33,35,37,38]},"scoresAfter":[-47,-38]},{"ply":39,"player":"human","action":24,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[4,11,13,15,23,36,41,49],"ai":[16,17,18,22,35,37,38,39]},"scoresAfter":[-67,-38]},{"ply":40,"player":"ai","action":48,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[4,11,15,23,36,41,44,49],"ai":[16,17,18,22,35,37,38,39]},"scoresAfter":[-67,-28]},{"ply":41,"player":"human","action":24,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[4,11,15,23,36,41,44,49],"ai":[1,16,17,18,22,37,38,39]},"scoresAfter":[-61,-28]},{"ply":42,"player":"ai","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[4,11,21,23,36,41,44,49],"ai":[1,16,17,18,22,37,38,39]},"scoresAfter":[-61,-28]},{"ply":43,"player":"human","action":90,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[4,11,21,23,36,41,44,49],"ai":[16,17,18,22,27,37,38,39]},"scoresAfter":[-61,-28]},{"ply":44,"player":"ai","action":36,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[4,11,21,23,34,36,41,44],"ai":[16,17,18,22,27,37,38,39]},"scoresAfter":[-61,-10]},{"ply":45,"player":"human","action":48,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[4,11,21,23,34,36,41,44],"ai":[16,17,18,27,37,38,39,47]},"scoresAfter":[-5,-10]},{"ply":46,"player":"ai","action":84,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[4,11,20,21,23,36,41,44],"ai":[16,17,18,27,37,38,39,47]},"scoresAfter":[-5,0]},{"ply":47,"player":"human","action":25,"playedCard":20,"placeType":"play","drawSource":"discard_0","drawnCard":1,"handsBefore":{"human":[4,11,20,21,23,36,41,44],"ai":[16,17,18,27,37,38,39,46]},"scoresAfter":[16,0]},{"ply":48,"player":"ai","action":66,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[1,4,11,21,23,36,41,44],"ai":[16,17,18,27,37,38,39,46]},"scoresAfter":[16,0]},{"ply":49,"player":"human","action":52,"playedCard":23,"placeType":"play","drawSource":"discard_3","drawnCard":38,"handsBefore":{"human":[1,4,11,21,23,36,41,44],"ai":[16,17,18,27,37,39,42,46]},"scoresAfter":[46,0]},{"ply":50,"player":"ai","action":6,"playedCard":16,"placeType":"discard","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[1,4,11,21,36,38,41,44],"ai":[16,17,18,27,37,39,42,46]},"scoresAfter":[46,0]}],"finalScores":[46,0],"outcome":"YOU WIN","finalState":{"deckOrder":[6,24,11,3,0,32,29,57,54,59,55,18,7,45,25,28,56,43,2,26,30,40,14,5,48,19,41,12,23,17,9,50,8,38,53,52,4,10,58,33,31,37,49,35,13,22,36,16,15,39,44,1,21,27,34,47,20,46,42,51],"drawPtr":60,"cardLoc":[3,1,3,3,1,5,3,4,4,4,4,1,4,3,3,3,5,2,2,4,3,1,4,3,3,3,3,2,4,3,3,3,3,4,3,4,1,2,1,2,5,1,2,5,1,4,2,4,3,5,3,2,5,3,4,4,3,3,3,4],"handPublic":[false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[5,10,9,0,9],[9,9,10,10,10]],"colHandshakes":[[2,2,3,0,2],[0,1,0,0,0]],"colLength":[[4,5,8,0,6],[4,3,3,2,3]],"piles":[[5],[16],[],[40,43],[52,49]],"toMove":0,"stepCount":50,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"ecd890ac-3bad-45c8-be2e-c0735d004ab4","seed":"fonkeh","startedAt":"2026-07-14T16:51:26.973Z","finishedAt":"2026-07-14T16:53:39.100Z","initialDeckOrder":[2,39,41,53,9,55,6,8,29,5,11,17,27,46,32,44,22,16,23,18,13,12,58,59,33,20,57,30,25,7,35,40,56,4,52,54,36,21,10,19,14,31,48,43,3,28,37,38,15,26,34,1,51,49,24,42,47,0,45,50],"moves":[{"ply":1,"player":"human","action":0,"playedCard":2,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[2,6,8,9,39,41,53,55],"ai":[5,11,17,27,29,32,44,46]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[6,8,9,22,39,41,53,55],"ai":[5,11,17,27,29,32,44,46]},"scoresAfter":[-40,-16]},{"ply":3,"player":"human","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[6,8,9,22,39,41,53,55],"ai":[11,16,17,27,29,32,44,46]},"scoresAfter":[-30,-16]},{"ply":4,"player":"ai","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[8,9,22,23,39,41,53,55],"ai":[11,16,17,27,29,32,44,46]},"scoresAfter":[-30,-6]},{"ply":5,"player":"human","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[8,9,22,23,39,41,53,55],"ai":[16,17,18,27,29,32,44,46]},"scoresAfter":[-16,-6]},{"ply":6,"player":"ai","action":0,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[9,13,22,23,39,41,53,55],"ai":[16,17,18,27,29,32,44,46]},"scoresAfter":[-16,-23]},{"ply":7,"player":"human","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[9,13,22,23,39,41,53,55],"ai":[12,17,18,27,29,32,44,46]},"scoresAfter":[0,-23]},{"ply":8,"player":"ai","action":6,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[13,22,23,39,41,53,55,58],"ai":[12,17,18,27,29,32,44,46]},"scoresAfter":[0,-23]},{"ply":9,"player":"human","action":2,"playedCard":13,"placeType":"play","drawSource":"discard_1","drawnCard":12,"handsBefore":{"human":[13,22,23,39,41,53,55,58],"ai":[17,18,27,29,32,44,46,59]},"scoresAfter":[-40,-23]},{"ply":10,"player":"ai","action":0,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[12,22,23,39,41,53,55,58],"ai":[17,18,27,29,32,44,46,59]},"scoresAfter":[-40,-19]},{"ply":11,"player":"human","action":0,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[12,22,23,39,41,53,55,58],"ai":[18,27,29,32,33,44,46,59]},"scoresAfter":[-60,-19]},{"ply":12,"player":"ai","action":0,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[20,22,23,39,41,53,55,58],"ai":[18,27,29,32,33,44,46,59]},"scoresAfter":[-60,-14]},{"ply":13,"player":"human","action":60,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[20,22,23,39,41,53,55,58],"ai":[27,29,32,33,44,46,57,59]},"scoresAfter":[-76,-14]},{"ply":14,"player":"ai","action":72,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[20,22,23,30,39,41,55,58],"ai":[27,29,32,33,44,46,57,59]},"scoresAfter":[-76,-26]},{"ply":15,"player":"human","action":72,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[20,22,23,30,39,41,55,58],"ai":[25,27,29,32,33,44,46,59]},"scoresAfter":[-70,-26]},{"ply":16,"player":"ai","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[7,20,22,23,30,39,41,58],"ai":[25,27,29,32,33,44,46,59]},"scoresAfter":[-70,-16]},{"ply":17,"player":"human","action":6,"playedCard":7,"placeType":"discard","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[7,20,22,23,30,39,41,58],"ai":[25,27,29,32,33,35,44,46]},"scoresAfter":[-70,-16]},{"ply":18,"player":"ai","action":72,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[20,22,23,30,39,40,41,58],"ai":[25,27,29,32,33,35,44,46]},"scoresAfter":[-70,-29]},{"ply":19,"player":"human","action":48,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[20,22,23,30,39,40,41,58],"ai":[25,27,29,32,33,35,46,56]},"scoresAfter":[-88,-29]},{"ply":20,"player":"ai","action":72,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[4,20,22,23,30,40,41,58],"ai":[25,27,29,32,33,35,46,56]},"scoresAfter":[-88,-20]},{"ply":21,"player":"human","action":60,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[4,20,22,23,30,40,41,58],"ai":[25,27,29,32,33,35,52,56]},"scoresAfter":[-85,-20]},{"ply":22,"player":"ai","action":90,"playedCard":56,"placeType":"discard","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[4,20,22,23,30,41,54,58],"ai":[25,27,29,32,33,35,52,56]},"scoresAfter":[-85,-20]},{"ply":23,"player":"human","action":60,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[4,20,22,23,30,41,54,58],"ai":[25,27,29,32,33,35,36,52]},"scoresAfter":[-81,-20]},{"ply":24,"player":"ai","action":90,"playedCard":52,"placeType":"discard","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[4,20,21,22,23,30,54,58],"ai":[25,27,29,32,33,35,36,52]},"scoresAfter":[-81,-20]},{"ply":25,"player":"human","action":17,"playedCard":20,"placeType":"play","drawSource":"discard_4","drawnCard":52,"handsBefore":{"human":[4,20,21,22,23,30,54,58],"ai":[10,25,27,29,32,33,35,36]},"scoresAfter":[-60,-20]},{"ply":26,"player":"ai","action":90,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[4,21,22,23,30,52,54,58],"ai":[10,25,27,29,32,33,35,36]},"scoresAfter":[-60,-20]},{"ply":27,"player":"human","action":17,"playedCard":21,"placeType":"play","drawSource":"discard_4","drawnCard":56,"handsBefore":{"human":[4,21,22,23,30,52,54,58],"ai":[10,19,25,27,29,32,33,35]},"scoresAfter":[-36,-20]},{"ply":28,"player":"ai","action":12,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[4,22,23,30,52,54,56,58],"ai":[10,19,25,27,29,32,33,35]},"scoresAfter":[-36,-14]},{"ply":29,"player":"human","action":72,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[4,22,23,30,52,54,56,58],"ai":[10,14,25,27,29,32,33,35]},"scoresAfter":[-29,-14]},{"ply":30,"player":"ai","action":18,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[4,22,23,30,31,52,54,58],"ai":[10,14,25,27,29,32,33,35]},"scoresAfter":[-29,-14]},{"ply":31,"player":"human","action":12,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[4,22,23,30,31,52,54,58],"ai":[10,25,27,29,32,33,35,48]},"scoresAfter":[-2,-14]},{"ply":32,"player":"ai","action":90,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[4,23,30,31,43,52,54,58],"ai":[10,25,27,29,32,33,35,48]},"scoresAfter":[-2,-14]},{"ply":33,"player":"human","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[4,23,30,31,43,52,54,58],"ai":[3,10,25,27,29,32,33,35]},"scoresAfter":[7,-14]},{"ply":34,"player":"ai","action":24,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[4,23,28,30,31,43,52,54],"ai":[3,10,25,27,29,32,33,35]},"scoresAfter":[7,-54]},{"ply":35,"player":"human","action":12,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[4,23,28,30,31,43,52,54],"ai":[3,10,27,29,32,33,35,37]},"scoresAfter":[37,-54]},{"ply":36,"player":"ai","action":90,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[4,28,30,31,38,43,52,54],"ai":[3,10,27,29,32,33,35,37]},"scoresAfter":[37,-54]},{"ply":37,"player":"human","action":60,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[4,28,30,31,38,43,52,54],"ai":[3,10,15,27,29,32,33,35]},"scoresAfter":[43,-54]},{"ply":38,"player":"ai","action":36,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[4,26,28,30,31,38,52,54],"ai":[3,10,15,27,29,32,33,35]},"scoresAfter":[43,-50]},{"ply":39,"player":"human","action":6,"playedCard":4,"placeType":"discard","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[4,26,28,30,31,38,52,54],"ai":[3,10,15,29,32,33,34,35]},"scoresAfter":[43,-50]},{"ply":40,"player":"ai","action":41,"playedCard":29,"placeType":"play","drawSource":"discard_4","drawnCard":48,"handsBefore":{"human":[1,26,28,30,31,38,52,54],"ai":[3,10,15,29,32,33,34,35]},"scoresAfter":[43,-42]},{"ply":41,"player":"human","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[1,26,28,30,31,38,52,54],"ai":[3,10,15,32,33,34,35,48]},"scoresAfter":[43,-42]},{"ply":42,"player":"ai","action":36,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[26,28,30,31,38,51,52,54],"ai":[3,10,15,32,33,34,35,48]},"scoresAfter":[43,-28]},{"ply":43,"player":"human","action":6,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[26,28,30,31,38,51,52,54],"ai":[3,10,15,33,34,35,48,49]},"scoresAfter":[43,-28]},{"ply":44,"player":"ai","action":40,"playedCard":33,"placeType":"play","drawSource":"discard_3","drawnCard":37,"handsBefore":{"human":[24,28,30,31,38,51,52,54],"ai":[3,10,15,33,34,35,48,49]},"scoresAfter":[43,-12]},{"ply":45,"player":"human","action":6,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[24,28,30,31,38,51,52,54],"ai":[3,10,15,34,35,37,48,49]},"scoresAfter":[43,-12]},{"ply":46,"player":"ai","action":36,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[28,30,31,38,42,51,52,54],"ai":[3,10,15,34,35,37,48,49]},"scoresAfter":[43,6]},{"ply":47,"player":"human","action":42,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[28,30,31,38,42,51,52,54],"ai":[3,10,15,35,37,47,48,49]},"scoresAfter":[43,6]},{"ply":48,"player":"ai","action":38,"playedCard":35,"placeType":"play","drawSource":"discard_1","drawnCard":14,"handsBefore":{"human":[0,28,30,31,42,51,52,54],"ai":[3,10,15,35,37,47,48,49]},"scoresAfter":[43,26]},{"ply":49,"player":"human","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[0,28,30,31,42,51,52,54],"ai":[3,10,14,15,37,47,48,49]},"scoresAfter":[43,26]},{"ply":50,"player":"ai","action":60,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[28,30,31,42,45,51,52,54],"ai":[3,10,14,15,37,47,48,49]},"scoresAfter":[43,36]}],"finalScores":[43,36],"outcome":"YOU WIN","finalState":{"deckOrder":[2,39,41,53,9,55,6,8,29,5,11,17,27,46,32,44,22,16,23,18,13,12,58,59,33,20,57,30,25,7,35,40,56,4,52,54,36,21,10,19,14,31,48,43,3,28,37,38,15,26,34,1,51,49,24,42,47,0,45,50],"drawPtr":60,"cardLoc":[5,5,3,2,5,4,3,5,3,3,2,4,3,3,2,2,4,4,4,4,3,3,3,3,5,4,5,4,1,4,1,1,4,4,4,4,5,2,5,3,3,3,1,3,4,1,4,4,2,2,2,1,1,3,1,3,3,4,3,4],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,true,false,false,false,true,false,false,false,false,false,false,false],"colTop":[[8,10,0,6,9],[10,6,10,10,10]],"colHandshakes":[[1,2,0,0,0],[0,0,1,0,0]],"colLength":[[4,6,0,4,4],[2,4,7,3,2]],"piles":[[7,4,1,0],[],[26,24],[36,38],[]],"toMove":0,"stepCount":50,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"6e0292db-de9d-48d6-b465-e24f7819e7ca","seed":"f6dr25","startedAt":"2026-07-14T16:53:39.957Z","finishedAt":"2026-07-14T16:55:23.259Z","initialDeckOrder":[8,34,29,37,56,50,24,38,28,46,35,16,42,26,58,32,4,55,33,17,39,5,49,18,11,31,40,51,1,57,12,54,6,3,19,22,15,10,43,52,27,0,14,45,20,23,9,21,47,41,30,7,2,59,44,13,25,48,53,36],"moves":[{"ply":1,"player":"human","action":12,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[8,24,29,34,37,38,50,56],"ai":[16,26,28,32,35,42,46,58]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":0,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[4,8,29,34,37,38,50,56],"ai":[16,26,28,32,35,42,46,58]},"scoresAfter":[-40,-17]},{"ply":3,"player":"human","action":72,"playedCard":50,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[4,8,29,34,37,38,50,56],"ai":[26,28,32,35,42,46,55,58]},"scoresAfter":[-80,-17]},{"ply":4,"player":"ai","action":72,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[4,8,29,33,34,37,38,56],"ai":[26,28,32,35,42,46,55,58]},"scoresAfter":[-80,-31]},{"ply":5,"player":"human","action":24,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[4,8,29,33,34,37,38,56],"ai":[17,26,28,32,35,42,46,58]},"scoresAfter":[-72,-31]},{"ply":6,"player":"ai","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[4,8,33,34,37,38,39,56],"ai":[17,26,28,32,35,42,46,58]},"scoresAfter":[-72,-22]},{"ply":7,"player":"human","action":54,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[4,8,33,34,37,38,39,56],"ai":[5,17,26,28,32,35,42,46]},"scoresAfter":[-72,-22]},{"ply":8,"player":"ai","action":24,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[4,8,33,34,38,39,49,56],"ai":[5,17,26,28,32,35,42,46]},"scoresAfter":[-72,-62]},{"ply":9,"player":"human","action":54,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[4,8,33,34,38,39,49,56],"ai":[5,17,18,28,32,35,42,46]},"scoresAfter":[-72,-62]},{"ply":10,"player":"ai","action":4,"playedCard":5,"placeType":"play","drawSource":"discard_3","drawnCard":38,"handsBefore":{"human":[4,8,11,33,34,39,49,56],"ai":[5,17,18,28,32,35,42,46]},"scoresAfter":[-72,-78]},{"ply":11,"player":"human","action":72,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[4,8,11,33,34,39,49,56],"ai":[17,18,28,32,35,38,42,46]},"scoresAfter":[-92,-78]},{"ply":12,"player":"ai","action":0,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[4,8,11,31,33,34,39,56],"ai":[17,18,28,32,35,38,42,46]},"scoresAfter":[-92,-74]},{"ply":13,"player":"human","action":36,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[4,8,11,31,33,34,39,56],"ai":[18,28,32,35,38,40,42,46]},"scoresAfter":[-80,-74]},{"ply":14,"player":"ai","action":48,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[4,8,11,33,34,39,51,56],"ai":[18,28,32,35,38,40,42,46]},"scoresAfter":[-80,-114]},{"ply":15,"player":"human","action":72,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[4,8,11,33,34,39,51,56],"ai":[1,18,28,32,35,40,42,46]},"scoresAfter":[-74,-114]},{"ply":16,"player":"ai","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[4,8,11,33,34,39,56,57],"ai":[1,18,28,32,35,40,42,46]},"scoresAfter":[-74,-114]},{"ply":17,"player":"human","action":37,"playedCard":33,"placeType":"play","drawSource":"discard_0","drawnCard":1,"handsBefore":{"human":[4,8,11,33,34,39,56,57],"ai":[12,18,28,32,35,40,42,46]},"scoresAfter":[-58,-114]},{"ply":18,"player":"ai","action":16,"playedCard":18,"placeType":"play","drawSource":"discard_3","drawnCard":37,"handsBefore":{"human":[1,4,8,11,34,39,56,57],"ai":[12,18,28,32,35,40,42,46]},"scoresAfter":[-58,-109]},{"ply":19,"player":"human","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[1,4,8,11,34,39,56,57],"ai":[12,28,32,35,37,40,42,46]},"scoresAfter":[-98,-109]},{"ply":20,"player":"ai","action":48,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[4,8,11,34,39,54,56,57],"ai":[12,28,32,35,37,40,42,46]},"scoresAfter":[-98,-129]},{"ply":21,"player":"human","action":60,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[4,8,11,34,39,54,56,57],"ai":[6,12,28,32,35,40,42,46]},"scoresAfter":[-83,-129]},{"ply":22,"player":"ai","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[3,4,8,11,34,39,56,57],"ai":[6,12,28,32,35,40,42,46]},"scoresAfter":[-83,-124]},{"ply":23,"player":"human","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[3,4,8,11,34,39,56,57],"ai":[12,19,28,32,35,40,42,46]},"scoresAfter":[-79,-124]},{"ply":24,"player":"ai","action":24,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[4,8,11,22,34,39,56,57],"ai":[12,19,28,32,35,40,42,46]},"scoresAfter":[-79,-118]},{"ply":25,"player":"human","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[4,8,11,22,34,39,56,57],"ai":[12,15,19,32,35,40,42,46]},"scoresAfter":[-73,-118]},{"ply":26,"player":"ai","action":24,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[8,10,11,22,34,39,56,57],"ai":[12,15,19,32,35,40,42,46]},"scoresAfter":[-73,-112]},{"ply":27,"player":"human","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[8,10,11,22,34,39,56,57],"ai":[12,15,32,35,40,42,43,46]},"scoresAfter":[-59,-112]},{"ply":28,"player":"ai","action":24,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[10,11,22,34,39,52,56,57],"ai":[12,15,32,35,40,42,43,46]},"scoresAfter":[-59,-98]},{"ply":29,"player":"human","action":72,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[10,11,22,34,39,52,56,57],"ai":[12,15,27,35,40,42,43,46]},"scoresAfter":[-38,-98]},{"ply":30,"player":"ai","action":36,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[0,10,11,22,34,39,52,57],"ai":[12,15,27,35,40,42,43,46]},"scoresAfter":[-38,-78]},{"ply":31,"player":"human","action":84,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[0,10,11,22,34,39,52,57],"ai":[12,14,15,27,40,42,43,46]},"scoresAfter":[-14,-78]},{"ply":32,"player":"ai","action":48,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[0,10,11,22,34,39,45,52],"ai":[12,14,15,27,40,42,43,46]},"scoresAfter":[-14,-69]},{"ply":33,"player":"human","action":48,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[0,10,11,22,34,39,45,52],"ai":[12,14,15,20,27,42,43,46]},"scoresAfter":[4,-69]},{"ply":34,"player":"ai","action":36,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[0,10,11,22,23,39,45,52],"ai":[12,14,15,20,27,42,43,46]},"scoresAfter":[4,-62]},{"ply":35,"player":"human","action":12,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[0,10,11,22,23,39,45,52],"ai":[9,12,14,15,27,42,43,46]},"scoresAfter":[22,-62]},{"ply":36,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[0,11,21,22,23,39,45,52],"ai":[9,12,14,15,27,42,43,46]},"scoresAfter":[22,-54]},{"ply":37,"player":"human","action":12,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[0,11,21,22,23,39,45,52],"ai":[12,14,15,27,42,43,46,47]},"scoresAfter":[42,-54]},{"ply":38,"player":"ai","action":48,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[0,21,22,23,39,41,45,52],"ai":[12,14,15,27,42,43,46,47]},"scoresAfter":[42,-39]},{"ply":39,"player":"human","action":12,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[0,21,22,23,39,41,45,52],"ai":[12,14,15,27,30,43,46,47]},"scoresAfter":[30,-39]},{"ply":40,"player":"ai","action":18,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[0,7,22,23,39,41,45,52],"ai":[12,14,15,27,30,43,46,47]},"scoresAfter":[30,-39]},{"ply":41,"player":"human","action":24,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[0,7,22,23,39,41,45,52],"ai":[2,12,15,27,30,43,46,47]},"scoresAfter":[39,-39]},{"ply":42,"player":"ai","action":18,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[0,7,23,39,41,45,52,59],"ai":[2,12,15,27,30,43,46,47]},"scoresAfter":[39,-39]},{"ply":43,"player":"human","action":24,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[0,7,23,39,41,45,52,59],"ai":[2,15,27,30,43,44,46,47]},"scoresAfter":[49,-39]},{"ply":44,"player":"ai","action":50,"playedCard":43,"placeType":"play","drawSource":"discard_1","drawnCard":12,"handsBefore":{"human":[0,7,13,39,41,45,52,59],"ai":[2,15,27,30,43,44,46,47]},"scoresAfter":[49,-21]},{"ply":45,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[0,7,13,39,41,45,52,59],"ai":[2,12,15,27,30,44,46,47]},"scoresAfter":[79,-21]},{"ply":46,"player":"ai","action":62,"playedCard":44,"placeType":"play","drawSource":"discard_1","drawnCard":14,"handsBefore":{"human":[0,7,13,25,39,41,45,52],"ai":[2,12,15,27,30,44,46,47]},"scoresAfter":[79,0]},{"ply":47,"player":"human","action":42,"playedCard":25,"placeType":"discard","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[0,7,13,25,39,41,45,52],"ai":[2,12,14,15,27,30,46,47]},"scoresAfter":[79,0]},{"ply":48,"player":"ai","action":45,"playedCard":15,"placeType":"discard","drawSource":"discard_2","drawnCard":25,"handsBefore":{"human":[0,7,13,39,41,45,48,52],"ai":[2,12,14,15,27,30,46,47]},"scoresAfter":[79,0]},{"ply":49,"player":"human","action":78,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[0,7,13,39,41,45,48,52],"ai":[2,12,14,25,27,30,46,47]},"scoresAfter":[79,0]},{"ply":50,"player":"ai","action":74,"playedCard":46,"placeType":"play","drawSource":"discard_1","drawnCard":15,"handsBefore":{"human":[0,7,13,39,41,45,52,53],"ai":[2,12,14,25,27,30,46,47]},"scoresAfter":[79,27]},{"ply":51,"player":"human","action":78,"playedCard":52,"placeType":"discard","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[0,7,13,39,41,45,52,53],"ai":[2,12,14,15,25,27,30,47]},"scoresAfter":[79,27]}],"finalScores":[79,27],"outcome":"YOU WIN","finalState":{"deckOrder":[8,34,29,37,56,50,24,38,28,46,35,16,42,26,58,32,4,55,33,17,39,5,49,18,11,31,40,51,1,57,12,54,6,3,19,22,15,10,43,52,27,0,14,45,20,23,9,21,47,41,30,7,2,59,44,13,25,48,53,36],"drawPtr":60,"cardLoc":[1,3,2,3,3,4,4,1,3,4,3,3,2,1,2,2,4,4,4,4,4,3,3,3,3,2,4,2,4,3,2,3,4,3,3,4,1,4,4,1,4,1,4,4,4,1,4,2,5,3,3,3,5,1,3,4,3,3,4,3],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,true,false,true,true,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,10,9,0,10],[8,7,10,9,9]],"colHandshakes":[[1,0,1,0,2],[0,0,1,2,0]],"colLength":[[6,3,5,0,7],[3,5,4,7,2]],"piles":[[],[],[],[],[48,52]],"toMove":1,"stepCount":51,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"7e8efd4e-070d-44b0-adb9-4b30876f3687","seed":"rs60fe","startedAt":"2026-07-14T16:55:24.180Z","finishedAt":"2026-07-14T16:58:31.039Z","initialDeckOrder":[52,59,2,17,26,12,0,58,57,18,9,35,36,25,53,47,38,43,31,33,45,42,29,15,10,54,4,20,1,40,27,32,19,5,13,55,3,23,24,34,22,49,56,41,37,48,14,6,16,21,51,46,44,50,7,30,28,8,11,39],"moves":[{"ply":1,"player":"human","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[0,2,12,17,26,52,58,59],"ai":[9,18,25,35,36,47,53,57]},"scoresAfter":[0,0]},{"ply":2,"player":"ai","action":72,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[2,12,17,26,38,52,58,59],"ai":[9,18,25,35,36,47,53,57]},"scoresAfter":[0,-16]},{"ply":3,"player":"human","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[2,12,17,26,38,52,58,59],"ai":[9,18,25,35,36,43,47,57]},"scoresAfter":[0,-16]},{"ply":4,"player":"ai","action":84,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[12,17,26,31,38,52,58,59],"ai":[9,18,25,35,36,43,47,57]},"scoresAfter":[0,-8]},{"ply":5,"player":"human","action":54,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[12,17,26,31,38,52,58,59],"ai":[9,18,25,33,35,36,43,47]},"scoresAfter":[0,-8]},{"ply":6,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[12,17,26,31,45,52,58,59],"ai":[9,18,25,33,35,36,43,47]},"scoresAfter":[0,-20]},{"ply":7,"player":"human","action":6,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[12,17,26,31,45,52,58,59],"ai":[18,25,33,35,36,42,43,47]},"scoresAfter":[0,-20]},{"ply":8,"player":"ai","action":12,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[17,26,29,31,45,52,58,59],"ai":[18,25,33,35,36,42,43,47]},"scoresAfter":[0,-60]},{"ply":9,"player":"human","action":12,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[17,26,29,31,45,52,58,59],"ai":[15,18,33,35,36,42,43,47]},"scoresAfter":[-40,-60]},{"ply":10,"player":"ai","action":0,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[10,17,29,31,45,52,58,59],"ai":[15,18,33,35,36,42,43,47]},"scoresAfter":[-40,-78]},{"ply":11,"player":"human","action":24,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[10,17,29,31,45,52,58,59],"ai":[18,33,35,36,42,43,47,54]},"scoresAfter":[-32,-78]},{"ply":12,"player":"ai","action":90,"playedCard":54,"placeType":"discard","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[4,10,17,31,45,52,58,59],"ai":[18,33,35,36,42,43,47,54]},"scoresAfter":[-32,-78]},{"ply":13,"player":"human","action":37,"playedCard":31,"placeType":"play","drawSource":"discard_0","drawnCard":2,"handsBefore":{"human":[4,10,17,31,45,52,58,59],"ai":[18,20,33,35,36,42,43,47]},"scoresAfter":[-20,-78]},{"ply":14,"player":"ai","action":0,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[2,4,10,17,45,52,58,59],"ai":[18,20,33,35,36,42,43,47]},"scoresAfter":[-20,-73]},{"ply":15,"player":"human","action":1,"playedCard":2,"placeType":"play","drawSource":"discard_0","drawnCard":0,"handsBefore":{"human":[2,4,10,17,45,52,58,59],"ai":[1,20,33,35,36,42,43,47]},"scoresAfter":[-60,-73]},{"ply":16,"player":"ai","action":12,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[0,4,10,17,45,52,58,59],"ai":[1,20,33,35,36,42,43,47]},"scoresAfter":[-60,-66]},{"ply":17,"player":"human","action":0,"playedCard":0,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[0,4,10,17,45,52,58,59],"ai":[1,33,35,36,40,42,43,47]},"scoresAfter":[-80,-66]},{"ply":18,"player":"ai","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[4,10,17,27,45,52,58,59],"ai":[1,33,35,36,40,42,43,47]},"scoresAfter":[-80,-66]},{"ply":19,"player":"human","action":65,"playedCard":52,"placeType":"play","drawSource":"discard_4","drawnCard":54,"handsBefore":{"human":[4,10,17,27,45,52,58,59],"ai":[32,33,35,36,40,42,43,47]},"scoresAfter":[-97,-66]},{"ply":20,"player":"ai","action":36,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[4,10,17,27,45,54,58,59],"ai":[32,33,35,36,40,42,43,47]},"scoresAfter":[-97,-106]},{"ply":21,"player":"human","action":61,"playedCard":54,"placeType":"play","drawSource":"discard_0","drawnCard":1,"handsBefore":{"human":[4,10,17,27,45,54,58,59],"ai":[19,32,33,35,40,42,43,47]},"scoresAfter":[-92,-106]},{"ply":22,"player":"ai","action":10,"playedCard":19,"placeType":"discard","drawSource":"discard_3","drawnCard":38,"handsBefore":{"human":[1,4,10,17,27,45,58,59],"ai":[19,32,33,35,40,42,43,47]},"scoresAfter":[-92,-106]},{"ply":23,"player":"human","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[1,4,10,17,27,45,58,59],"ai":[32,33,35,38,40,42,43,47]},"scoresAfter":[-112,-106]},{"ply":24,"player":"ai","action":0,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[4,5,10,17,27,45,58,59],"ai":[32,33,35,38,40,42,43,47]},"scoresAfter":[-112,-92]},{"ply":25,"player":"human","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[4,5,10,17,27,45,58,59],"ai":[13,33,35,38,40,42,43,47]},"scoresAfter":[-100,-92]},{"ply":26,"player":"ai","action":12,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[5,10,17,27,45,55,58,59],"ai":[13,33,35,38,40,42,43,47]},"scoresAfter":[-100,-76]},{"ply":27,"player":"human","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[5,10,17,27,45,55,58,59],"ai":[3,13,35,38,40,42,43,47]},"scoresAfter":[-84,-76]},{"ply":28,"player":"ai","action":24,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[10,17,23,27,45,55,58,59],"ai":[3,13,35,38,40,42,43,47]},"scoresAfter":[-84,-56]},{"ply":29,"player":"human","action":60,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[10,17,23,27,45,55,58,59],"ai":[3,13,24,38,40,42,43,47]},"scoresAfter":[-78,-56]},{"ply":30,"player":"ai","action":18,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[10,17,23,27,34,45,58,59],"ai":[3,13,24,38,40,42,43,47]},"scoresAfter":[-78,-56]},{"ply":31,"player":"human","action":50,"playedCard":34,"placeType":"play","drawSource":"discard_1","drawnCard":13,"handsBefore":{"human":[10,17,23,27,34,45,58,59],"ai":[3,22,24,38,40,42,43,47]},"scoresAfter":[-60,-56]},{"ply":32,"player":"ai","action":12,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[10,13,17,23,27,45,58,59],"ai":[3,22,24,38,40,42,43,47]},"scoresAfter":[-60,-47]},{"ply":33,"player":"human","action":14,"playedCard":13,"placeType":"play","drawSource":"discard_1","drawnCard":19,"handsBefore":{"human":[10,13,17,23,27,45,58,59],"ai":[3,24,38,40,42,43,47,49]},"scoresAfter":[-100,-47]},{"ply":34,"player":"ai","action":90,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[10,17,19,23,27,45,58,59],"ai":[3,24,38,40,42,43,47,49]},"scoresAfter":[-100,-47]},{"ply":35,"player":"human","action":56,"playedCard":27,"placeType":"discard","drawSource":"discard_1","drawnCard":12,"handsBefore":{"human":[10,17,19,23,27,45,58,59],"ai":[3,24,38,40,42,43,47,56]},"scoresAfter":[-100,-47]},{"ply":36,"player":"ai","action":6,"playedCard":3,"placeType":"discard","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[10,12,17,19,23,45,58,59],"ai":[3,24,38,40,42,43,47,56]},"scoresAfter":[-100,-47]},{"ply":37,"player":"human","action":12,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[10,12,17,19,23,45,58,59],"ai":[24,38,40,41,42,43,47,56]},"scoresAfter":[-120,-47]},{"ply":38,"player":"ai","action":12,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[10,17,19,23,37,45,58,59],"ai":[24,38,40,41,42,43,47,56]},"scoresAfter":[-120,-67]},{"ply":39,"player":"human","action":12,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[10,17,19,23,37,45,58,59],"ai":[24,40,41,42,43,47,48,56]},"scoresAfter":[-108,-67]},{"ply":40,"player":"ai","action":90,"playedCard":56,"placeType":"discard","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[10,14,19,23,37,45,58,59],"ai":[24,40,41,42,43,47,48,56]},"scoresAfter":[-108,-67]},{"ply":41,"player":"human","action":59,"playedCard":37,"placeType":"discard","drawSource":"discard_4","drawnCard":56,"handsBefore":{"human":[10,14,19,23,37,45,58,59],"ai":[6,24,40,41,42,43,47,48]},"scoresAfter":[-108,-67]},{"ply":42,"player":"ai","action":94,"playedCard":48,"placeType":"discard","drawSource":"discard_3","drawnCard":37,"handsBefore":{"human":[10,14,19,23,45,56,58,59],"ai":[6,24,40,41,42,43,47,48]},"scoresAfter":[-108,-67]},{"ply":43,"player":"human","action":60,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[10,14,19,23,45,56,58,59],"ai":[6,24,37,40,41,42,43,47]},"scoresAfter":[-101,-67]},{"ply":44,"player":"ai","action":24,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[10,14,16,19,23,45,58,59],"ai":[6,24,37,40,41,42,43,47]},"scoresAfter":[-101,-87]},{"ply":45,"player":"human","action":36,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[10,14,16,19,23,45,58,59],"ai":[6,21,24,40,41,42,43,47]},"scoresAfter":[-83,-87]},{"ply":46,"player":"ai","action":36,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[10,14,16,23,45,51,58,59],"ai":[6,21,24,40,41,42,43,47]},"scoresAfter":[-83,-75]},{"ply":47,"player":"human","action":72,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[10,14,16,23,45,51,58,59],"ai":[6,21,24,41,42,43,46,47]},"scoresAfter":[-74,-75]},{"ply":48,"player":"ai","action":36,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[10,14,16,23,44,45,51,59],"ai":[6,21,24,41,42,43,46,47]},"scoresAfter":[-74,-59]},{"ply":49,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[10,14,16,23,44,45,51,59],"ai":[6,21,24,42,43,46,47,50]},"scoresAfter":[-64,-59]},{"ply":50,"player":"ai","action":36,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[7,10,14,16,23,44,45,51],"ai":[6,21,24,42,43,46,47,50]},"scoresAfter":[-64,-39]},{"ply":51,"player":"human","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[7,10,14,16,23,44,45,51],"ai":[6,21,24,30,43,46,47,50]},"scoresAfter":[-40,-39]},{"ply":52,"player":"ai","action":53,"playedCard":43,"placeType":"play","drawSource":"discard_4","drawnCard":48,"handsBefore":{"human":[10,14,16,23,28,44,45,51],"ai":[6,21,24,30,43,46,47,50]},"scoresAfter":[-40,-15]},{"ply":53,"player":"human","action":36,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[10,14,16,23,28,44,45,51],"ai":[6,21,24,30,46,47,48,50]},"scoresAfter":[-10,-15]},{"ply":54,"player":"ai","action":53,"playedCard":46,"placeType":"play","drawSource":"discard_4","drawnCard":49,"handsBefore":{"human":[8,10,14,16,28,44,45,51],"ai":[6,21,24,30,46,47,48,50]},"scoresAfter":[-10,41]},{"ply":55,"player":"human","action":3,"playedCard":8,"placeType":"play","drawSource":"discard_2","drawnCard":27,"handsBefore":{"human":[8,10,14,16,28,44,45,51],"ai":[6,21,24,30,47,48,49,50]},"scoresAfter":[18,41]},{"ply":56,"player":"ai","action":48,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[10,14,16,27,28,44,45,51],"ai":[6,21,24,30,47,48,49,50]},"scoresAfter":[18,81]},{"ply":57,"player":"human","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[10,14,16,27,28,44,45,51],"ai":[6,11,21,24,30,48,49,50]},"scoresAfter":[74,81]}],"finalScores":[74,81],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[52,59,2,17,26,12,0,58,57,18,9,35,36,25,53,47,38,43,31,33,45,42,29,15,10,54,4,20,1,40,27,32,19,5,13,55,3,23,24,34,22,49,56,41,37,48,14,6,16,21,51,46,44,50,7,30,28,8,11,39],"drawPtr":60,"cardLoc":[3,3,3,5,3,3,2,3,3,4,3,2,3,3,1,4,1,3,4,3,4,2,4,3,2,4,3,1,1,3,2,3,4,4,3,4,4,4,4,1,4,4,4,4,1,1,4,4,2,2,2,1,3,4,3,3,3,4,3,3],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,false,false,false,false,false,false,false,false,false,false],"colTop":[[9,10,9,0,10],[8,9,10,10,8]],"colHandshakes":[[3,2,1,0,0],[0,0,1,3,0]],"colLength":[[8,5,4,0,6],[1,4,4,9,2]],"piles":[[3],[],[],[],[]],"toMove":1,"stepCount":57,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"96b83918-3fda-42d4-b162-95893d172135","seed":"ctkc1x","startedAt":"2026-07-14T16:58:32.195Z","finishedAt":"2026-07-14T17:00:29.647Z","initialDeckOrder":[52,23,17,57,38,48,8,9,44,12,54,13,33,25,1,58,47,36,39,53,27,46,50,32,34,26,21,19,10,4,42,31,55,37,5,22,3,20,29,16,15,49,45,7,35,2,30,14,59,24,11,41,6,0,18,51,56,40,43,28],"moves":[{"ply":1,"player":"human","action":60,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[8,9,17,23,38,48,52,57],"ai":[1,12,13,25,33,44,54,58]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[8,9,17,23,38,47,52,57],"ai":[1,12,13,25,33,44,54,58]},"scoresAfter":[-40,0]},{"ply":3,"player":"human","action":48,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[8,9,17,23,38,47,52,57],"ai":[12,13,25,33,36,44,54,58]},"scoresAfter":[-80,0]},{"ply":4,"player":"ai","action":72,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[8,9,17,23,39,47,52,57],"ai":[12,13,25,33,36,44,54,58]},"scoresAfter":[-80,-15]},{"ply":5,"player":"human","action":48,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[8,9,17,23,39,47,52,57],"ai":[12,13,25,33,36,44,53,58]},"scoresAfter":[-76,-15]},{"ply":6,"player":"ai","action":18,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[8,9,17,23,27,47,52,57],"ai":[12,13,25,33,36,44,53,58]},"scoresAfter":[-76,-15]},{"ply":7,"player":"human","action":54,"playedCard":27,"placeType":"discard","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[8,9,17,23,27,47,52,57],"ai":[12,25,33,36,44,46,53,58]},"scoresAfter":[-76,-15]},{"ply":8,"player":"ai","action":36,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[8,9,17,23,47,50,52,57],"ai":[12,25,33,36,44,46,53,58]},"scoresAfter":[-76,-55]},{"ply":9,"player":"human","action":60,"playedCard":50,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[8,9,17,23,47,50,52,57],"ai":[12,25,32,33,44,46,53,58]},"scoresAfter":[-96,-55]},{"ply":10,"player":"ai","action":12,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[8,9,17,23,34,47,52,57],"ai":[12,25,32,33,44,46,53,58]},"scoresAfter":[-96,-95]},{"ply":11,"player":"human","action":72,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[8,9,17,23,34,47,52,57],"ai":[12,26,32,33,44,46,53,58]},"scoresAfter":[-87,-95]},{"ply":12,"player":"ai","action":0,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[8,9,17,21,23,34,47,57],"ai":[12,26,32,33,44,46,53,58]},"scoresAfter":[-87,-135]},{"ply":13,"player":"human","action":24,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[8,9,17,21,23,34,47,57],"ai":[19,26,32,33,44,46,53,58]},"scoresAfter":[-103,-135]},{"ply":14,"player":"ai","action":0,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[8,9,10,21,23,34,47,57],"ai":[19,26,32,33,44,46,53,58]},"scoresAfter":[-103,-123]},{"ply":15,"player":"human","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[8,9,10,21,23,34,47,57],"ai":[4,26,32,33,44,46,53,58]},"scoresAfter":[-116,-123]},{"ply":16,"player":"ai","action":78,"playedCard":53,"placeType":"discard","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[9,10,21,23,34,42,47,57],"ai":[4,26,32,33,44,46,53,58]},"scoresAfter":[-116,-123]},{"ply":17,"player":"human","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[9,10,21,23,34,42,47,57],"ai":[4,26,31,32,33,44,46,58]},"scoresAfter":[-108,-123]},{"ply":18,"player":"ai","action":87,"playedCard":58,"placeType":"play","drawSource":"discard_2","drawnCard":27,"handsBefore":{"human":[10,21,23,34,42,47,55,57],"ai":[4,26,31,32,33,44,46,58]},"scoresAfter":[-108,-114]},{"ply":19,"player":"human","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[10,21,23,34,42,47,55,57],"ai":[4,26,27,31,32,33,44,46]},"scoresAfter":[-99,-114]},{"ply":20,"player":"ai","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[21,23,34,37,42,47,55,57],"ai":[4,26,27,31,32,33,44,46]},"scoresAfter":[-99,-131]},{"ply":21,"player":"human","action":53,"playedCard":42,"placeType":"play","drawSource":"discard_4","drawnCard":53,"handsBefore":{"human":[21,23,34,37,42,47,55,57],"ai":[5,26,27,31,32,33,44,46]},"scoresAfter":[-89,-131]},{"ply":22,"player":"ai","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[21,23,34,37,47,53,55,57],"ai":[5,26,27,31,32,33,44,46]},"scoresAfter":[-89,-127]},{"ply":23,"player":"human","action":60,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[21,23,34,37,47,53,55,57],"ai":[22,26,27,31,32,33,44,46]},"scoresAfter":[-77,-127]},{"ply":24,"player":"ai","action":0,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[3,21,23,34,37,47,55,57],"ai":[22,26,27,31,32,33,44,46]},"scoresAfter":[-77,-109]},{"ply":25,"player":"human","action":6,"playedCard":3,"placeType":"discard","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[3,21,23,34,37,47,55,57],"ai":[20,26,27,31,32,33,44,46]},"scoresAfter":[-77,-109]},{"ply":26,"player":"ai","action":72,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[21,23,29,34,37,47,55,57],"ai":[20,26,27,31,32,33,44,46]},"scoresAfter":[-77,-95]},{"ply":27,"player":"human","action":72,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[21,23,29,34,37,47,55,57],"ai":[16,20,26,27,31,32,33,46]},"scoresAfter":[-59,-95]},{"ply":28,"player":"ai","action":24,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[15,21,23,29,34,37,47,57],"ai":[16,20,26,27,31,32,33,46]},"scoresAfter":[-59,-115]},{"ply":29,"player":"human","action":12,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[15,21,23,29,34,37,47,57],"ai":[16,20,27,31,32,33,46,49]},"scoresAfter":[-51,-115]},{"ply":30,"player":"ai","action":72,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[15,23,29,34,37,45,47,57],"ai":[16,20,27,31,32,33,46,49]},"scoresAfter":[-51,-97]},{"ply":31,"player":"human","action":12,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[15,23,29,34,37,45,47,57],"ai":[7,16,20,27,31,32,33,49]},"scoresAfter":[-41,-97]},{"ply":32,"player":"ai","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[15,29,34,35,37,45,47,57],"ai":[7,16,20,27,31,32,33,49]},"scoresAfter":[-41,-91]},{"ply":33,"player":"human","action":60,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[15,29,34,35,37,45,47,57],"ai":[2,16,20,27,31,32,33,49]},"scoresAfter":[-25,-91]},{"ply":34,"player":"ai","action":36,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[15,29,30,34,35,37,47,57],"ai":[2,16,20,27,31,32,33,49]},"scoresAfter":[-25,-85]},{"ply":35,"player":"human","action":72,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[15,29,30,34,35,37,47,57],"ai":[2,14,16,20,31,32,33,49]},"scoresAfter":[-5,-85]},{"ply":36,"player":"ai","action":48,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[15,29,30,34,35,37,57,59],"ai":[2,14,16,20,31,32,33,49]},"scoresAfter":[-5,-67]},{"ply":37,"player":"human","action":72,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[15,29,30,34,35,37,57,59],"ai":[2,14,16,20,24,32,33,49]},"scoresAfter":[19,-67]},{"ply":38,"player":"ai","action":54,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[11,15,29,30,34,35,37,59],"ai":[2,14,16,20,24,32,33,49]},"scoresAfter":[19,-67]},{"ply":39,"player":"human","action":85,"playedCard":59,"placeType":"play","drawSource":"discard_0","drawnCard":3,"handsBefore":{"human":[11,15,29,30,34,35,37,59],"ai":[2,14,16,20,32,33,41,49]},"scoresAfter":[49,-67]},{"ply":40,"player":"ai","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[3,11,15,29,30,34,35,37],"ai":[2,14,16,20,32,33,41,49]},"scoresAfter":[49,-67]},{"ply":41,"player":"human","action":12,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[3,11,15,29,30,34,35,37],"ai":[6,14,16,20,32,33,41,49]},"scoresAfter":[59,-67]},{"ply":42,"player":"ai","action":78,"playedCard":41,"placeType":"discard","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[0,3,15,29,30,34,35,37],"ai":[6,14,16,20,32,33,41,49]},"scoresAfter":[59,-67]},{"ply":43,"player":"human","action":40,"playedCard":29,"placeType":"play","drawSource":"discard_3","drawnCard":41,"handsBefore":{"human":[0,3,15,29,30,34,35,37],"ai":[6,14,16,18,20,32,33,49]},"scoresAfter":[43,-67]},{"ply":44,"player":"ai","action":9,"playedCard":6,"placeType":"discard","drawSource":"discard_2","drawnCard":24,"handsBefore":{"human":[0,3,15,30,34,35,37,41],"ai":[6,14,16,18,20,32,33,49]},"scoresAfter":[43,-67]},{"ply":45,"player":"human","action":38,"playedCard":30,"placeType":"play","drawSource":"discard_1","drawnCard":13,"handsBefore":{"human":[0,3,15,30,34,35,37,41],"ai":[14,16,18,20,24,32,33,49]},"scoresAfter":[48,-67]},{"ply":46,"player":"ai","action":31,"playedCard":18,"placeType":"discard","drawSource":"discard_0","drawnCard":6,"handsBefore":{"human":[0,3,13,15,34,35,37,41],"ai":[14,16,18,20,24,32,33,49]},"scoresAfter":[48,-67]},{"ply":47,"player":"human","action":48,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[0,3,13,15,34,35,37,41],"ai":[6,14,16,20,24,32,33,49]},"scoresAfter":[57,-67]},{"ply":48,"player":"ai","action":60,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[0,3,13,15,35,37,41,51],"ai":[6,14,16,20,24,32,33,49]},"scoresAfter":[57,-46]},{"ply":49,"player":"human","action":48,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[0,3,13,15,35,37,41,51],"ai":[6,14,16,20,24,33,49,56]},"scoresAfter":[67,-46]},{"ply":50,"player":"ai","action":62,"playedCard":33,"placeType":"play","drawSource":"discard_1","drawnCard":18,"handsBefore":{"human":[0,3,13,15,37,40,41,51],"ai":[6,14,16,20,24,33,49,56]},"scoresAfter":[67,-22]},{"ply":51,"player":"human","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[0,3,13,15,37,40,41,51],"ai":[6,14,16,18,20,24,49,56]},"scoresAfter":[67,-22]},{"ply":52,"player":"ai","action":18,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[3,13,15,37,40,41,43,51],"ai":[6,14,16,18,20,24,49,56]},"scoresAfter":[67,-22]}],"finalScores":[67,-22],"outcome":"YOU WIN","finalState":{"deckOrder":[52,23,17,57,38,48,8,9,44,12,54,13,33,25,1,58,47,36,39,53,27,46,50,32,34,26,21,19,10,4,42,31,55,37,5,22,3,20,29,16,15,49,45,7,35,2,30,14,59,24,11,41,6,0,18,51,56,40,43,28],"drawPtr":60,"cardLoc":[5,5,5,1,4,4,2,4,3,3,3,3,4,1,5,1,2,3,2,4,2,3,4,3,2,4,4,4,2,3,3,4,4,4,3,3,4,1,3,3,1,1,3,1,4,3,4,3,3,2,3,1,3,3,4,3,2,3,4,3],"handPublic":[false,false,false,true,false,false,true,false,false,false,false,false,false,true,false,false,false,false,true,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,10,10,10,10],[6,9,8,9,9]],"colHandshakes":[[0,0,0,1,2],[0,1,2,1,0]],"colLength":[[4,3,4,5,7],[3,3,6,3,2]],"piles":[[1,2,0],[14],[],[],[]],"toMove":0,"stepCount":52,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"c02934cc-1de8-404e-95e1-6393c90349b5","seed":"v1qynb","startedAt":"2026-07-14T17:00:30.890Z","finishedAt":"2026-07-14T17:02:28.546Z","initialDeckOrder":[58,45,27,5,34,40,43,55,2,6,19,22,18,51,23,28,37,38,10,11,54,41,46,36,30,39,42,52,21,35,1,14,49,59,20,8,16,9,48,26,4,13,33,29,57,47,44,31,0,3,32,50,12,15,56,24,7,53,17,25],"moves":[{"ply":1,"player":"human","action":12,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[5,27,34,40,43,45,55,58],"ai":[2,6,18,19,22,23,28,51]},"scoresAfter":[-18,0]},{"ply":2,"player":"ai","action":84,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[5,34,37,40,43,45,55,58],"ai":[2,6,18,19,22,23,28,51]},"scoresAfter":[-18,-18]},{"ply":3,"player":"human","action":24,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[5,34,37,40,43,45,55,58],"ai":[2,6,18,19,22,23,28,38]},"scoresAfter":[-58,-18]},{"ply":4,"player":"ai","action":72,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[5,10,34,40,43,45,55,58],"ai":[2,6,18,19,22,23,28,38]},"scoresAfter":[-58,-35]},{"ply":5,"player":"human","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[5,10,34,40,43,45,55,58],"ai":[2,6,11,18,19,22,23,38]},"scoresAfter":[-74,-35]},{"ply":6,"player":"ai","action":0,"playedCard":2,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[10,34,40,43,45,54,55,58],"ai":[2,6,11,18,19,22,23,38]},"scoresAfter":[-74,-75]},{"ply":7,"player":"human","action":60,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[10,34,40,43,45,54,55,58],"ai":[6,11,18,19,22,23,38,41]},"scoresAfter":[-89,-75]},{"ply":8,"player":"ai","action":72,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[10,34,40,43,45,46,55,58],"ai":[6,11,18,19,22,23,38,41]},"scoresAfter":[-89,-115]},{"ply":9,"player":"human","action":24,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[10,34,40,43,45,46,55,58],"ai":[6,11,18,19,22,23,36,41]},"scoresAfter":[-83,-115]},{"ply":10,"player":"ai","action":72,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[10,30,34,43,45,46,55,58],"ai":[6,11,18,19,22,23,36,41]},"scoresAfter":[-83,-135]},{"ply":11,"player":"human","action":12,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[10,30,34,43,45,46,55,58],"ai":[6,11,18,19,22,23,39,41]},"scoresAfter":[-78,-135]},{"ply":12,"player":"ai","action":72,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[10,34,42,43,45,46,55,58],"ai":[6,11,18,19,22,23,39,41]},"scoresAfter":[-78,-129]},{"ply":13,"player":"human","action":24,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[10,34,42,43,45,46,55,58],"ai":[6,11,18,19,22,23,41,52]},"scoresAfter":[-68,-129]},{"ply":14,"player":"ai","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[10,21,34,43,45,46,55,58],"ai":[6,11,18,19,22,23,41,52]},"scoresAfter":[-68,-119]},{"ply":15,"player":"human","action":36,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[10,21,34,43,45,46,55,58],"ai":[11,18,19,22,23,35,41,52]},"scoresAfter":[-56,-119]},{"ply":16,"player":"ai","action":84,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[1,10,21,34,45,46,55,58],"ai":[11,18,19,22,23,35,41,52]},"scoresAfter":[-56,-116]},{"ply":17,"player":"human","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[1,10,21,34,45,46,55,58],"ai":[11,14,18,19,22,23,35,41]},"scoresAfter":[-56,-116]},{"ply":18,"player":"ai","action":84,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[10,21,34,45,46,49,55,58],"ai":[11,14,18,19,22,23,35,41]},"scoresAfter":[-56,-104]},{"ply":19,"player":"human","action":72,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[10,21,34,45,46,49,55,58],"ai":[11,14,18,19,22,23,35,59]},"scoresAfter":[-50,-104]},{"ply":20,"player":"ai","action":12,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[10,20,21,34,45,46,49,58],"ai":[11,14,18,19,22,23,35,59]},"scoresAfter":[-50,-144]},{"ply":21,"player":"human","action":48,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[10,20,21,34,45,46,49,58],"ai":[8,11,18,19,22,23,35,59]},"scoresAfter":[-34,-144]},{"ply":22,"player":"ai","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[10,16,20,21,34,46,49,58],"ai":[8,11,18,19,22,23,35,59]},"scoresAfter":[-34,-130]},{"ply":23,"player":"human","action":60,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[10,16,20,21,34,46,49,58],"ai":[9,11,18,19,22,23,35,59]},"scoresAfter":[-16,-130]},{"ply":24,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[10,16,20,21,34,48,49,58],"ai":[9,11,18,19,22,23,35,59]},"scoresAfter":[-16,-114]},{"ply":25,"player":"human","action":12,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[10,16,20,21,34,48,49,58],"ai":[11,18,19,22,23,26,35,59]},"scoresAfter":[-33,-114]},{"ply":26,"player":"ai","action":72,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[4,10,20,21,34,48,49,58],"ai":[11,18,19,22,23,26,35,59]},"scoresAfter":[-33,-104]},{"ply":27,"player":"human","action":24,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[4,10,20,21,34,48,49,58],"ai":[11,13,18,19,22,23,26,59]},"scoresAfter":[-26,-104]},{"ply":28,"player":"ai","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[4,10,21,33,34,48,49,58],"ai":[11,13,18,19,22,23,26,59]},"scoresAfter":[-26,-84]},{"ply":29,"player":"human","action":36,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[4,10,21,33,34,48,49,58],"ai":[13,18,19,22,23,26,29,59]},"scoresAfter":[-18,-84]},{"ply":30,"player":"ai","action":66,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[4,10,21,34,48,49,57,58],"ai":[13,18,19,22,23,26,29,59]},"scoresAfter":[-18,-84]},{"ply":31,"player":"human","action":36,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[4,10,21,34,48,49,57,58],"ai":[13,18,19,22,23,29,47,59]},"scoresAfter":[-9,-84]},{"ply":32,"player":"ai","action":0,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[4,10,21,44,48,49,57,58],"ai":[13,18,19,22,23,29,47,59]},"scoresAfter":[-9,-104]},{"ply":33,"player":"human","action":72,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[4,10,21,44,48,49,57,58],"ai":[18,19,22,23,29,31,47,59]},"scoresAfter":[-1,-104]},{"ply":34,"player":"ai","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[0,4,10,21,44,48,49,58],"ai":[18,19,22,23,29,31,47,59]},"scoresAfter":[-1,-94]},{"ply":35,"player":"human","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[0,4,10,21,44,48,49,58],"ai":[3,18,19,22,23,29,31,47]},"scoresAfter":[8,-94]},{"ply":36,"player":"ai","action":84,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[0,4,10,21,32,44,48,49],"ai":[3,18,19,22,23,29,31,47]},"scoresAfter":[8,-64]},{"ply":37,"player":"human","action":36,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[0,4,10,21,32,44,48,49],"ai":[3,18,19,22,23,29,31,50]},"scoresAfter":[16,-64]},{"ply":38,"player":"ai","action":12,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[0,4,10,12,32,44,48,49],"ai":[3,18,19,22,23,29,31,50]},"scoresAfter":[16,-49]},{"ply":39,"player":"human","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[0,4,10,12,32,44,48,49],"ai":[3,15,19,22,23,29,31,50]},"scoresAfter":[16,-49]},{"ply":40,"player":"ai","action":25,"playedCard":19,"placeType":"play","drawSource":"discard_0","drawnCard":0,"handsBefore":{"human":[4,10,12,32,44,48,49,56],"ai":[3,15,19,22,23,29,31,50]},"scoresAfter":[16,-31]},{"ply":41,"player":"human","action":42,"playedCard":32,"placeType":"discard","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[4,10,12,32,44,48,49,56],"ai":[0,3,15,22,23,29,31,50]},"scoresAfter":[16,-31]},{"ply":42,"player":"ai","action":37,"playedCard":22,"placeType":"play","drawSource":"discard_0","drawnCard":1,"handsBefore":{"human":[4,10,12,24,44,48,49,56],"ai":[0,3,15,22,23,29,31,50]},"scoresAfter":[16,-4]},{"ply":43,"player":"human","action":42,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[4,10,12,24,44,48,49,56],"ai":[0,1,3,15,23,29,31,50]},"scoresAfter":[16,-4]},{"ply":44,"player":"ai","action":51,"playedCard":23,"placeType":"play","drawSource":"discard_2","drawnCard":24,"handsBefore":{"human":[4,7,10,12,44,48,49,56],"ai":[0,1,3,15,23,29,31,50]},"scoresAfter":[16,26]},{"ply":45,"player":"human","action":12,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[4,7,10,12,44,48,49,56],"ai":[0,1,3,15,24,29,31,50]},"scoresAfter":[22,26]},{"ply":46,"player":"ai","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[4,10,12,44,48,49,53,56],"ai":[0,1,3,15,24,29,31,50]},"scoresAfter":[22,26]},{"ply":47,"player":"human","action":12,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[4,10,12,44,48,49,53,56],"ai":[1,3,15,17,24,29,31,50]},"scoresAfter":[31,26]}],"finalScores":[31,26],"outcome":"YOU WIN","finalState":{"deckOrder":[58,45,27,5,34,40,43,55,2,6,19,22,18,51,23,28,37,38,10,11,54,41,46,36,30,39,42,52,21,35,1,14,49,59,20,8,16,9,48,26,4,13,33,29,57,47,44,31,0,3,32,50,12,15,56,24,7,53,17,25],"drawPtr":60,"cardLoc":[5,2,4,2,1,3,4,3,4,4,3,4,1,4,4,2,3,2,4,4,3,3,4,4,2,1,5,3,4,2,3,2,5,3,3,4,4,3,4,4,3,4,3,3,1,3,3,4,1,1,2,4,4,1,3,3,1,3,3,4],"handPublic":[false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[9,8,9,9,9],[10,10,10,10,10]],"colHandshakes":[[0,0,0,1,0],[1,2,0,2,0]],"colLength":[[3,3,4,6,4],[5,6,2,5,3]],"piles":[[0],[],[26,32],[],[]],"toMove":1,"stepCount":47,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"8d4ab515-6534-4d48-a174-10fa9f2f9051","seed":"ft9n5l","startedAt":"2026-07-14T17:02:29.246Z","finishedAt":"2026-07-14T17:04:38.356Z","initialDeckOrder":[0,9,52,26,13,53,33,17,1,42,22,56,29,50,45,44,2,31,43,28,51,18,12,39,36,7,3,6,55,38,30,41,32,59,15,40,57,35,25,10,19,16,21,48,37,5,46,58,49,24,54,14,8,20,27,34,47,23,4,11],"moves":[{"ply":1,"player":"human","action":48,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[0,9,13,17,26,33,52,53],"ai":[1,22,29,42,44,45,50,56]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[0,2,9,13,17,33,52,53],"ai":[1,22,29,42,44,45,50,56]},"scoresAfter":[-40,0]},{"ply":3,"player":"human","action":1,"playedCard":0,"placeType":"play","drawSource":"discard_0","drawnCard":1,"handsBefore":{"human":[0,2,9,13,17,33,52,53],"ai":[22,29,31,42,44,45,50,56]},"scoresAfter":[-80,0]},{"ply":4,"player":"ai","action":72,"playedCard":50,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[1,2,9,13,17,33,52,53],"ai":[22,29,31,42,44,45,50,56]},"scoresAfter":[-80,-40]},{"ply":5,"player":"human","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[1,2,9,13,17,33,52,53],"ai":[22,29,31,42,43,44,45,56]},"scoresAfter":[-100,-40]},{"ply":6,"player":"ai","action":24,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[2,9,13,17,28,33,52,53],"ai":[22,29,31,42,43,44,45,56]},"scoresAfter":[-100,-54]},{"ply":7,"player":"human","action":0,"playedCard":2,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[2,9,13,17,28,33,52,53],"ai":[22,29,42,43,44,45,51,56]},"scoresAfter":[-120,-54]},{"ply":8,"player":"ai","action":24,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[9,13,17,18,28,33,52,53],"ai":[22,29,42,43,44,45,51,56]},"scoresAfter":[-120,-69]},{"ply":9,"player":"human","action":12,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[9,13,17,18,28,33,52,53],"ai":[12,22,29,43,44,45,51,56]},"scoresAfter":[-160,-69]},{"ply":10,"player":"ai","action":36,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[9,17,18,28,33,39,52,53],"ai":[12,22,29,43,44,45,51,56]},"scoresAfter":[-160,-63]},{"ply":11,"player":"human","action":66,"playedCard":39,"placeType":"discard","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[9,17,18,28,33,39,52,53],"ai":[12,22,29,36,44,45,51,56]},"scoresAfter":[-160,-63]},{"ply":12,"player":"ai","action":42,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[7,9,17,18,28,33,52,53],"ai":[12,22,29,36,44,45,51,56]},"scoresAfter":[-160,-63]},{"ply":13,"player":"human","action":48,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[7,9,17,18,28,33,52,53],"ai":[3,12,22,29,44,45,51,56]},"scoresAfter":[-154,-63]},{"ply":14,"player":"ai","action":60,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[6,7,9,17,18,33,52,53],"ai":[3,12,22,29,44,45,51,56]},"scoresAfter":[-154,-55]},{"ply":15,"player":"human","action":36,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[6,7,9,17,18,33,52,53],"ai":[3,12,22,29,44,51,55,56]},"scoresAfter":[-146,-55]},{"ply":16,"player":"ai","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[6,7,9,18,33,38,52,53],"ai":[3,12,22,29,44,51,55,56]},"scoresAfter":[-146,-73]},{"ply":17,"player":"human","action":66,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[6,7,9,18,33,38,52,53],"ai":[12,22,29,30,44,51,55,56]},"scoresAfter":[-146,-73]},{"ply":18,"player":"ai","action":0,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[6,7,9,18,33,41,52,53],"ai":[12,22,29,30,44,51,55,56]},"scoresAfter":[-146,-113]},{"ply":19,"player":"human","action":66,"playedCard":41,"placeType":"discard","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[6,7,9,18,33,41,52,53],"ai":[22,29,30,32,44,51,55,56]},"scoresAfter":[-146,-113]},{"ply":20,"player":"ai","action":60,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[6,7,9,18,33,52,53,59],"ai":[22,29,30,32,44,51,55,56]},"scoresAfter":[-146,-109]},{"ply":21,"player":"human","action":36,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[6,7,9,18,33,52,53,59],"ai":[15,22,29,30,32,44,55,56]},"scoresAfter":[-136,-109]},{"ply":22,"player":"ai","action":48,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[6,7,9,33,40,52,53,59],"ai":[15,22,29,30,32,44,55,56]},"scoresAfter":[-136,-102]},{"ply":23,"player":"human","action":54,"playedCard":40,"placeType":"discard","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[6,7,9,33,40,52,53,59],"ai":[15,22,29,30,44,55,56,57]},"scoresAfter":[-136,-102]},{"ply":24,"player":"ai","action":30,"playedCard":29,"placeType":"discard","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[6,7,9,33,35,52,53,59],"ai":[15,22,29,30,44,55,56,57]},"scoresAfter":[-136,-102]},{"ply":25,"player":"human","action":69,"playedCard":52,"placeType":"discard","drawSource":"discard_2","drawnCard":29,"handsBefore":{"human":[6,7,9,33,35,52,53,59],"ai":[15,22,25,30,44,55,56,57]},"scoresAfter":[-136,-102]},{"ply":26,"player":"ai","action":30,"playedCard":25,"placeType":"discard","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[6,7,9,29,33,35,53,59],"ai":[15,22,25,30,44,55,56,57]},"scoresAfter":[-136,-102]},{"ply":27,"player":"human","action":36,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[6,7,9,29,33,35,53,59],"ai":[10,15,22,30,44,55,56,57]},"scoresAfter":[-128,-102]},{"ply":28,"player":"ai","action":60,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[6,7,9,19,33,35,53,59],"ai":[10,15,22,30,44,55,56,57]},"scoresAfter":[-128,-90]},{"ply":29,"player":"human","action":36,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[6,7,9,19,33,35,53,59],"ai":[10,15,16,22,30,44,56,57]},"scoresAfter":[-116,-90]},{"ply":30,"player":"ai","action":24,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[6,7,9,21,33,35,53,59],"ai":[10,15,16,22,30,44,56,57]},"scoresAfter":[-116,-84]},{"ply":31,"player":"human","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[6,7,9,21,33,35,53,59],"ai":[10,15,22,30,44,48,56,57]},"scoresAfter":[-96,-84]},{"ply":32,"player":"ai","action":66,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[7,9,21,33,35,37,53,59],"ai":[10,15,22,30,44,48,56,57]},"scoresAfter":[-96,-84]},{"ply":33,"player":"human","action":66,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[7,9,21,33,35,37,53,59],"ai":[5,10,15,22,30,44,56,57]},"scoresAfter":[-96,-84]},{"ply":34,"player":"ai","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[7,9,21,33,35,46,53,59],"ai":[5,10,15,22,30,44,56,57]},"scoresAfter":[-96,-80]},{"ply":35,"player":"human","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[7,9,21,33,35,46,53,59],"ai":[10,15,22,30,44,56,57,58]},"scoresAfter":[-72,-80]},{"ply":36,"player":"ai","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[9,21,33,35,46,49,53,59],"ai":[10,15,22,30,44,56,57,58]},"scoresAfter":[-72,-71]},{"ply":37,"player":"human","action":24,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[9,21,33,35,46,49,53,59],"ai":[15,22,24,30,44,56,57,58]},"scoresAfter":[-56,-71]},{"ply":38,"player":"ai","action":60,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[9,21,35,46,49,53,54,59],"ai":[15,22,24,30,44,56,57,58]},"scoresAfter":[-56,-57]},{"ply":39,"player":"human","action":54,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[9,21,35,46,49,53,54,59],"ai":[14,15,22,24,30,44,57,58]},"scoresAfter":[-56,-57]},{"ply":40,"player":"ai","action":24,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[8,9,21,35,46,53,54,59],"ai":[14,15,22,24,30,44,57,58]},"scoresAfter":[-56,-39]},{"ply":41,"player":"human","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[8,9,21,35,46,53,54,59],"ai":[14,15,20,24,30,44,57,58]},"scoresAfter":[-28,-39]},{"ply":42,"player":"ai","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[9,21,27,35,46,53,54,59],"ai":[14,15,20,24,30,44,57,58]},"scoresAfter":[-28,-21]},{"ply":43,"player":"human","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[9,21,27,35,46,53,54,59],"ai":[14,15,20,24,30,34,44,57]},"scoresAfter":[4,-21]},{"ply":44,"player":"ai","action":60,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[21,27,35,46,47,53,54,59],"ai":[14,15,20,24,30,34,44,57]},"scoresAfter":[4,-12]},{"ply":45,"player":"human","action":5,"playedCard":21,"placeType":"play","drawSource":"discard_4","drawnCard":49,"handsBefore":{"human":[21,27,35,46,47,53,54,59],"ai":[14,15,20,23,24,30,44,57]},"scoresAfter":[20,-12]},{"ply":46,"player":"ai","action":36,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[27,35,46,47,49,53,54,59],"ai":[14,15,20,23,24,30,44,57]},"scoresAfter":[20,8]},{"ply":47,"player":"human","action":12,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[27,35,46,47,49,53,54,59],"ai":[4,14,15,20,24,30,44,57]},"scoresAfter":[40,8]}],"finalScores":[40,8],"outcome":"YOU WIN","finalState":{"deckOrder":[0,9,52,26,13,53,33,17,1,42,22,56,29,50,45,44,2,31,43,28,51,18,12,39,36,7,3,6,55,38,30,41,32,59,15,40,57,35,25,10,19,16,21,48,37,5,46,58,49,24,54,14,8,20,27,34,47,23,4,11],"drawPtr":60,"cardLoc":[3,3,3,4,2,4,3,3,3,3,4,1,4,3,2,2,4,3,3,3,2,3,4,4,2,5,3,1,3,3,2,4,4,3,4,3,5,5,5,5,5,5,4,4,2,4,1,1,5,1,4,4,5,1,1,4,4,2,4,1],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false],"colTop":[[8,8,10,0,0],[9,10,9,8,9]],"colHandshakes":[[3,1,1,0,0],[0,1,0,0,1]],"colLength":[[7,5,5,0,0],[3,4,3,3,5]],"piles":[[],[],[25],[39,36,38,41,40,37],[52,48]],"toMove":1,"stepCount":47,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"10c05672-f2ca-4dbc-aec2-63c3a745c789","seed":"kluags","startedAt":"2026-07-14T17:04:38.993Z","finishedAt":"2026-07-14T17:07:24.992Z","initialDeckOrder":[33,18,27,58,20,55,52,36,49,7,12,50,17,53,41,13,29,1,4,47,45,15,22,24,35,42,26,56,21,48,3,5,46,57,31,19,59,14,8,43,9,0,16,11,25,34,54,6,10,2,51,30,32,28,44,39,40,38,37,23],"moves":[{"ply":1,"player":"human","action":54,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[18,20,27,33,36,52,55,58],"ai":[7,12,13,17,41,49,50,53]},"scoresAfter":[0,0]},{"ply":2,"player":"ai","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[18,20,27,29,33,52,55,58],"ai":[7,12,13,17,41,49,50,53]},"scoresAfter":[0,-14]},{"ply":3,"player":"human","action":60,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[18,20,27,29,33,52,55,58],"ai":[1,12,13,17,41,49,50,53]},"scoresAfter":[-17,-14]},{"ply":4,"player":"ai","action":12,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[4,18,20,27,29,33,55,58],"ai":[1,12,13,17,41,49,50,53]},"scoresAfter":[-17,-54]},{"ply":5,"player":"human","action":6,"playedCard":4,"placeType":"discard","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[4,18,20,27,29,33,55,58],"ai":[1,13,17,41,47,49,50,53]},"scoresAfter":[-17,-54]},{"ply":6,"player":"ai","action":78,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[18,20,27,29,33,45,55,58],"ai":[1,13,17,41,47,49,50,53]},"scoresAfter":[-17,-54]},{"ply":7,"player":"human","action":24,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[18,20,27,29,33,45,55,58],"ai":[1,13,15,17,41,47,49,53]},"scoresAfter":[-35,-54]},{"ply":8,"player":"ai","action":12,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[18,20,22,29,33,45,55,58],"ai":[1,13,15,17,41,47,49,53]},"scoresAfter":[-35,-74]},{"ply":9,"player":"human","action":0,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[18,20,22,29,33,45,55,58],"ai":[1,15,17,24,41,47,49,53]},"scoresAfter":[-50,-74]},{"ply":10,"player":"ai","action":78,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[20,22,29,33,35,45,55,58],"ai":[1,15,17,24,41,47,49,53]},"scoresAfter":[-50,-74]},{"ply":11,"player":"human","action":24,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[20,22,29,33,35,45,55,58],"ai":[1,15,17,24,41,42,47,53]},"scoresAfter":[-46,-74]},{"ply":12,"player":"ai","action":90,"playedCard":53,"placeType":"discard","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[20,22,26,33,35,45,55,58],"ai":[1,15,17,24,41,42,47,53]},"scoresAfter":[-46,-74]},{"ply":13,"player":"human","action":35,"playedCard":26,"placeType":"discard","drawSource":"discard_4","drawnCard":53,"handsBefore":{"human":[20,22,26,33,35,45,55,58],"ai":[1,15,17,24,41,42,47,56]},"scoresAfter":[-46,-74]},{"ply":14,"player":"ai","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[20,22,33,35,45,53,55,58],"ai":[1,15,17,24,41,42,47,56]},"scoresAfter":[-46,-74]},{"ply":15,"player":"human","action":60,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[20,22,33,35,45,53,55,58],"ai":[15,17,21,24,41,42,47,56]},"scoresAfter":[-42,-74]},{"ply":16,"player":"ai","action":54,"playedCard":41,"placeType":"discard","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[20,22,33,35,45,48,55,58],"ai":[15,17,21,24,41,42,47,56]},"scoresAfter":[-42,-74]},{"ply":17,"player":"human","action":72,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[20,22,33,35,45,48,55,58],"ai":[3,15,17,21,24,42,47,56]},"scoresAfter":[-36,-74]},{"ply":18,"player":"ai","action":6,"playedCard":3,"placeType":"discard","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[5,20,22,33,35,45,48,58],"ai":[3,15,17,21,24,42,47,56]},"scoresAfter":[-36,-74]},{"ply":19,"player":"human","action":6,"playedCard":5,"placeType":"discard","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[5,20,22,33,35,45,48,58],"ai":[15,17,21,24,42,46,47,56]},"scoresAfter":[-36,-74]},{"ply":20,"player":"ai","action":0,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[20,22,33,35,45,48,57,58],"ai":[15,17,21,24,42,46,47,56]},"scoresAfter":[-36,-68]},{"ply":21,"player":"human","action":72,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[20,22,33,35,45,48,57,58],"ai":[17,21,24,31,42,46,47,56]},"scoresAfter":[-28,-68]},{"ply":22,"player":"ai","action":0,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[19,20,22,33,35,45,48,58],"ai":[17,21,24,31,42,46,47,56]},"scoresAfter":[-28,-56]},{"ply":23,"player":"human","action":0,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[19,20,22,33,35,45,48,58],"ai":[21,24,31,42,46,47,56,59]},"scoresAfter":[-22,-56]},{"ply":24,"player":"ai","action":4,"playedCard":21,"placeType":"play","drawSource":"discard_3","drawnCard":41,"handsBefore":{"human":[14,20,22,33,35,45,48,58],"ai":[21,24,31,42,46,47,56,59]},"scoresAfter":[-22,-32]},{"ply":25,"player":"human","action":12,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[14,20,22,33,35,45,48,58],"ai":[24,31,41,42,46,47,56,59]},"scoresAfter":[-15,-32]},{"ply":26,"player":"ai","action":0,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[8,14,22,33,35,45,48,58],"ai":[24,31,41,42,46,47,56,59]},"scoresAfter":[-15,-72]},{"ply":27,"player":"human","action":24,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[8,14,22,33,35,45,48,58],"ai":[31,41,42,43,46,47,56,59]},"scoresAfter":[-6,-72]},{"ply":28,"player":"ai","action":78,"playedCard":56,"placeType":"discard","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[8,9,14,33,35,45,48,58],"ai":[31,41,42,43,46,47,56,59]},"scoresAfter":[-6,-72]},{"ply":29,"player":"human","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[8,9,14,33,35,45,48,58],"ai":[0,31,41,42,43,46,47,59]},"scoresAfter":[3,-72]},{"ply":30,"player":"ai","action":94,"playedCard":59,"placeType":"discard","drawSource":"discard_3","drawnCard":36,"handsBefore":{"human":[8,9,14,16,33,35,45,48],"ai":[0,31,41,42,43,46,47,59]},"scoresAfter":[3,-72]},{"ply":31,"player":"human","action":30,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[8,9,14,16,33,35,45,48],"ai":[0,31,36,41,42,43,46,47]},"scoresAfter":[3,-72]},{"ply":32,"player":"ai","action":12,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[8,9,11,16,33,35,45,48],"ai":[0,31,36,41,42,43,46,47]},"scoresAfter":[3,-60]},{"ply":33,"player":"human","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[8,9,11,16,33,35,45,48],"ai":[0,25,36,41,42,43,46,47]},"scoresAfter":[-10,-60]},{"ply":34,"player":"ai","action":24,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[9,11,16,33,34,35,45,48],"ai":[0,25,36,41,42,43,46,47]},"scoresAfter":[-10,-100]},{"ply":35,"player":"human","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[9,11,16,33,34,35,45,48],"ai":[0,25,41,42,43,46,47,54]},"scoresAfter":[-2,-100]},{"ply":36,"player":"ai","action":24,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[6,11,16,33,34,35,45,48],"ai":[0,25,41,42,43,46,47,54]},"scoresAfter":[-2,-92]},{"ply":37,"player":"human","action":12,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[6,11,16,33,34,35,45,48],"ai":[0,10,25,42,43,46,47,54]},"scoresAfter":[8,-92]},{"ply":38,"player":"ai","action":12,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[2,6,16,33,34,35,45,48],"ai":[0,10,25,42,43,46,47,54]},"scoresAfter":[8,-83]},{"ply":39,"player":"human","action":11,"playedCard":2,"placeType":"discard","drawSource":"discard_4","drawnCard":59,"handsBefore":{"human":[2,6,16,33,34,35,45,48],"ai":[0,25,42,43,46,47,51,54]},"scoresAfter":[8,-83]},{"ply":40,"player":"ai","action":24,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[6,16,33,34,35,45,48,59],"ai":[0,25,42,43,46,47,51,54]},"scoresAfter":[8,-73]},{"ply":41,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[6,16,33,34,35,45,48,59],"ai":[0,25,30,43,46,47,51,54]},"scoresAfter":[18,-73]},{"ply":42,"player":"ai","action":36,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[6,16,32,33,34,35,45,48],"ai":[0,25,30,43,46,47,51,54]},"scoresAfter":[18,-61]},{"ply":43,"player":"human","action":24,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[6,16,32,33,34,35,45,48],"ai":[0,25,28,30,46,47,51,54]},"scoresAfter":[25,-61]},{"ply":44,"player":"ai","action":30,"playedCard":28,"placeType":"discard","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[6,16,33,34,35,44,45,48],"ai":[0,25,28,30,46,47,51,54]},"scoresAfter":[25,-61]},{"ply":45,"player":"human","action":24,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[6,16,33,34,35,44,45,48],"ai":[0,25,30,39,46,47,51,54]},"scoresAfter":[33,-61]},{"ply":46,"player":"ai","action":48,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[6,16,34,35,40,44,45,48],"ai":[0,25,30,39,46,47,51,54]},"scoresAfter":[33,-43]},{"ply":47,"player":"human","action":27,"playedCard":34,"placeType":"play","drawSource":"discard_2","drawnCard":28,"handsBefore":{"human":[6,16,34,35,40,44,45,48],"ai":[0,25,30,38,39,47,51,54]},"scoresAfter":[42,-43]},{"ply":48,"player":"ai","action":60,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[6,16,28,35,40,44,45,48],"ai":[0,25,30,38,39,47,51,54]},"scoresAfter":[42,-23]},{"ply":49,"player":"human","action":36,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[6,16,28,35,40,44,45,48],"ai":[0,25,30,37,38,39,51,54]},"scoresAfter":[52,-23]}],"finalScores":[52,-23],"outcome":"YOU WIN","finalState":{"deckOrder":[33,18,27,58,20,55,52,36,49,7,12,50,17,53,41,13,29,1,4,47,45,15,22,24,35,42,26,56,21,48,3,5,46,57,31,19,59,14,8,43,9,0,16,11,25,34,54,6,10,2,51,30,32,28,44,39,40,38,37,23],"drawPtr":60,"cardLoc":[2,5,5,5,5,5,1,4,3,3,4,3,4,4,5,4,1,4,3,3,3,4,3,1,4,2,5,3,1,3,2,4,3,3,3,3,4,2,2,2,1,4,4,4,1,1,4,4,1,5,5,2,3,3,2,3,5,3,3,3],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,9,10,0,10],[9,8,6,10,0]],"colHandshakes":[[0,0,0,0,0],[0,2,1,1,0]],"colLength":[[3,4,6,0,6],[2,5,2,6,0]],"piles":[[4,1,3,5,2],[14],[26],[],[50,49,56]],"toMove":1,"stepCount":49,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"d49a82bf-b0eb-4096-a543-0da023996525","seed":"205uiv","startedAt":"2026-07-14T17:07:26.074Z","finishedAt":"2026-07-14T17:10:00.405Z","initialDeckOrder":[28,10,14,40,5,47,50,26,52,20,12,37,21,13,45,9,8,25,22,38,46,55,15,35,36,19,23,39,32,3,43,2,57,17,27,33,30,11,6,7,58,29,18,56,16,0,49,1,31,53,42,44,51,59,41,48,34,4,24,54],"moves":[{"ply":1,"player":"human","action":90,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[5,10,14,26,28,40,47,50],"ai":[9,12,13,20,21,37,45,52]},"scoresAfter":[0,0]},{"ply":2,"player":"ai","action":12,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[5,8,10,14,26,28,40,47],"ai":[9,12,13,20,21,37,45,52]},"scoresAfter":[0,-40]},{"ply":3,"player":"human","action":42,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[5,8,10,14,26,28,40,47],"ai":[9,13,20,21,25,37,45,52]},"scoresAfter":[0,-40]},{"ply":4,"player":"ai","action":84,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[5,8,10,22,26,28,40,47],"ai":[9,13,20,21,25,37,45,52]},"scoresAfter":[0,-57]},{"ply":5,"player":"human","action":74,"playedCard":40,"placeType":"play","drawSource":"discard_1","drawnCard":14,"handsBefore":{"human":[5,8,10,22,26,28,40,47],"ai":[9,13,20,21,25,37,38,45]},"scoresAfter":[-17,-57]},{"ply":6,"player":"ai","action":60,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[5,8,10,14,22,26,28,47],"ai":[9,13,20,21,25,37,38,45]},"scoresAfter":[-17,-97]},{"ply":7,"player":"human","action":36,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[5,8,10,14,22,26,28,47],"ai":[9,13,20,21,25,38,45,46]},"scoresAfter":[-57,-97]},{"ply":8,"player":"ai","action":60,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[5,8,10,22,26,28,47,55],"ai":[9,13,20,21,25,38,45,46]},"scoresAfter":[-57,-117]},{"ply":9,"player":"human","action":54,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[5,8,10,22,26,28,47,55],"ai":[9,13,15,20,21,25,45,46]},"scoresAfter":[-57,-117]},{"ply":10,"player":"ai","action":12,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[5,8,10,22,28,35,47,55],"ai":[9,13,15,20,21,25,45,46]},"scoresAfter":[-57,-137]},{"ply":11,"player":"human","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[5,8,10,22,28,35,47,55],"ai":[9,15,20,21,25,36,45,46]},"scoresAfter":[-73,-137]},{"ply":12,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[8,10,19,22,28,35,47,55],"ai":[9,15,20,21,25,36,45,46]},"scoresAfter":[-73,-149]},{"ply":13,"player":"human","action":48,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[8,10,19,22,28,35,47,55],"ai":[15,20,21,23,25,36,45,46]},"scoresAfter":[-90,-149]},{"ply":14,"player":"ai","action":48,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[8,10,19,22,35,39,47,55],"ai":[15,20,21,23,25,36,45,46]},"scoresAfter":[-90,-189]},{"ply":15,"player":"human","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[8,10,19,22,35,39,47,55],"ai":[15,20,21,23,32,36,45,46]},"scoresAfter":[-83,-189]},{"ply":16,"player":"ai","action":60,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[3,10,19,22,35,39,47,55],"ai":[15,20,21,23,32,36,45,46]},"scoresAfter":[-83,-209]},{"ply":17,"player":"human","action":6,"playedCard":3,"placeType":"discard","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[3,10,19,22,35,39,47,55],"ai":[15,20,21,23,32,43,45,46]},"scoresAfter":[-83,-209]},{"ply":18,"player":"ai","action":0,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[2,10,19,22,35,39,47,55],"ai":[15,20,21,23,32,43,45,46]},"scoresAfter":[-83,-203]},{"ply":19,"player":"human","action":12,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[2,10,19,22,35,39,47,55],"ai":[20,21,23,32,43,45,46,57]},"scoresAfter":[-74,-203]},{"ply":20,"player":"ai","action":84,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[2,17,19,22,35,39,47,55],"ai":[20,21,23,32,43,45,46,57]},"scoresAfter":[-74,-195]},{"ply":21,"player":"human","action":12,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[2,17,19,22,35,39,47,55],"ai":[20,21,23,27,32,43,45,46]},"scoresAfter":[-66,-195]},{"ply":22,"player":"ai","action":0,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[2,19,22,33,35,39,47,55],"ai":[20,21,23,27,32,43,45,46]},"scoresAfter":[-66,-174]},{"ply":23,"player":"human","action":90,"playedCard":55,"placeType":"discard","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[2,19,22,33,35,39,47,55],"ai":[21,23,27,30,32,43,45,46]},"scoresAfter":[-66,-174]},{"ply":24,"player":"ai","action":0,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[2,11,19,22,33,35,39,47],"ai":[21,23,27,30,32,43,45,46]},"scoresAfter":[-66,-150]},{"ply":25,"player":"human","action":12,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[2,11,19,22,33,35,39,47],"ai":[6,23,27,30,32,43,45,46]},"scoresAfter":[-56,-150]},{"ply":26,"player":"ai","action":12,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[2,7,19,22,33,35,39,47],"ai":[6,23,27,30,32,43,45,46]},"scoresAfter":[-56,-120]},{"ply":27,"player":"human","action":18,"playedCard":7,"placeType":"discard","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[2,7,19,22,33,35,39,47],"ai":[6,27,30,32,43,45,46,58]},"scoresAfter":[-56,-120]},{"ply":28,"player":"ai","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[2,19,22,29,33,35,39,47],"ai":[6,27,30,32,43,45,46,58]},"scoresAfter":[-56,-111]},{"ply":29,"player":"human","action":36,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[2,19,22,29,33,35,39,47],"ai":[6,18,27,30,32,43,45,46]},"scoresAfter":[-52,-111]},{"ply":30,"player":"ai","action":36,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[2,19,22,33,35,39,47,56],"ai":[6,18,27,30,32,43,45,46]},"scoresAfter":[-52,-101]},{"ply":31,"player":"human","action":12,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[2,19,22,33,35,39,47,56],"ai":[6,16,18,27,32,43,45,46]},"scoresAfter":[-40,-101]},{"ply":32,"player":"ai","action":6,"playedCard":6,"placeType":"discard","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[0,2,22,33,35,39,47,56],"ai":[6,16,18,27,32,43,45,46]},"scoresAfter":[-40,-101]},{"ply":33,"player":"human","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[0,2,22,33,35,39,47,56],"ai":[16,18,27,32,43,45,46,49]},"scoresAfter":[-40,-101]},{"ply":34,"player":"ai","action":36,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[1,2,22,33,35,39,47,56],"ai":[16,18,27,32,43,45,46,49]},"scoresAfter":[-40,-87]},{"ply":35,"player":"human","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[1,2,22,33,35,39,47,56],"ai":[16,18,27,31,43,45,46,49]},"scoresAfter":[-40,-87]},{"ply":36,"player":"ai","action":18,"playedCard":18,"placeType":"discard","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[2,22,33,35,39,47,53,56],"ai":[16,18,27,31,43,45,46,49]},"scoresAfter":[-40,-87]},{"ply":37,"player":"human","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[2,22,33,35,39,47,53,56],"ai":[16,27,31,42,43,45,46,49]},"scoresAfter":[-40,-87]},{"ply":38,"player":"ai","action":36,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[22,33,35,39,44,47,53,56],"ai":[16,27,31,42,43,45,46,49]},"scoresAfter":[-40,-67]},{"ply":39,"player":"human","action":0,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[22,33,35,39,44,47,53,56],"ai":[16,27,31,43,45,46,49,51]},"scoresAfter":[-22,-67]},{"ply":40,"player":"ai","action":36,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[33,35,39,44,47,53,56,59],"ai":[16,27,31,43,45,46,49,51]},"scoresAfter":[-22,-43]},{"ply":41,"player":"human","action":65,"playedCard":53,"placeType":"play","drawSource":"discard_4","drawnCard":55,"handsBefore":{"human":[33,35,39,44,47,53,56,59],"ai":[16,27,31,41,45,46,49,51]},"scoresAfter":[-38,-43]},{"ply":42,"player":"ai","action":48,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[33,35,39,44,47,55,56,59],"ai":[16,27,31,41,45,46,49,51]},"scoresAfter":[-38,-11]},{"ply":43,"player":"human","action":60,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[33,35,39,44,47,55,56,59],"ai":[16,27,31,41,46,48,49,51]},"scoresAfter":[-32,-11]},{"ply":44,"player":"ai","action":48,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[33,34,35,39,44,47,56,59],"ai":[16,27,31,41,46,48,49,51]},"scoresAfter":[-32,25]},{"ply":45,"player":"human","action":27,"playedCard":35,"placeType":"play","drawSource":"discard_2","drawnCard":26,"handsBefore":{"human":[33,34,35,39,44,47,56,59],"ai":[4,16,27,31,41,48,49,51]},"scoresAfter":[-22,25]},{"ply":46,"player":"ai","action":30,"playedCard":27,"placeType":"discard","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[26,33,34,39,44,47,56,59],"ai":[4,16,27,31,41,48,49,51]},"scoresAfter":[-22,25]},{"ply":47,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[26,33,34,39,44,47,56,59],"ai":[4,16,24,31,41,48,49,51]},"scoresAfter":[-12,25]}],"finalScores":[-12,25],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[28,10,14,40,5,47,50,26,52,20,12,37,21,13,45,9,8,25,22,38,46,55,15,35,36,19,23,39,32,3,43,2,57,17,27,33,30,11,6,7,58,29,18,56,16,0,49,1,31,53,42,44,51,59,41,48,34,4,24,54],"drawPtr":60,"cardLoc":[5,5,5,5,2,3,5,5,3,4,3,3,4,4,3,4,2,3,5,3,4,4,3,4,2,4,1,5,3,3,4,2,4,1,1,3,4,4,4,1,3,2,4,4,1,4,4,1,2,2,5,2,4,3,1,3,1,4,4,3],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,9,10,3,10],[8,10,7,9,9]],"colHandshakes":[[0,1,0,0,0],[0,2,1,3,0]],"colLength":[[4,4,3,1,3],[1,6,3,7,3]],"piles":[[3,7,6,0,1,2],[18],[27],[],[50]],"toMove":1,"stepCount":47,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"3e7a7f67-0e17-494f-947b-38f9e4fce44b","seed":"5med5i","startedAt":"2026-07-14T17:10:01.321Z","finishedAt":"2026-07-14T17:12:08.608Z","initialDeckOrder":[13,31,38,12,10,15,18,42,46,39,8,9,33,7,6,52,59,20,5,11,34,17,27,26,41,40,23,53,49,21,57,58,2,1,32,37,43,55,36,3,29,54,56,16,35,44,47,4,51,25,22,50,28,14,19,24,0,45,48,30],"moves":[{"ply":1,"player":"human","action":12,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[10,12,13,15,18,31,38,42],"ai":[6,7,8,9,33,39,46,52]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":48,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[10,13,15,18,31,38,42,59],"ai":[6,7,8,9,33,39,46,52]},"scoresAfter":[-40,-12]},{"ply":3,"player":"human","action":12,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[10,13,15,18,31,38,42,59],"ai":[6,7,8,9,20,39,46,52]},"scoresAfter":[-60,-12]},{"ply":4,"player":"ai","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[5,10,15,18,31,38,42,59],"ai":[6,7,8,9,20,39,46,52]},"scoresAfter":[-60,-27]},{"ply":5,"player":"human","action":24,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[5,10,15,18,31,38,42,59],"ai":[7,8,9,11,20,39,46,52]},"scoresAfter":[-54,-27]},{"ply":6,"player":"ai","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[5,10,18,31,34,38,42,59],"ai":[7,8,9,11,20,39,46,52]},"scoresAfter":[-54,-21]},{"ply":7,"player":"human","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[5,10,18,31,34,38,42,59],"ai":[8,9,11,17,20,39,46,52]},"scoresAfter":[-70,-21]},{"ply":8,"player":"ai","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[10,18,27,31,34,38,42,59],"ai":[8,9,11,17,20,39,46,52]},"scoresAfter":[-70,-14]},{"ply":9,"player":"human","action":24,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[10,18,27,31,34,38,42,59],"ai":[9,11,17,20,26,39,46,52]},"scoresAfter":[-88,-14]},{"ply":10,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[10,18,31,34,38,41,42,59],"ai":[9,11,17,20,26,39,46,52]},"scoresAfter":[-88,-6]},{"ply":11,"player":"human","action":48,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[10,18,31,34,38,41,42,59],"ai":[11,17,20,26,39,40,46,52]},"scoresAfter":[-128,-6]},{"ply":12,"player":"ai","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[10,18,23,31,34,41,42,59],"ai":[11,17,20,26,39,40,46,52]},"scoresAfter":[-128,4]},{"ply":13,"player":"human","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[10,18,23,31,34,41,42,59],"ai":[17,20,26,39,40,46,52,53]},"scoresAfter":[-119,4]},{"ply":14,"player":"ai","action":0,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[18,23,31,34,41,42,49,59],"ai":[17,20,26,39,40,46,52,53]},"scoresAfter":[-119,-12]},{"ply":15,"player":"human","action":24,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[18,23,31,34,41,42,49,59],"ai":[20,21,26,39,40,46,52,53]},"scoresAfter":[-113,-12]},{"ply":16,"player":"ai","action":0,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[18,23,34,41,42,49,57,59],"ai":[20,21,26,39,40,46,52,53]},"scoresAfter":[-113,-5]},{"ply":17,"player":"human","action":60,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[18,23,34,41,42,49,57,59],"ai":[21,26,39,40,46,52,53,58]},"scoresAfter":[-153,-5]},{"ply":18,"player":"ai","action":0,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[2,18,23,34,41,42,57,59],"ai":[21,26,39,40,46,52,53,58]},"scoresAfter":[-153,3]},{"ply":19,"player":"human","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[2,18,23,34,41,42,57,59],"ai":[1,26,39,40,46,52,53,58]},"scoresAfter":[-153,3]},{"ply":20,"player":"ai","action":60,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[18,23,32,34,41,42,57,59],"ai":[1,26,39,40,46,52,53,58]},"scoresAfter":[-153,-14]},{"ply":21,"player":"human","action":24,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[18,23,32,34,41,42,57,59],"ai":[1,26,37,39,40,46,53,58]},"scoresAfter":[-146,-14]},{"ply":22,"player":"ai","action":72,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[18,23,34,41,42,43,57,59],"ai":[1,26,37,39,40,46,53,58]},"scoresAfter":[-146,-10]},{"ply":23,"player":"human","action":36,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[18,23,34,41,42,43,57,59],"ai":[1,26,37,39,40,46,55,58]},"scoresAfter":[-138,-10]},{"ply":24,"player":"ai","action":72,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[18,23,34,36,42,43,57,59],"ai":[1,26,37,39,40,46,55,58]},"scoresAfter":[-138,-4]},{"ply":25,"player":"human","action":48,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[18,23,34,36,42,43,57,59],"ai":[1,3,26,37,39,40,46,58]},"scoresAfter":[-128,-4]},{"ply":26,"player":"ai","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[18,23,29,34,36,43,57,59],"ai":[1,3,26,37,39,40,46,58]},"scoresAfter":[-128,-4]},{"ply":27,"player":"human","action":60,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[18,23,29,34,36,43,57,59],"ai":[3,26,37,39,40,46,54,58]},"scoresAfter":[-116,-4]},{"ply":28,"player":"ai","action":24,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[18,23,29,34,36,56,57,59],"ai":[3,26,37,39,40,46,54,58]},"scoresAfter":[-116,-44]},{"ply":29,"player":"human","action":36,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[18,23,29,34,36,56,57,59],"ai":[3,16,26,39,40,46,54,58]},"scoresAfter":[-107,-44]},{"ply":30,"player":"ai","action":36,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[18,23,29,35,36,56,57,59],"ai":[3,16,26,39,40,46,54,58]},"scoresAfter":[-107,-40]},{"ply":31,"player":"human","action":36,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[18,23,29,35,36,56,57,59],"ai":[3,16,26,40,44,46,54,58]},"scoresAfter":[-97,-40]},{"ply":32,"player":"ai","action":6,"playedCard":3,"placeType":"discard","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[18,23,29,36,47,56,57,59],"ai":[3,16,26,40,44,46,54,58]},"scoresAfter":[-97,-40]},{"ply":33,"player":"human","action":0,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[18,23,29,36,47,56,57,59],"ai":[4,16,26,40,44,46,54,58]},"scoresAfter":[-82,-40]},{"ply":34,"player":"ai","action":36,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[23,29,36,47,51,56,57,59],"ai":[4,16,26,40,44,46,54,58]},"scoresAfter":[-82,-34]},{"ply":35,"player":"human","action":48,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[23,29,36,47,51,56,57,59],"ai":[4,16,25,26,44,46,54,58]},"scoresAfter":[-78,-34]},{"ply":36,"player":"ai","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[22,23,29,36,47,56,57,59],"ai":[4,16,25,26,44,46,54,58]},"scoresAfter":[-78,-25]},{"ply":37,"player":"human","action":0,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[22,23,29,36,47,56,57,59],"ai":[4,16,25,26,44,46,50,54]},"scoresAfter":[-51,-25]},{"ply":38,"player":"ai","action":48,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[23,28,29,36,47,56,57,59],"ai":[4,16,25,26,44,46,50,54]},"scoresAfter":[-51,-11]},{"ply":39,"player":"human","action":0,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[23,28,29,36,47,56,57,59],"ai":[4,14,16,25,26,46,50,54]},"scoresAfter":[-21,-11]},{"ply":40,"player":"ai","action":60,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[19,28,29,36,47,56,57,59],"ai":[4,14,16,25,26,46,50,54]},"scoresAfter":[-21,7]},{"ply":41,"player":"human","action":61,"playedCard":56,"placeType":"play","drawSource":"discard_0","drawnCard":3,"handsBefore":{"human":[19,28,29,36,47,56,57,59],"ai":[4,14,16,24,25,26,50,54]},"scoresAfter":[-7,7]},{"ply":42,"player":"ai","action":6,"playedCard":4,"placeType":"discard","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[3,19,28,29,36,47,57,59],"ai":[4,14,16,24,25,26,50,54]},"scoresAfter":[-7,7]},{"ply":43,"player":"human","action":73,"playedCard":57,"placeType":"play","drawSource":"discard_0","drawnCard":4,"handsBefore":{"human":[3,19,28,29,36,47,57,59],"ai":[0,14,16,24,25,26,50,54]},"scoresAfter":[9,7]},{"ply":44,"player":"ai","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[3,4,19,28,29,36,47,59],"ai":[0,14,16,24,25,26,50,54]},"scoresAfter":[9,7]},{"ply":45,"player":"human","action":73,"playedCard":47,"placeType":"play","drawSource":"discard_0","drawnCard":0,"handsBefore":{"human":[3,4,19,28,29,36,47,59],"ai":[14,16,24,25,26,45,50,54]},"scoresAfter":[29,7]},{"ply":46,"player":"ai","action":6,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[0,3,4,19,28,29,36,59],"ai":[14,16,24,25,26,45,50,54]},"scoresAfter":[29,7]},{"ply":47,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[0,3,4,19,28,29,36,59],"ai":[16,24,25,26,45,48,50,54]},"scoresAfter":[49,7]}],"finalScores":[49,7],"outcome":"YOU WIN","finalState":{"deckOrder":[13,31,38,12,10,15,18,42,46,39,8,9,33,7,6,52,59,20,5,11,34,17,27,26,41,40,23,53,49,21,57,58,2,1,32,37,43,55,36,3,29,54,56,16,35,44,47,4,51,25,22,50,28,14,19,24,0,45,48,30],"drawPtr":60,"cardLoc":[1,5,5,1,1,3,4,4,4,4,3,4,3,3,5,3,2,4,3,1,4,4,3,3,2,2,2,3,1,1,1,3,3,4,3,3,1,4,3,4,4,3,3,3,4,2,4,3,2,3,2,3,4,4,2,4,3,3,4,3],"handPublic":[true,false,false,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[9,10,10,10,10],[10,8,8,9,9]],"colHandshakes":[[0,2,0,1,1],[0,0,0,1,0]],"colLength":[[2,6,5,5,5],[5,3,1,5,4]],"piles":[[2,1],[14],[],[],[]],"toMove":1,"stepCount":47,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"736227ed-ea41-4fb5-be2e-0267dc08638d","seed":"togbmp","startedAt":"2026-07-14T17:12:09.448Z","finishedAt":"2026-07-14T17:14:27.707Z","initialDeckOrder":[49,31,57,32,53,13,36,6,0,5,38,46,19,25,39,9,2,45,54,43,34,35,51,18,7,41,55,47,3,11,29,50,52,30,59,17,4,22,8,10,37,21,26,16,48,44,15,24,58,20,23,12,33,28,1,40,27,56,42,14],"moves":[{"ply":1,"player":"human","action":60,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[6,13,31,32,36,49,53,57],"ai":[0,5,9,19,25,38,39,46]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":60,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[2,6,13,31,32,36,53,57],"ai":[0,5,9,19,25,38,39,46]},"scoresAfter":[-40,-40]},{"ply":3,"player":"human","action":66,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[2,6,13,31,32,36,53,57],"ai":[0,5,9,19,25,39,45,46]},"scoresAfter":[-40,-40]},{"ply":4,"player":"ai","action":0,"playedCard":0,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[2,6,13,31,32,53,54,57],"ai":[0,5,9,19,25,39,45,46]},"scoresAfter":[-40,-80]},{"ply":5,"player":"human","action":60,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[2,6,13,31,32,53,54,57],"ai":[5,9,19,25,39,43,45,46]},"scoresAfter":[-32,-80]},{"ply":6,"player":"ai","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[2,6,13,31,32,34,54,57],"ai":[5,9,19,25,39,43,45,46]},"scoresAfter":[-32,-72]},{"ply":7,"player":"human","action":72,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[2,6,13,31,32,34,54,57],"ai":[9,19,25,35,39,43,45,46]},"scoresAfter":[-22,-72]},{"ply":8,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[2,6,13,31,32,34,51,57],"ai":[9,19,25,35,39,43,45,46]},"scoresAfter":[-22,-56]},{"ply":9,"player":"human","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[2,6,13,31,32,34,51,57],"ai":[18,19,25,35,39,43,45,46]},"scoresAfter":[-22,-56]},{"ply":10,"player":"ai","action":0,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[6,7,13,31,32,34,51,57],"ai":[18,19,25,35,39,43,45,46]},"scoresAfter":[-22,-71]},{"ply":11,"player":"human","action":31,"playedCard":13,"placeType":"discard","drawSource":"discard_0","drawnCard":2,"handsBefore":{"human":[6,7,13,31,32,34,51,57],"ai":[19,25,35,39,41,43,45,46]},"scoresAfter":[-22,-71]},{"ply":12,"player":"ai","action":0,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[2,6,7,31,32,34,51,57],"ai":[19,25,35,39,41,43,45,46]},"scoresAfter":[-22,-65]},{"ply":13,"player":"human","action":0,"playedCard":2,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[2,6,7,31,32,34,51,57],"ai":[25,35,39,41,43,45,46,55]},"scoresAfter":[-62,-65]},{"ply":14,"player":"ai","action":84,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[6,7,31,32,34,47,51,57],"ai":[25,35,39,41,43,45,46,55]},"scoresAfter":[-62,-79]},{"ply":15,"player":"human","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[6,7,31,32,34,47,51,57],"ai":[3,25,35,39,41,43,45,46]},"scoresAfter":[-52,-79]},{"ply":16,"player":"ai","action":12,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[7,11,31,32,34,47,51,57],"ai":[3,25,35,39,41,43,45,46]},"scoresAfter":[-52,-119]},{"ply":17,"player":"human","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[7,11,31,32,34,47,51,57],"ai":[3,29,35,39,41,43,45,46]},"scoresAfter":[-40,-119]},{"ply":18,"player":"ai","action":10,"playedCard":3,"placeType":"discard","drawSource":"discard_3","drawnCard":36,"handsBefore":{"human":[11,31,32,34,47,50,51,57],"ai":[3,29,35,39,41,43,45,46]},"scoresAfter":[-40,-119]},{"ply":19,"player":"human","action":12,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[11,31,32,34,47,50,51,57],"ai":[29,35,36,39,41,43,45,46]},"scoresAfter":[-54,-119]},{"ply":20,"player":"ai","action":12,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[11,32,34,47,50,51,52,57],"ai":[29,35,36,39,41,43,45,46]},"scoresAfter":[-54,-99]},{"ply":21,"player":"human","action":12,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[11,32,34,47,50,51,52,57],"ai":[29,30,36,39,41,43,45,46]},"scoresAfter":[-47,-99]},{"ply":22,"player":"ai","action":18,"playedCard":30,"placeType":"discard","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[11,34,47,50,51,52,57,59],"ai":[29,30,36,39,41,43,45,46]},"scoresAfter":[-47,-99]},{"ply":23,"player":"human","action":42,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[11,34,47,50,51,52,57,59],"ai":[17,29,36,39,41,43,45,46]},"scoresAfter":[-47,-99]},{"ply":24,"player":"ai","action":18,"playedCard":29,"placeType":"discard","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[4,11,34,47,51,52,57,59],"ai":[17,29,36,39,41,43,45,46]},"scoresAfter":[-47,-99]},{"ply":25,"player":"human","action":54,"playedCard":51,"placeType":"discard","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[4,11,34,47,51,52,57,59],"ai":[17,22,36,39,41,43,45,46]},"scoresAfter":[-47,-99]},{"ply":26,"player":"ai","action":12,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[4,8,11,34,47,52,57,59],"ai":[17,22,36,39,41,43,45,46]},"scoresAfter":[-47,-90]},{"ply":27,"player":"human","action":66,"playedCard":52,"placeType":"discard","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[4,8,11,34,47,52,57,59],"ai":[10,17,36,39,41,43,45,46]},"scoresAfter":[-47,-90]},{"ply":28,"player":"ai","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[4,8,11,34,37,47,57,59],"ai":[10,17,36,39,41,43,45,46]},"scoresAfter":[-47,-72]},{"ply":29,"player":"human","action":12,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[4,8,11,34,37,47,57,59],"ai":[17,21,36,39,41,43,45,46]},"scoresAfter":[-33,-72]},{"ply":30,"player":"ai","action":24,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[4,11,26,34,37,47,57,59],"ai":[17,21,36,39,41,43,45,46]},"scoresAfter":[-33,-92]},{"ply":31,"player":"human","action":12,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[4,11,26,34,37,47,57,59],"ai":[16,17,21,39,41,43,45,46]},"scoresAfter":[-13,-92]},{"ply":32,"player":"ai","action":18,"playedCard":17,"placeType":"discard","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[4,26,34,37,47,48,57,59],"ai":[16,17,21,39,41,43,45,46]},"scoresAfter":[-13,-92]},{"ply":33,"player":"human","action":42,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[4,26,34,37,47,48,57,59],"ai":[16,21,39,41,43,44,45,46]},"scoresAfter":[-13,-92]},{"ply":34,"player":"ai","action":10,"playedCard":16,"placeType":"discard","drawSource":"discard_3","drawnCard":37,"handsBefore":{"human":[4,15,26,34,47,48,57,59],"ai":[16,21,39,41,43,44,45,46]},"scoresAfter":[-13,-92]},{"ply":35,"player":"human","action":66,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[4,15,26,34,47,48,57,59],"ai":[21,37,39,41,43,44,45,46]},"scoresAfter":[-13,-92]},{"ply":36,"player":"ai","action":12,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[4,15,24,26,34,47,57,59],"ai":[21,37,39,41,43,44,45,46]},"scoresAfter":[-13,-112]},{"ply":37,"player":"human","action":42,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[4,15,24,26,34,47,57,59],"ai":[21,39,41,43,44,45,46,58]},"scoresAfter":[-13,-112]},{"ply":38,"player":"ai","action":12,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[4,15,20,24,34,47,57,59],"ai":[21,39,41,43,44,45,46,58]},"scoresAfter":[-13,-104]},{"ply":39,"player":"human","action":42,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[4,15,20,24,34,47,57,59],"ai":[21,23,41,43,44,45,46,58]},"scoresAfter":[-13,-104]},{"ply":40,"player":"ai","action":14,"playedCard":23,"placeType":"play","drawSource":"discard_1","drawnCard":16,"handsBefore":{"human":[4,12,15,20,34,47,57,59],"ai":[21,23,41,43,44,45,46,58]},"scoresAfter":[-13,-94]},{"ply":41,"player":"human","action":18,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[4,12,15,20,34,47,57,59],"ai":[16,21,41,43,44,45,46,58]},"scoresAfter":[-13,-94]},{"ply":42,"player":"ai","action":25,"playedCard":41,"placeType":"play","drawSource":"discard_0","drawnCard":3,"handsBefore":{"human":[4,15,20,33,34,47,57,59],"ai":[16,21,41,43,44,45,46,58]},"scoresAfter":[-13,-78]},{"ply":43,"player":"human","action":36,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[4,15,20,33,34,47,57,59],"ai":[3,16,21,43,44,45,46,58]},"scoresAfter":[-5,-78]},{"ply":44,"player":"ai","action":41,"playedCard":43,"placeType":"play","drawSource":"discard_4","drawnCard":48,"handsBefore":{"human":[4,15,20,28,34,47,57,59],"ai":[3,16,21,43,44,45,46,58]},"scoresAfter":[-5,-54]},{"ply":45,"player":"human","action":48,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[4,15,20,28,34,47,57,59],"ai":[3,16,21,44,45,46,48,58]},"scoresAfter":[4,-54]},{"ply":46,"player":"ai","action":38,"playedCard":44,"placeType":"play","drawSource":"discard_1","drawnCard":12,"handsBefore":{"human":[1,4,15,20,28,47,57,59],"ai":[3,16,21,44,45,46,48,58]},"scoresAfter":[4,-26]},{"ply":47,"player":"human","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[1,4,15,20,28,47,57,59],"ai":[3,12,16,21,45,46,48,58]},"scoresAfter":[4,-26]},{"ply":48,"player":"ai","action":53,"playedCard":45,"placeType":"play","drawSource":"discard_4","drawnCard":52,"handsBefore":{"human":[4,15,20,28,40,47,57,59],"ai":[3,12,16,21,45,46,48,58]},"scoresAfter":[4,26]},{"ply":49,"player":"human","action":54,"playedCard":40,"placeType":"discard","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[4,15,20,28,40,47,57,59],"ai":[3,12,16,21,46,48,52,58]},"scoresAfter":[4,26]},{"ply":50,"player":"ai","action":48,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[4,15,20,27,28,47,57,59],"ai":[3,12,16,21,46,48,52,58]},"scoresAfter":[4,62]},{"ply":51,"player":"human","action":77,"playedCard":57,"placeType":"play","drawSource":"discard_4","drawnCard":51,"handsBefore":{"human":[4,15,20,27,28,47,57,59],"ai":[3,12,16,21,48,52,56,58]},"scoresAfter":[20,62]},{"ply":52,"player":"ai","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[4,15,20,27,28,47,51,59],"ai":[3,12,16,21,48,52,56,58]},"scoresAfter":[20,71]},{"ply":53,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[4,15,20,27,28,47,51,59],"ai":[3,12,16,21,42,48,52,56]},"scoresAfter":[40,71]}],"finalScores":[40,71],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[49,31,57,32,53,13,36,6,0,5,38,46,19,25,39,9,2,45,54,43,34,35,51,18,7,41,55,47,3,11,29,50,52,30,59,17,4,22,8,10,37,21,26,16,48,44,15,24,58,20,23,12,33,28,1,40,27,56,42,14],"drawPtr":60,"cardLoc":[4,5,3,2,1,4,3,3,3,4,4,3,2,5,1,1,2,5,4,4,1,2,4,4,5,4,5,1,1,5,5,3,3,3,3,4,4,4,4,4,5,4,2,4,4,4,4,1,2,3,5,1,2,3,3,4,2,3,4,3],"handPublic":[false,false,false,true,false,false,false,false,false,false,false,false,true,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,true,true,false,false,false,false,false,false,false],"colTop":[[10,0,9,0,10],[9,10,10,9,9]],"colHandshakes":[[1,0,0,0,1],[1,0,1,3,0]],"colLength":[[5,0,4,0,5],[4,4,2,9,2]],"piles":[[1],[13,17],[30,29,26,24],[40],[50]],"toMove":1,"stepCount":53,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"52eb0332-a4a4-4f5e-a418-8c63612de29d","seed":"6edv02","startedAt":"2026-07-14T17:14:28.450Z","finishedAt":"2026-07-14T17:16:32.624Z","initialDeckOrder":[20,48,37,11,7,59,8,16,3,24,33,23,46,1,36,51,41,52,43,0,31,10,27,57,54,13,29,21,22,53,6,17,19,44,30,42,25,14,15,4,55,26,5,39,34,12,32,56,58,2,49,35,40,9,18,47,38,28,50,45],"moves":[{"ply":1,"player":"human","action":72,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[7,8,11,16,20,37,48,59],"ai":[1,3,23,24,33,36,46,51]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":84,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[7,8,11,16,20,37,41,59],"ai":[1,3,23,24,33,36,46,51]},"scoresAfter":[-40,-18]},{"ply":3,"player":"human","action":60,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[7,8,11,16,20,37,41,59],"ai":[1,3,23,24,33,36,46,52]},"scoresAfter":[-80,-18]},{"ply":4,"player":"ai","action":84,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[7,8,11,16,20,41,43,59],"ai":[1,3,23,24,33,36,46,52]},"scoresAfter":[-80,-15]},{"ply":5,"player":"human","action":36,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[7,8,11,16,20,41,43,59],"ai":[0,1,3,23,24,33,36,46]},"scoresAfter":[-97,-15]},{"ply":6,"player":"ai","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[7,8,11,20,31,41,43,59],"ai":[0,1,3,23,24,33,36,46]},"scoresAfter":[-97,-15]},{"ply":7,"player":"human","action":61,"playedCard":41,"placeType":"play","drawSource":"discard_0","drawnCard":0,"handsBefore":{"human":[7,8,11,20,31,41,43,59],"ai":[1,3,10,23,24,33,36,46]},"scoresAfter":[-89,-15]},{"ply":8,"player":"ai","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[0,7,8,11,20,31,43,59],"ai":[1,3,10,23,24,33,36,46]},"scoresAfter":[-89,-55]},{"ply":9,"player":"human","action":0,"playedCard":0,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[0,7,8,11,20,31,43,59],"ai":[3,10,23,24,27,33,36,46]},"scoresAfter":[-129,-55]},{"ply":10,"player":"ai","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[7,8,11,20,31,43,57,59],"ai":[3,10,23,24,27,33,36,46]},"scoresAfter":[-129,-51]},{"ply":11,"player":"human","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[7,8,11,20,31,43,57,59],"ai":[10,23,24,27,33,36,46,54]},"scoresAfter":[-117,-51]},{"ply":12,"player":"ai","action":24,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[8,11,13,20,31,43,57,59],"ai":[10,23,24,27,33,36,46,54]},"scoresAfter":[-117,-91]},{"ply":13,"player":"human","action":30,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[8,11,13,20,31,43,57,59],"ai":[10,23,27,29,33,36,46,54]},"scoresAfter":[-117,-91]},{"ply":14,"player":"ai","action":12,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[8,11,20,21,31,43,57,59],"ai":[10,23,27,29,33,36,46,54]},"scoresAfter":[-117,-101]},{"ply":15,"player":"human","action":60,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[8,11,20,21,31,43,57,59],"ai":[10,22,27,29,33,36,46,54]},"scoresAfter":[-105,-101]},{"ply":16,"player":"ai","action":18,"playedCard":22,"placeType":"discard","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[8,11,20,21,31,53,57,59],"ai":[10,22,27,29,33,36,46,54]},"scoresAfter":[-105,-101]},{"ply":17,"player":"human","action":60,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[8,11,20,21,31,53,57,59],"ai":[6,10,27,29,33,36,46,54]},"scoresAfter":[-97,-101]},{"ply":18,"player":"ai","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[8,11,17,20,21,31,57,59],"ai":[6,10,27,29,33,36,46,54]},"scoresAfter":[-97,-91]},{"ply":19,"player":"human","action":24,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[8,11,17,20,21,31,57,59],"ai":[10,19,27,29,33,36,46,54]},"scoresAfter":[-93,-91]},{"ply":20,"player":"ai","action":84,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[8,11,20,21,31,44,57,59],"ai":[10,19,27,29,33,36,46,54]},"scoresAfter":[-93,-86]},{"ply":21,"player":"human","action":62,"playedCard":44,"placeType":"play","drawSource":"discard_1","drawnCard":22,"handsBefore":{"human":[8,11,20,21,31,44,57,59],"ai":[10,19,27,29,30,33,36,46]},"scoresAfter":[-79,-86]},{"ply":22,"player":"ai","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[8,11,20,21,22,31,57,59],"ai":[10,19,27,29,30,33,36,46]},"scoresAfter":[-79,-68]},{"ply":23,"player":"human","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[8,11,20,21,22,31,57,59],"ai":[19,27,29,30,33,36,42,46]},"scoresAfter":[-65,-68]},{"ply":24,"player":"ai","action":12,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[11,20,21,22,25,31,57,59],"ai":[19,27,29,30,33,36,42,46]},"scoresAfter":[-65,-64]},{"ply":25,"player":"human","action":12,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[11,20,21,22,25,31,57,59],"ai":[14,19,29,30,33,36,42,46]},"scoresAfter":[-58,-64]},{"ply":26,"player":"ai","action":18,"playedCard":19,"placeType":"discard","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[11,15,21,22,25,31,57,59],"ai":[14,19,29,30,33,36,42,46]},"scoresAfter":[-58,-64]},{"ply":27,"player":"human","action":24,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[11,15,21,22,25,31,57,59],"ai":[4,14,29,30,33,36,42,46]},"scoresAfter":[-50,-64]},{"ply":28,"player":"ai","action":24,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[11,15,22,25,31,55,57,59],"ai":[4,14,29,30,33,36,42,46]},"scoresAfter":[-50,-56]},{"ply":29,"player":"human","action":24,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[11,15,22,25,31,55,57,59],"ai":[4,14,26,30,33,36,42,46]},"scoresAfter":[-41,-56]},{"ply":30,"player":"ai","action":30,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[5,11,15,25,31,55,57,59],"ai":[4,14,26,30,33,36,42,46]},"scoresAfter":[-41,-56]},{"ply":31,"player":"human","action":60,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[5,11,15,25,31,55,57,59],"ai":[4,14,30,33,36,39,42,46]},"scoresAfter":[-29,-56]},{"ply":32,"player":"ai","action":24,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[5,11,15,25,31,34,57,59],"ai":[4,14,30,33,36,39,42,46]},"scoresAfter":[-29,-46]},{"ply":33,"player":"human","action":6,"playedCard":5,"placeType":"discard","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[5,11,15,25,31,34,57,59],"ai":[4,12,14,33,36,39,42,46]},"scoresAfter":[-29,-46]},{"ply":34,"player":"ai","action":18,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[11,15,25,31,32,34,57,59],"ai":[4,12,14,33,36,39,42,46]},"scoresAfter":[-29,-46]},{"ply":35,"player":"human","action":72,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[11,15,25,31,32,34,57,59],"ai":[4,14,33,36,39,42,46,56]},"scoresAfter":[-13,-46]},{"ply":36,"player":"ai","action":24,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[11,15,25,31,32,34,58,59],"ai":[4,14,33,36,39,42,46,56]},"scoresAfter":[-13,-30]},{"ply":37,"player":"human","action":72,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[11,15,25,31,32,34,58,59],"ai":[2,4,14,36,39,42,46,56]},"scoresAfter":[5,-30]},{"ply":38,"player":"ai","action":84,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[11,15,25,31,32,34,49,59],"ai":[2,4,14,36,39,42,46,56]},"scoresAfter":[5,-23]},{"ply":39,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[11,15,25,31,32,34,49,59],"ai":[2,4,14,35,36,39,42,46]},"scoresAfter":[25,-23]},{"ply":40,"player":"ai","action":18,"playedCard":4,"placeType":"discard","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[11,15,25,31,32,34,40,49],"ai":[2,4,14,35,36,39,42,46]},"scoresAfter":[25,-23]},{"ply":41,"player":"human","action":3,"playedCard":11,"placeType":"play","drawSource":"discard_2","drawnCard":26,"handsBefore":{"human":[11,15,25,31,32,34,40,49],"ai":[2,9,14,35,36,39,42,46]},"scoresAfter":[45,-23]},{"ply":42,"player":"ai","action":18,"playedCard":9,"placeType":"discard","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[15,25,26,31,32,34,40,49],"ai":[2,9,14,35,36,39,42,46]},"scoresAfter":[45,-23]},{"ply":43,"player":"human","action":26,"playedCard":26,"placeType":"play","drawSource":"discard_1","drawnCard":12,"handsBefore":{"human":[15,25,26,31,32,34,40,49],"ai":[2,14,18,35,36,39,42,46]},"scoresAfter":[5,-23]},{"ply":44,"player":"ai","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[12,15,25,31,32,34,40,49],"ai":[2,14,18,35,36,39,42,46]},"scoresAfter":[5,-23]},{"ply":45,"player":"human","action":26,"playedCard":25,"placeType":"play","drawSource":"discard_1","drawnCard":19,"handsBefore":{"human":[12,15,25,31,32,34,40,49],"ai":[14,18,35,36,39,42,46,47]},"scoresAfter":[-15,-23]},{"ply":46,"player":"ai","action":24,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[12,15,19,31,32,34,40,49],"ai":[14,18,35,36,39,42,46,47]},"scoresAfter":[-15,-3]},{"ply":47,"player":"human","action":38,"playedCard":31,"placeType":"play","drawSource":"discard_1","drawnCard":13,"handsBefore":{"human":[12,15,19,31,32,34,40,49],"ai":[14,18,36,38,39,42,46,47]},"scoresAfter":[3,-3]},{"ply":48,"player":"ai","action":43,"playedCard":38,"placeType":"discard","drawSource":"discard_0","drawnCard":2,"handsBefore":{"human":[12,13,15,19,32,34,40,49],"ai":[14,18,36,38,39,42,46,47]},"scoresAfter":[3,-3]},{"ply":49,"player":"human","action":49,"playedCard":32,"placeType":"play","drawSource":"discard_0","drawnCard":9,"handsBefore":{"human":[12,13,15,19,32,34,40,49],"ai":[2,14,18,36,39,42,46,47]},"scoresAfter":[24,-3]},{"ply":50,"player":"ai","action":61,"playedCard":42,"placeType":"play","drawSource":"discard_0","drawnCard":4,"handsBefore":{"human":[9,12,13,15,19,34,40,49],"ai":[2,14,18,36,39,42,46,47]},"scoresAfter":[24,-18]},{"ply":51,"player":"human","action":60,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[9,12,13,15,19,34,40,49],"ai":[2,4,14,18,36,39,46,47]},"scoresAfter":[51,-18]},{"ply":52,"player":"ai","action":72,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[9,12,13,15,19,28,40,49],"ai":[2,4,14,18,36,39,46,47]},"scoresAfter":[51,-9]},{"ply":53,"player":"human","action":42,"playedCard":15,"placeType":"discard","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[9,12,13,15,19,28,40,49],"ai":[2,4,14,18,36,39,47,50]},"scoresAfter":[51,-9]}],"finalScores":[51,-9],"outcome":"YOU WIN","finalState":{"deckOrder":[20,48,37,11,7,59,8,16,3,24,33,23,46,1,36,51,41,52,43,0,31,10,27,57,54,13,29,21,22,53,6,17,19,44,30,42,25,14,15,4,55,26,5,39,34,12,32,56,58,2,49,35,40,9,18,47,38,28,50,45],"drawPtr":60,"cardLoc":[3,4,2,4,2,5,4,3,3,1,4,3,1,1,2,5,3,3,2,1,3,3,3,4,4,3,3,4,1,4,4,3,3,4,3,4,2,3,5,2,1,3,4,3,3,1,4,2,3,1,2,4,4,3,4,3,4,3,3,3],"handPublic":[false,false,true,false,true,false,false,false,false,true,false,false,true,true,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,9,9,7,10],[9,10,10,9,7]],"colHandshakes":[[1,0,2,1,1],[1,0,1,0,0]],"colLength":[[4,5,5,4,6],[4,1,6,2,4]],"piles":[[5],[15],[],[38],[]],"toMove":1,"stepCount":53,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"e83da5a7-6434-4a35-a17b-11f67d80b40b","seed":"o92j6w","startedAt":"2026-07-14T17:16:33.358Z","finishedAt":"2026-07-14T17:19:53.207Z","initialDeckOrder":[18,17,19,6,22,46,34,14,32,49,42,23,56,16,33,1,43,38,4,0,28,24,26,51,15,59,27,58,30,2,41,48,55,53,54,3,13,57,11,29,12,9,45,40,21,39,20,25,5,10,36,52,37,35,7,47,31,8,44,50],"moves":[{"ply":1,"player":"human","action":12,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[6,14,17,18,19,22,34,46],"ai":[1,16,23,32,33,42,49,56]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":60,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[6,17,18,19,22,34,43,46],"ai":[1,16,23,32,33,42,49,56]},"scoresAfter":[-40,-15]},{"ply":3,"player":"human","action":12,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[6,17,18,19,22,34,43,46],"ai":[1,16,23,32,33,38,49,56]},"scoresAfter":[-32,-15]},{"ply":4,"player":"ai","action":72,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[4,6,18,19,22,34,43,46],"ai":[1,16,23,32,33,38,49,56]},"scoresAfter":[-32,-55]},{"ply":5,"player":"human","action":24,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[4,6,18,19,22,34,43,46],"ai":[0,1,16,23,32,33,38,56]},"scoresAfter":[-22,-55]},{"ply":6,"player":"ai","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[4,6,19,22,28,34,43,46],"ai":[0,1,16,23,32,33,38,56]},"scoresAfter":[-22,-55]},{"ply":7,"player":"human","action":24,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[4,6,19,22,28,34,43,46],"ai":[1,16,23,24,32,33,38,56]},"scoresAfter":[-10,-55]},{"ply":8,"player":"ai","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[4,6,22,26,28,34,43,46],"ai":[1,16,23,24,32,33,38,56]},"scoresAfter":[-10,-55]},{"ply":9,"player":"human","action":36,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[4,6,22,26,28,34,43,46],"ai":[16,23,24,32,33,38,51,56]},"scoresAfter":[-50,-55]},{"ply":10,"player":"ai","action":66,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[4,6,15,22,28,34,43,46],"ai":[16,23,24,32,33,38,51,56]},"scoresAfter":[-50,-55]},{"ply":11,"player":"human","action":48,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[4,6,15,22,28,34,43,46],"ai":[16,23,24,32,33,51,56,59]},"scoresAfter":[-44,-55]},{"ply":12,"player":"ai","action":24,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[4,6,15,22,27,34,43,46],"ai":[16,23,24,32,33,51,56,59]},"scoresAfter":[-44,-95]},{"ply":13,"player":"human","action":54,"playedCard":27,"placeType":"discard","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[4,6,15,22,27,34,43,46],"ai":[16,23,32,33,51,56,58,59]},"scoresAfter":[-44,-95]},{"ply":14,"player":"ai","action":0,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[4,6,15,22,30,34,43,46],"ai":[16,23,32,33,51,56,58,59]},"scoresAfter":[-44,-112]},{"ply":15,"player":"human","action":48,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[4,6,15,22,30,34,43,46],"ai":[2,23,32,33,51,56,58,59]},"scoresAfter":[-34,-112]},{"ply":16,"player":"ai","action":12,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[4,6,15,22,34,41,43,46],"ai":[2,23,32,33,51,56,58,59]},"scoresAfter":[-34,-102]},{"ply":17,"player":"human","action":34,"playedCard":15,"placeType":"discard","drawSource":"discard_3","drawnCard":38,"handsBefore":{"human":[4,6,15,22,34,41,43,46],"ai":[2,32,33,48,51,56,58,59]},"scoresAfter":[-34,-102]},{"ply":18,"player":"ai","action":36,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[4,6,22,34,38,41,43,46],"ai":[2,32,33,48,51,56,58,59]},"scoresAfter":[-34,-122]},{"ply":19,"player":"human","action":48,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[4,6,22,34,38,41,43,46],"ai":[2,32,33,51,55,56,58,59]},"scoresAfter":[-74,-122]},{"ply":20,"player":"ai","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[4,6,22,34,41,43,46,53],"ai":[2,32,33,51,55,56,58,59]},"scoresAfter":[-74,-122]},{"ply":21,"player":"human","action":48,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[4,6,22,34,41,43,46,53],"ai":[32,33,51,54,55,56,58,59]},"scoresAfter":[-66,-122]},{"ply":22,"player":"ai","action":0,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[3,4,6,22,34,43,46,53],"ai":[32,33,51,54,55,56,58,59]},"scoresAfter":[-66,-108]},{"ply":23,"player":"human","action":60,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[3,4,6,22,34,43,46,53],"ai":[13,33,51,54,55,56,58,59]},"scoresAfter":[-54,-108]},{"ply":24,"player":"ai","action":12,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[3,4,6,22,34,46,53,57],"ai":[13,33,51,54,55,56,58,59]},"scoresAfter":[-54,-92]},{"ply":25,"player":"human","action":37,"playedCard":22,"placeType":"play","drawSource":"discard_0","drawnCard":2,"handsBefore":{"human":[3,4,6,22,34,46,53,57],"ai":[11,13,51,54,55,56,58,59]},"scoresAfter":[-36,-92]},{"ply":26,"player":"ai","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[2,3,4,6,34,46,53,57],"ai":[11,13,51,54,55,56,58,59]},"scoresAfter":[-36,-102]},{"ply":27,"player":"human","action":1,"playedCard":2,"placeType":"play","drawSource":"discard_0","drawnCard":1,"handsBefore":{"human":[2,3,4,6,34,46,53,57],"ai":[13,29,51,54,55,56,58,59]},"scoresAfter":[-76,-102]},{"ply":28,"player":"ai","action":6,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[1,3,4,6,34,46,53,57],"ai":[13,29,51,54,55,56,58,59]},"scoresAfter":[-76,-102]},{"ply":29,"player":"human","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[1,3,4,6,34,46,53,57],"ai":[12,29,51,54,55,56,58,59]},"scoresAfter":[-96,-102]},{"ply":30,"player":"ai","action":6,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[3,4,6,9,34,46,53,57],"ai":[12,29,51,54,55,56,58,59]},"scoresAfter":[-96,-102]},{"ply":31,"player":"human","action":49,"playedCard":34,"placeType":"play","drawSource":"discard_0","drawnCard":0,"handsBefore":{"human":[3,4,6,9,34,46,53,57],"ai":[29,45,51,54,55,56,58,59]},"scoresAfter":[-78,-102]},{"ply":32,"player":"ai","action":12,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[0,3,4,6,9,46,53,57],"ai":[29,45,51,54,55,56,58,59]},"scoresAfter":[-78,-94]},{"ply":33,"player":"human","action":0,"playedCard":0,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[0,3,4,6,9,46,53,57],"ai":[29,40,51,54,55,56,58,59]},"scoresAfter":[-98,-94]},{"ply":34,"player":"ai","action":6,"playedCard":29,"placeType":"discard","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[3,4,6,9,21,46,53,57],"ai":[29,40,51,54,55,56,58,59]},"scoresAfter":[-98,-94]},{"ply":35,"player":"human","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[3,4,6,9,21,46,53,57],"ai":[39,40,51,54,55,56,58,59]},"scoresAfter":[-90,-94]},{"ply":36,"player":"ai","action":6,"playedCard":39,"placeType":"discard","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[4,6,9,20,21,46,53,57],"ai":[39,40,51,54,55,56,58,59]},"scoresAfter":[-90,-94]},{"ply":37,"player":"human","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[4,6,9,20,21,46,53,57],"ai":[25,40,51,54,55,56,58,59]},"scoresAfter":[-78,-94]},{"ply":38,"player":"ai","action":24,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[5,6,9,20,21,46,53,57],"ai":[25,40,51,54,55,56,58,59]},"scoresAfter":[-78,-88]},{"ply":39,"player":"human","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[5,6,9,20,21,46,53,57],"ai":[10,25,40,54,55,56,58,59]},"scoresAfter":[-62,-88]},{"ply":40,"player":"ai","action":36,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[6,9,20,21,36,46,53,57],"ai":[10,25,40,54,55,56,58,59]},"scoresAfter":[-62,-73]},{"ply":41,"player":"human","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[6,9,20,21,36,46,53,57],"ai":[10,25,40,52,55,56,58,59]},"scoresAfter":[-42,-73]},{"ply":42,"player":"ai","action":48,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[9,20,21,36,37,46,53,57],"ai":[10,25,40,52,55,56,58,59]},"scoresAfter":[-42,-55]},{"ply":43,"player":"human","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[9,20,21,36,37,46,53,57],"ai":[10,25,35,40,52,56,58,59]},"scoresAfter":[10,-55]},{"ply":44,"player":"ai","action":27,"playedCard":35,"placeType":"play","drawSource":"discard_2","drawnCard":29,"handsBefore":{"human":[7,20,21,36,37,46,53,57],"ai":[10,25,35,40,52,56,58,59]},"scoresAfter":[10,-35]},{"ply":45,"player":"human","action":18,"playedCard":20,"placeType":"discard","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[7,20,21,36,37,46,53,57],"ai":[10,25,29,40,52,56,58,59]},"scoresAfter":[10,-35]},{"ply":46,"player":"ai","action":62,"playedCard":56,"placeType":"play","drawSource":"discard_1","drawnCard":20,"handsBefore":{"human":[7,21,36,37,46,47,53,57],"ai":[10,25,29,40,52,56,58,59]},"scoresAfter":[10,-14]},{"ply":47,"player":"human","action":48,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[7,21,36,37,46,47,53,57],"ai":[10,20,25,29,40,52,58,59]},"scoresAfter":[28,-14]},{"ply":48,"player":"ai","action":74,"playedCard":58,"placeType":"play","drawSource":"discard_1","drawnCard":12,"handsBefore":{"human":[7,21,31,36,37,47,53,57],"ai":[10,20,25,29,40,52,58,59]},"scoresAfter":[28,13]},{"ply":49,"player":"human","action":60,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[7,21,31,36,37,47,53,57],"ai":[10,12,20,25,29,40,52,59]},"scoresAfter":[48,13]},{"ply":50,"player":"ai","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[7,8,21,31,36,37,53,57],"ai":[10,12,20,25,29,40,52,59]},"scoresAfter":[48,63]},{"ply":51,"player":"human","action":30,"playedCard":21,"placeType":"discard","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[7,8,21,31,36,37,53,57],"ai":[10,12,20,25,29,40,44,52]},"scoresAfter":[48,63]}],"finalScores":[48,63],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[18,17,19,6,22,46,34,14,32,49,42,23,56,16,33,1,43,38,4,0,28,24,26,51,15,59,27,58,30,2,41,48,55,53,54,3,13,57,11,29,12,9,45,40,21,39,20,25,5,10,36,52,37,35,7,47,31,8,44,50],"drawPtr":60,"cardLoc":[3,3,3,3,3,3,3,1,1,3,2,4,2,5,3,5,4,3,3,3,2,5,3,4,4,2,3,5,3,2,3,1,4,4,3,4,1,1,3,5,2,3,4,3,2,4,3,3,4,4,1,4,2,1,4,4,4,1,4,4],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[8,9,9,10,0],[10,10,10,8,10]],"colHandshakes":[[3,1,1,1,0],[0,0,1,0,2]],"colLength":[[8,5,4,5,0],[1,2,4,2,8]],"piles":[[],[15,13,21],[27],[39],[]],"toMove":1,"stepCount":51,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"dbbfbf6d-4abb-4fdd-b5cd-426220b1c783","seed":"tlgiup","startedAt":"2026-07-14T17:19:54.335Z","finishedAt":"2026-07-14T17:21:29.716Z","initialDeckOrder":[57,43,30,9,36,10,3,39,31,12,27,51,16,28,47,35,5,49,56,40,1,21,0,13,15,25,2,23,33,37,7,54,58,44,55,26,11,41,53,29,38,22,59,17,14,4,45,6,46,18,48,32,50,42,24,34,19,52,20,8],"moves":[{"ply":1,"player":"human","action":48,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[3,9,10,30,36,39,43,57],"ai":[12,16,27,28,31,35,47,51]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":84,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[3,5,9,10,30,39,43,57],"ai":[12,16,27,28,31,35,47,51]},"scoresAfter":[-40,-18]},{"ply":3,"player":"human","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[3,5,9,10,30,39,43,57],"ai":[12,16,27,28,31,35,47,49]},"scoresAfter":[-58,-18]},{"ply":4,"player":"ai","action":90,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[5,9,10,30,39,43,56,57],"ai":[12,16,27,28,31,35,47,49]},"scoresAfter":[-58,-18]},{"ply":5,"player":"human","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[5,9,10,30,39,43,56,57],"ai":[12,16,27,28,31,35,40,47]},"scoresAfter":[-54,-18]},{"ply":6,"player":"ai","action":0,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[1,9,10,30,39,43,56,57],"ai":[12,16,27,28,31,35,40,47]},"scoresAfter":[-54,-58]},{"ply":7,"player":"human","action":48,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[1,9,10,30,39,43,56,57],"ai":[16,21,27,28,31,35,40,47]},"scoresAfter":[-50,-58]},{"ply":8,"player":"ai","action":24,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[0,1,9,10,30,43,56,57],"ai":[16,21,27,28,31,35,40,47]},"scoresAfter":[-50,-76]},{"ply":9,"player":"human","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[0,1,9,10,30,43,56,57],"ai":[13,16,21,28,31,35,40,47]},"scoresAfter":[-50,-76]},{"ply":10,"player":"ai","action":36,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[1,9,10,15,30,43,56,57],"ai":[13,16,21,28,31,35,40,47]},"scoresAfter":[-50,-73]},{"ply":11,"player":"human","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[1,9,10,15,30,43,56,57],"ai":[13,16,21,25,31,35,40,47]},"scoresAfter":[-50,-73]},{"ply":12,"player":"ai","action":0,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[2,9,10,15,30,43,56,57],"ai":[13,16,21,25,31,35,40,47]},"scoresAfter":[-50,-93]},{"ply":13,"player":"human","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[2,9,10,15,30,43,56,57],"ai":[16,21,23,25,31,35,40,47]},"scoresAfter":[-50,-93]},{"ply":14,"player":"ai","action":42,"playedCard":25,"placeType":"discard","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[9,10,15,30,33,43,56,57],"ai":[16,21,23,25,31,35,40,47]},"scoresAfter":[-50,-93]},{"ply":15,"player":"human","action":30,"playedCard":15,"placeType":"discard","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[9,10,15,30,33,43,56,57],"ai":[16,21,23,31,35,37,40,47]},"scoresAfter":[-50,-93]},{"ply":16,"player":"ai","action":60,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[7,9,10,30,33,43,56,57],"ai":[16,21,23,31,35,37,40,47]},"scoresAfter":[-50,-133]},{"ply":17,"player":"human","action":3,"playedCard":7,"placeType":"play","drawSource":"discard_2","drawnCard":25,"handsBefore":{"human":[7,9,10,30,33,43,56,57],"ai":[16,21,23,31,35,40,47,54]},"scoresAfter":[-44,-133]},{"ply":18,"player":"ai","action":84,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[9,10,25,30,33,43,56,57],"ai":[16,21,23,31,35,40,47,54]},"scoresAfter":[-44,-128]},{"ply":19,"player":"human","action":24,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[9,10,25,30,33,43,56,57],"ai":[16,21,23,31,35,40,47,58]},"scoresAfter":[-84,-128]},{"ply":20,"player":"ai","action":60,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[9,10,30,33,43,44,56,57],"ai":[16,21,23,31,35,40,47,58]},"scoresAfter":[-84,-122]},{"ply":21,"player":"human","action":24,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[9,10,30,33,43,44,56,57],"ai":[16,21,23,31,35,47,55,58]},"scoresAfter":[-74,-122]},{"ply":22,"player":"ai","action":74,"playedCard":55,"placeType":"play","drawSource":"discard_1","drawnCard":15,"handsBefore":{"human":[9,10,26,33,43,44,56,57],"ai":[16,21,23,31,35,47,55,58]},"scoresAfter":[-74,-116]},{"ply":23,"player":"human","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[9,10,26,33,43,44,56,57],"ai":[15,16,21,23,31,35,47,58]},"scoresAfter":[-66,-116]},{"ply":24,"player":"ai","action":48,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[10,11,26,33,43,44,56,57],"ai":[15,16,21,23,31,35,47,58]},"scoresAfter":[-66,-110]},{"ply":25,"player":"human","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[10,11,26,33,43,44,56,57],"ai":[15,16,21,23,35,41,47,58]},"scoresAfter":[-57,-110]},{"ply":26,"player":"ai","action":60,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[11,26,33,43,44,53,56,57],"ai":[15,16,21,23,35,41,47,58]},"scoresAfter":[-57,-102]},{"ply":27,"player":"human","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[11,26,33,43,44,53,56,57],"ai":[15,16,21,23,29,35,47,58]},"scoresAfter":[-47,-102]},{"ply":28,"player":"ai","action":0,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[26,33,38,43,44,53,56,57],"ai":[15,16,21,23,29,35,47,58]},"scoresAfter":[-47,-96]},{"ply":29,"player":"human","action":11,"playedCard":26,"placeType":"discard","drawSource":"discard_4","drawnCard":49,"handsBefore":{"human":[26,33,38,43,44,53,56,57],"ai":[16,21,22,23,29,35,47,58]},"scoresAfter":[-47,-96]},{"ply":30,"player":"ai","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[33,38,43,44,49,53,56,57],"ai":[16,21,22,23,29,35,47,58]},"scoresAfter":[-47,-87]},{"ply":31,"player":"human","action":48,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[33,38,43,44,49,53,56,57],"ai":[16,21,22,23,29,35,47,59]},"scoresAfter":[-87,-87]},{"ply":32,"player":"ai","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[17,33,38,43,44,53,56,57],"ai":[16,21,22,23,29,35,47,59]},"scoresAfter":[-87,-77]},{"ply":33,"player":"human","action":60,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[17,33,38,43,44,53,56,57],"ai":[14,16,21,22,23,29,35,47]},"scoresAfter":[-79,-77]},{"ply":34,"player":"ai","action":12,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[4,17,33,38,43,44,56,57],"ai":[14,16,21,22,23,29,35,47]},"scoresAfter":[-79,-68]},{"ply":35,"player":"human","action":48,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[4,17,33,38,43,44,56,57],"ai":[14,21,22,23,29,35,45,47]},"scoresAfter":[-67,-68]},{"ply":36,"player":"ai","action":60,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[4,6,17,33,38,44,56,57],"ai":[14,21,22,23,29,35,45,47]},"scoresAfter":[-67,-58]},{"ply":37,"player":"human","action":60,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[4,6,17,33,38,44,56,57],"ai":[14,21,22,23,29,45,46,47]},"scoresAfter":[-53,-58]},{"ply":38,"player":"ai","action":60,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[4,6,17,18,33,38,56,57],"ai":[14,21,22,23,29,45,46,47]},"scoresAfter":[-53,-42]},{"ply":39,"player":"human","action":72,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[4,6,17,18,33,38,56,57],"ai":[14,21,22,23,29,46,47,48]},"scoresAfter":[-39,-42]},{"ply":40,"player":"ai","action":60,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[4,6,17,18,32,33,38,57],"ai":[14,21,22,23,29,46,47,48]},"scoresAfter":[-39,-24]},{"ply":41,"player":"human","action":84,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[4,6,17,18,32,33,38,57],"ai":[14,21,22,23,29,47,48,50]},"scoresAfter":[-23,-24]},{"ply":42,"player":"ai","action":60,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[4,6,17,18,32,33,38,42],"ai":[14,21,22,23,29,47,48,50]},"scoresAfter":[-23,-4]},{"ply":43,"player":"human","action":48,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[4,6,17,18,32,33,38,42],"ai":[14,21,22,23,24,29,48,50]},"scoresAfter":[-9,-4]},{"ply":44,"player":"ai","action":12,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[4,6,17,18,33,34,38,42],"ai":[14,21,22,23,24,29,48,50]},"scoresAfter":[-9,20]},{"ply":45,"player":"human","action":48,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[4,6,17,18,33,34,38,42],"ai":[14,19,22,23,24,29,48,50]},"scoresAfter":[7,20]},{"ply":46,"player":"ai","action":27,"playedCard":22,"placeType":"play","drawSource":"discard_2","drawnCard":26,"handsBefore":{"human":[4,6,17,18,34,38,42,52],"ai":[14,19,22,23,24,29,48,50]},"scoresAfter":[7,47]},{"ply":47,"player":"human","action":48,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[4,6,17,18,34,38,42,52],"ai":[14,19,23,24,26,29,48,50]},"scoresAfter":[25,47]},{"ply":48,"player":"ai","action":24,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[4,6,17,18,20,38,42,52],"ai":[14,19,23,24,26,29,48,50]},"scoresAfter":[25,77]}],"finalScores":[25,77],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[57,43,30,9,36,10,3,39,31,12,27,51,16,28,47,35,5,49,56,40,1,21,0,13,15,25,2,23,33,37,7,54,58,44,55,26,11,41,53,29,38,22,59,17,14,4,45,6,46,18,48,32,50,42,24,34,19,52,20,8],"drawPtr":60,"cardLoc":[5,5,5,3,1,3,1,3,2,3,3,3,4,4,2,4,4,1,1,2,1,4,4,4,2,3,2,4,4,2,3,4,3,3,3,4,3,4,1,3,4,4,1,3,3,4,4,4,2,3,2,4,1,3,4,4,3,3,4,4],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,0,9,7,8],[0,10,10,10,10]],"colHandshakes":[[0,0,1,1,1],[0,2,0,1,0]],"colLength":[[6,0,5,4,4],[0,7,4,6,5]],"piles":[[0,1,2],[],[],[],[]],"toMove":0,"stepCount":48,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"64284949-346e-4053-8a9f-e00a3e34c809","seed":"5d050z","startedAt":"2026-07-14T17:21:30.960Z","finishedAt":"2026-07-14T17:24:03.501Z","initialDeckOrder":[17,4,31,27,16,47,10,58,49,24,0,34,53,45,20,19,44,36,48,7,54,8,51,29,33,13,52,18,56,50,55,39,12,6,35,41,32,11,26,59,14,23,1,15,25,42,9,46,30,22,43,40,57,5,38,3,2,28,21,37],"moves":[{"ply":1,"player":"human","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[4,10,16,17,27,31,47,58],"ai":[0,19,20,24,34,45,49,53]},"scoresAfter":[-17,0]},{"ply":2,"player":"ai","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[10,16,17,27,31,44,47,58],"ai":[0,19,20,24,34,45,49,53]},"scoresAfter":[-17,0]},{"ply":3,"player":"human","action":12,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[10,16,17,27,31,44,47,58],"ai":[19,20,24,34,36,45,49,53]},"scoresAfter":[-34,0]},{"ply":4,"player":"ai","action":72,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[10,17,27,31,44,47,48,58],"ai":[19,20,24,34,36,45,49,53]},"scoresAfter":[-34,-40]},{"ply":5,"player":"human","action":72,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[10,17,27,31,44,47,48,58],"ai":[7,19,20,24,34,36,45,53]},"scoresAfter":[-74,-40]},{"ply":6,"player":"ai","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[10,17,27,31,44,47,54,58],"ai":[7,19,20,24,34,36,45,53]},"scoresAfter":[-74,-54]},{"ply":7,"player":"human","action":24,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[10,17,27,31,44,47,54,58],"ai":[8,19,20,24,34,36,45,53]},"scoresAfter":[-92,-54]},{"ply":8,"player":"ai","action":60,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[10,17,31,44,47,51,54,58],"ai":[8,19,20,24,34,36,45,53]},"scoresAfter":[-92,-94]},{"ply":9,"player":"human","action":60,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[10,17,31,44,47,51,54,58],"ai":[8,19,20,24,29,34,45,53]},"scoresAfter":[-88,-94]},{"ply":10,"player":"ai","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[10,17,31,33,44,47,54,58],"ai":[8,19,20,24,29,34,45,53]},"scoresAfter":[-88,-87]},{"ply":11,"player":"human","action":12,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[10,17,31,33,44,47,54,58],"ai":[13,19,20,24,29,34,45,53]},"scoresAfter":[-84,-87]},{"ply":12,"player":"ai","action":0,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[10,31,33,44,47,52,54,58],"ai":[13,19,20,24,29,34,45,53]},"scoresAfter":[-84,-127]},{"ply":13,"player":"human","action":60,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[10,31,33,44,47,52,54,58],"ai":[18,19,20,24,29,34,45,53]},"scoresAfter":[-78,-127]},{"ply":14,"player":"ai","action":84,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[10,31,33,44,47,54,56,58],"ai":[18,19,20,24,29,34,45,53]},"scoresAfter":[-78,-119]},{"ply":15,"player":"human","action":60,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[10,31,33,44,47,54,56,58],"ai":[18,19,20,24,29,34,45,50]},"scoresAfter":[-68,-119]},{"ply":16,"player":"ai","action":90,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[10,31,33,44,47,55,56,58],"ai":[18,19,20,24,29,34,45,50]},"scoresAfter":[-68,-119]},{"ply":17,"player":"human","action":60,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[10,31,33,44,47,55,56,58],"ai":[18,19,20,24,29,34,39,45]},"scoresAfter":[-56,-119]},{"ply":18,"player":"ai","action":48,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[10,12,31,33,44,47,56,58],"ai":[18,19,20,24,29,34,39,45]},"scoresAfter":[-56,-135]},{"ply":19,"player":"human","action":72,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[10,12,31,33,44,47,56,58],"ai":[6,18,19,20,24,34,39,45]},"scoresAfter":[-42,-135]},{"ply":20,"player":"ai","action":6,"playedCard":6,"placeType":"discard","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[10,12,31,33,35,44,47,58],"ai":[6,18,19,20,24,34,39,45]},"scoresAfter":[-42,-135]},{"ply":21,"player":"human","action":19,"playedCard":12,"placeType":"discard","drawSource":"discard_0","drawnCard":6,"handsBefore":{"human":[10,12,31,33,35,44,47,58],"ai":[18,19,20,24,34,39,41,45]},"scoresAfter":[-42,-135]},{"ply":22,"player":"ai","action":60,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[6,10,31,33,35,44,47,58],"ai":[18,19,20,24,34,39,41,45]},"scoresAfter":[-42,-131]},{"ply":23,"player":"human","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[6,10,31,33,35,44,47,58],"ai":[18,19,20,24,32,34,41,45]},"scoresAfter":[-37,-131]},{"ply":24,"player":"ai","action":48,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[10,11,31,33,35,44,47,58],"ai":[18,19,20,24,32,34,41,45]},"scoresAfter":[-37,-124]},{"ply":25,"player":"human","action":24,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[10,11,31,33,35,44,47,58],"ai":[18,19,20,24,26,34,41,45]},"scoresAfter":[-31,-124]},{"ply":26,"player":"ai","action":60,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[10,11,33,35,44,47,58,59],"ai":[18,19,20,24,26,34,41,45]},"scoresAfter":[-31,-115]},{"ply":27,"player":"human","action":24,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[10,11,33,35,44,47,58,59],"ai":[14,18,19,20,24,26,41,45]},"scoresAfter":[-23,-115]},{"ply":28,"player":"ai","action":0,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[10,11,23,35,44,47,58,59],"ai":[14,18,19,20,24,26,41,45]},"scoresAfter":[-23,-135]},{"ply":29,"player":"human","action":36,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[10,11,23,35,44,47,58,59],"ai":[1,18,19,20,24,26,41,45]},"scoresAfter":[-13,-135]},{"ply":30,"player":"ai","action":74,"playedCard":41,"placeType":"play","drawSource":"discard_1","drawnCard":12,"handsBefore":{"human":[10,11,15,23,44,47,58,59],"ai":[1,18,19,20,24,26,41,45]},"scoresAfter":[-13,-127]},{"ply":31,"player":"human","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[10,11,15,23,44,47,58,59],"ai":[1,12,18,19,20,24,26,45]},"scoresAfter":[-4,-127]},{"ply":32,"player":"ai","action":84,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[11,15,23,25,44,47,58,59],"ai":[1,12,18,19,20,24,26,45]},"scoresAfter":[-4,-111]},{"ply":33,"player":"human","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[11,15,23,25,44,47,58,59],"ai":[1,12,18,19,20,24,26,42]},"scoresAfter":[6,-111]},{"ply":34,"player":"ai","action":12,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[9,15,23,25,44,47,58,59],"ai":[1,12,18,19,20,24,26,42]},"scoresAfter":[6,-131]},{"ply":35,"player":"human","action":42,"playedCard":25,"placeType":"discard","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[9,15,23,25,44,47,58,59],"ai":[1,18,19,20,24,26,42,46]},"scoresAfter":[6,-131]},{"ply":36,"player":"ai","action":84,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[9,15,23,30,44,47,58,59],"ai":[1,18,19,20,24,26,42,46]},"scoresAfter":[6,-113]},{"ply":37,"player":"human","action":42,"playedCard":30,"placeType":"discard","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[9,15,23,30,44,47,58,59],"ai":[1,18,19,20,22,24,26,42]},"scoresAfter":[6,-113]},{"ply":38,"player":"ai","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[9,15,23,43,44,47,58,59],"ai":[1,18,19,20,22,24,26,42]},"scoresAfter":[6,-113]},{"ply":39,"player":"human","action":36,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[9,15,23,43,44,47,58,59],"ai":[18,19,20,22,24,26,40,42]},"scoresAfter":[-8,-113]},{"ply":40,"player":"ai","action":0,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[9,15,23,44,47,57,58,59],"ai":[18,19,20,22,24,26,40,42]},"scoresAfter":[-8,-93]},{"ply":41,"player":"human","action":60,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[9,15,23,44,47,57,58,59],"ai":[5,19,20,22,24,26,40,42]},"scoresAfter":[8,-93]},{"ply":42,"player":"ai","action":12,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[9,15,23,38,44,47,58,59],"ai":[5,19,20,22,24,26,40,42]},"scoresAfter":[8,-69]},{"ply":43,"player":"human","action":75,"playedCard":58,"placeType":"play","drawSource":"discard_2","drawnCard":30,"handsBefore":{"human":[9,15,23,38,44,47,58,59],"ai":[3,5,20,22,24,26,40,42]},"scoresAfter":[46,-69]},{"ply":44,"player":"ai","action":24,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[9,15,23,30,38,44,47,59],"ai":[3,5,20,22,24,26,40,42]},"scoresAfter":[46,-41]},{"ply":45,"player":"human","action":63,"playedCard":44,"placeType":"play","drawSource":"discard_2","drawnCard":25,"handsBefore":{"human":[9,15,23,30,38,44,47,59],"ai":[2,3,5,22,24,26,40,42]},"scoresAfter":[53,-41]},{"ply":46,"player":"ai","action":36,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[9,15,23,25,30,38,47,59],"ai":[2,3,5,22,24,26,40,42]},"scoresAfter":[53,-5]},{"ply":47,"player":"human","action":89,"playedCard":59,"placeType":"play","drawSource":"discard_4","drawnCard":50,"handsBefore":{"human":[9,15,23,25,30,38,47,59],"ai":[2,3,5,24,26,28,40,42]},"scoresAfter":[73,-5]},{"ply":48,"player":"ai","action":66,"playedCard":28,"placeType":"discard","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[9,15,23,25,30,38,47,50],"ai":[2,3,5,24,26,28,40,42]},"scoresAfter":[73,-5]},{"ply":49,"player":"human","action":27,"playedCard":23,"placeType":"play","drawSource":"discard_2","drawnCard":28,"handsBefore":{"human":[9,15,23,25,30,38,47,50],"ai":[2,3,5,21,24,26,40,42]},"scoresAfter":[83,-5]},{"ply":50,"player":"ai","action":79,"playedCard":40,"placeType":"discard","drawSource":"discard_0","drawnCard":1,"handsBefore":{"human":[9,15,25,28,30,38,47,50],"ai":[2,3,5,21,24,26,40,42]},"scoresAfter":[83,-5]},{"ply":51,"player":"human","action":72,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[9,15,25,28,30,38,47,50],"ai":[1,2,3,5,21,24,26,42]},"scoresAfter":[93,-5]}],"finalScores":[93,-5],"outcome":"YOU WIN","finalState":{"deckOrder":[17,4,31,27,16,47,10,58,49,24,0,34,53,45,20,19,44,36,48,7,54,8,51,29,33,13,52,18,56,50,55,39,12,6,35,41,32,11,26,59,14,23,1,15,25,42,9,46,30,22,43,40,57,5,38,3,2,28,21,37],"drawPtr":60,"cardLoc":[5,2,2,2,3,2,3,4,4,1,3,3,4,4,4,1,3,3,4,4,4,2,4,3,2,1,2,3,1,4,1,3,4,3,4,3,4,1,1,4,5,4,2,3,3,4,4,3,3,4,1,3,3,4,3,3,3,3,3,3],"handPublic":[false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,true,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false],"colTop":[[10,10,10,10,10],[7,9,9,9,4]],"colHandshakes":[[0,0,0,0,1],[0,3,0,1,1]],"colLength":[[4,3,4,3,9],[2,7,3,5,2]],"piles":[[0],[],[],[40],[]],"toMove":1,"stepCount":51,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"895773d7-79b4-4f97-912b-de9d1b8b24ee","seed":"21sc4f","startedAt":"2026-07-14T17:24:04.359Z","finishedAt":"2026-07-14T17:27:02.989Z","initialDeckOrder":[18,4,2,57,47,1,42,34,20,22,15,39,58,16,21,36,28,0,45,9,33,14,30,52,26,27,54,7,31,8,17,23,50,55,12,49,43,35,48,11,6,41,38,3,13,53,56,24,32,40,46,44,29,10,51,25,59,19,37,5],"moves":[{"ply":1,"player":"human","action":18,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[1,2,4,18,34,42,47,57],"ai":[15,16,20,21,22,36,39,58]},"scoresAfter":[0,0]},{"ply":2,"player":"ai","action":30,"playedCard":20,"placeType":"discard","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[1,4,18,28,34,42,47,57],"ai":[15,16,20,21,22,36,39,58]},"scoresAfter":[0,0]},{"ply":3,"player":"human","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[1,4,18,28,34,42,47,57],"ai":[0,15,16,21,22,36,39,58]},"scoresAfter":[0,0]},{"ply":4,"player":"ai","action":30,"playedCard":16,"placeType":"discard","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[4,18,28,34,42,45,47,57],"ai":[0,15,16,21,22,36,39,58]},"scoresAfter":[0,0]},{"ply":5,"player":"human","action":24,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[4,18,28,34,42,45,47,57],"ai":[0,9,15,21,22,36,39,58]},"scoresAfter":[-17,0]},{"ply":6,"player":"ai","action":30,"playedCard":15,"placeType":"discard","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[4,18,33,34,42,45,47,57],"ai":[0,9,15,21,22,36,39,58]},"scoresAfter":[-17,0]},{"ply":7,"player":"human","action":6,"playedCard":4,"placeType":"discard","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[4,18,33,34,42,45,47,57],"ai":[0,9,14,21,22,36,39,58]},"scoresAfter":[-17,0]},{"ply":8,"player":"ai","action":66,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[18,30,33,34,42,45,47,57],"ai":[0,9,14,21,22,36,39,58]},"scoresAfter":[-17,0]},{"ply":9,"player":"human","action":12,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[18,30,33,34,42,45,47,57],"ai":[0,9,14,21,22,39,52,58]},"scoresAfter":[-12,0]},{"ply":10,"player":"ai","action":30,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[18,26,33,34,42,45,47,57],"ai":[0,9,14,21,22,39,52,58]},"scoresAfter":[-12,0]},{"ply":11,"player":"human","action":22,"playedCard":26,"placeType":"discard","drawSource":"discard_3","drawnCard":36,"handsBefore":{"human":[18,26,33,34,42,45,47,57],"ai":[0,9,21,22,27,39,52,58]},"scoresAfter":[-12,0]},{"ply":12,"player":"ai","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[18,33,34,36,42,45,47,57],"ai":[0,9,21,22,27,39,52,58]},"scoresAfter":[-12,0]},{"ply":13,"player":"human","action":36,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[18,33,34,36,42,45,47,57],"ai":[9,21,22,27,39,52,54,58]},"scoresAfter":[-52,0]},{"ply":14,"player":"ai","action":60,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[7,18,33,34,42,45,47,57],"ai":[9,21,22,27,39,52,54,58]},"scoresAfter":[-52,-17]},{"ply":15,"player":"human","action":24,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[7,18,33,34,42,45,47,57],"ai":[9,21,22,27,31,39,54,58]},"scoresAfter":[-44,-17]},{"ply":16,"player":"ai","action":60,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[7,8,18,34,42,45,47,57],"ai":[9,21,22,27,31,39,54,58]},"scoresAfter":[-44,-35]},{"ply":17,"player":"human","action":49,"playedCard":42,"placeType":"play","drawSource":"discard_0","drawnCard":0,"handsBefore":{"human":[7,8,18,34,42,45,47,57],"ai":[9,17,21,22,27,31,54,58]},"scoresAfter":[-34,-35]},{"ply":18,"player":"ai","action":74,"playedCard":54,"placeType":"play","drawSource":"discard_1","drawnCard":14,"handsBefore":{"human":[0,7,8,18,34,45,47,57],"ai":[9,17,21,22,27,31,54,58]},"scoresAfter":[-34,-30]},{"ply":19,"player":"human","action":1,"playedCard":0,"placeType":"play","drawSource":"discard_0","drawnCard":4,"handsBefore":{"human":[0,7,8,18,34,45,47,57],"ai":[9,14,17,21,22,27,31,58]},"scoresAfter":[-74,-30]},{"ply":20,"player":"ai","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[4,7,8,18,34,45,47,57],"ai":[9,14,17,21,22,27,31,58]},"scoresAfter":[-74,-21]},{"ply":21,"player":"human","action":49,"playedCard":34,"placeType":"play","drawSource":"discard_0","drawnCard":1,"handsBefore":{"human":[4,7,8,18,34,45,47,57],"ai":[9,14,17,21,22,23,27,31]},"scoresAfter":[-65,-21]},{"ply":22,"player":"ai","action":90,"playedCard":31,"placeType":"discard","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[1,4,7,8,18,45,47,57],"ai":[9,14,17,21,22,23,27,31]},"scoresAfter":[-65,-21]},{"ply":23,"player":"human","action":91,"playedCard":57,"placeType":"discard","drawSource":"discard_0","drawnCard":2,"handsBefore":{"human":[1,4,7,8,18,45,47,57],"ai":[9,14,17,21,22,23,27,50]},"scoresAfter":[-65,-21]},{"ply":24,"player":"ai","action":90,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[1,2,4,7,8,18,45,47],"ai":[9,14,17,21,22,23,27,50]},"scoresAfter":[-65,-21]},{"ply":25,"player":"human","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[1,2,4,7,8,18,45,47],"ai":[9,14,17,21,22,23,27,55]},"scoresAfter":[-85,-21]},{"ply":26,"player":"ai","action":90,"playedCard":55,"placeType":"discard","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[2,4,7,8,12,18,45,47],"ai":[9,14,17,21,22,23,27,55]},"scoresAfter":[-85,-21]},{"ply":27,"player":"human","action":0,"playedCard":2,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[2,4,7,8,12,18,45,47],"ai":[9,14,17,21,22,23,27,49]},"scoresAfter":[-105,-21]},{"ply":28,"player":"ai","action":90,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[4,7,8,12,18,43,45,47],"ai":[9,14,17,21,22,23,27,49]},"scoresAfter":[-105,-21]},{"ply":29,"player":"human","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[4,7,8,12,18,43,45,47],"ai":[9,14,17,21,22,23,27,35]},"scoresAfter":[-93,-21]},{"ply":30,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[7,8,12,18,43,45,47,48],"ai":[9,14,17,21,22,23,27,35]},"scoresAfter":[-93,-33]},{"ply":31,"player":"human","action":48,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[7,8,12,18,43,45,47,48],"ai":[11,14,17,21,22,23,27,35]},"scoresAfter":[-81,-33]},{"ply":32,"player":"ai","action":2,"playedCard":11,"placeType":"play","drawSource":"discard_1","drawnCard":15,"handsBefore":{"human":[6,7,8,12,18,45,47,48],"ai":[11,14,17,21,22,23,27,35]},"scoresAfter":[-81,-23]},{"ply":33,"player":"human","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[6,7,8,12,18,45,47,48],"ai":[14,15,17,21,22,23,27,35]},"scoresAfter":[-61,-23]},{"ply":34,"player":"ai","action":2,"playedCard":14,"placeType":"play","drawSource":"discard_1","drawnCard":16,"handsBefore":{"human":[7,8,12,18,41,45,47,48],"ai":[14,15,17,21,22,23,27,35]},"scoresAfter":[-61,-63]},{"ply":35,"player":"human","action":90,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[7,8,12,18,41,45,47,48],"ai":[15,16,17,21,22,23,27,35]},"scoresAfter":[-61,-63]},{"ply":36,"player":"ai","action":2,"playedCard":15,"placeType":"play","drawSource":"discard_1","drawnCard":20,"handsBefore":{"human":[7,8,12,18,38,41,45,47],"ai":[15,16,17,21,22,23,27,35]},"scoresAfter":[-61,-59]},{"ply":37,"player":"human","action":54,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[7,8,12,18,38,41,45,47],"ai":[16,17,20,21,22,23,27,35]},"scoresAfter":[-61,-59]},{"ply":38,"player":"ai","action":0,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[3,7,8,12,18,41,45,47],"ai":[16,17,20,21,22,23,27,35]},"scoresAfter":[-61,-53]},{"ply":39,"player":"human","action":6,"playedCard":3,"placeType":"discard","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[3,7,8,12,18,41,45,47],"ai":[13,17,20,21,22,23,27,35]},"scoresAfter":[-61,-53]},{"ply":40,"player":"ai","action":15,"playedCard":17,"placeType":"play","drawSource":"discard_2","drawnCard":31,"handsBefore":{"human":[7,8,12,18,41,45,47,53],"ai":[13,17,20,21,22,23,27,35]},"scoresAfter":[-61,-45]},{"ply":41,"player":"human","action":90,"playedCard":53,"placeType":"discard","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[7,8,12,18,41,45,47,53],"ai":[13,20,21,22,23,27,31,35]},"scoresAfter":[-61,-45]},{"ply":42,"player":"ai","action":60,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[7,8,12,18,41,45,47,56],"ai":[13,20,21,22,23,27,31,35]},"scoresAfter":[-61,-63]},{"ply":43,"player":"human","action":90,"playedCard":56,"placeType":"discard","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[7,8,12,18,41,45,47,56],"ai":[13,20,21,22,23,24,31,35]},"scoresAfter":[-61,-63]},{"ply":44,"player":"ai","action":12,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[7,8,12,18,32,41,45,47],"ai":[13,20,21,22,23,24,31,35]},"scoresAfter":[-61,-49]},{"ply":45,"player":"human","action":42,"playedCard":18,"placeType":"discard","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[7,8,12,18,32,41,45,47],"ai":[13,21,22,23,24,31,35,40]},"scoresAfter":[-61,-49]},{"ply":46,"player":"ai","action":62,"playedCard":31,"placeType":"play","drawSource":"discard_1","drawnCard":18,"handsBefore":{"human":[7,8,12,32,41,45,46,47],"ai":[13,21,22,23,24,31,35,40]},"scoresAfter":[-61,-43]},{"ply":47,"player":"human","action":30,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[7,8,12,32,41,45,46,47],"ai":[13,18,21,22,23,24,35,40]},"scoresAfter":[-61,-43]},{"ply":48,"player":"ai","action":6,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[7,8,32,41,44,45,46,47],"ai":[13,18,21,22,23,24,35,40]},"scoresAfter":[-61,-43]},{"ply":49,"player":"human","action":48,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[7,8,32,41,44,45,46,47],"ai":[18,21,22,23,24,29,35,40]},"scoresAfter":[-47,-43]},{"ply":50,"player":"ai","action":12,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[7,8,10,32,41,45,46,47],"ai":[18,21,22,23,24,29,35,40]},"scoresAfter":[-47,-27]},{"ply":51,"player":"human","action":5,"playedCard":7,"placeType":"play","drawSource":"discard_4","drawnCard":56,"handsBefore":{"human":[7,8,10,32,41,45,46,47],"ai":[18,22,23,24,29,35,40,51]},"scoresAfter":[-23,-27]},{"ply":52,"player":"ai","action":12,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[8,10,32,41,45,46,47,56],"ai":[18,22,23,24,29,35,40,51]},"scoresAfter":[-23,-9]},{"ply":53,"player":"human","action":5,"playedCard":8,"placeType":"play","drawSource":"discard_4","drawnCard":53,"handsBefore":{"human":[8,10,32,41,45,46,47,56],"ai":[18,23,24,25,29,35,40,51]},"scoresAfter":[5,-9]},{"ply":54,"player":"ai","action":12,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[10,32,41,45,46,47,53,56],"ai":[18,23,24,25,29,35,40,51]},"scoresAfter":[5,31]},{"ply":55,"player":"human","action":5,"playedCard":10,"placeType":"play","drawSource":"discard_4","drawnCard":48,"handsBefore":{"human":[10,32,41,45,46,47,53,56],"ai":[18,24,25,29,35,40,51,59]},"scoresAfter":[61,31]},{"ply":56,"player":"ai","action":48,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[32,41,45,46,47,48,53,56],"ai":[18,24,25,29,35,40,51,59]},"scoresAfter":[61,41]},{"ply":57,"player":"human","action":29,"playedCard":45,"placeType":"play","drawSource":"discard_4","drawnCard":49,"handsBefore":{"human":[32,41,45,46,47,48,53,56],"ai":[18,19,24,25,29,40,51,59]},"scoresAfter":[77,41]},{"ply":58,"player":"ai","action":60,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[32,41,46,47,48,49,53,56],"ai":[18,19,24,25,29,40,51,59]},"scoresAfter":[77,44]},{"ply":59,"player":"human","action":36,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[32,41,46,47,48,49,53,56],"ai":[18,19,24,25,29,37,51,59]},"scoresAfter":[97,44]}],"finalScores":[97,44],"outcome":"YOU WIN","finalState":{"deckOrder":[18,4,2,57,47,1,42,34,20,22,15,39,58,16,21,36,28,0,45,9,33,14,30,52,26,27,54,7,31,8,17,23,50,55,12,49,43,35,48,11,6,41,38,3,13,53,56,24,32,40,46,44,29,10,51,25,59,19,37,5],"drawPtr":60,"cardLoc":[3,3,3,5,3,1,3,3,3,4,3,4,5,5,4,4,4,4,2,2,4,4,4,4,2,2,5,4,3,2,3,4,1,3,3,4,3,2,5,4,4,1,3,3,3,3,1,3,1,1,5,2,4,1,4,5,1,5,4,2],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,false,false,false,true,false,false,true,false,false,false],"colTop":[[9,0,9,10,0],[10,10,10,3,9]],"colHandshakes":[[3,0,0,1,0],[0,1,0,0,0]],"colLength":[[8,0,4,6,0],[2,8,3,2,3]],"piles":[[3],[12,13],[26],[38],[57,50,55]],"toMove":1,"stepCount":59,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"15e8b570-f77d-4499-a986-84980867189a","seed":"da8sec","startedAt":"2026-07-14T17:27:03.810Z","finishedAt":"2026-07-14T17:29:19.921Z","initialDeckOrder":[20,53,45,6,29,57,10,27,37,15,9,11,28,30,59,56,23,41,14,49,38,22,42,31,25,24,17,5,39,2,51,36,34,26,54,18,0,52,3,13,1,12,19,21,40,46,35,33,43,8,47,7,16,4,50,55,32,58,48,44],"moves":[{"ply":1,"player":"human","action":42,"playedCard":27,"placeType":"discard","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[6,10,20,27,29,45,53,57],"ai":[9,11,15,28,30,37,56,59]},"scoresAfter":[0,0]},{"ply":2,"player":"ai","action":18,"playedCard":11,"placeType":"discard","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[6,10,20,23,29,45,53,57],"ai":[9,11,15,28,30,37,56,59]},"scoresAfter":[0,0]},{"ply":3,"player":"human","action":55,"playedCard":29,"placeType":"discard","drawSource":"discard_0","drawnCard":11,"handsBefore":{"human":[6,10,20,23,29,45,53,57],"ai":[9,15,28,30,37,41,56,59]},"scoresAfter":[0,0]},{"ply":4,"player":"ai","action":66,"playedCard":41,"placeType":"discard","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[6,10,11,20,23,45,53,57],"ai":[9,15,28,30,37,41,56,59]},"scoresAfter":[0,0]},{"ply":5,"player":"human","action":76,"playedCard":53,"placeType":"play","drawSource":"discard_3","drawnCard":41,"handsBefore":{"human":[6,10,11,20,23,45,53,57],"ai":[9,14,15,28,30,37,56,59]},"scoresAfter":[-16,0]},{"ply":6,"player":"ai","action":18,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[6,10,11,20,23,41,45,57],"ai":[9,14,15,28,30,37,56,59]},"scoresAfter":[-16,0]},{"ply":7,"player":"human","action":62,"playedCard":41,"placeType":"play","drawSource":"discard_1","drawnCard":14,"handsBefore":{"human":[6,10,11,20,23,41,45,57],"ai":[9,15,28,30,37,49,56,59]},"scoresAfter":[-32,0]},{"ply":8,"player":"ai","action":54,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[6,10,11,14,20,23,45,57],"ai":[9,15,28,30,37,49,56,59]},"scoresAfter":[-32,0]},{"ply":9,"player":"human","action":36,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[6,10,11,14,20,23,45,57],"ai":[9,15,28,30,38,49,56,59]},"scoresAfter":[-72,0]},{"ply":10,"player":"ai","action":48,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[6,10,11,20,22,23,45,57],"ai":[9,15,28,30,38,49,56,59]},"scoresAfter":[-72,-40]},{"ply":11,"player":"human","action":36,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[6,10,11,20,22,23,45,57],"ai":[9,15,28,30,42,49,56,59]},"scoresAfter":[-58,-40]},{"ply":12,"player":"ai","action":12,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[6,10,11,22,23,31,45,57],"ai":[9,15,28,30,42,49,56,59]},"scoresAfter":[-58,-58]},{"ply":13,"player":"human","action":36,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[6,10,11,22,23,31,45,57],"ai":[9,25,28,30,42,49,56,59]},"scoresAfter":[-40,-58]},{"ply":14,"player":"ai","action":48,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[6,10,11,23,24,31,45,57],"ai":[9,25,28,30,42,49,56,59]},"scoresAfter":[-40,-48]},{"ply":15,"player":"human","action":36,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[6,10,11,23,24,31,45,57],"ai":[9,17,25,28,30,49,56,59]},"scoresAfter":[-20,-48]},{"ply":16,"player":"ai","action":60,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[5,6,10,11,24,31,45,57],"ai":[9,17,25,28,30,49,56,59]},"scoresAfter":[-20,-88]},{"ply":17,"player":"human","action":54,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[5,6,10,11,24,31,45,57],"ai":[9,17,25,28,30,39,56,59]},"scoresAfter":[-20,-88]},{"ply":18,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[2,5,6,10,11,31,45,57],"ai":[9,17,25,28,30,39,56,59]},"scoresAfter":[-20,-100]},{"ply":19,"player":"human","action":0,"playedCard":2,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[2,5,6,10,11,31,45,57],"ai":[17,25,28,30,39,51,56,59]},"scoresAfter":[-60,-100]},{"ply":20,"player":"ai","action":12,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[5,6,10,11,31,36,45,57],"ai":[17,25,28,30,39,51,56,59]},"scoresAfter":[-60,-140]},{"ply":21,"player":"human","action":66,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[5,6,10,11,31,36,45,57],"ai":[17,28,30,34,39,51,56,59]},"scoresAfter":[-60,-140]},{"ply":22,"player":"ai","action":54,"playedCard":39,"placeType":"discard","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[5,6,10,11,26,31,45,57],"ai":[17,28,30,34,39,51,56,59]},"scoresAfter":[-60,-140]},{"ply":23,"player":"human","action":54,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[5,6,10,11,26,31,45,57],"ai":[17,28,30,34,51,54,56,59]},"scoresAfter":[-60,-140]},{"ply":24,"player":"ai","action":48,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[5,6,10,11,18,31,45,57],"ai":[17,28,30,34,51,54,56,59]},"scoresAfter":[-60,-136]},{"ply":25,"player":"human","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[5,6,10,11,18,31,45,57],"ai":[0,17,28,30,34,54,56,59]},"scoresAfter":[-52,-136]},{"ply":26,"player":"ai","action":63,"playedCard":54,"placeType":"play","drawSource":"discard_2","drawnCard":26,"handsBefore":{"human":[6,10,11,18,31,45,52,57],"ai":[0,17,28,30,34,54,56,59]},"scoresAfter":[-52,-126]},{"ply":27,"player":"human","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[6,10,11,18,31,45,52,57],"ai":[0,17,26,28,30,34,56,59]},"scoresAfter":[-42,-126]},{"ply":28,"player":"ai","action":15,"playedCard":17,"placeType":"play","drawSource":"discard_2","drawnCard":24,"handsBefore":{"human":[3,10,11,18,31,45,52,57],"ai":[0,17,26,28,30,34,56,59]},"scoresAfter":[-42,-122]},{"ply":29,"player":"human","action":6,"playedCard":3,"placeType":"discard","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[3,10,11,18,31,45,52,57],"ai":[0,24,26,28,30,34,56,59]},"scoresAfter":[-42,-122]},{"ply":30,"player":"ai","action":75,"playedCard":56,"placeType":"play","drawSource":"discard_2","drawnCard":29,"handsBefore":{"human":[10,11,13,18,31,45,52,57],"ai":[0,24,26,28,30,34,56,59]},"scoresAfter":[-42,-108]},{"ply":31,"player":"human","action":30,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[10,11,13,18,31,45,52,57],"ai":[0,24,26,28,29,30,34,59]},"scoresAfter":[-42,-108]},{"ply":32,"player":"ai","action":15,"playedCard":24,"placeType":"play","drawSource":"discard_2","drawnCard":27,"handsBefore":{"human":[1,10,11,18,31,45,52,57],"ai":[0,24,26,28,29,30,34,59]},"scoresAfter":[-42,-128]},{"ply":33,"player":"human","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[1,10,11,18,31,45,52,57],"ai":[0,26,27,28,29,30,34,59]},"scoresAfter":[-42,-128]},{"ply":34,"player":"ai","action":12,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[10,11,12,18,31,45,52,57],"ai":[0,26,27,28,29,30,34,59]},"scoresAfter":[-42,-148]},{"ply":35,"player":"human","action":30,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[10,11,12,18,31,45,52,57],"ai":[0,19,27,28,29,30,34,59]},"scoresAfter":[-42,-148]},{"ply":36,"player":"ai","action":12,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[10,11,18,21,31,45,52,57],"ai":[0,19,27,28,29,30,34,59]},"scoresAfter":[-42,-142]},{"ply":37,"player":"human","action":30,"playedCard":18,"placeType":"discard","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[10,11,18,21,31,45,52,57],"ai":[0,27,28,29,30,34,40,59]},"scoresAfter":[-42,-142]},{"ply":38,"player":"ai","action":12,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[10,11,21,31,45,46,52,57],"ai":[0,27,28,29,30,34,40,59]},"scoresAfter":[-42,-134]},{"ply":39,"player":"human","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[10,11,21,31,45,46,52,57],"ai":[0,28,29,30,34,35,40,59]},"scoresAfter":[-24,-134]},{"ply":40,"player":"ai","action":12,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[11,21,31,33,45,46,52,57],"ai":[0,28,29,30,34,35,40,59]},"scoresAfter":[-24,-122]},{"ply":41,"player":"human","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[11,21,31,33,45,46,52,57],"ai":[0,29,30,34,35,40,43,59]},"scoresAfter":[-4,-122]},{"ply":42,"player":"ai","action":12,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[8,21,31,33,45,46,52,57],"ai":[0,29,30,34,35,40,43,59]},"scoresAfter":[-4,-106]},{"ply":43,"player":"human","action":6,"playedCard":8,"placeType":"discard","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[8,21,31,33,45,46,52,57],"ai":[0,30,34,35,40,43,47,59]},"scoresAfter":[-4,-106]},{"ply":44,"player":"ai","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[7,21,31,33,45,46,52,57],"ai":[0,30,34,35,40,43,47,59]},"scoresAfter":[-4,-86]},{"ply":45,"player":"human","action":48,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[7,21,31,33,45,46,52,57],"ai":[0,16,30,34,35,40,43,47]},"scoresAfter":[4,-86]},{"ply":46,"player":"ai","action":72,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[4,7,21,31,33,46,52,57],"ai":[0,16,30,34,35,40,43,47]},"scoresAfter":[4,-74]},{"ply":47,"player":"human","action":60,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[4,7,21,31,33,46,52,57],"ai":[0,16,30,34,35,40,47,50]},"scoresAfter":[13,-74]},{"ply":48,"player":"ai","action":24,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[4,7,21,31,33,52,55,57],"ai":[0,16,30,34,35,40,47,50]},"scoresAfter":[13,-54]},{"ply":49,"player":"human","action":72,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[4,7,21,31,33,52,55,57],"ai":[0,16,32,34,35,40,47,50]},"scoresAfter":[19,-54]},{"ply":50,"player":"ai","action":40,"playedCard":34,"placeType":"play","drawSource":"discard_3","drawnCard":39,"handsBefore":{"human":[4,7,21,31,33,52,57,58],"ai":[0,16,32,34,35,40,47,50]},"scoresAfter":[19,2]},{"ply":51,"player":"human","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[4,7,21,31,33,52,57,58],"ai":[0,16,32,35,39,40,47,50]},"scoresAfter":[28,2]},{"ply":52,"player":"ai","action":40,"playedCard":35,"placeType":"play","drawSource":"discard_3","drawnCard":36,"handsBefore":{"human":[4,7,21,31,33,48,52,57],"ai":[0,16,32,35,39,40,47,50]},"scoresAfter":[28,42]},{"ply":53,"player":"human","action":18,"playedCard":7,"placeType":"discard","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[4,7,21,31,33,48,52,57],"ai":[0,16,32,36,39,40,47,50]},"scoresAfter":[28,42]}],"finalScores":[28,42],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[20,53,45,6,29,57,10,27,37,15,9,11,28,30,59,56,23,41,14,49,38,22,42,31,25,24,17,5,39,2,51,36,34,26,54,18,0,52,3,13,1,12,19,21,40,46,35,33,43,8,47,7,16,4,50,55,32,58,48,44],"drawPtr":60,"cardLoc":[2,5,3,5,1,3,3,5,5,4,3,3,5,5,3,4,2,4,5,4,3,1,3,3,4,4,4,4,4,4,4,1,2,1,4,4,2,5,4,2,2,3,4,4,1,3,3,2,1,4,2,4,1,3,4,3,4,1,3,4],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,10,0,9,9],[8,6,10,6,10]],"colHandshakes":[[1,1,0,0,0],[0,0,3,1,1]],"colLength":[[5,4,0,3,3],[1,3,9,3,5]],"piles":[[3,1,8,7],[13,12,18],[],[37],[]],"toMove":1,"stepCount":53,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"3f11ef4f-18eb-449e-9bf0-995b02245e5d","seed":"7xo5vh","startedAt":"2026-07-14T17:29:20.576Z","finishedAt":"2026-07-14T17:32:08.561Z","initialDeckOrder":[11,0,35,6,53,12,43,39,33,42,14,25,15,48,58,17,26,54,40,9,3,7,4,59,27,2,32,38,47,37,10,23,57,19,34,1,5,55,50,16,31,46,52,41,56,51,49,24,13,18,21,45,44,20,8,36,22,29,28,30],"moves":[{"ply":1,"player":"human","action":0,"playedCard":0,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[0,6,11,12,35,39,43,53],"ai":[14,15,17,25,33,42,48,58]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":6,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[6,11,12,26,35,39,43,53],"ai":[14,15,17,25,33,42,48,58]},"scoresAfter":[-40,0]},{"ply":3,"player":"human","action":36,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[6,11,12,26,35,39,43,53],"ai":[15,17,25,33,42,48,54,58]},"scoresAfter":[-80,0]},{"ply":4,"player":"ai","action":0,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[6,11,12,35,39,40,43,53],"ai":[15,17,25,33,42,48,54,58]},"scoresAfter":[-80,-18]},{"ply":5,"player":"human","action":30,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[6,11,12,35,39,40,43,53],"ai":[9,17,25,33,42,48,54,58]},"scoresAfter":[-80,-18]},{"ply":6,"player":"ai","action":60,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[3,6,11,35,39,40,43,53],"ai":[9,17,25,33,42,48,54,58]},"scoresAfter":[-80,-58]},{"ply":7,"player":"human","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[3,6,11,35,39,40,43,53],"ai":[7,9,17,25,33,42,54,58]},"scoresAfter":[-76,-58]},{"ply":8,"player":"ai","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[4,6,11,35,39,40,43,53],"ai":[7,9,17,25,33,42,54,58]},"scoresAfter":[-76,-72]},{"ply":9,"player":"human","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[4,6,11,35,39,40,43,53],"ai":[9,17,25,33,42,54,58,59]},"scoresAfter":[-70,-72]},{"ply":10,"player":"ai","action":12,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[6,11,27,35,39,40,43,53],"ai":[9,17,25,33,42,54,58,59]},"scoresAfter":[-70,-68]},{"ply":11,"player":"human","action":24,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[6,11,27,35,39,40,43,53],"ai":[2,9,25,33,42,54,58,59]},"scoresAfter":[-66,-68]},{"ply":12,"player":"ai","action":12,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[6,11,32,35,39,40,43,53],"ai":[2,9,25,33,42,54,58,59]},"scoresAfter":[-66,-60]},{"ply":13,"player":"human","action":48,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[6,11,32,35,39,40,43,53],"ai":[2,25,33,38,42,54,58,59]},"scoresAfter":[-84,-60]},{"ply":14,"player":"ai","action":36,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[6,11,32,35,40,43,47,53],"ai":[2,25,33,38,42,54,58,59]},"scoresAfter":[-84,-100]},{"ply":15,"player":"human","action":48,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[6,11,32,35,40,43,47,53],"ai":[2,25,33,37,42,54,58,59]},"scoresAfter":[-81,-100]},{"ply":16,"player":"ai","action":36,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[6,10,11,32,35,43,47,53],"ai":[2,25,33,37,42,54,58,59]},"scoresAfter":[-81,-120]},{"ply":17,"player":"human","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[6,10,11,32,35,43,47,53],"ai":[2,23,25,33,42,54,58,59]},"scoresAfter":[-71,-120]},{"ply":18,"player":"ai","action":36,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[10,11,32,35,43,47,53,57],"ai":[2,23,25,33,42,54,58,59]},"scoresAfter":[-71,-132]},{"ply":19,"player":"human","action":48,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[10,11,32,35,43,47,53,57],"ai":[2,19,23,25,42,54,58,59]},"scoresAfter":[-65,-132]},{"ply":20,"player":"ai","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[10,11,32,34,35,47,53,57],"ai":[2,19,23,25,42,54,58,59]},"scoresAfter":[-65,-132]},{"ply":21,"player":"human","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[10,11,32,34,35,47,53,57],"ai":[1,19,23,25,42,54,58,59]},"scoresAfter":[-47,-132]},{"ply":22,"player":"ai","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[5,11,32,34,35,47,53,57],"ai":[1,19,23,25,42,54,58,59]},"scoresAfter":[-47,-132]},{"ply":23,"player":"human","action":12,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[5,11,32,34,35,47,53,57],"ai":[19,23,25,42,54,55,58,59]},"scoresAfter":[-27,-132]},{"ply":24,"player":"ai","action":0,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[5,32,34,35,47,50,53,57],"ai":[19,23,25,42,54,55,58,59]},"scoresAfter":[-27,-126]},{"ply":25,"player":"human","action":6,"playedCard":5,"placeType":"discard","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[5,32,34,35,47,50,53,57],"ai":[16,23,25,42,54,55,58,59]},"scoresAfter":[-27,-126]},{"ply":26,"player":"ai","action":12,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[31,32,34,35,47,50,53,57],"ai":[16,23,25,42,54,55,58,59]},"scoresAfter":[-27,-116]},{"ply":27,"player":"human","action":66,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[31,32,34,35,47,50,53,57],"ai":[16,25,42,46,54,55,58,59]},"scoresAfter":[-27,-116]},{"ply":28,"player":"ai","action":29,"playedCard":42,"placeType":"play","drawSource":"discard_4","drawnCard":50,"handsBefore":{"human":[31,32,34,35,47,52,53,57],"ai":[16,25,42,46,54,55,58,59]},"scoresAfter":[-27,-101]},{"ply":29,"player":"human","action":0,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[31,32,34,35,47,52,53,57],"ai":[16,25,46,50,54,55,58,59]},"scoresAfter":[-15,-101]},{"ply":30,"player":"ai","action":24,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[32,34,35,41,47,52,53,57],"ai":[16,25,46,50,54,55,58,59]},"scoresAfter":[-15,-74]},{"ply":31,"player":"human","action":0,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[32,34,35,41,47,52,53,57],"ai":[16,25,50,54,55,56,58,59]},"scoresAfter":[-1,-74]},{"ply":32,"player":"ai","action":24,"playedCard":50,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[34,35,41,47,51,52,53,57],"ai":[16,25,50,54,55,56,58,59]},"scoresAfter":[-1,-94]},{"ply":33,"player":"human","action":0,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[34,35,41,47,51,52,53,57],"ai":[16,25,49,54,55,56,58,59]},"scoresAfter":[17,-94]},{"ply":34,"player":"ai","action":24,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[24,35,41,47,51,52,53,57],"ai":[16,25,49,54,55,56,58,59]},"scoresAfter":[17,-114]},{"ply":35,"player":"human","action":12,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[24,35,41,47,51,52,53,57],"ai":[13,16,25,54,55,56,58,59]},"scoresAfter":[37,-114]},{"ply":36,"player":"ai","action":36,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[18,24,41,47,51,52,53,57],"ai":[13,16,25,54,55,56,58,59]},"scoresAfter":[37,-94]},{"ply":37,"player":"human","action":48,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[18,24,41,47,51,52,53,57],"ai":[13,16,21,25,55,56,58,59]},"scoresAfter":[19,-94]},{"ply":38,"player":"ai","action":48,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[18,24,41,45,47,52,53,57],"ai":[13,16,21,25,55,56,58,59]},"scoresAfter":[19,-70]},{"ply":39,"player":"human","action":60,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[18,24,41,45,47,52,53,57],"ai":[13,16,21,25,44,56,58,59]},"scoresAfter":[22,-70]},{"ply":40,"player":"ai","action":60,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[18,20,24,41,45,47,53,57],"ai":[13,16,21,25,44,56,58,59]},"scoresAfter":[22,-42]},{"ply":41,"player":"human","action":48,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[18,20,24,41,45,47,53,57],"ai":[8,13,16,21,25,44,58,59]},"scoresAfter":[30,-42]},{"ply":42,"player":"ai","action":72,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[18,20,24,36,41,47,53,57],"ai":[8,13,16,21,25,44,58,59]},"scoresAfter":[30,-6]},{"ply":43,"player":"human","action":73,"playedCard":53,"placeType":"play","drawSource":"discard_0","drawnCard":5,"handsBefore":{"human":[18,20,24,36,41,47,53,57],"ai":[8,13,16,21,22,25,44,59]},"scoresAfter":[34,-6]},{"ply":44,"player":"ai","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[5,18,20,24,36,41,47,57],"ai":[8,13,16,21,22,25,44,59]},"scoresAfter":[34,54]},{"ply":45,"player":"human","action":74,"playedCard":47,"placeType":"play","drawSource":"discard_1","drawnCard":12,"handsBefore":{"human":[5,18,20,24,36,41,47,57],"ai":[8,13,16,21,22,25,29,44]},"scoresAfter":[44,54]},{"ply":46,"player":"ai","action":78,"playedCard":29,"placeType":"discard","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[5,12,18,20,24,36,41,57],"ai":[8,13,16,21,22,25,29,44]},"scoresAfter":[44,54]},{"ply":47,"player":"human","action":84,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[5,12,18,20,24,36,41,57],"ai":[8,13,16,21,22,25,28,44]},"scoresAfter":[52,54]}],"finalScores":[52,54],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[11,0,35,6,53,12,43,39,33,42,14,25,15,48,58,17,26,54,40,9,3,7,4,59,27,2,32,38,47,37,10,23,57,19,34,1,5,55,50,16,31,46,52,41,56,51,49,24,13,18,21,45,44,20,8,36,22,29,28,30],"drawPtr":60,"cardLoc":[3,5,5,3,3,1,3,4,2,4,3,3,1,2,5,4,2,4,1,4,1,2,2,4,1,2,3,3,2,5,1,3,3,4,3,3,1,4,4,3,3,1,4,3,2,3,4,3,4,4,4,3,3,3,4,4,4,3,4,4],"handPublic":[false,false,false,false,false,true,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,0,10,10,8],[8,10,8,9,10]],"colHandshakes":[[1,0,1,0,0],[0,0,0,2,3]],"colLength":[[6,0,6,5,4],[2,4,1,4,8]],"piles":[[2,1],[14],[29],[],[]],"toMove":1,"stepCount":47,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"6dcd4c8f-3927-4d0f-898a-acc9017333c6","seed":"pozki6","startedAt":"2026-07-14T17:32:09.528Z","finishedAt":"2026-07-14T17:34:47.385Z","initialDeckOrder":[16,17,53,40,58,42,31,32,1,27,9,20,43,36,8,49,24,46,51,28,12,55,38,6,13,35,22,29,47,26,10,30,33,23,48,15,41,57,4,52,45,34,7,2,11,56,50,44,39,0,3,18,19,5,37,14,21,54,59,25],"moves":[{"ply":1,"player":"human","action":6,"playedCard":16,"placeType":"discard","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[16,17,31,32,40,42,53,58],"ai":[1,8,9,20,27,36,43,49]},"scoresAfter":[0,0]},{"ply":2,"player":"ai","action":54,"playedCard":27,"placeType":"discard","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[17,24,31,32,40,42,53,58],"ai":[1,8,9,20,27,36,43,49]},"scoresAfter":[0,0]},{"ply":3,"player":"human","action":15,"playedCard":24,"placeType":"play","drawSource":"discard_2","drawnCard":27,"handsBefore":{"human":[17,24,31,32,40,42,53,58],"ai":[1,8,9,20,36,43,46,49]},"scoresAfter":[-40,0]},{"ply":4,"player":"ai","action":48,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[17,27,31,32,40,42,53,58],"ai":[1,8,9,20,36,43,46,49]},"scoresAfter":[-40,-40]},{"ply":5,"player":"human","action":12,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[17,27,31,32,40,42,53,58],"ai":[1,8,9,20,43,46,49,51]},"scoresAfter":[-36,-40]},{"ply":6,"player":"ai","action":90,"playedCard":51,"placeType":"discard","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[17,28,31,32,40,42,53,58],"ai":[1,8,9,20,43,46,49,51]},"scoresAfter":[-36,-40]},{"ply":7,"player":"human","action":12,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[17,28,31,32,40,42,53,58],"ai":[1,8,9,12,20,43,46,49]},"scoresAfter":[-30,-40]},{"ply":8,"player":"ai","action":90,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[17,31,32,40,42,53,55,58],"ai":[1,8,9,12,20,43,46,49]},"scoresAfter":[-30,-40]},{"ply":9,"player":"human","action":11,"playedCard":17,"placeType":"discard","drawSource":"discard_4","drawnCard":49,"handsBefore":{"human":[17,31,32,40,42,53,55,58],"ai":[1,8,9,12,20,38,43,46]},"scoresAfter":[-30,-40]},{"ply":10,"player":"ai","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[31,32,40,42,49,53,55,58],"ai":[1,8,9,12,20,38,43,46]},"scoresAfter":[-30,-80]},{"ply":11,"player":"human","action":53,"playedCard":49,"placeType":"play","drawSource":"discard_4","drawnCard":51,"handsBefore":{"human":[31,32,40,42,49,53,55,58],"ai":[6,8,9,12,20,38,43,46]},"scoresAfter":[-70,-80]},{"ply":12,"player":"ai","action":54,"playedCard":20,"placeType":"discard","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[31,32,40,42,51,53,55,58],"ai":[6,8,9,12,20,38,43,46]},"scoresAfter":[-70,-80]},{"ply":13,"player":"human","action":48,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[31,32,40,42,51,53,55,58],"ai":[6,8,9,12,13,38,43,46]},"scoresAfter":[-66,-80]},{"ply":14,"player":"ai","action":2,"playedCard":6,"placeType":"play","drawSource":"discard_1","drawnCard":20,"handsBefore":{"human":[31,32,35,40,42,53,55,58],"ai":[6,8,9,12,13,38,43,46]},"scoresAfter":[-66,-70]},{"ply":15,"player":"human","action":60,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[31,32,35,40,42,53,55,58],"ai":[8,9,12,13,20,38,43,46]},"scoresAfter":[-58,-70]},{"ply":16,"player":"ai","action":2,"playedCard":8,"placeType":"play","drawSource":"discard_1","drawnCard":17,"handsBefore":{"human":[22,31,32,35,40,42,55,58],"ai":[8,9,12,13,20,38,43,46]},"scoresAfter":[-58,-56]},{"ply":17,"player":"human","action":74,"playedCard":55,"placeType":"play","drawSource":"discard_1","drawnCard":16,"handsBefore":{"human":[22,31,32,35,40,42,55,58],"ai":[9,12,13,17,20,38,43,46]},"scoresAfter":[-46,-56]},{"ply":18,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[16,22,31,32,35,40,42,58],"ai":[9,12,13,17,20,38,43,46]},"scoresAfter":[-46,-40]},{"ply":19,"player":"human","action":24,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[16,22,31,32,35,40,42,58],"ai":[12,13,17,20,29,38,43,46]},"scoresAfter":[-34,-40]},{"ply":20,"player":"ai","action":6,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[16,22,32,35,40,42,47,58],"ai":[12,13,17,20,29,38,43,46]},"scoresAfter":[-34,-40]},{"ply":21,"player":"human","action":48,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[16,22,32,35,40,42,47,58],"ai":[13,17,20,26,29,38,43,46]},"scoresAfter":[-51,-40]},{"ply":22,"player":"ai","action":60,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[10,16,22,32,35,42,47,58],"ai":[13,17,20,26,29,38,43,46]},"scoresAfter":[-51,-60]},{"ply":23,"player":"human","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[10,16,22,32,35,42,47,58],"ai":[13,17,20,26,29,30,43,46]},"scoresAfter":[-33,-60]},{"ply":24,"player":"ai","action":36,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[10,16,22,32,33,35,42,47],"ai":[13,17,20,26,29,30,43,46]},"scoresAfter":[-33,-100]},{"ply":25,"player":"human","action":36,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[10,16,22,32,33,35,42,47],"ai":[13,17,20,23,29,30,43,46]},"scoresAfter":[-19,-100]},{"ply":26,"player":"ai","action":62,"playedCard":30,"placeType":"play","drawSource":"discard_1","drawnCard":12,"handsBefore":{"human":[10,16,22,33,35,42,47,48],"ai":[13,17,20,23,29,30,43,46]},"scoresAfter":[-19,-90]},{"ply":27,"player":"human","action":36,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[10,16,22,33,35,42,47,48],"ai":[12,13,17,20,23,29,43,46]},"scoresAfter":[-3,-90]},{"ply":28,"player":"ai","action":6,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[10,15,16,22,35,42,47,48],"ai":[12,13,17,20,23,29,43,46]},"scoresAfter":[-3,-90]},{"ply":29,"player":"human","action":48,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[10,15,16,22,35,42,47,48],"ai":[13,17,20,23,29,41,43,46]},"scoresAfter":[17,-90]},{"ply":30,"player":"ai","action":62,"playedCard":41,"placeType":"play","drawSource":"discard_1","drawnCard":12,"handsBefore":{"human":[10,15,16,22,42,47,48,57],"ai":[13,17,20,23,29,41,43,46]},"scoresAfter":[17,-78]},{"ply":31,"player":"human","action":78,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[10,15,16,22,42,47,48,57],"ai":[12,13,17,20,23,29,43,46]},"scoresAfter":[17,-78]},{"ply":32,"player":"ai","action":6,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[4,10,15,16,22,42,47,57],"ai":[12,13,17,20,23,29,43,46]},"scoresAfter":[17,-78]},{"ply":33,"player":"human","action":60,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[4,10,15,16,22,42,47,57],"ai":[13,17,20,23,29,43,46,52]},"scoresAfter":[22,-78]},{"ply":34,"player":"ai","action":62,"playedCard":43,"placeType":"play","drawSource":"discard_1","drawnCard":12,"handsBefore":{"human":[4,10,15,16,22,45,47,57],"ai":[13,17,20,23,29,43,46,52]},"scoresAfter":[22,-60]},{"ply":35,"player":"human","action":60,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[4,10,15,16,22,45,47,57],"ai":[12,13,17,20,23,29,46,52]},"scoresAfter":[30,-60]},{"ply":36,"player":"ai","action":66,"playedCard":29,"placeType":"discard","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[4,10,15,16,22,34,47,57],"ai":[12,13,17,20,23,29,46,52]},"scoresAfter":[30,-60]},{"ply":37,"player":"human","action":24,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[4,10,15,16,22,34,47,57],"ai":[7,12,13,17,20,23,46,52]},"scoresAfter":[12,-60]},{"ply":38,"player":"ai","action":90,"playedCard":52,"placeType":"discard","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[2,4,10,16,22,34,47,57],"ai":[7,12,13,17,20,23,46,52]},"scoresAfter":[12,-60]},{"ply":39,"player":"human","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[2,4,10,16,22,34,47,57],"ai":[7,11,12,13,17,20,23,46]},"scoresAfter":[12,-60]},{"ply":40,"player":"ai","action":12,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[4,10,16,22,34,47,56,57],"ai":[7,11,12,13,17,20,23,46]},"scoresAfter":[12,-40]},{"ply":41,"player":"human","action":6,"playedCard":4,"placeType":"discard","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[4,10,16,22,34,47,56,57],"ai":[7,12,13,17,20,23,46,50]},"scoresAfter":[12,-40]},{"ply":42,"player":"ai","action":12,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[10,16,22,34,44,47,56,57],"ai":[7,12,13,17,20,23,46,50]},"scoresAfter":[12,-80]},{"ply":43,"player":"human","action":12,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[10,16,22,34,44,47,56,57],"ai":[7,13,17,20,23,39,46,50]},"scoresAfter":[15,-80]},{"ply":44,"player":"ai","action":12,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[0,10,22,34,44,47,56,57],"ai":[7,13,17,20,23,39,46,50]},"scoresAfter":[15,-100]},{"ply":45,"player":"human","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[0,10,22,34,44,47,56,57],"ai":[3,7,17,20,23,39,46,50]},"scoresAfter":[15,-100]},{"ply":46,"player":"ai","action":24,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[10,18,22,34,44,47,56,57],"ai":[3,7,17,20,23,39,46,50]},"scoresAfter":[15,-88]},{"ply":47,"player":"human","action":12,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[10,18,22,34,44,47,56,57],"ai":[3,7,19,20,23,39,46,50]},"scoresAfter":[20,-88]},{"ply":48,"player":"ai","action":24,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[5,10,22,34,44,47,56,57],"ai":[3,7,19,20,23,39,46,50]},"scoresAfter":[20,-70]},{"ply":49,"player":"human","action":6,"playedCard":5,"placeType":"discard","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[5,10,22,34,44,47,56,57],"ai":[3,7,20,23,37,39,46,50]},"scoresAfter":[20,-70]},{"ply":50,"player":"ai","action":24,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[10,14,22,34,44,47,56,57],"ai":[3,7,20,23,37,39,46,50]},"scoresAfter":[20,-49]},{"ply":51,"player":"human","action":25,"playedCard":22,"placeType":"play","drawSource":"discard_0","drawnCard":5,"handsBefore":{"human":[10,14,22,34,44,47,56,57],"ai":[3,7,21,23,37,39,46,50]},"scoresAfter":[29,-49]},{"ply":52,"player":"ai","action":29,"playedCard":21,"placeType":"play","drawSource":"discard_4","drawnCard":52,"handsBefore":{"human":[5,10,14,34,44,47,56,57],"ai":[3,7,21,23,37,39,46,50]},"scoresAfter":[29,-25]},{"ply":53,"player":"human","action":61,"playedCard":47,"placeType":"play","drawSource":"discard_0","drawnCard":0,"handsBefore":{"human":[5,10,14,34,44,47,56,57],"ai":[3,7,23,37,39,46,50,52]},"scoresAfter":[39,-25]},{"ply":54,"player":"ai","action":24,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[0,5,10,14,34,44,56,57],"ai":[3,7,23,37,39,46,50,52]},"scoresAfter":[39,5]},{"ply":55,"player":"human","action":42,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[0,5,10,14,34,44,56,57],"ai":[3,7,37,39,46,50,52,54]},"scoresAfter":[39,5]},{"ply":56,"player":"ai","action":48,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[0,5,10,34,44,56,57,59],"ai":[3,7,37,39,46,50,52,54]},"scoresAfter":[39,32]}],"finalScores":[39,32],"outcome":"YOU WIN","finalState":{"deckOrder":[16,17,53,40,58,42,31,32,1,27,9,20,43,36,8,49,24,46,51,28,12,55,38,6,13,35,22,29,47,26,10,30,33,23,48,15,41,57,4,52,45,34,7,2,11,56,50,44,39,0,3,18,19,5,37,14,21,54,59,25],"drawPtr":60,"cardLoc":[1,4,5,2,5,1,4,2,4,4,1,4,4,4,5,3,3,4,3,4,4,4,3,4,3,2,4,3,3,5,4,3,3,3,1,3,4,2,4,2,3,4,3,4,1,3,4,3,5,3,2,3,2,3,2,3,1,1,3,1],"handPublic":[true,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false],"colTop":[[0,9,10,10,9],[10,10,5,9,0]],"colHandshakes":[[0,0,1,0,1],[1,2,1,2,0]],"colLength":[[0,4,7,4,5],[5,7,2,5,0]],"piles":[[2,4],[14],[29],[],[48]],"toMove":0,"stepCount":56,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"3c806022-1142-43ae-ab30-21848ab31b91","seed":"zc7so2","startedAt":"2026-07-14T17:34:48.530Z","finishedAt":"2026-07-14T17:36:55.233Z","initialDeckOrder":[38,42,29,57,1,33,35,58,6,46,44,56,50,36,52,55,9,54,16,3,17,28,26,7,10,47,13,12,32,45,19,24,40,49,59,22,20,48,18,43,39,14,41,21,53,25,11,8,4,2,5,27,37,31,0,34,51,30,23,15],"moves":[{"ply":1,"player":"human","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[1,29,33,35,38,42,57,58],"ai":[6,36,44,46,50,52,55,56]},"scoresAfter":[0,0]},{"ply":2,"player":"ai","action":61,"playedCard":52,"placeType":"play","drawSource":"discard_0","drawnCard":1,"handsBefore":{"human":[9,29,33,35,38,42,57,58],"ai":[6,36,44,46,50,52,55,56]},"scoresAfter":[0,-17]},{"ply":3,"player":"human","action":54,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[9,29,33,35,38,42,57,58],"ai":[1,6,36,44,46,50,55,56]},"scoresAfter":[0,-17]},{"ply":4,"player":"ai","action":72,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[9,29,33,35,42,54,57,58],"ai":[1,6,36,44,46,50,55,56]},"scoresAfter":[0,-11]},{"ply":5,"player":"human","action":60,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[9,29,33,35,42,54,57,58],"ai":[1,6,16,36,44,46,50,56]},"scoresAfter":[-15,-11]},{"ply":6,"player":"ai","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[3,9,29,33,35,42,57,58],"ai":[1,6,16,36,44,46,50,56]},"scoresAfter":[-15,-51]},{"ply":7,"player":"human","action":24,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[3,9,29,33,35,42,57,58],"ai":[6,16,17,36,44,46,50,56]},"scoresAfter":[-31,-51]},{"ply":8,"player":"ai","action":84,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[3,9,28,33,35,42,57,58],"ai":[6,16,17,36,44,46,50,56]},"scoresAfter":[-31,-44]},{"ply":9,"player":"human","action":72,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[3,9,28,33,35,42,57,58],"ai":[6,16,17,26,36,44,46,50]},"scoresAfter":[-23,-44]},{"ply":10,"player":"ai","action":94,"playedCard":50,"placeType":"discard","drawSource":"discard_3","drawnCard":38,"handsBefore":{"human":[3,7,9,28,33,35,42,58],"ai":[6,16,17,26,36,44,46,50]},"scoresAfter":[-23,-44]},{"ply":11,"player":"human","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[3,7,9,28,33,35,42,58],"ai":[6,16,17,26,36,38,44,46]},"scoresAfter":[-14,-44]},{"ply":12,"player":"ai","action":42,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[3,7,9,10,28,33,35,42],"ai":[6,16,17,26,36,38,44,46]},"scoresAfter":[-14,-44]},{"ply":13,"player":"human","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[3,7,9,10,28,33,35,42],"ai":[6,16,17,36,38,44,46,47]},"scoresAfter":[-32,-44]},{"ply":14,"player":"ai","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[7,9,10,13,28,33,35,42],"ai":[6,16,17,36,38,44,46,47]},"scoresAfter":[-32,-34]},{"ply":15,"player":"human","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[7,9,10,13,28,33,35,42],"ai":[12,16,17,36,38,44,46,47]},"scoresAfter":[-26,-34]},{"ply":16,"player":"ai","action":36,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[9,10,13,28,32,33,35,42],"ai":[12,16,17,36,38,44,46,47]},"scoresAfter":[-26,-74]},{"ply":17,"player":"human","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[9,10,13,28,32,33,35,42],"ai":[12,16,17,38,44,45,46,47]},"scoresAfter":[-18,-74]},{"ply":18,"player":"ai","action":24,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[10,13,19,28,32,33,35,42],"ai":[12,16,17,38,44,45,46,47]},"scoresAfter":[-18,-90]},{"ply":19,"player":"human","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[10,13,19,28,32,33,35,42],"ai":[12,16,24,38,44,45,46,47]},"scoresAfter":[-9,-90]},{"ply":20,"player":"ai","action":36,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[13,19,28,32,33,35,40,42],"ai":[12,16,24,38,44,45,46,47]},"scoresAfter":[-9,-110]},{"ply":21,"player":"human","action":36,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[13,19,28,32,33,35,40,42],"ai":[12,16,24,44,45,46,47,49]},"scoresAfter":[-2,-110]},{"ply":22,"player":"ai","action":90,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[13,19,28,33,35,40,42,59],"ai":[12,16,24,44,45,46,47,49]},"scoresAfter":[-2,-110]},{"ply":23,"player":"human","action":36,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[13,19,28,33,35,40,42,59],"ai":[12,16,22,24,44,45,46,47]},"scoresAfter":[6,-110]},{"ply":24,"player":"ai","action":6,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[13,19,20,28,35,40,42,59],"ai":[12,16,22,24,44,45,46,47]},"scoresAfter":[6,-110]},{"ply":25,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[13,19,20,28,35,40,42,59],"ai":[16,22,24,44,45,46,47,48]},"scoresAfter":[16,-110]},{"ply":26,"player":"ai","action":6,"playedCard":16,"placeType":"discard","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[13,18,19,20,28,35,40,42],"ai":[16,22,24,44,45,46,47,48]},"scoresAfter":[16,-110]},{"ply":27,"player":"human","action":2,"playedCard":13,"placeType":"play","drawSource":"discard_1","drawnCard":16,"handsBefore":{"human":[13,18,19,20,28,35,40,42],"ai":[22,24,43,44,45,46,47,48]},"scoresAfter":[-24,-110]},{"ply":28,"player":"ai","action":0,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[16,18,19,20,28,35,40,42],"ai":[22,24,43,44,45,46,47,48]},"scoresAfter":[-24,-101]},{"ply":29,"player":"human","action":62,"playedCard":35,"placeType":"play","drawSource":"discard_1","drawnCard":12,"handsBefore":{"human":[16,18,19,20,28,35,40,42],"ai":[24,39,43,44,45,46,47,48]},"scoresAfter":[-14,-101]},{"ply":30,"player":"ai","action":0,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[12,16,18,19,20,28,40,42],"ai":[24,39,43,44,45,46,47,48]},"scoresAfter":[-14,-141]},{"ply":31,"player":"human","action":0,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[12,16,18,19,20,28,40,42],"ai":[14,39,43,44,45,46,47,48]},"scoresAfter":[-34,-141]},{"ply":32,"player":"ai","action":90,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[16,18,19,20,28,40,41,42],"ai":[14,39,43,44,45,46,47,48]},"scoresAfter":[-34,-141]},{"ply":33,"player":"human","action":0,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[16,18,19,20,28,40,41,42],"ai":[14,21,39,43,44,45,46,47]},"scoresAfter":[-25,-141]},{"ply":34,"player":"ai","action":24,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[18,19,20,28,40,41,42,53],"ai":[14,21,39,43,44,45,46,47]},"scoresAfter":[-25,-135]},{"ply":35,"player":"human","action":0,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[18,19,20,28,40,41,42,53],"ai":[14,21,25,43,44,45,46,47]},"scoresAfter":[-10,-135]},{"ply":36,"player":"ai","action":36,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[11,19,20,28,40,41,42,53],"ai":[14,21,25,43,44,45,46,47]},"scoresAfter":[-10,-117]},{"ply":37,"player":"human","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[11,19,20,28,40,41,42,53],"ai":[8,14,21,25,44,45,46,47]},"scoresAfter":[0,-117]},{"ply":38,"player":"ai","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[4,19,20,28,40,41,42,53],"ai":[8,14,21,25,44,45,46,47]},"scoresAfter":[0,-103]},{"ply":39,"player":"human","action":6,"playedCard":4,"placeType":"discard","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[4,19,20,28,40,41,42,53],"ai":[2,14,21,25,44,45,46,47]},"scoresAfter":[0,-103]},{"ply":40,"player":"ai","action":36,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[5,19,20,28,40,41,42,53],"ai":[2,14,21,25,44,45,46,47]},"scoresAfter":[0,-123]},{"ply":41,"player":"human","action":12,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[5,19,20,28,40,41,42,53],"ai":[2,14,21,27,44,45,46,47]},"scoresAfter":[18,-123]},{"ply":42,"player":"ai","action":36,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[5,20,28,37,40,41,42,53],"ai":[2,14,21,27,44,45,46,47]},"scoresAfter":[18,-117]},{"ply":43,"player":"human","action":12,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[5,20,28,37,40,41,42,53],"ai":[2,14,21,31,44,45,46,47]},"scoresAfter":[39,-117]},{"ply":44,"player":"ai","action":37,"playedCard":31,"placeType":"play","drawSource":"discard_0","drawnCard":4,"handsBefore":{"human":[0,5,28,37,40,41,42,53],"ai":[2,14,21,31,44,45,46,47]},"scoresAfter":[39,-99]},{"ply":45,"player":"human","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[0,5,28,37,40,41,42,53],"ai":[2,4,14,21,44,45,46,47]},"scoresAfter":[39,-99]},{"ply":46,"player":"ai","action":53,"playedCard":44,"placeType":"play","drawSource":"discard_4","drawnCard":48,"handsBefore":{"human":[5,28,34,37,40,41,42,53],"ai":[2,4,14,21,44,45,46,47]},"scoresAfter":[39,-78]},{"ply":47,"player":"human","action":18,"playedCard":28,"placeType":"discard","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[5,28,34,37,40,41,42,53],"ai":[2,4,14,21,45,46,47,48]},"scoresAfter":[39,-78]},{"ply":48,"player":"ai","action":53,"playedCard":45,"placeType":"play","drawSource":"discard_4","drawnCard":49,"handsBefore":{"human":[5,34,37,40,41,42,51,53],"ai":[2,4,14,21,45,46,47,48]},"scoresAfter":[39,-54]},{"ply":49,"player":"human","action":6,"playedCard":5,"placeType":"discard","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[5,34,37,40,41,42,51,53],"ai":[2,4,14,21,46,47,48,49]},"scoresAfter":[39,-54]},{"ply":50,"player":"ai","action":49,"playedCard":46,"placeType":"play","drawSource":"discard_0","drawnCard":5,"handsBefore":{"human":[30,34,37,40,41,42,51,53],"ai":[2,4,14,21,46,47,48,49]},"scoresAfter":[39,-27]},{"ply":51,"player":"human","action":78,"playedCard":51,"placeType":"discard","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[30,34,37,40,41,42,51,53],"ai":[2,4,5,14,21,47,48,49]},"scoresAfter":[39,-27]},{"ply":52,"player":"ai","action":60,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[23,30,34,37,40,41,42,53],"ai":[2,4,5,14,21,47,48,49]},"scoresAfter":[39,23]}],"finalScores":[39,23],"outcome":"YOU WIN","finalState":{"deckOrder":[38,42,29,57,1,33,35,58,6,46,44,56,50,36,52,55,9,54,16,3,17,28,26,7,10,47,13,12,32,45,19,24,40,49,59,22,20,48,18,43,39,14,41,21,53,25,11,8,4,2,5,27,37,31,0,34,51,30,23,15],"drawPtr":60,"cardLoc":[5,4,2,3,2,2,4,3,4,3,3,3,3,3,2,2,3,4,3,3,3,2,4,1,4,4,5,4,5,3,1,4,3,3,1,3,4,1,4,4,1,1,1,4,4,4,4,4,2,2,5,5,4,1,3,4,4,3,3,3],"handPublic":[false,false,false,false,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,7,10,0,10],[7,9,6,10,7]],"colHandshakes":[[0,2,0,0,0],[1,0,2,2,0]],"colLength":[[5,6,4,0,4],[3,2,4,8,3]],"piles":[[0],[],[26,28],[],[50,51]],"toMove":0,"stepCount":52,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"fac95dbe-1cab-4ec6-8675-f9edf399649f","seed":"d9g5te","startedAt":"2026-07-14T17:36:56.251Z","finishedAt":"2026-07-14T17:38:45.491Z","initialDeckOrder":[20,27,5,19,9,24,40,46,8,22,37,15,49,29,30,31,16,52,6,51,11,4,36,38,14,33,17,56,55,57,48,54,3,39,21,32,13,45,2,23,35,1,47,42,12,28,59,7,18,50,44,0,41,53,34,25,26,43,10,58],"moves":[{"ply":1,"player":"human","action":54,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[5,9,19,20,24,27,40,46],"ai":[8,15,22,29,30,31,37,49]},"scoresAfter":[0,0]},{"ply":2,"player":"ai","action":78,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[5,9,16,19,20,27,40,46],"ai":[8,15,22,29,30,31,37,49]},"scoresAfter":[0,0]},{"ply":3,"player":"human","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[5,9,16,19,20,27,40,46],"ai":[8,15,22,29,30,31,49,52]},"scoresAfter":[-16,0]},{"ply":4,"player":"ai","action":72,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[6,9,16,19,20,27,40,46],"ai":[8,15,22,29,30,31,49,52]},"scoresAfter":[-16,-40]},{"ply":5,"player":"human","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[6,9,16,19,20,27,40,46],"ai":[8,15,22,29,30,31,51,52]},"scoresAfter":[-11,-40]},{"ply":6,"player":"ai","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[9,11,16,19,20,27,40,46],"ai":[8,15,22,29,30,31,51,52]},"scoresAfter":[-11,-53]},{"ply":7,"player":"human","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[9,11,16,19,20,27,40,46],"ai":[4,15,22,29,30,31,51,52]},"scoresAfter":[-3,-53]},{"ply":8,"player":"ai","action":6,"playedCard":4,"placeType":"discard","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[11,16,19,20,27,36,40,46],"ai":[4,15,22,29,30,31,51,52]},"scoresAfter":[-3,-53]},{"ply":9,"player":"human","action":64,"playedCard":36,"placeType":"play","drawSource":"discard_3","drawnCard":37,"handsBefore":{"human":[11,16,19,20,27,36,40,46],"ai":[15,22,29,30,31,38,51,52]},"scoresAfter":[-43,-53]},{"ply":10,"player":"ai","action":72,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[11,16,19,20,27,37,40,46],"ai":[15,22,29,30,31,38,51,52]},"scoresAfter":[-43,-49]},{"ply":11,"player":"human","action":60,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[11,16,19,20,27,37,40,46],"ai":[14,15,22,29,30,31,38,52]},"scoresAfter":[-63,-49]},{"ply":12,"player":"ai","action":84,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[11,16,19,20,27,33,40,46],"ai":[14,15,22,29,30,31,38,52]},"scoresAfter":[-63,-43]},{"ply":13,"player":"human","action":72,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[11,16,19,20,27,33,40,46],"ai":[14,15,17,22,29,30,31,38]},"scoresAfter":[-54,-43]},{"ply":14,"player":"ai","action":0,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[11,16,19,20,27,33,46,56],"ai":[14,15,17,22,29,30,31,38]},"scoresAfter":[-54,-83]},{"ply":15,"player":"human","action":12,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[11,16,19,20,27,33,46,56],"ai":[15,17,22,29,30,31,38,55]},"scoresAfter":[-71,-83]},{"ply":16,"player":"ai","action":0,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[11,19,20,27,33,46,56,57],"ai":[15,17,22,29,30,31,38,55]},"scoresAfter":[-71,-79]},{"ply":17,"player":"human","action":12,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[11,19,20,27,33,46,56,57],"ai":[17,22,29,30,31,38,48,55]},"scoresAfter":[-65,-79]},{"ply":18,"player":"ai","action":0,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[11,20,27,33,46,54,56,57],"ai":[17,22,29,30,31,38,48,55]},"scoresAfter":[-65,-71]},{"ply":19,"player":"human","action":60,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[11,20,27,33,46,54,56,57],"ai":[3,22,29,30,31,38,48,55]},"scoresAfter":[-80,-71]},{"ply":20,"player":"ai","action":78,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[11,20,27,33,39,46,56,57],"ai":[3,22,29,30,31,38,48,55]},"scoresAfter":[-80,-71]},{"ply":21,"player":"human","action":72,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[11,20,27,33,39,46,56,57],"ai":[3,21,22,29,30,31,38,55]},"scoresAfter":[-73,-71]},{"ply":22,"player":"ai","action":72,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[11,20,27,32,33,39,46,57],"ai":[3,21,22,29,30,31,38,55]},"scoresAfter":[-73,-111]},{"ply":23,"player":"human","action":84,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[11,20,27,32,33,39,46,57],"ai":[3,13,21,22,29,30,31,55]},"scoresAfter":[-65,-111]},{"ply":24,"player":"ai","action":6,"playedCard":3,"placeType":"discard","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[11,20,27,32,33,39,45,46],"ai":[3,13,21,22,29,30,31,55]},"scoresAfter":[-65,-111]},{"ply":25,"player":"human","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[11,20,27,32,33,39,45,46],"ai":[2,13,21,22,29,30,31,55]},"scoresAfter":[-55,-111]},{"ply":26,"player":"ai","action":24,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[20,23,27,32,33,39,45,46],"ai":[2,13,21,22,29,30,31,55]},"scoresAfter":[-55,-95]},{"ply":27,"player":"human","action":0,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[20,23,27,32,33,39,45,46],"ai":[2,13,22,29,30,31,35,55]},"scoresAfter":[-48,-95]},{"ply":28,"player":"ai","action":84,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[1,23,27,32,33,39,45,46],"ai":[2,13,22,29,30,31,35,55]},"scoresAfter":[-48,-83]},{"ply":29,"player":"human","action":12,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[1,23,27,32,33,39,45,46],"ai":[2,13,22,29,30,31,35,47]},"scoresAfter":[-38,-83]},{"ply":30,"player":"ai","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[1,27,32,33,39,42,45,46],"ai":[2,13,22,29,30,31,35,47]},"scoresAfter":[-38,-83]},{"ply":31,"player":"human","action":60,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[1,27,32,33,39,42,45,46],"ai":[12,13,22,29,30,31,35,47]},"scoresAfter":[-23,-83]},{"ply":32,"player":"ai","action":24,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[1,27,28,32,33,39,45,46],"ai":[12,13,22,29,30,31,35,47]},"scoresAfter":[-23,-65]},{"ply":33,"player":"human","action":75,"playedCard":45,"placeType":"play","drawSource":"discard_2","drawnCard":24,"handsBefore":{"human":[1,27,28,32,33,39,45,46],"ai":[12,13,29,30,31,35,47,59]},"scoresAfter":[1,-65]},{"ply":34,"player":"ai","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[1,24,27,28,32,33,39,46],"ai":[12,13,29,30,31,35,47,59]},"scoresAfter":[1,-45]},{"ply":35,"player":"human","action":12,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[1,24,27,28,32,33,39,46],"ai":[7,12,13,29,30,31,35,47]},"scoresAfter":[-39,-45]},{"ply":36,"player":"ai","action":6,"playedCard":7,"placeType":"discard","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[1,18,27,28,32,33,39,46],"ai":[7,12,13,29,30,31,35,47]},"scoresAfter":[-39,-45]},{"ply":37,"player":"human","action":24,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[1,18,27,28,32,33,39,46],"ai":[12,13,29,30,31,35,47,50]},"scoresAfter":[-35,-45]},{"ply":38,"player":"ai","action":24,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[1,18,28,32,33,39,44,46],"ai":[12,13,29,30,31,35,47,50]},"scoresAfter":[-35,-61]},{"ply":39,"player":"human","action":24,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[1,18,28,32,33,39,44,46],"ai":[0,12,13,30,31,35,47,50]},"scoresAfter":[-29,-61]},{"ply":40,"player":"ai","action":36,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[1,18,32,33,39,41,44,46],"ai":[0,12,13,30,31,35,47,50]},"scoresAfter":[-29,-56]},{"ply":41,"player":"human","action":25,"playedCard":32,"placeType":"play","drawSource":"discard_0","drawnCard":7,"handsBefore":{"human":[1,18,32,33,39,41,44,46],"ai":[0,12,13,31,35,47,50,53]},"scoresAfter":[-15,-56]},{"ply":42,"player":"ai","action":60,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[1,7,18,33,39,41,44,46],"ai":[0,12,13,31,35,47,50,53]},"scoresAfter":[-15,-36]},{"ply":43,"player":"human","action":36,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[1,7,18,33,39,41,44,46],"ai":[0,12,13,31,34,35,50,53]},"scoresAfter":[1,-36]},{"ply":44,"player":"ai","action":36,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[1,7,18,25,39,41,44,46],"ai":[0,12,13,31,34,35,50,53]},"scoresAfter":[1,-30]},{"ply":45,"player":"human","action":84,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[1,7,18,25,39,41,44,46],"ai":[0,12,13,26,34,35,50,53]},"scoresAfter":[28,-30]},{"ply":46,"player":"ai","action":48,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[1,7,18,25,39,41,43,44],"ai":[0,12,13,26,34,35,50,53]},"scoresAfter":[28,-21]},{"ply":47,"player":"human","action":78,"playedCard":43,"placeType":"discard","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[1,7,18,25,39,41,43,44],"ai":[0,10,12,13,26,35,50,53]},"scoresAfter":[28,-21]}],"finalScores":[28,-21],"outcome":"YOU WIN","finalState":{"deckOrder":[20,27,5,19,9,24,40,46,8,22,37,15,49,29,30,31,16,52,6,51,11,4,36,38,14,33,17,56,55,57,48,54,3,39,21,32,13,45,2,23,35,1,47,42,12,28,59,7,18,50,44,0,41,53,34,25,26,43,10,58],"drawPtr":60,"cardLoc":[2,1,5,5,5,3,3,1,4,3,2,3,2,2,4,4,3,4,1,3,3,4,4,3,3,1,2,3,3,4,4,4,3,3,4,2,3,3,4,1,3,1,3,5,1,3,3,4,5,4,2,4,4,2,3,4,3,3,1,4],"handPublic":[false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,10,8,9,8],[7,9,9,10,10]],"colHandshakes":[[0,0,1,2,0],[0,1,0,1,1]],"colLength":[[4,4,5,6,3],[1,5,4,2,5]],"piles":[[4,3,2],[],[],[43],[48]],"toMove":1,"stepCount":47,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"facb1b22-53a5-43b1-b1f7-10a42c243535","seed":"qfzl16","startedAt":"2026-07-14T17:38:46.495Z","finishedAt":"2026-07-14T17:40:18.962Z","initialDeckOrder":[14,27,30,10,25,52,16,44,49,36,37,7,21,56,42,29,4,12,2,54,0,33,32,55,35,6,48,41,20,46,34,40,43,53,19,5,23,50,3,59,8,17,28,26,15,58,9,47,11,38,31,45,57,18,24,39,1,13,51,22],"moves":[{"ply":1,"player":"human","action":36,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[10,14,16,25,27,30,44,52],"ai":[7,21,29,36,37,42,49,56]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":72,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[4,10,14,16,27,30,44,52],"ai":[7,21,29,36,37,42,49,56]},"scoresAfter":[-40,-40]},{"ply":3,"player":"human","action":48,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[4,10,14,16,27,30,44,52],"ai":[7,12,21,29,36,37,42,56]},"scoresAfter":[-36,-40]},{"ply":4,"player":"ai","action":48,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[2,4,10,14,16,30,44,52],"ai":[7,12,21,29,36,37,42,56]},"scoresAfter":[-36,-80]},{"ply":5,"player":"human","action":0,"playedCard":2,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[2,4,10,14,16,30,44,52],"ai":[7,12,21,29,37,42,54,56]},"scoresAfter":[-76,-80]},{"ply":6,"player":"ai","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[0,4,10,14,16,30,44,52],"ai":[7,12,21,29,37,42,54,56]},"scoresAfter":[-76,-94]},{"ply":7,"player":"human","action":0,"playedCard":0,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[0,4,10,14,16,30,44,52],"ai":[12,21,29,33,37,42,54,56]},"scoresAfter":[-96,-94]},{"ply":8,"player":"ai","action":48,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[4,10,14,16,30,32,44,52],"ai":[12,21,29,33,37,42,54,56]},"scoresAfter":[-96,-114]},{"ply":9,"player":"human","action":48,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[4,10,14,16,30,32,44,52],"ai":[12,21,29,33,42,54,55,56]},"scoresAfter":[-86,-114]},{"ply":10,"player":"ai","action":0,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[4,10,14,16,32,35,44,52],"ai":[12,21,29,33,42,54,55,56]},"scoresAfter":[-86,-154]},{"ply":11,"player":"human","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[4,10,14,16,32,35,44,52],"ai":[6,21,29,33,42,54,55,56]},"scoresAfter":[-77,-154]},{"ply":12,"player":"ai","action":48,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[10,14,16,32,35,44,48,52],"ai":[6,21,29,33,42,54,55,56]},"scoresAfter":[-77,-139]},{"ply":13,"player":"human","action":36,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[10,14,16,32,35,44,48,52],"ai":[6,21,29,33,41,54,55,56]},"scoresAfter":[-63,-139]},{"ply":14,"player":"ai","action":24,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[10,14,16,20,35,44,48,52],"ai":[6,21,29,33,41,54,55,56]},"scoresAfter":[-63,-155]},{"ply":15,"player":"human","action":12,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[10,14,16,20,35,44,48,52],"ai":[6,21,33,41,46,54,55,56]},"scoresAfter":[-103,-155]},{"ply":16,"player":"ai","action":60,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[10,16,20,34,35,44,48,52],"ai":[6,21,33,41,46,54,55,56]},"scoresAfter":[-103,-145]},{"ply":17,"player":"human","action":36,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[10,16,20,34,35,44,48,52],"ai":[6,21,33,40,41,46,55,56]},"scoresAfter":[-85,-145]},{"ply":18,"player":"ai","action":72,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[10,16,20,35,43,44,48,52],"ai":[6,21,33,40,41,46,55,56]},"scoresAfter":[-85,-133]},{"ply":19,"player":"human","action":36,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[10,16,20,35,43,44,48,52],"ai":[6,21,33,40,41,46,53,56]},"scoresAfter":[-65,-133]},{"ply":20,"player":"ai","action":84,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[10,16,19,20,43,44,48,52],"ai":[6,21,33,40,41,46,53,56]},"scoresAfter":[-65,-119]},{"ply":21,"player":"human","action":12,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[10,16,19,20,43,44,48,52],"ai":[5,6,21,33,40,41,46,53]},"scoresAfter":[-59,-119]},{"ply":22,"player":"ai","action":24,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[10,19,20,23,43,44,48,52],"ai":[5,6,21,33,40,41,46,53]},"scoresAfter":[-59,-103]},{"ply":23,"player":"human","action":12,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[10,19,20,23,43,44,48,52],"ai":[5,6,33,40,41,46,50,53]},"scoresAfter":[-47,-103]},{"ply":24,"player":"ai","action":78,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[3,10,20,23,43,44,48,52],"ai":[5,6,33,40,41,46,50,53]},"scoresAfter":[-47,-103]},{"ply":25,"player":"human","action":24,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[3,10,20,23,43,44,48,52],"ai":[5,6,33,40,41,46,53,59]},"scoresAfter":[-33,-103]},{"ply":26,"player":"ai","action":24,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[3,8,10,23,43,44,48,52],"ai":[5,6,33,40,41,46,53,59]},"scoresAfter":[-33,-95]},{"ply":27,"player":"human","action":78,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[3,8,10,23,43,44,48,52],"ai":[5,6,17,40,41,46,53,59]},"scoresAfter":[-33,-95]},{"ply":28,"player":"ai","action":30,"playedCard":17,"placeType":"discard","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[3,8,10,23,28,43,44,52],"ai":[5,6,17,40,41,46,53,59]},"scoresAfter":[-33,-95]},{"ply":29,"player":"human","action":6,"playedCard":3,"placeType":"discard","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[3,8,10,23,28,43,44,52],"ai":[5,6,26,40,41,46,53,59]},"scoresAfter":[-33,-95]},{"ply":30,"player":"ai","action":30,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[8,10,15,23,28,43,44,52],"ai":[5,6,26,40,41,46,53,59]},"scoresAfter":[-33,-95]},{"ply":31,"player":"human","action":54,"playedCard":28,"placeType":"discard","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[8,10,15,23,28,43,44,52],"ai":[5,6,40,41,46,53,58,59]},"scoresAfter":[-33,-95]},{"ply":32,"player":"ai","action":66,"playedCard":53,"placeType":"discard","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[8,9,10,15,23,43,44,52],"ai":[5,6,40,41,46,53,58,59]},"scoresAfter":[-33,-95]},{"ply":33,"player":"human","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[8,9,10,15,23,43,44,52],"ai":[5,6,40,41,46,47,58,59]},"scoresAfter":[-12,-95]},{"ply":34,"player":"ai","action":72,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[9,10,11,15,23,43,44,52],"ai":[5,6,40,41,46,47,58,59]},"scoresAfter":[-12,-77]},{"ply":35,"player":"human","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[9,10,11,15,23,43,44,52],"ai":[5,6,38,40,41,46,47,59]},"scoresAfter":[12,-77]},{"ply":36,"player":"ai","action":18,"playedCard":6,"placeType":"discard","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[10,11,15,23,31,43,44,52],"ai":[5,6,38,40,41,46,47,59]},"scoresAfter":[12,-77]},{"ply":37,"player":"human","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[10,11,15,23,31,43,44,52],"ai":[5,38,40,41,45,46,47,59]},"scoresAfter":[39,-77]},{"ply":38,"player":"ai","action":48,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[11,15,23,31,43,44,52,57],"ai":[5,38,40,41,45,46,47,59]},"scoresAfter":[39,-53]},{"ply":39,"player":"human","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[11,15,23,31,43,44,52,57],"ai":[5,18,38,40,41,46,47,59]},"scoresAfter":[69,-53]},{"ply":40,"player":"ai","action":65,"playedCard":46,"placeType":"play","drawSource":"discard_4","drawnCard":53,"handsBefore":{"human":[15,23,24,31,43,44,52,57],"ai":[5,18,38,40,41,46,47,59]},"scoresAfter":[69,-26]},{"ply":41,"player":"human","action":6,"playedCard":15,"placeType":"discard","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[15,23,24,31,43,44,52,57],"ai":[5,18,38,40,41,47,53,59]},"scoresAfter":[69,-26]},{"ply":42,"player":"ai","action":65,"playedCard":47,"placeType":"play","drawSource":"discard_4","drawnCard":48,"handsBefore":{"human":[23,24,31,39,43,44,52,57],"ai":[5,18,38,40,41,47,53,59]},"scoresAfter":[69,4]},{"ply":43,"player":"human","action":42,"playedCard":39,"placeType":"discard","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[23,24,31,39,43,44,52,57],"ai":[5,18,38,40,41,48,53,59]},"scoresAfter":[69,4]},{"ply":44,"player":"ai","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[1,23,24,31,43,44,52,57],"ai":[5,18,38,40,41,48,53,59]},"scoresAfter":[69,24]},{"ply":45,"player":"human","action":12,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[1,23,24,31,43,44,52,57],"ai":[5,13,18,38,40,41,48,53]},"scoresAfter":[89,24]},{"ply":46,"player":"ai","action":18,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[1,24,31,43,44,51,52,57],"ai":[5,13,18,38,40,41,48,53]},"scoresAfter":[89,24]}],"finalScores":[89,24],"outcome":"YOU WIN","finalState":{"deckOrder":[14,27,30,10,25,52,16,44,49,36,37,7,21,56,42,29,4,12,2,54,0,33,32,55,35,6,48,41,20,46,34,40,43,53,19,5,23,50,3,59,8,17,28,26,15,58,9,47,11,38,31,45,57,18,24,39,1,13,51,22],"drawPtr":60,"cardLoc":[3,1,3,5,3,2,5,4,3,3,3,3,4,5,3,5,3,5,2,3,3,4,2,3,1,3,5,3,5,4,3,1,3,4,3,3,4,4,2,5,2,2,4,1,1,4,4,4,2,4,5,1,1,2,4,4,4,1,4,4],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,true,false,false,false,false,false,false],"colTop":[[10,10,10,0,0],[6,8,8,10,10]],"colHandshakes":[[2,1,1,0,0],[0,1,0,2,1]],"colLength":[[7,5,6,0,0],[1,2,2,6,6]],"piles":[[3,6],[17,15,13],[26,28],[39],[50]],"toMove":0,"stepCount":46,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"5bbaf83d-5052-4a03-b2e6-a3e8241491d2","seed":"bdgu7b","startedAt":"2026-07-14T17:40:20.033Z","finishedAt":"2026-07-14T17:41:58.371Z","initialDeckOrder":[34,22,39,33,14,48,26,8,41,1,24,15,30,27,40,19,53,59,3,17,52,11,7,56,9,10,35,2,46,23,20,21,45,38,51,25,47,31,16,18,5,42,28,57,32,6,4,49,12,13,0,50,44,36,55,54,58,29,37,43],"moves":[{"ply":1,"player":"human","action":36,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[8,14,22,26,33,34,39,48],"ai":[1,15,19,24,27,30,40,41]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[8,14,22,33,34,39,48,53],"ai":[1,15,19,24,27,30,40,41]},"scoresAfter":[-40,0]},{"ply":3,"player":"human","action":13,"playedCard":14,"placeType":"play","drawSource":"discard_0","drawnCard":1,"handsBefore":{"human":[8,14,22,33,34,39,48,53],"ai":[15,19,24,27,30,40,41,59]},"scoresAfter":[-80,0]},{"ply":4,"player":"ai","action":60,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[1,8,22,33,34,39,48,53],"ai":[15,19,24,27,30,40,41,59]},"scoresAfter":[-80,-17]},{"ply":5,"player":"human","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[1,8,22,33,34,39,48,53],"ai":[3,15,19,24,27,30,41,59]},"scoresAfter":[-120,-17]},{"ply":6,"player":"ai","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[8,17,22,33,34,39,48,53],"ai":[3,15,19,24,27,30,41,59]},"scoresAfter":[-120,-35]},{"ply":7,"player":"human","action":12,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[8,17,22,33,34,39,48,53],"ai":[15,19,24,27,30,41,52,59]},"scoresAfter":[-112,-35]},{"ply":8,"player":"ai","action":12,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[8,11,22,33,34,39,48,53],"ai":[15,19,24,27,30,41,52,59]},"scoresAfter":[-112,-49]},{"ply":9,"player":"human","action":66,"playedCard":39,"placeType":"discard","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[8,11,22,33,34,39,48,53],"ai":[7,15,24,27,30,41,52,59]},"scoresAfter":[-112,-49]},{"ply":10,"player":"ai","action":24,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[8,11,22,33,34,48,53,56],"ai":[7,15,24,27,30,41,52,59]},"scoresAfter":[-112,-89]},{"ply":11,"player":"human","action":60,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[8,11,22,33,34,48,53,56],"ai":[7,9,15,27,30,41,52,59]},"scoresAfter":[-152,-89]},{"ply":12,"player":"ai","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[8,10,11,22,33,34,53,56],"ai":[7,9,15,27,30,41,52,59]},"scoresAfter":[-152,-83]},{"ply":13,"player":"human","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[8,10,11,22,33,34,53,56],"ai":[9,15,27,30,35,41,52,59]},"scoresAfter":[-138,-83]},{"ply":14,"player":"ai","action":18,"playedCard":15,"placeType":"discard","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[2,10,11,22,33,34,53,56],"ai":[9,15,27,30,35,41,52,59]},"scoresAfter":[-138,-83]},{"ply":15,"player":"human","action":12,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[2,10,11,22,33,34,53,56],"ai":[9,27,30,35,41,46,52,59]},"scoresAfter":[-120,-83]},{"ply":16,"player":"ai","action":48,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[2,11,22,23,33,34,53,56],"ai":[9,27,30,35,41,46,52,59]},"scoresAfter":[-120,-79]},{"ply":17,"player":"human","action":12,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[2,11,22,23,33,34,53,56],"ai":[9,20,27,30,35,46,52,59]},"scoresAfter":[-100,-79]},{"ply":18,"player":"ai","action":12,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[2,21,22,23,33,34,53,56],"ai":[9,20,27,30,35,46,52,59]},"scoresAfter":[-100,-72]},{"ply":19,"player":"human","action":12,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[2,21,22,23,33,34,53,56],"ai":[9,27,30,35,45,46,52,59]},"scoresAfter":[-84,-72]},{"ply":20,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[2,22,23,33,34,38,53,56],"ai":[9,27,30,35,45,46,52,59]},"scoresAfter":[-84,-64]},{"ply":21,"player":"human","action":12,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[2,22,23,33,34,38,53,56],"ai":[27,30,35,45,46,51,52,59]},"scoresAfter":[-66,-64]},{"ply":22,"player":"ai","action":0,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[2,23,25,33,34,38,53,56],"ai":[27,30,35,45,46,51,52,59]},"scoresAfter":[-66,-60]},{"ply":23,"player":"human","action":12,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[2,23,25,33,34,38,53,56],"ai":[30,35,45,46,47,51,52,59]},"scoresAfter":[-46,-60]},{"ply":24,"player":"ai","action":42,"playedCard":46,"placeType":"discard","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[2,25,31,33,34,38,53,56],"ai":[30,35,45,46,47,51,52,59]},"scoresAfter":[-46,-60]},{"ply":25,"player":"human","action":12,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[2,25,31,33,34,38,53,56],"ai":[16,30,35,45,47,51,52,59]},"scoresAfter":[-66,-60]},{"ply":26,"player":"ai","action":10,"playedCard":16,"placeType":"discard","drawSource":"discard_3","drawnCard":46,"handsBefore":{"human":[2,18,31,33,34,38,53,56],"ai":[16,30,35,45,47,51,52,59]},"scoresAfter":[-66,-60]},{"ply":27,"player":"human","action":66,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[2,18,31,33,34,38,53,56],"ai":[30,35,45,46,47,51,52,59]},"scoresAfter":[-66,-60]},{"ply":28,"player":"ai","action":0,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[2,5,18,31,33,34,53,56],"ai":[30,35,45,46,47,51,52,59]},"scoresAfter":[-66,-50]},{"ply":29,"player":"human","action":72,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[2,5,18,31,33,34,53,56],"ai":[35,42,45,46,47,51,52,59]},"scoresAfter":[-58,-50]},{"ply":30,"player":"ai","action":0,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[2,5,18,28,31,33,34,56],"ai":[35,42,45,46,47,51,52,59]},"scoresAfter":[-58,-30]},{"ply":31,"player":"human","action":36,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[2,5,18,28,31,33,34,56],"ai":[42,45,46,47,51,52,57,59]},"scoresAfter":[-49,-30]},{"ply":32,"player":"ai","action":0,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[2,5,18,31,32,33,34,56],"ai":[42,45,46,47,51,52,57,59]},"scoresAfter":[-49,-25]},{"ply":33,"player":"human","action":36,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[2,5,18,31,32,33,34,56],"ai":[6,45,46,47,51,52,57,59]},"scoresAfter":[-31,-25]},{"ply":34,"player":"ai","action":10,"playedCard":6,"placeType":"discard","drawSource":"discard_3","drawnCard":38,"handsBefore":{"human":[2,4,5,18,32,33,34,56],"ai":[6,45,46,47,51,52,57,59]},"scoresAfter":[-31,-25]},{"ply":35,"player":"human","action":48,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[2,4,5,18,32,33,34,56],"ai":[38,45,46,47,51,52,57,59]},"scoresAfter":[-10,-25]},{"ply":36,"player":"ai","action":12,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[2,4,5,18,33,34,49,56],"ai":[38,45,46,47,51,52,57,59]},"scoresAfter":[-10,-17]},{"ply":37,"player":"human","action":48,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[2,4,5,18,33,34,49,56],"ai":[12,38,46,47,51,52,57,59]},"scoresAfter":[14,-17]},{"ply":38,"player":"ai","action":24,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[2,4,5,13,18,34,49,56],"ai":[12,38,46,47,51,52,57,59]},"scoresAfter":[14,-8]},{"ply":39,"player":"human","action":60,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[2,4,5,13,18,34,49,56],"ai":[0,12,38,47,51,52,57,59]},"scoresAfter":[41,-8]},{"ply":40,"player":"ai","action":36,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[2,4,5,13,18,49,50,56],"ai":[0,12,38,47,51,52,57,59]},"scoresAfter":[41,2]},{"ply":41,"player":"human","action":78,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[2,4,5,13,18,49,50,56],"ai":[0,12,38,44,51,52,57,59]},"scoresAfter":[41,2]},{"ply":42,"player":"ai","action":48,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[2,4,5,13,18,36,49,56],"ai":[0,12,38,44,51,52,57,59]},"scoresAfter":[41,-16]},{"ply":43,"player":"human","action":78,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[2,4,5,13,18,36,49,56],"ai":[0,12,38,44,52,55,57,59]},"scoresAfter":[41,-16]},{"ply":44,"player":"ai","action":48,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[2,4,5,13,18,36,54,56],"ai":[0,12,38,44,52,55,57,59]},"scoresAfter":[41,-13]},{"ply":45,"player":"human","action":72,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[2,4,5,13,18,36,54,56],"ai":[0,12,38,44,55,57,58,59]},"scoresAfter":[51,-13]},{"ply":46,"player":"ai","action":50,"playedCard":55,"placeType":"play","drawSource":"discard_1","drawnCard":16,"handsBefore":{"human":[2,4,5,13,18,29,36,56],"ai":[0,12,38,44,55,57,58,59]},"scoresAfter":[51,-7]},{"ply":47,"player":"human","action":84,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[2,4,5,13,18,29,36,56],"ai":[0,12,16,38,44,57,58,59]},"scoresAfter":[65,-7]},{"ply":48,"player":"ai","action":62,"playedCard":57,"placeType":"play","drawSource":"discard_1","drawnCard":15,"handsBefore":{"human":[2,4,5,13,18,29,36,37],"ai":[0,12,16,38,44,57,58,59]},"scoresAfter":[65,1]},{"ply":49,"player":"human","action":54,"playedCard":18,"placeType":"discard","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[2,4,5,13,18,29,36,37],"ai":[0,12,15,16,38,44,58,59]},"scoresAfter":[65,1]}],"finalScores":[65,1],"outcome":"YOU WIN","finalState":{"deckOrder":[34,22,39,33,14,48,26,8,41,1,24,15,30,27,40,19,53,59,3,17,52,11,7,56,9,10,35,2,46,23,20,21,45,38,51,25,47,31,16,18,5,42,28,57,32,6,4,49,12,13,0,50,44,36,55,54,58,29,37,43],"drawPtr":60,"cardLoc":[2,3,1,4,1,1,5,4,3,4,3,3,2,1,3,2,2,3,5,4,4,3,3,3,4,3,3,4,3,1,4,3,3,3,3,4,1,1,2,5,4,4,4,1,2,4,4,4,3,5,5,4,4,3,3,4,3,4,2,2],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,10,9,0,7],[8,7,10,10,8]],"colHandshakes":[[1,1,2,0,1],[0,0,1,0,0]],"colLength":[[4,5,7,0,4],[3,2,4,6,4]],"piles":[[6],[18],[],[39],[50,49]],"toMove":1,"stepCount":49,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"7f4eebec-3255-409b-af05-d37d16537c70","seed":"5nhlb1","startedAt":"2026-07-14T17:41:59.365Z","finishedAt":"2026-07-14T17:43:26.244Z","initialDeckOrder":[34,52,24,59,35,32,18,36,2,47,20,16,21,54,55,4,56,12,37,13,25,9,6,14,28,17,42,31,10,57,7,23,33,22,49,38,44,3,8,26,39,41,11,46,29,53,48,0,50,45,19,27,5,51,30,40,15,58,1,43],"moves":[{"ply":1,"player":"human","action":12,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[18,24,32,34,35,36,52,59],"ai":[2,4,16,20,21,47,54,55]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":12,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[18,32,34,35,36,52,56,59],"ai":[2,4,16,20,21,47,54,55]},"scoresAfter":[-40,-17]},{"ply":3,"player":"human","action":60,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[18,32,34,35,36,52,56,59],"ai":[2,12,16,20,21,47,54,55]},"scoresAfter":[-57,-17]},{"ply":4,"player":"ai","action":72,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[18,32,34,35,36,37,56,59],"ai":[2,12,16,20,21,47,54,55]},"scoresAfter":[-57,-32]},{"ply":5,"player":"human","action":54,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[18,32,34,35,36,37,56,59],"ai":[2,12,13,16,20,21,47,55]},"scoresAfter":[-57,-32]},{"ply":6,"player":"ai","action":84,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[18,25,32,34,35,37,56,59],"ai":[2,12,13,16,20,21,47,55]},"scoresAfter":[-57,-26]},{"ply":7,"player":"human","action":66,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[18,25,32,34,35,37,56,59],"ai":[2,9,12,13,16,20,21,47]},"scoresAfter":[-57,-26]},{"ply":8,"player":"ai","action":30,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[6,18,25,32,34,35,56,59],"ai":[2,9,12,13,16,20,21,47]},"scoresAfter":[-57,-26]},{"ply":9,"player":"human","action":24,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[6,18,25,32,34,35,56,59],"ai":[2,9,13,14,16,20,21,47]},"scoresAfter":[-77,-26]},{"ply":10,"player":"ai","action":8,"playedCard":2,"placeType":"discard","drawSource":"discard_1","drawnCard":12,"handsBefore":{"human":[6,18,28,32,34,35,56,59],"ai":[2,9,13,14,16,20,21,47]},"scoresAfter":[-77,-26]},{"ply":11,"player":"human","action":24,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[6,18,28,32,34,35,56,59],"ai":[9,12,13,14,16,20,21,47]},"scoresAfter":[-68,-26]},{"ply":12,"player":"ai","action":12,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[6,17,18,32,34,35,56,59],"ai":[9,12,13,14,16,20,21,47]},"scoresAfter":[-68,-66]},{"ply":13,"player":"human","action":72,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[6,17,18,32,34,35,56,59],"ai":[9,13,14,16,20,21,42,47]},"scoresAfter":[-61,-66]},{"ply":14,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[6,17,18,31,32,34,35,59],"ai":[9,13,14,16,20,21,42,47]},"scoresAfter":[-61,-58]},{"ply":15,"player":"human","action":36,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[6,17,18,31,32,34,35,59],"ai":[10,13,14,16,20,21,42,47]},"scoresAfter":[-43,-58]},{"ply":16,"player":"ai","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[6,17,18,32,34,35,57,59],"ai":[10,13,14,16,20,21,42,47]},"scoresAfter":[-43,-49]},{"ply":17,"player":"human","action":36,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[6,17,18,32,34,35,57,59],"ai":[7,13,14,16,20,21,42,47]},"scoresAfter":[-22,-49]},{"ply":18,"player":"ai","action":12,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[6,17,18,23,34,35,57,59],"ai":[7,13,14,16,20,21,42,47]},"scoresAfter":[-22,-69]},{"ply":19,"player":"human","action":72,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[6,17,18,23,34,35,57,59],"ai":[7,14,16,20,21,33,42,47]},"scoresAfter":[-14,-69]},{"ply":20,"player":"ai","action":6,"playedCard":7,"placeType":"discard","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[6,17,18,22,23,34,35,59],"ai":[7,14,16,20,21,33,42,47]},"scoresAfter":[-14,-69]},{"ply":21,"player":"human","action":60,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[6,17,18,22,23,34,35,59],"ai":[14,16,20,21,33,42,47,49]},"scoresAfter":[13,-69]},{"ply":22,"player":"ai","action":52,"playedCard":33,"placeType":"play","drawSource":"discard_3","drawnCard":37,"handsBefore":{"human":[6,17,18,22,23,35,38,59],"ai":[14,16,20,21,33,42,47,49]},"scoresAfter":[13,-81]},{"ply":23,"player":"human","action":60,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[6,17,18,22,23,35,38,59],"ai":[14,16,20,21,37,42,47,49]},"scoresAfter":[43,-81]},{"ply":24,"player":"ai","action":54,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[6,17,18,22,23,38,44,59],"ai":[14,16,20,21,37,42,47,49]},"scoresAfter":[43,-81]},{"ply":25,"player":"human","action":6,"playedCard":6,"placeType":"discard","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[6,17,18,22,23,38,44,59],"ai":[3,14,16,20,21,42,47,49]},"scoresAfter":[43,-81]},{"ply":26,"player":"ai","action":90,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[8,17,18,22,23,38,44,59],"ai":[3,14,16,20,21,42,47,49]},"scoresAfter":[43,-81]},{"ply":27,"player":"human","action":6,"playedCard":8,"placeType":"discard","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[8,17,18,22,23,38,44,59],"ai":[3,14,16,20,21,26,42,47]},"scoresAfter":[43,-81]},{"ply":28,"player":"ai","action":90,"playedCard":47,"placeType":"discard","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[17,18,22,23,38,39,44,59],"ai":[3,14,16,20,21,26,42,47]},"scoresAfter":[43,-81]},{"ply":29,"player":"human","action":52,"playedCard":38,"placeType":"play","drawSource":"discard_3","drawnCard":47,"handsBefore":{"human":[17,18,22,23,38,39,44,59],"ai":[3,14,16,20,21,26,41,42]},"scoresAfter":[3,-81]},{"ply":30,"player":"ai","action":66,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[17,18,22,23,39,44,47,59],"ai":[3,14,16,20,21,26,41,42]},"scoresAfter":[3,-81]},{"ply":31,"player":"human","action":0,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[17,18,22,23,39,44,47,59],"ai":[3,11,14,16,20,21,41,42]},"scoresAfter":[-13,-81]},{"ply":32,"player":"ai","action":84,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[18,22,23,39,44,46,47,59],"ai":[3,11,14,16,20,21,41,42]},"scoresAfter":[-13,-96]},{"ply":33,"player":"human","action":0,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[18,22,23,39,44,46,47,59],"ai":[3,11,14,16,20,21,29,41]},"scoresAfter":[-8,-96]},{"ply":34,"player":"ai","action":12,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[22,23,39,44,46,47,53,59],"ai":[3,11,14,16,20,21,29,41]},"scoresAfter":[-8,-86]},{"ply":35,"player":"human","action":0,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[22,23,39,44,46,47,53,59],"ai":[3,14,16,20,21,29,41,48]},"scoresAfter":[1,-86]},{"ply":36,"player":"ai","action":12,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[0,23,39,44,46,47,53,59],"ai":[3,14,16,20,21,29,41,48]},"scoresAfter":[1,-106]},{"ply":37,"player":"human","action":12,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[0,23,39,44,46,47,53,59],"ai":[3,16,20,21,29,41,48,50]},"scoresAfter":[11,-106]},{"ply":38,"player":"ai","action":58,"playedCard":29,"placeType":"discard","drawSource":"discard_3","drawnCard":37,"handsBefore":{"human":[0,39,44,45,46,47,53,59],"ai":[3,16,20,21,29,41,48,50]},"scoresAfter":[11,-106]},{"ply":39,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[0,39,44,45,46,47,53,59],"ai":[3,16,20,21,37,41,48,50]},"scoresAfter":[21,-106]},{"ply":40,"player":"ai","action":15,"playedCard":16,"placeType":"play","drawSource":"discard_2","drawnCard":29,"handsBefore":{"human":[0,19,39,44,45,46,47,53],"ai":[3,16,20,21,37,41,48,50]},"scoresAfter":[21,-94]},{"ply":41,"player":"human","action":24,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[0,19,39,44,45,46,47,53],"ai":[3,20,21,29,37,41,48,50]},"scoresAfter":[25,-94]},{"ply":42,"player":"ai","action":42,"playedCard":29,"placeType":"discard","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[0,19,27,44,45,46,47,53],"ai":[3,20,21,29,37,41,48,50]},"scoresAfter":[25,-94]},{"ply":43,"player":"human","action":36,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[0,19,27,44,45,46,47,53],"ai":[3,5,20,21,37,41,48,50]},"scoresAfter":[39,-94]},{"ply":44,"player":"ai","action":81,"playedCard":48,"placeType":"discard","drawSource":"discard_2","drawnCard":29,"handsBefore":{"human":[0,19,27,45,46,47,51,53],"ai":[3,5,20,21,37,41,48,50]},"scoresAfter":[39,-94]},{"ply":45,"player":"human","action":36,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[0,19,27,45,46,47,51,53],"ai":[3,5,20,21,29,37,41,50]},"scoresAfter":[55,-94]},{"ply":46,"player":"ai","action":24,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[0,19,27,30,46,47,51,53],"ai":[3,5,20,21,29,37,41,50]},"scoresAfter":[55,-66]},{"ply":47,"player":"human","action":48,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[0,19,27,30,46,47,51,53],"ai":[3,5,21,29,37,40,41,50]},"scoresAfter":[73,-66]},{"ply":48,"player":"ai","action":24,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[0,15,19,27,30,47,51,53],"ai":[3,5,21,29,37,40,41,50]},"scoresAfter":[73,-34]},{"ply":49,"player":"human","action":60,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[0,15,19,27,30,47,51,53],"ai":[3,5,29,37,40,41,50,58]},"scoresAfter":[93,-34]},{"ply":50,"player":"ai","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[0,1,15,19,27,30,51,53],"ai":[3,5,29,37,40,41,50,58]},"scoresAfter":[93,-25]}],"finalScores":[93,-25],"outcome":"YOU WIN","finalState":{"deckOrder":[34,52,24,59,35,32,18,36,2,47,20,16,21,54,55,4,56,12,37,13,25,9,6,14,28,17,42,31,10,57,7,23,33,22,49,38,44,3,8,26,39,41,11,46,29,53,48,0,50,45,19,27,5,51,30,40,15,58,1,43],"drawPtr":60,"cardLoc":[1,1,5,2,4,2,5,5,5,4,4,4,4,4,4,1,4,3,3,1,4,4,3,3,3,3,5,1,3,2,1,3,3,4,3,3,5,2,3,3,2,2,4,2,3,3,3,3,5,5,2,1,3,1,4,4,3,3,4,3],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[0,10,10,10,10],[10,8,8,5,9]],"colHandshakes":[[0,0,2,1,0],[0,3,0,0,0]],"colLength":[[0,4,7,6,4],[4,6,1,1,3]],"piles":[[2,7,6,8],[],[26],[36],[49,48]],"toMove":0,"stepCount":50,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"9d2d40d4-1200-4c0f-a2d7-21967f29d7e4","seed":"nz2z3m","startedAt":"2026-07-14T17:43:27.107Z","finishedAt":"2026-07-14T17:46:02.145Z","initialDeckOrder":[36,56,6,17,38,51,2,54,33,15,40,41,19,49,35,12,0,44,20,28,57,48,8,14,21,29,24,34,52,31,30,27,46,3,45,22,50,18,53,10,13,39,43,9,16,4,37,7,5,42,32,47,26,55,25,1,58,11,23,59],"moves":[{"ply":1,"player":"human","action":42,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[2,6,17,36,38,51,54,56],"ai":[12,15,19,33,35,40,41,49]},"scoresAfter":[0,0]},{"ply":2,"player":"ai","action":18,"playedCard":15,"placeType":"discard","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[0,2,6,17,38,51,54,56],"ai":[12,15,19,33,35,40,41,49]},"scoresAfter":[0,0]},{"ply":3,"player":"human","action":54,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[0,2,6,17,38,51,54,56],"ai":[12,19,33,35,40,41,44,49]},"scoresAfter":[0,0]},{"ply":4,"player":"ai","action":0,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[0,2,6,17,20,51,54,56],"ai":[12,19,33,35,40,41,44,49]},"scoresAfter":[0,-40]},{"ply":5,"player":"human","action":2,"playedCard":0,"placeType":"play","drawSource":"discard_1","drawnCard":15,"handsBefore":{"human":[0,2,6,17,20,51,54,56],"ai":[19,28,33,35,40,41,44,49]},"scoresAfter":[-40,-40]},{"ply":6,"player":"ai","action":48,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[2,6,15,17,20,51,54,56],"ai":[19,28,33,35,40,41,44,49]},"scoresAfter":[-40,-57]},{"ply":7,"player":"human","action":24,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[2,6,15,17,20,51,54,56],"ai":[19,28,33,35,41,44,49,57]},"scoresAfter":[-58,-57]},{"ply":8,"player":"ai","action":48,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[2,6,17,20,48,51,54,56],"ai":[19,28,33,35,41,44,49,57]},"scoresAfter":[-58,-53]},{"ply":9,"player":"human","action":24,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[2,6,17,20,48,51,54,56],"ai":[8,19,28,33,35,44,49,57]},"scoresAfter":[-54,-53]},{"ply":10,"player":"ai","action":72,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[2,6,14,20,48,51,54,56],"ai":[8,19,28,33,35,44,49,57]},"scoresAfter":[-54,-93]},{"ply":11,"player":"human","action":30,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[2,6,14,20,48,51,54,56],"ai":[8,19,21,28,33,35,44,57]},"scoresAfter":[-54,-93]},{"ply":12,"player":"ai","action":12,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[2,6,20,29,48,51,54,56],"ai":[8,19,21,28,33,35,44,57]},"scoresAfter":[-54,-81]},{"ply":13,"player":"human","action":0,"playedCard":2,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[2,6,20,29,48,51,54,56],"ai":[8,21,24,28,33,35,44,57]},"scoresAfter":[-74,-81]},{"ply":14,"player":"ai","action":12,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[6,20,29,34,48,51,54,56],"ai":[8,21,24,28,33,35,44,57]},"scoresAfter":[-74,-65]},{"ply":15,"player":"human","action":48,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[6,20,29,34,48,51,54,56],"ai":[8,24,28,33,35,44,52,57]},"scoresAfter":[-114,-65]},{"ply":16,"player":"ai","action":12,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[6,20,29,31,34,51,54,56],"ai":[8,24,28,33,35,44,52,57]},"scoresAfter":[-114,-105]},{"ply":17,"player":"human","action":60,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[6,20,29,31,34,51,54,56],"ai":[8,28,30,33,35,44,52,57]},"scoresAfter":[-110,-105]},{"ply":18,"player":"ai","action":72,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[6,20,27,29,31,34,54,56],"ai":[8,28,30,33,35,44,52,57]},"scoresAfter":[-110,-99]},{"ply":19,"player":"human","action":24,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[6,20,27,29,31,34,54,56],"ai":[8,28,30,33,35,44,46,57]},"scoresAfter":[-128,-99]},{"ply":20,"player":"ai","action":60,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[3,6,20,29,31,34,54,56],"ai":[8,28,30,33,35,44,46,57]},"scoresAfter":[-128,-92]},{"ply":21,"player":"human","action":36,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[3,6,20,29,31,34,54,56],"ai":[8,28,30,33,35,45,46,57]},"scoresAfter":[-124,-92]},{"ply":22,"player":"ai","action":60,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[3,6,20,22,31,34,54,56],"ai":[8,28,30,33,35,45,46,57]},"scoresAfter":[-124,-84]},{"ply":23,"player":"human","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[3,6,20,22,31,34,54,56],"ai":[8,28,30,33,35,46,50,57]},"scoresAfter":[-118,-84]},{"ply":24,"player":"ai","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[6,18,20,22,31,34,54,56],"ai":[8,28,30,33,35,46,50,57]},"scoresAfter":[-118,-97]},{"ply":25,"player":"human","action":12,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[6,18,20,22,31,34,54,56],"ai":[28,30,33,35,46,50,53,57]},"scoresAfter":[-113,-97]},{"ply":26,"player":"ai","action":48,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[6,10,20,22,31,34,54,56],"ai":[28,30,33,35,46,50,53,57]},"scoresAfter":[-113,-88]},{"ply":27,"player":"human","action":24,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[6,10,20,22,31,34,54,56],"ai":[13,28,30,33,35,50,53,57]},"scoresAfter":[-106,-88]},{"ply":28,"player":"ai","action":72,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[6,10,22,31,34,39,54,56],"ai":[13,28,30,33,35,50,53,57]},"scoresAfter":[-106,-80]},{"ply":29,"player":"human","action":24,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[6,10,22,31,34,39,54,56],"ai":[13,28,30,33,35,43,50,57]},"scoresAfter":[-97,-80]},{"ply":30,"player":"ai","action":66,"playedCard":43,"placeType":"discard","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[6,9,10,31,34,39,54,56],"ai":[13,28,30,33,35,43,50,57]},"scoresAfter":[-97,-80]},{"ply":31,"player":"human","action":72,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[6,9,10,31,34,39,54,56],"ai":[13,16,28,30,33,35,50,57]},"scoresAfter":[-87,-80]},{"ply":32,"player":"ai","action":84,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[4,6,9,10,31,34,39,56],"ai":[13,16,28,30,33,35,50,57]},"scoresAfter":[-87,-64]},{"ply":33,"player":"human","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[4,6,9,10,31,34,39,56],"ai":[13,16,28,30,33,35,37,50]},"scoresAfter":[-78,-64]},{"ply":34,"player":"ai","action":24,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[6,7,9,10,31,34,39,56],"ai":[13,16,28,30,33,35,37,50]},"scoresAfter":[-78,-58]},{"ply":35,"player":"human","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[6,7,9,10,31,34,39,56],"ai":[5,13,16,30,33,35,37,50]},"scoresAfter":[-63,-58]},{"ply":36,"player":"ai","action":6,"playedCard":5,"placeType":"discard","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[7,9,10,31,34,39,42,56],"ai":[5,13,16,30,33,35,37,50]},"scoresAfter":[-63,-58]},{"ply":37,"player":"human","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[7,9,10,31,34,39,42,56],"ai":[13,16,30,32,33,35,37,50]},"scoresAfter":[-45,-58]},{"ply":38,"player":"ai","action":24,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[9,10,31,34,39,42,47,56],"ai":[13,16,30,32,33,35,37,50]},"scoresAfter":[-45,-48]},{"ply":39,"player":"human","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[9,10,31,34,39,42,47,56],"ai":[13,16,26,32,33,35,37,50]},"scoresAfter":[-21,-48]},{"ply":40,"player":"ai","action":36,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[10,31,34,39,42,47,55,56],"ai":[13,16,26,32,33,35,37,50]},"scoresAfter":[-21,-34]},{"ply":41,"player":"human","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[10,31,34,39,42,47,55,56],"ai":[13,16,25,26,33,35,37,50]},"scoresAfter":[26,-34]},{"ply":42,"player":"ai","action":48,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[1,31,34,39,42,47,55,56],"ai":[13,16,25,26,33,35,37,50]},"scoresAfter":[26,-18]},{"ply":43,"player":"human","action":12,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[1,31,34,39,42,47,55,56],"ai":[13,16,25,26,35,37,50,58]},"scoresAfter":[32,-18]},{"ply":44,"player":"ai","action":48,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[1,11,34,39,42,47,55,56],"ai":[13,16,25,26,35,37,50,58]},"scoresAfter":[32,2]},{"ply":45,"player":"human","action":12,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[1,11,34,39,42,47,55,56],"ai":[13,16,23,25,26,37,50,58]},"scoresAfter":[62,2]}],"finalScores":[62,2],"outcome":"YOU WIN","finalState":{"deckOrder":[36,56,6,17,38,51,2,54,33,15,40,41,19,49,35,12,0,44,20,28,57,48,8,14,21,29,24,34,52,31,30,27,46,3,45,22,50,18,53,10,13,39,43,9,16,4,37,7,5,42,32,47,26,55,25,1,58,11,23,59],"drawPtr":60,"cardLoc":[3,1,3,3,3,5,3,3,4,3,3,3,4,2,5,3,2,3,3,4,3,4,3,2,4,2,2,3,4,3,4,3,4,4,1,4,5,2,5,1,4,4,1,5,4,4,4,1,3,4,2,3,4,4,3,1,1,4,2,1],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,9,6,0,5],[7,8,10,9,8]],"colHandshakes":[[2,0,0,0,1],[0,1,1,0,1]],"colLength":[[9,5,3,0,3],[1,3,6,5,4]],"piles":[[5],[14],[],[36,38,43],[]],"toMove":1,"stepCount":45,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"e6f10e41-3224-4d03-b806-06c08ec86c28","seed":"8tlbo8","startedAt":"2026-07-14T17:46:02.960Z","finishedAt":"2026-07-14T17:47:29.880Z","initialDeckOrder":[30,16,56,18,51,59,17,23,43,0,27,38,32,39,14,44,54,52,41,37,42,45,8,49,36,48,11,9,19,31,4,3,47,6,29,58,34,46,40,26,1,33,20,12,35,22,53,50,10,5,13,24,28,15,2,7,25,21,57,55],"moves":[{"ply":1,"player":"human","action":0,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[16,17,18,23,30,51,56,59],"ai":[0,14,27,32,38,39,43,44]},"scoresAfter":[-17,0]},{"ply":2,"player":"ai","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[17,18,23,30,51,54,56,59],"ai":[0,14,27,32,38,39,43,44]},"scoresAfter":[-17,0]},{"ply":3,"player":"human","action":0,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[17,18,23,30,51,54,56,59],"ai":[14,27,32,38,39,43,44,52]},"scoresAfter":[-13,0]},{"ply":4,"player":"ai","action":6,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[18,23,30,41,51,54,56,59],"ai":[14,27,32,38,39,43,44,52]},"scoresAfter":[-13,0]},{"ply":5,"player":"human","action":0,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[18,23,30,41,51,54,56,59],"ai":[27,32,37,38,39,43,44,52]},"scoresAfter":[-8,0]},{"ply":6,"player":"ai","action":36,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[23,30,41,42,51,54,56,59],"ai":[27,32,37,38,39,43,44,52]},"scoresAfter":[-8,-40]},{"ply":7,"player":"human","action":48,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[23,30,41,42,51,54,56,59],"ai":[27,32,37,39,43,44,45,52]},"scoresAfter":[-26,-40]},{"ply":8,"player":"ai","action":0,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[8,23,30,41,42,54,56,59],"ai":[27,32,37,39,43,44,45,52]},"scoresAfter":[-26,-58]},{"ply":9,"player":"human","action":60,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[8,23,30,41,42,54,56,59],"ai":[32,37,39,43,44,45,49,52]},"scoresAfter":[-21,-58]},{"ply":10,"player":"ai","action":90,"playedCard":52,"placeType":"discard","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[8,23,30,36,41,42,56,59],"ai":[32,37,39,43,44,45,49,52]},"scoresAfter":[-21,-58]},{"ply":11,"player":"human","action":36,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[8,23,30,36,41,42,56,59],"ai":[32,37,39,43,44,45,48,49]},"scoresAfter":[-61,-58]},{"ply":12,"player":"ai","action":90,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[8,11,23,30,41,42,56,59],"ai":[32,37,39,43,44,45,48,49]},"scoresAfter":[-61,-58]},{"ply":13,"player":"human","action":73,"playedCard":56,"placeType":"play","drawSource":"discard_0","drawnCard":0,"handsBefore":{"human":[8,11,23,30,41,42,56,59],"ai":[9,32,37,39,43,44,45,48]},"scoresAfter":[-54,-58]},{"ply":14,"player":"ai","action":90,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[0,8,11,23,30,41,42,59],"ai":[9,32,37,39,43,44,45,48]},"scoresAfter":[-54,-58]},{"ply":15,"player":"human","action":0,"playedCard":0,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[0,8,11,23,30,41,42,59],"ai":[9,19,32,37,39,43,44,45]},"scoresAfter":[-94,-58]},{"ply":16,"player":"ai","action":24,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[8,11,23,30,31,41,42,59],"ai":[9,19,32,37,39,43,44,45]},"scoresAfter":[-94,-51]},{"ply":17,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[8,11,23,30,31,41,42,59],"ai":[4,9,19,37,39,43,44,45]},"scoresAfter":[-84,-51]},{"ply":18,"player":"ai","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[3,8,11,23,30,31,41,42],"ai":[4,9,19,37,39,43,44,45]},"scoresAfter":[-84,-68]},{"ply":19,"player":"human","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[3,8,11,23,30,31,41,42],"ai":[9,19,37,39,43,44,45,47]},"scoresAfter":[-80,-68]},{"ply":20,"player":"ai","action":12,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[6,8,11,23,30,31,41,42],"ai":[9,19,37,39,43,44,45,47]},"scoresAfter":[-80,-82]},{"ply":21,"player":"human","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[6,8,11,23,30,31,41,42],"ai":[9,29,37,39,43,44,45,47]},"scoresAfter":[-70,-82]},{"ply":22,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[8,11,23,30,31,41,42,58],"ai":[9,29,37,39,43,44,45,47]},"scoresAfter":[-70,-74]},{"ply":23,"player":"human","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[8,11,23,30,31,41,42,58],"ai":[29,34,37,39,43,44,45,47]},"scoresAfter":[-56,-74]},{"ply":24,"player":"ai","action":12,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[11,23,30,31,41,42,46,58],"ai":[29,34,37,39,43,44,45,47]},"scoresAfter":[-56,-65]},{"ply":25,"player":"human","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[11,23,30,31,41,42,46,58],"ai":[29,37,39,40,43,44,45,47]},"scoresAfter":[-36,-65]},{"ply":26,"player":"ai","action":12,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[23,26,30,31,41,42,46,58],"ai":[29,37,39,40,43,44,45,47]},"scoresAfter":[-36,-85]},{"ply":27,"player":"human","action":12,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[23,26,30,31,41,42,46,58],"ai":[1,29,39,40,43,44,45,47]},"scoresAfter":[-76,-85]},{"ply":28,"player":"ai","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[23,30,31,33,41,42,46,58],"ai":[1,29,39,40,43,44,45,47]},"scoresAfter":[-76,-85]},{"ply":29,"player":"human","action":12,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[23,30,31,33,41,42,46,58],"ai":[20,29,39,40,43,44,45,47]},"scoresAfter":[-66,-85]},{"ply":30,"player":"ai","action":0,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[12,23,31,33,41,42,46,58],"ai":[20,29,39,40,43,44,45,47]},"scoresAfter":[-66,-78]},{"ply":31,"player":"human","action":24,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[12,23,31,33,41,42,46,58],"ai":[29,35,39,40,43,44,45,47]},"scoresAfter":[-54,-78]},{"ply":32,"player":"ai","action":12,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[12,22,23,33,41,42,46,58],"ai":[29,35,39,40,43,44,45,47]},"scoresAfter":[-54,-68]},{"ply":33,"player":"human","action":12,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[12,22,23,33,41,42,46,58],"ai":[29,39,40,43,44,45,47,53]},"scoresAfter":[-45,-68]},{"ply":34,"player":"ai","action":12,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[12,23,33,41,42,46,50,58],"ai":[29,39,40,43,44,45,47,53]},"scoresAfter":[-45,-62]},{"ply":35,"player":"human","action":12,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[12,23,33,41,42,46,50,58],"ai":[10,29,40,43,44,45,47,53]},"scoresAfter":[-35,-62]},{"ply":36,"player":"ai","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[5,12,33,41,42,46,50,58],"ai":[10,29,40,43,44,45,47,53]},"scoresAfter":[-35,-53]},{"ply":37,"player":"human","action":24,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[5,12,33,41,42,46,50,58],"ai":[13,29,40,43,44,45,47,53]},"scoresAfter":[-19,-53]},{"ply":38,"player":"ai","action":24,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[5,12,24,41,42,46,50,58],"ai":[13,29,40,43,44,45,47,53]},"scoresAfter":[-19,-44]},{"ply":39,"player":"human","action":36,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[5,12,24,41,42,46,50,58],"ai":[13,28,29,43,44,45,47,53]},"scoresAfter":[-11,-44]},{"ply":40,"player":"ai","action":36,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[5,12,15,24,42,46,50,58],"ai":[13,28,29,43,44,45,47,53]},"scoresAfter":[-11,-26]},{"ply":41,"player":"human","action":48,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[5,12,15,24,42,46,50,58],"ai":[2,13,28,29,44,45,47,53]},"scoresAfter":[-1,-26]},{"ply":42,"player":"ai","action":48,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[5,7,12,15,24,46,50,58],"ai":[2,13,28,29,44,45,47,53]},"scoresAfter":[-1,-5]},{"ply":43,"player":"human","action":54,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[5,7,12,15,24,46,50,58],"ai":[2,13,25,28,29,45,47,53]},"scoresAfter":[-1,-5]},{"ply":44,"player":"ai","action":65,"playedCard":45,"placeType":"play","drawSource":"discard_4","drawnCard":48,"handsBefore":{"human":[5,7,12,15,21,46,50,58],"ai":[2,13,25,28,29,45,47,53]},"scoresAfter":[-1,19]},{"ply":45,"player":"human","action":60,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[5,7,12,15,21,46,50,58],"ai":[2,13,25,28,29,47,48,53]},"scoresAfter":[17,19]},{"ply":46,"player":"ai","action":60,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[5,7,12,15,21,50,57,58],"ai":[2,13,25,28,29,47,48,53]},"scoresAfter":[17,69]}],"finalScores":[17,69],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[30,16,56,18,51,59,17,23,43,0,27,38,32,39,14,44,54,52,41,37,42,45,8,49,36,48,11,9,19,31,4,3,47,6,29,58,34,46,40,26,1,33,20,12,35,22,53,50,10,5,13,24,28,15,2,7,25,21,57,55],"drawPtr":60,"cardLoc":[3,5,2,3,4,1,3,1,3,4,4,3,1,2,5,1,3,3,3,4,4,1,3,3,5,2,3,4,2,2,3,3,4,3,4,4,3,4,4,4,4,3,3,4,4,4,3,4,2,5,1,3,5,2,3,2,3,1,1,3],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,10,8,9,10],[9,7,10,10,0]],"colHandshakes":[[1,0,1,1,0],[0,0,0,2,0]],"colLength":[[5,5,4,4,4],[3,2,4,8,0]],"piles":[[1],[14],[24],[],[52,49]],"toMove":0,"stepCount":46,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"732abaee-b640-48ee-bb43-78af0a3b3bbd","seed":"1ezfqf","startedAt":"2026-07-14T17:47:30.965Z","finishedAt":"2026-07-14T17:49:22.524Z","initialDeckOrder":[7,10,5,3,49,25,2,59,20,34,58,27,6,57,1,42,37,21,50,23,19,48,8,14,47,24,46,38,30,0,54,16,4,22,51,12,43,39,28,53,15,33,45,32,44,40,35,55,36,9,41,31,56,52,11,26,13,29,18,17],"moves":[{"ply":1,"player":"human","action":0,"playedCard":2,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[2,3,5,7,10,25,49,59],"ai":[1,6,20,27,34,42,57,58]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":12,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[3,5,7,10,25,37,49,59],"ai":[1,6,20,27,34,42,57,58]},"scoresAfter":[-40,-15]},{"ply":3,"player":"human","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[3,5,7,10,25,37,49,59],"ai":[1,20,21,27,34,42,57,58]},"scoresAfter":[-36,-15]},{"ply":4,"player":"ai","action":60,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[5,7,10,25,37,49,50,59],"ai":[1,20,21,27,34,42,57,58]},"scoresAfter":[-36,-30]},{"ply":5,"player":"human","action":60,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[5,7,10,25,37,49,50,59],"ai":[1,20,21,23,27,34,57,58]},"scoresAfter":[-76,-30]},{"ply":6,"player":"ai","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[5,7,10,19,25,37,50,59],"ai":[1,20,21,23,27,34,57,58]},"scoresAfter":[-76,-30]},{"ply":7,"player":"human","action":72,"playedCard":50,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[5,7,10,19,25,37,50,59],"ai":[20,21,23,27,34,48,57,58]},"scoresAfter":[-96,-30]},{"ply":8,"player":"ai","action":60,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[5,7,8,10,19,25,37,59],"ai":[20,21,23,27,34,48,57,58]},"scoresAfter":[-96,-70]},{"ply":9,"player":"human","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[5,7,8,10,19,25,37,59],"ai":[14,20,21,23,27,34,57,58]},"scoresAfter":[-88,-70]},{"ply":10,"player":"ai","action":0,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[7,8,10,19,25,37,47,59],"ai":[14,20,21,23,27,34,57,58]},"scoresAfter":[-88,-110]},{"ply":11,"player":"human","action":60,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[7,8,10,19,25,37,47,59],"ai":[20,21,23,24,27,34,57,58]},"scoresAfter":[-128,-110]},{"ply":12,"player":"ai","action":36,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[7,8,10,19,25,46,47,59],"ai":[20,21,23,24,27,34,57,58]},"scoresAfter":[-128,-150]},{"ply":13,"player":"human","action":54,"playedCard":25,"placeType":"discard","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[7,8,10,19,25,46,47,59],"ai":[20,21,23,27,34,38,57,58]},"scoresAfter":[-128,-150]},{"ply":14,"player":"ai","action":66,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[7,8,10,19,30,46,47,59],"ai":[20,21,23,27,34,38,57,58]},"scoresAfter":[-128,-150]},{"ply":15,"player":"human","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[7,8,10,19,30,46,47,59],"ai":[0,20,21,23,27,34,57,58]},"scoresAfter":[-116,-150]},{"ply":16,"player":"ai","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[8,10,19,30,46,47,54,59],"ai":[0,20,21,23,27,34,57,58]},"scoresAfter":[-116,-150]},{"ply":17,"player":"human","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[8,10,19,30,46,47,54,59],"ai":[16,20,21,23,27,34,57,58]},"scoresAfter":[-102,-150]},{"ply":18,"player":"ai","action":48,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[4,10,19,30,46,47,54,59],"ai":[16,20,21,23,27,34,57,58]},"scoresAfter":[-102,-146]},{"ply":19,"player":"human","action":12,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[4,10,19,30,46,47,54,59],"ai":[16,20,21,22,23,34,57,58]},"scoresAfter":[-84,-146]},{"ply":20,"player":"ai","action":0,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[4,19,30,46,47,51,54,59],"ai":[16,20,21,22,23,34,57,58]},"scoresAfter":[-84,-140]},{"ply":21,"player":"human","action":60,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[4,19,30,46,47,51,54,59],"ai":[12,20,21,22,23,34,57,58]},"scoresAfter":[-78,-140]},{"ply":22,"player":"ai","action":6,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[4,19,30,43,46,47,54,59],"ai":[12,20,21,22,23,34,57,58]},"scoresAfter":[-78,-140]},{"ply":23,"player":"human","action":10,"playedCard":4,"placeType":"discard","drawSource":"discard_3","drawnCard":38,"handsBefore":{"human":[4,19,30,43,46,47,54,59],"ai":[20,21,22,23,34,39,57,58]},"scoresAfter":[-78,-140]},{"ply":24,"player":"ai","action":74,"playedCard":57,"placeType":"play","drawSource":"discard_1","drawnCard":12,"handsBefore":{"human":[19,30,38,43,46,47,54,59],"ai":[20,21,22,23,34,39,57,58]},"scoresAfter":[-78,-124]},{"ply":25,"player":"human","action":24,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[19,30,38,43,46,47,54,59],"ai":[12,20,21,22,23,34,39,58]},"scoresAfter":[-98,-124]},{"ply":26,"player":"ai","action":60,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[19,28,30,43,46,47,54,59],"ai":[12,20,21,22,23,34,39,58]},"scoresAfter":[-98,-106]},{"ply":27,"player":"human","action":18,"playedCard":28,"placeType":"discard","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[19,28,30,43,46,47,54,59],"ai":[12,20,21,22,23,39,53,58]},"scoresAfter":[-98,-106]},{"ply":28,"player":"ai","action":66,"playedCard":39,"placeType":"discard","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[15,19,30,43,46,47,54,59],"ai":[12,20,21,22,23,39,53,58]},"scoresAfter":[-98,-106]},{"ply":29,"player":"human","action":6,"playedCard":15,"placeType":"discard","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[15,19,30,43,46,47,54,59],"ai":[12,20,21,22,23,33,53,58]},"scoresAfter":[-98,-106]},{"ply":30,"player":"ai","action":12,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[19,30,43,45,46,47,54,59],"ai":[12,20,21,22,23,33,53,58]},"scoresAfter":[-98,-92]},{"ply":31,"player":"human","action":10,"playedCard":19,"placeType":"discard","drawSource":"discard_3","drawnCard":39,"handsBefore":{"human":[19,30,43,45,46,47,54,59],"ai":[12,21,22,23,32,33,53,58]},"scoresAfter":[-98,-92]},{"ply":32,"player":"ai","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[30,39,43,45,46,47,54,59],"ai":[12,21,22,23,32,33,53,58]},"scoresAfter":[-98,-74]},{"ply":33,"player":"human","action":12,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[30,39,43,45,46,47,54,59],"ai":[12,21,22,23,32,33,44,53]},"scoresAfter":[-92,-74]},{"ply":34,"player":"ai","action":74,"playedCard":44,"placeType":"play","drawSource":"discard_1","drawnCard":19,"handsBefore":{"human":[30,40,43,45,46,47,54,59],"ai":[12,21,22,23,32,33,44,53]},"scoresAfter":[-92,-67]},{"ply":35,"player":"human","action":12,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[30,40,43,45,46,47,54,59],"ai":[12,19,21,22,23,32,33,53]},"scoresAfter":[-83,-67]},{"ply":36,"player":"ai","action":6,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[30,35,43,45,46,47,54,59],"ai":[12,19,21,22,23,32,33,53]},"scoresAfter":[-83,-67]},{"ply":37,"player":"human","action":24,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[30,35,43,45,46,47,54,59],"ai":[19,21,22,23,32,33,53,55]},"scoresAfter":[-65,-67]},{"ply":38,"player":"ai","action":12,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[30,35,36,45,46,47,54,59],"ai":[19,21,22,23,32,33,53,55]},"scoresAfter":[-65,-51]},{"ply":39,"player":"human","action":36,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[30,35,36,45,46,47,54,59],"ai":[9,19,22,23,32,33,53,55]},"scoresAfter":[-41,-51]},{"ply":40,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[30,35,36,41,46,47,54,59],"ai":[9,19,22,23,32,33,53,55]},"scoresAfter":[-41,-43]},{"ply":41,"player":"human","action":48,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[30,35,36,41,46,47,54,59],"ai":[19,22,23,31,32,33,53,55]},"scoresAfter":[-14,-43]},{"ply":42,"player":"ai","action":12,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[30,35,36,41,47,54,56,59],"ai":[19,22,23,31,32,33,53,55]},"scoresAfter":[-14,-25]},{"ply":43,"player":"human","action":48,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[30,35,36,41,47,54,56,59],"ai":[19,23,31,32,33,52,53,55]},"scoresAfter":[36,-25]},{"ply":44,"player":"ai","action":12,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[11,30,35,36,41,54,56,59],"ai":[19,23,31,32,33,52,53,55]},"scoresAfter":[36,-5]},{"ply":45,"player":"human","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[11,30,35,36,41,54,56,59],"ai":[19,26,31,32,33,52,53,55]},"scoresAfter":[56,-5]},{"ply":46,"player":"ai","action":18,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[13,30,35,36,41,54,56,59],"ai":[19,26,31,32,33,52,53,55]},"scoresAfter":[56,-5]},{"ply":47,"player":"human","action":63,"playedCard":54,"placeType":"play","drawSource":"discard_2","drawnCard":26,"handsBefore":{"human":[13,30,35,36,41,54,56,59],"ai":[19,29,31,32,33,52,53,55]},"scoresAfter":[71,-5]},{"ply":48,"player":"ai","action":18,"playedCard":29,"placeType":"discard","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[13,26,30,35,36,41,56,59],"ai":[19,29,31,32,33,52,53,55]},"scoresAfter":[71,-5]},{"ply":49,"player":"human","action":75,"playedCard":56,"placeType":"play","drawSource":"discard_2","drawnCard":29,"handsBefore":{"human":[13,26,30,35,36,41,56,59],"ai":[18,19,31,32,33,52,53,55]},"scoresAfter":[92,-5]},{"ply":50,"player":"ai","action":69,"playedCard":52,"placeType":"discard","drawSource":"discard_2","drawnCard":28,"handsBefore":{"human":[13,26,29,30,35,36,41,59],"ai":[18,19,31,32,33,52,53,55]},"scoresAfter":[92,-5]},{"ply":51,"player":"human","action":89,"playedCard":59,"placeType":"play","drawSource":"discard_4","drawnCard":52,"handsBefore":{"human":[13,26,29,30,35,36,41,59],"ai":[18,19,28,31,32,33,53,55]},"scoresAfter":[122,-5]},{"ply":52,"player":"ai","action":92,"playedCard":55,"placeType":"discard","drawSource":"discard_1","drawnCard":12,"handsBefore":{"human":[13,26,29,30,35,36,41,52],"ai":[18,19,28,31,32,33,53,55]},"scoresAfter":[122,-5]},{"ply":53,"player":"human","action":90,"playedCard":52,"placeType":"discard","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[13,26,29,30,35,36,41,52],"ai":[12,18,19,28,31,32,33,53]},"scoresAfter":[122,-5]}],"finalScores":[122,-5],"outcome":"YOU WIN","finalState":{"deckOrder":[7,10,5,3,49,25,2,59,20,34,58,27,6,57,1,42,37,21,50,23,19,48,8,14,47,24,46,38,30,0,54,16,4,22,51,12,43,39,28,53,15,33,45,32,44,40,35,55,36,9,41,31,56,52,11,26,13,29,18,17],"drawPtr":60,"cardLoc":[5,5,3,3,5,3,4,3,3,4,3,3,2,1,4,5,4,1,2,2,4,4,4,4,4,5,1,4,2,1,1,2,2,2,4,1,1,3,3,3,3,1,4,3,4,3,3,3,4,3,3,3,5,2,3,5,3,4,4,3],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,true,false,false,false,false,false,false,true,false,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,0,0,10,10],[8,10,9,7,9]],"colHandshakes":[[1,0,0,2,2],[0,1,1,0,1]],"colLength":[[7,0,0,8,6],[2,6,3,2,3]],"piles":[[1,0,4],[15],[25],[],[55,52]],"toMove":1,"stepCount":53,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"c1cc9467-17ac-466d-b67a-176d684f5468","seed":"zqiawb","startedAt":"2026-07-14T17:49:23.509Z","finishedAt":"2026-07-14T17:51:09.036Z","initialDeckOrder":[40,26,21,37,28,1,30,58,13,15,3,47,48,6,43,19,39,33,0,59,31,53,32,44,45,11,20,46,14,12,49,8,16,17,52,24,25,29,54,56,5,51,22,38,55,36,7,23,2,27,42,4,34,10,18,50,57,9,35,41],"moves":[{"ply":1,"player":"human","action":24,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[1,21,26,28,30,37,40,58],"ai":[3,6,13,15,19,43,47,48]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[1,21,28,30,37,39,40,58],"ai":[3,6,13,15,19,43,47,48]},"scoresAfter":[-40,-18]},{"ply":3,"player":"human","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[1,21,28,30,37,39,40,58],"ai":[6,13,15,19,33,43,47,48]},"scoresAfter":[-40,-18]},{"ply":4,"player":"ai","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[0,21,28,30,37,39,40,58],"ai":[6,13,15,19,33,43,47,48]},"scoresAfter":[-40,-13]},{"ply":5,"player":"human","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[0,21,28,30,37,39,40,58],"ai":[13,15,19,33,43,47,48,59]},"scoresAfter":[-40,-13]},{"ply":6,"player":"ai","action":0,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[21,28,30,31,37,39,40,58],"ai":[13,15,19,33,43,47,48,59]},"scoresAfter":[-40,-53]},{"ply":7,"player":"human","action":12,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[21,28,30,31,37,39,40,58],"ai":[15,19,33,43,47,48,53,59]},"scoresAfter":[-34,-53]},{"ply":8,"player":"ai","action":60,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[21,30,31,32,37,39,40,58],"ai":[15,19,33,43,47,48,53,59]},"scoresAfter":[-34,-93]},{"ply":9,"player":"human","action":12,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[21,30,31,32,37,39,40,58],"ai":[15,19,33,43,44,47,53,59]},"scoresAfter":[-24,-93]},{"ply":10,"player":"ai","action":0,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[21,31,32,37,39,40,45,58],"ai":[15,19,33,43,44,47,53,59]},"scoresAfter":[-24,-89]},{"ply":11,"player":"human","action":36,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[21,31,32,37,39,40,45,58],"ai":[11,19,33,43,44,47,53,59]},"scoresAfter":[-64,-89]},{"ply":12,"player":"ai","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[20,21,31,32,39,40,45,58],"ai":[11,19,33,43,44,47,53,59]},"scoresAfter":[-64,-79]},{"ply":13,"player":"human","action":48,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[20,21,31,32,39,40,45,58],"ai":[19,33,43,44,46,47,53,59]},"scoresAfter":[-60,-79]},{"ply":14,"player":"ai","action":0,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[14,20,21,31,32,40,45,58],"ai":[19,33,43,44,46,47,53,59]},"scoresAfter":[-60,-67]},{"ply":15,"player":"human","action":60,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[14,20,21,31,32,40,45,58],"ai":[12,33,43,44,46,47,53,59]},"scoresAfter":[-54,-67]},{"ply":16,"player":"ai","action":12,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[14,20,21,31,32,45,49,58],"ai":[12,33,43,44,46,47,53,59]},"scoresAfter":[-54,-79]},{"ply":17,"player":"human","action":36,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[14,20,21,31,32,45,49,58],"ai":[8,12,43,44,46,47,53,59]},"scoresAfter":[-42,-79]},{"ply":18,"player":"ai","action":18,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[14,16,20,21,32,45,49,58],"ai":[8,12,43,44,46,47,53,59]},"scoresAfter":[-42,-79]},{"ply":19,"player":"human","action":48,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[14,16,20,21,32,45,49,58],"ai":[8,17,43,44,46,47,53,59]},"scoresAfter":[-28,-79]},{"ply":20,"player":"ai","action":18,"playedCard":17,"placeType":"discard","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[14,16,20,21,45,49,52,58],"ai":[8,17,43,44,46,47,53,59]},"scoresAfter":[-28,-79]},{"ply":21,"player":"human","action":2,"playedCard":14,"placeType":"play","drawSource":"discard_1","drawnCard":17,"handsBefore":{"human":[14,16,20,21,45,49,52,58],"ai":[8,24,43,44,46,47,53,59]},"scoresAfter":[-68,-79]},{"ply":22,"player":"ai","action":18,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[16,17,20,21,45,49,52,58],"ai":[8,24,43,44,46,47,53,59]},"scoresAfter":[-68,-79]},{"ply":23,"player":"human","action":0,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[16,17,20,21,45,49,52,58],"ai":[8,25,43,44,46,47,53,59]},"scoresAfter":[-62,-79]},{"ply":24,"player":"ai","action":18,"playedCard":25,"placeType":"discard","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[17,20,21,29,45,49,52,58],"ai":[8,25,43,44,46,47,53,59]},"scoresAfter":[-62,-79]},{"ply":25,"player":"human","action":0,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[17,20,21,29,45,49,52,58],"ai":[8,43,44,46,47,53,54,59]},"scoresAfter":[-54,-79]},{"ply":26,"player":"ai","action":12,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[20,21,29,45,49,52,56,58],"ai":[8,43,44,46,47,53,54,59]},"scoresAfter":[-54,-93]},{"ply":27,"player":"human","action":48,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[20,21,29,45,49,52,56,58],"ai":[5,8,44,46,47,53,54,59]},"scoresAfter":[-94,-93]},{"ply":28,"player":"ai","action":24,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[20,21,29,45,51,52,56,58],"ai":[5,8,44,46,47,53,54,59]},"scoresAfter":[-94,-86]},{"ply":29,"player":"human","action":48,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[20,21,29,45,51,52,56,58],"ai":[5,8,22,46,47,53,54,59]},"scoresAfter":[-90,-86]},{"ply":30,"player":"ai","action":24,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[20,21,29,38,45,52,56,58],"ai":[5,8,22,46,47,53,54,59]},"scoresAfter":[-90,-68]},{"ply":31,"player":"human","action":60,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[20,21,29,38,45,52,56,58],"ai":[5,8,46,47,53,54,55,59]},"scoresAfter":[-84,-68]},{"ply":32,"player":"ai","action":24,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[20,21,29,36,38,45,56,58],"ai":[5,8,46,47,53,54,55,59]},"scoresAfter":[-84,-59]},{"ply":33,"player":"human","action":0,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[20,21,29,36,38,45,56,58],"ai":[5,7,8,47,53,54,55,59]},"scoresAfter":[-70,-59]},{"ply":34,"player":"ai","action":36,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[21,23,29,36,38,45,56,58],"ai":[5,7,8,47,53,54,55,59]},"scoresAfter":[-70,-49]},{"ply":35,"player":"human","action":0,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[21,23,29,36,38,45,56,58],"ai":[2,5,7,8,53,54,55,59]},"scoresAfter":[-54,-49]},{"ply":36,"player":"ai","action":48,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[23,27,29,36,38,45,56,58],"ai":[2,5,7,8,53,54,55,59]},"scoresAfter":[-54,-41]},{"ply":37,"player":"human","action":0,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[23,27,29,36,38,45,56,58],"ai":[2,5,7,8,42,54,55,59]},"scoresAfter":[-34,-41]},{"ply":38,"player":"ai","action":60,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[4,27,29,36,38,45,56,58],"ai":[2,5,7,8,42,54,55,59]},"scoresAfter":[-34,-31]},{"ply":39,"player":"human","action":72,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[4,27,29,36,38,45,56,58],"ai":[2,5,7,8,34,42,55,59]},"scoresAfter":[-20,-31]},{"ply":40,"player":"ai","action":48,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[4,10,27,29,36,38,45,58],"ai":[2,5,7,8,34,42,55,59]},"scoresAfter":[-20,-22]},{"ply":41,"player":"human","action":72,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[4,10,27,29,36,38,45,58],"ai":[2,5,7,8,18,42,55,59]},"scoresAfter":[-4,-22]},{"ply":42,"player":"ai","action":72,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[4,10,27,29,36,38,50,58],"ai":[2,5,7,8,18,42,55,59]},"scoresAfter":[-4,-10]},{"ply":43,"player":"human","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[4,10,27,29,36,38,50,58],"ai":[2,5,7,8,18,42,57,59]},"scoresAfter":[14,-10]},{"ply":44,"player":"ai","action":74,"playedCard":57,"placeType":"play","drawSource":"discard_1","drawnCard":12,"handsBefore":{"human":[4,9,10,27,29,36,38,50],"ai":[2,5,7,8,18,42,57,59]},"scoresAfter":[14,6]},{"ply":45,"player":"human","action":30,"playedCard":10,"placeType":"discard","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[4,9,10,27,29,36,38,50],"ai":[2,5,7,8,12,18,42,59]},"scoresAfter":[14,6]},{"ply":46,"player":"ai","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[4,9,27,29,35,36,38,50],"ai":[2,5,7,8,12,18,42,59]},"scoresAfter":[14,26]}],"finalScores":[14,26],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[40,26,21,37,28,1,30,58,13,15,3,47,48,6,43,19,39,33,0,59,31,53,32,44,45,11,20,46,14,12,49,8,16,17,52,24,25,29,54,56,5,51,22,38,55,36,7,23,2,27,42,4,34,10,18,50,57,9,35,41],"drawPtr":60,"cardLoc":[5,5,2,4,1,2,4,2,2,1,5,4,2,4,3,4,3,3,2,4,3,3,4,3,5,5,3,1,3,1,3,3,3,4,4,1,1,3,1,3,3,2,2,4,4,3,4,4,4,3,1,3,3,4,4,4,3,4,3,4],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[0,10,7,8,9],[10,9,9,10,10]],"colHandshakes":[[0,1,1,1,1],[0,1,0,0,1]],"colLength":[[0,6,5,4,5],[3,4,2,4,6]],"piles":[[1,0,10],[],[24,25],[],[]],"toMove":0,"stepCount":46,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"bbc8c73f-5de4-48d1-b1bb-35d2d669ef43","seed":"wkfje7","startedAt":"2026-07-14T17:51:10.256Z","finishedAt":"2026-07-14T17:53:57.825Z","initialDeckOrder":[43,22,46,55,27,31,0,10,49,42,36,59,34,54,8,35,26,45,52,53,57,33,17,23,18,7,44,40,48,21,12,47,51,20,24,25,30,11,1,32,16,28,39,15,6,58,41,38,13,37,9,50,14,5,19,29,56,2,3,4],"moves":[{"ply":1,"player":"human","action":0,"playedCard":0,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[0,10,22,27,31,43,46,55],"ai":[8,34,35,36,42,49,54,59]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":60,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[10,22,26,27,31,43,46,55],"ai":[8,34,35,36,42,49,54,59]},"scoresAfter":[-40,-40]},{"ply":3,"player":"human","action":24,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[10,22,26,27,31,43,46,55],"ai":[8,34,35,36,42,45,54,59]},"scoresAfter":[-80,-40]},{"ply":4,"player":"ai","action":36,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[10,22,27,31,43,46,52,55],"ai":[8,34,35,36,42,45,54,59]},"scoresAfter":[-80,-80]},{"ply":5,"player":"human","action":24,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[10,22,27,31,43,46,52,55],"ai":[8,34,35,42,45,53,54,59]},"scoresAfter":[-76,-80]},{"ply":6,"player":"ai","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[10,22,31,43,46,52,55,57],"ai":[8,34,35,42,45,53,54,59]},"scoresAfter":[-76,-93]},{"ply":7,"player":"human","action":60,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[10,22,31,43,46,52,55,57],"ai":[33,34,35,42,45,53,54,59]},"scoresAfter":[-93,-93]},{"ply":8,"player":"ai","action":60,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[10,17,22,31,43,46,55,57],"ai":[33,34,35,42,45,53,54,59]},"scoresAfter":[-93,-85]},{"ply":9,"player":"human","action":12,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[10,17,22,31,43,46,55,57],"ai":[23,33,34,35,42,45,54,59]},"scoresAfter":[-109,-85]},{"ply":10,"player":"ai","action":72,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[10,18,22,31,43,46,55,57],"ai":[23,33,34,35,42,45,54,59]},"scoresAfter":[-109,-75]},{"ply":11,"player":"human","action":12,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[10,18,22,31,43,46,55,57],"ai":[7,23,33,34,35,42,45,59]},"scoresAfter":[-104,-75]},{"ply":12,"player":"ai","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[10,22,31,43,44,46,55,57],"ai":[7,23,33,34,35,42,45,59]},"scoresAfter":[-104,-55]},{"ply":13,"player":"human","action":36,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[10,22,31,43,44,46,55,57],"ai":[7,23,33,34,35,40,42,45]},"scoresAfter":[-118,-55]},{"ply":14,"player":"ai","action":6,"playedCard":7,"placeType":"discard","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[10,22,31,44,46,48,55,57],"ai":[7,23,33,34,35,40,42,45]},"scoresAfter":[-118,-55]},{"ply":15,"player":"human","action":36,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[10,22,31,44,46,48,55,57],"ai":[21,23,33,34,35,40,42,45]},"scoresAfter":[-111,-55]},{"ply":16,"player":"ai","action":60,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[10,12,22,31,46,48,55,57],"ai":[21,23,33,34,35,40,42,45]},"scoresAfter":[-111,-49]},{"ply":17,"player":"human","action":48,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[10,12,22,31,46,48,55,57],"ai":[21,23,33,34,35,42,45,47]},"scoresAfter":[-102,-49]},{"ply":18,"player":"ai","action":60,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[10,12,22,31,48,51,55,57],"ai":[21,23,33,34,35,42,45,47]},"scoresAfter":[-102,-39]},{"ply":19,"player":"human","action":19,"playedCard":12,"placeType":"discard","drawSource":"discard_0","drawnCard":7,"handsBefore":{"human":[10,12,22,31,48,51,55,57],"ai":[20,21,23,33,34,35,45,47]},"scoresAfter":[-102,-39]},{"ply":20,"player":"ai","action":72,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[7,10,22,31,48,51,55,57],"ai":[20,21,23,33,34,35,45,47]},"scoresAfter":[-102,-23]},{"ply":21,"player":"human","action":54,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[7,10,22,31,48,51,55,57],"ai":[20,21,23,24,33,34,35,47]},"scoresAfter":[-102,-23]},{"ply":22,"player":"ai","action":84,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[7,10,22,25,31,51,55,57],"ai":[20,21,23,24,33,34,35,47]},"scoresAfter":[-102,-3]},{"ply":23,"player":"human","action":42,"playedCard":25,"placeType":"discard","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[7,10,22,25,31,51,55,57],"ai":[20,21,23,24,30,33,34,35]},"scoresAfter":[-102,-3]},{"ply":24,"player":"ai","action":3,"playedCard":20,"placeType":"play","drawSource":"discard_2","drawnCard":25,"handsBefore":{"human":[7,10,11,22,31,51,55,57],"ai":[20,21,23,24,30,33,34,35]},"scoresAfter":[-102,-16]},{"ply":25,"player":"human","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[7,10,11,22,31,51,55,57],"ai":[21,23,24,25,30,33,34,35]},"scoresAfter":[-90,-16]},{"ply":26,"player":"ai","action":24,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[1,10,11,22,31,51,55,57],"ai":[21,23,24,25,30,33,34,35]},"scoresAfter":[-90,-56]},{"ply":27,"player":"human","action":12,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[1,10,11,22,31,51,55,57],"ai":[21,23,25,30,32,33,34,35]},"scoresAfter":[-72,-56]},{"ply":28,"player":"ai","action":0,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[1,11,16,22,31,51,55,57],"ai":[21,23,25,30,32,33,34,35]},"scoresAfter":[-72,-48]},{"ply":29,"player":"human","action":12,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[1,11,16,22,31,51,55,57],"ai":[23,25,28,30,32,33,34,35]},"scoresAfter":[-52,-48]},{"ply":30,"player":"ai","action":0,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[1,16,22,31,39,51,55,57],"ai":[23,25,28,30,32,33,34,35]},"scoresAfter":[-52,-38]},{"ply":31,"player":"human","action":72,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[1,16,22,31,39,51,55,57],"ai":[15,25,28,30,32,33,34,35]},"scoresAfter":[-46,-38]},{"ply":32,"player":"ai","action":12,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[1,6,16,22,31,39,51,57],"ai":[15,25,28,30,32,33,34,35]},"scoresAfter":[-46,-58]},{"ply":33,"player":"human","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[1,6,16,22,31,39,51,57],"ai":[15,28,30,32,33,34,35,58]},"scoresAfter":[-46,-58]},{"ply":34,"player":"ai","action":90,"playedCard":58,"placeType":"discard","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[6,16,22,31,39,41,51,57],"ai":[15,28,30,32,33,34,35,58]},"scoresAfter":[-46,-58]},{"ply":35,"player":"human","action":89,"playedCard":57,"placeType":"play","drawSource":"discard_4","drawnCard":58,"handsBefore":{"human":[6,16,22,31,39,41,51,57],"ai":[15,28,30,32,33,34,35,38]},"scoresAfter":[-38,-58]},{"ply":36,"player":"ai","action":12,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[6,16,22,31,39,41,51,58],"ai":[15,28,30,32,33,34,35,38]},"scoresAfter":[-38,-49]},{"ply":37,"player":"human","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[6,16,22,31,39,41,51,58],"ai":[13,15,30,32,33,34,35,38]},"scoresAfter":[-29,-49]},{"ply":38,"player":"ai","action":6,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[6,16,22,31,37,39,41,51],"ai":[13,15,30,32,33,34,35,38]},"scoresAfter":[-29,-49]},{"ply":39,"player":"human","action":36,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[6,16,22,31,37,39,41,51],"ai":[9,15,30,32,33,34,35,38]},"scoresAfter":[-17,-49]},{"ply":40,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[6,16,22,37,39,41,50,51],"ai":[9,15,30,32,33,34,35,38]},"scoresAfter":[-17,-41]},{"ply":41,"player":"human","action":6,"playedCard":6,"placeType":"discard","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[6,16,22,37,39,41,50,51],"ai":[14,15,30,32,33,34,35,38]},"scoresAfter":[-17,-41]},{"ply":42,"player":"ai","action":26,"playedCard":30,"placeType":"play","drawSource":"discard_1","drawnCard":13,"handsBefore":{"human":[5,16,22,37,39,41,50,51],"ai":[14,15,30,32,33,34,35,38]},"scoresAfter":[-17,-26]},{"ply":43,"player":"human","action":6,"playedCard":5,"placeType":"discard","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[5,16,22,37,39,41,50,51],"ai":[13,14,15,32,33,34,35,38]},"scoresAfter":[-17,-26]},{"ply":44,"player":"ai","action":37,"playedCard":32,"placeType":"play","drawSource":"discard_0","drawnCard":5,"handsBefore":{"human":[16,19,22,37,39,41,50,51],"ai":[13,14,15,32,33,34,35,38]},"scoresAfter":[-17,-5]},{"ply":45,"player":"human","action":12,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[16,19,22,37,39,41,50,51],"ai":[5,13,14,15,33,34,35,38]},"scoresAfter":[-11,-5]},{"ply":46,"player":"ai","action":53,"playedCard":33,"placeType":"play","drawSource":"discard_4","drawnCard":48,"handsBefore":{"human":[16,22,29,37,39,41,50,51],"ai":[5,13,14,15,33,34,35,38]},"scoresAfter":[-11,19]},{"ply":47,"player":"human","action":12,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[16,22,29,37,39,41,50,51],"ai":[5,13,14,15,34,35,38,48]},"scoresAfter":[-2,19]},{"ply":48,"player":"ai","action":50,"playedCard":34,"placeType":"play","drawSource":"discard_1","drawnCard":12,"handsBefore":{"human":[16,29,37,39,41,50,51,56],"ai":[5,13,14,15,34,35,38,48]},"scoresAfter":[-2,46]},{"ply":49,"player":"human","action":18,"playedCard":29,"placeType":"discard","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[16,29,37,39,41,50,51,56],"ai":[5,12,13,14,15,35,38,48]},"scoresAfter":[-2,46]},{"ply":50,"player":"ai","action":60,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[2,16,37,39,41,50,51,56],"ai":[5,12,13,14,15,35,38,48]},"scoresAfter":[-2,96]},{"ply":51,"player":"human","action":90,"playedCard":56,"placeType":"discard","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[2,16,37,39,41,50,51,56],"ai":[3,5,12,13,14,15,38,48]},"scoresAfter":[-2,96]}],"finalScores":[-2,96],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[43,22,46,55,27,31,0,10,49,42,36,59,34,54,8,35,26,45,52,53,57,33,17,23,18,7,44,40,48,21,12,47,51,20,24,25,30,11,1,32,16,28,39,15,6,58,41,38,13,37,9,50,14,5,19,29,56,2,3,4],"drawPtr":60,"cardLoc":[3,5,1,2,1,2,5,3,4,4,3,3,2,2,2,2,1,3,3,3,4,4,3,4,4,4,3,3,4,5,4,3,4,4,4,4,4,1,2,1,4,1,4,3,3,4,3,4,2,4,1,1,3,4,4,3,5,3,3,4],"handPublic":[false,false,false,false,false,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,9,6,9,9],[8,10,10,10,10]],"colHandshakes":[[1,0,1,0,0],[0,0,2,1,1]],"colLength":[[4,4,3,3,4],[2,3,8,5,4]],"piles":[[1,6],[],[29],[],[56]],"toMove":1,"stepCount":51,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"93d4ee63-1168-4d78-aae3-65cf5991aa44","seed":"sv8sih","startedAt":"2026-07-14T17:54:05.814Z","finishedAt":"2026-07-14T17:56:13.582Z","initialDeckOrder":[22,30,9,6,36,19,50,42,10,38,3,59,51,40,25,44,34,15,53,55,58,57,8,56,16,28,32,26,29,0,14,37,1,35,49,23,43,47,48,13,21,33,5,31,18,39,12,4,45,24,27,54,17,7,11,41,20,52,2,46],"moves":[{"ply":1,"player":"human","action":90,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[6,9,19,22,30,36,42,50],"ai":[3,10,25,38,40,44,51,59]},"scoresAfter":[0,0]},{"ply":2,"player":"ai","action":36,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[6,9,19,22,30,34,36,42],"ai":[3,10,25,38,40,44,51,59]},"scoresAfter":[0,-40]},{"ply":3,"player":"human","action":78,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[6,9,19,22,30,34,36,42],"ai":[3,10,15,25,40,44,51,59]},"scoresAfter":[0,-40]},{"ply":4,"player":"ai","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[6,9,19,22,30,34,42,53],"ai":[3,10,15,25,40,44,51,59]},"scoresAfter":[0,-58]},{"ply":5,"player":"human","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[6,9,19,22,30,34,42,53],"ai":[10,15,25,40,44,51,55,59]},"scoresAfter":[-15,-58]},{"ply":6,"player":"ai","action":12,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[9,19,22,30,34,42,53,58],"ai":[10,15,25,40,44,51,55,59]},"scoresAfter":[-15,-76]},{"ply":7,"player":"human","action":72,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[9,19,22,30,34,42,53,58],"ai":[10,25,40,44,51,55,57,59]},"scoresAfter":[-31,-76]},{"ply":8,"player":"ai","action":5,"playedCard":10,"placeType":"play","drawSource":"discard_4","drawnCard":50,"handsBefore":{"human":[8,9,19,22,30,34,42,58],"ai":[10,25,40,44,51,55,57,59]},"scoresAfter":[-31,-67]},{"ply":9,"player":"human","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[8,9,19,22,30,34,42,58],"ai":[25,40,44,50,51,55,57,59]},"scoresAfter":[-24,-67]},{"ply":10,"player":"ai","action":24,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[9,19,22,30,34,42,56,58],"ai":[25,40,44,50,51,55,57,59]},"scoresAfter":[-24,-53]},{"ply":11,"player":"human","action":72,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[9,19,22,30,34,42,56,58],"ai":[16,25,40,50,51,55,57,59]},"scoresAfter":[-17,-53]},{"ply":12,"player":"ai","action":0,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[9,19,22,28,30,34,42,58],"ai":[16,25,40,50,51,55,57,59]},"scoresAfter":[-17,-50]},{"ply":13,"player":"human","action":36,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[9,19,22,28,30,34,42,58],"ai":[25,32,40,50,51,55,57,59]},"scoresAfter":[-34,-50]},{"ply":14,"player":"ai","action":0,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[9,19,22,26,30,34,42,58],"ai":[25,32,40,50,51,55,57,59]},"scoresAfter":[-34,-90]},{"ply":15,"player":"human","action":48,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[9,19,22,26,30,34,42,58],"ai":[29,32,40,50,51,55,57,59]},"scoresAfter":[-29,-90]},{"ply":16,"player":"ai","action":0,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[0,9,19,22,26,34,42,58],"ai":[29,32,40,50,51,55,57,59]},"scoresAfter":[-29,-82]},{"ply":17,"player":"human","action":12,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[0,9,19,22,26,34,42,58],"ai":[14,32,40,50,51,55,57,59]},"scoresAfter":[-21,-82]},{"ply":18,"player":"ai","action":12,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[0,19,22,26,34,37,42,58],"ai":[14,32,40,50,51,55,57,59]},"scoresAfter":[-21,-68]},{"ply":19,"player":"human","action":12,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[0,19,22,26,34,37,42,58],"ai":[1,14,40,50,51,55,57,59]},"scoresAfter":[-35,-68]},{"ply":20,"player":"ai","action":36,"playedCard":50,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[0,22,26,34,35,37,42,58],"ai":[1,14,40,50,51,55,57,59]},"scoresAfter":[-35,-108]},{"ply":21,"player":"human","action":36,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[0,22,26,34,35,37,42,58],"ai":[1,14,40,49,51,55,57,59]},"scoresAfter":[-26,-108]},{"ply":22,"player":"ai","action":36,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[0,22,23,26,35,37,42,58],"ai":[1,14,40,49,51,55,57,59]},"scoresAfter":[-26,-128]},{"ply":23,"player":"human","action":48,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[0,22,23,26,35,37,42,58],"ai":[1,14,40,43,51,55,57,59]},"scoresAfter":[-16,-128]},{"ply":24,"player":"ai","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[0,22,23,26,37,42,47,58],"ai":[1,14,40,43,51,55,57,59]},"scoresAfter":[-16,-128]},{"ply":25,"player":"human","action":12,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[0,22,23,26,37,42,47,58],"ai":[14,40,43,48,51,55,57,59]},"scoresAfter":[-7,-128]},{"ply":26,"player":"ai","action":36,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[0,13,23,26,37,42,47,58],"ai":[14,40,43,48,51,55,57,59]},"scoresAfter":[-7,-148]},{"ply":27,"player":"human","action":24,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[0,13,23,26,37,42,47,58],"ai":[14,21,40,43,51,55,57,59]},"scoresAfter":[3,-148]},{"ply":28,"player":"ai","action":12,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[0,13,26,33,37,42,47,58],"ai":[14,21,40,43,51,55,57,59]},"scoresAfter":[3,-140]},{"ply":29,"player":"human","action":52,"playedCard":37,"placeType":"play","drawSource":"discard_3","drawnCard":36,"handsBefore":{"human":[0,13,26,33,37,42,47,58],"ai":[5,14,40,43,51,55,57,59]},"scoresAfter":[-37,-140]},{"ply":30,"player":"ai","action":6,"playedCard":5,"placeType":"discard","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[0,13,26,33,36,42,47,58],"ai":[5,14,40,43,51,55,57,59]},"scoresAfter":[-37,-140]},{"ply":31,"player":"human","action":48,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[0,13,26,33,36,42,47,58],"ai":[14,31,40,43,51,55,57,59]},"scoresAfter":[-57,-140]},{"ply":32,"player":"ai","action":18,"playedCard":31,"placeType":"discard","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[0,13,18,26,33,42,47,58],"ai":[14,31,40,43,51,55,57,59]},"scoresAfter":[-57,-140]},{"ply":33,"player":"human","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[0,13,18,26,33,42,47,58],"ai":[14,39,40,43,51,55,57,59]},"scoresAfter":[-48,-140]},{"ply":34,"player":"ai","action":6,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[0,12,13,18,26,33,42,47],"ai":[14,39,40,43,51,55,57,59]},"scoresAfter":[-48,-140]},{"ply":35,"player":"human","action":18,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[0,12,13,18,26,33,42,47],"ai":[4,39,40,43,51,55,57,59]},"scoresAfter":[-48,-140]},{"ply":36,"player":"ai","action":48,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[0,13,18,26,33,42,45,47],"ai":[4,39,40,43,51,55,57,59]},"scoresAfter":[-48,-132]},{"ply":37,"player":"human","action":18,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[0,13,18,26,33,42,45,47],"ai":[4,24,39,40,43,55,57,59]},"scoresAfter":[-48,-132]},{"ply":38,"player":"ai","action":18,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[0,18,26,27,33,42,45,47],"ai":[4,24,39,40,43,55,57,59]},"scoresAfter":[-48,-132]},{"ply":39,"player":"human","action":30,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[0,18,26,27,33,42,45,47],"ai":[4,39,40,43,54,55,57,59]},"scoresAfter":[-48,-132]},{"ply":40,"player":"ai","action":48,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[0,17,18,27,33,42,45,47],"ai":[4,39,40,43,54,55,57,59]},"scoresAfter":[-48,-112]},{"ply":41,"player":"human","action":60,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[0,17,18,27,33,42,45,47],"ai":[4,7,39,40,43,55,57,59]},"scoresAfter":[-33,-112]},{"ply":42,"player":"ai","action":60,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[0,11,17,18,27,33,45,47],"ai":[4,7,39,40,43,55,57,59]},"scoresAfter":[-33,-88]},{"ply":43,"player":"human","action":12,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[0,11,17,18,27,33,45,47],"ai":[4,7,39,40,41,43,57,59]},"scoresAfter":[-23,-88]},{"ply":44,"player":"ai","action":74,"playedCard":57,"placeType":"play","drawSource":"discard_1","drawnCard":13,"handsBefore":{"human":[0,17,18,20,27,33,45,47],"ai":[4,7,39,40,41,43,57,59]},"scoresAfter":[-23,-56]},{"ply":45,"player":"human","action":72,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[0,17,18,20,27,33,45,47],"ai":[4,7,13,39,40,41,43,59]},"scoresAfter":[1,-56]},{"ply":46,"player":"ai","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[0,17,18,20,27,33,47,52],"ai":[4,7,13,39,40,41,43,59]},"scoresAfter":[1,4]},{"ply":47,"player":"human","action":72,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[0,17,18,20,27,33,47,52],"ai":[2,4,7,13,39,40,41,43]},"scoresAfter":[31,4]}],"finalScores":[31,4],"outcome":"YOU WIN","finalState":{"deckOrder":[22,30,9,6,36,19,50,42,10,38,3,59,51,40,25,44,34,15,53,55,58,57,8,56,16,28,32,26,29,0,14,37,1,35,49,23,43,47,48,13,21,33,5,31,18,39,12,4,45,24,27,54,17,7,11,41,20,52,2,46],"drawPtr":60,"cardLoc":[1,5,2,4,2,5,3,2,3,3,4,3,5,2,5,4,4,1,1,3,1,4,3,3,5,4,5,1,3,4,3,5,4,1,3,3,3,3,4,2,2,2,3,2,4,3,1,3,4,4,4,4,1,3,4,4,3,4,3,4],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,10,10,10,9],[9,8,7,7,10]],"colHandshakes":[[0,0,0,2,0],[0,0,1,1,3]],"colLength":[[4,3,4,5,3],[2,3,3,2,8]],"piles":[[1,5],[14,12],[31,24,26],[],[]],"toMove":1,"stepCount":47,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"7a2fc87b-752c-4382-a00a-8640fdd582d9","seed":"d2w34f","startedAt":"2026-07-14T17:56:14.656Z","finishedAt":"2026-07-14T17:58:42.459Z","initialDeckOrder":[58,15,30,59,2,26,51,42,37,24,0,29,4,55,16,33,3,8,44,28,32,40,11,7,50,36,21,10,38,34,49,5,54,1,41,57,31,52,12,47,53,17,27,20,56,9,25,6,18,35,19,14,46,43,39,48,13,22,23,45],"moves":[{"ply":1,"player":"human","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[2,15,26,30,42,51,58,59],"ai":[0,4,16,24,29,33,37,55]},"scoresAfter":[0,0]},{"ply":2,"player":"ai","action":12,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[3,15,26,30,42,51,58,59],"ai":[0,4,16,24,29,33,37,55]},"scoresAfter":[0,-17]},{"ply":3,"player":"human","action":6,"playedCard":3,"placeType":"discard","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[3,15,26,30,42,51,58,59],"ai":[0,8,16,24,29,33,37,55]},"scoresAfter":[0,-17]},{"ply":4,"player":"ai","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[15,26,30,42,44,51,58,59],"ai":[0,8,16,24,29,33,37,55]},"scoresAfter":[0,-17]},{"ply":5,"player":"human","action":6,"playedCard":15,"placeType":"discard","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[15,26,30,42,44,51,58,59],"ai":[8,16,24,28,29,33,37,55]},"scoresAfter":[0,-17]},{"ply":6,"player":"ai","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[26,30,32,42,44,51,58,59],"ai":[8,16,24,28,29,33,37,55]},"scoresAfter":[0,-10]},{"ply":7,"player":"human","action":0,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[26,30,32,42,44,51,58,59],"ai":[16,24,28,29,33,37,40,55]},"scoresAfter":[-40,-10]},{"ply":8,"player":"ai","action":0,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[11,30,32,42,44,51,58,59],"ai":[16,24,28,29,33,37,40,55]},"scoresAfter":[-40,-27]},{"ply":9,"player":"human","action":12,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[11,30,32,42,44,51,58,59],"ai":[7,24,28,29,33,37,40,55]},"scoresAfter":[-30,-27]},{"ply":10,"player":"ai","action":72,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[11,32,42,44,50,51,58,59],"ai":[7,24,28,29,33,37,40,55]},"scoresAfter":[-30,-44]},{"ply":11,"player":"human","action":48,"playedCard":50,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[11,32,42,44,50,51,58,59],"ai":[7,24,28,29,33,36,37,55]},"scoresAfter":[-70,-44]},{"ply":12,"player":"ai","action":78,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[11,21,32,42,44,51,58,59],"ai":[7,24,28,29,33,36,37,55]},"scoresAfter":[-70,-44]},{"ply":13,"player":"human","action":60,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[11,21,32,42,44,51,58,59],"ai":[7,10,24,28,29,33,36,55]},"scoresAfter":[-66,-44]},{"ply":14,"player":"ai","action":78,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[11,21,32,38,42,44,58,59],"ai":[7,10,24,28,29,33,36,55]},"scoresAfter":[-66,-44]},{"ply":15,"player":"human","action":36,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[11,21,32,38,42,44,58,59],"ai":[7,10,24,28,29,33,34,55]},"scoresAfter":[-106,-44]},{"ply":16,"player":"ai","action":84,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[11,21,32,42,44,49,58,59],"ai":[7,10,24,28,29,33,34,55]},"scoresAfter":[-106,-58]},{"ply":17,"player":"human","action":36,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[11,21,32,42,44,49,58,59],"ai":[5,7,10,24,28,29,33,34]},"scoresAfter":[-96,-58]},{"ply":18,"player":"ai","action":6,"playedCard":5,"placeType":"discard","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[11,21,32,44,49,54,58,59],"ai":[5,7,10,24,28,29,33,34]},"scoresAfter":[-96,-58]},{"ply":19,"player":"human","action":60,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[11,21,32,44,49,54,58,59],"ai":[1,7,10,24,28,29,33,34]},"scoresAfter":[-86,-58]},{"ply":20,"player":"ai","action":24,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[11,21,32,41,44,49,58,59],"ai":[1,7,10,24,28,29,33,34]},"scoresAfter":[-86,-49]},{"ply":21,"player":"human","action":66,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[11,21,32,41,44,49,58,59],"ai":[1,7,24,28,29,33,34,57]},"scoresAfter":[-86,-49]},{"ply":22,"player":"ai","action":84,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[11,21,31,32,41,44,58,59],"ai":[1,7,24,28,29,33,34,57]},"scoresAfter":[-86,-41]},{"ply":23,"player":"human","action":24,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[11,21,31,32,41,44,58,59],"ai":[1,7,24,28,29,33,34,52]},"scoresAfter":[-74,-41]},{"ply":24,"player":"ai","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[11,12,21,32,41,44,58,59],"ai":[1,7,24,28,29,33,34,52]},"scoresAfter":[-74,-41]},{"ply":25,"player":"human","action":36,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[11,12,21,32,41,44,58,59],"ai":[7,24,28,29,33,34,47,52]},"scoresAfter":[-60,-41]},{"ply":26,"player":"ai","action":12,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[11,12,21,41,44,53,58,59],"ai":[7,24,28,29,33,34,47,52]},"scoresAfter":[-60,-81]},{"ply":27,"player":"human","action":66,"playedCard":53,"placeType":"discard","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[11,12,21,41,44,53,58,59],"ai":[7,17,28,29,33,34,47,52]},"scoresAfter":[-60,-81]},{"ply":28,"player":"ai","action":12,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[11,12,21,27,41,44,58,59],"ai":[7,17,28,29,33,34,47,52]},"scoresAfter":[-60,-77]},{"ply":29,"player":"human","action":60,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[11,12,21,27,41,44,58,59],"ai":[7,20,28,29,33,34,47,52]},"scoresAfter":[-46,-77]},{"ply":30,"player":"ai","action":12,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[11,12,21,27,41,56,58,59],"ai":[7,20,28,29,33,34,47,52]},"scoresAfter":[-46,-70]},{"ply":31,"player":"human","action":60,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[11,12,21,27,41,56,58,59],"ai":[7,9,28,29,33,34,47,52]},"scoresAfter":[-32,-70]},{"ply":32,"player":"ai","action":24,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[11,12,21,25,27,41,58,59],"ai":[7,9,28,29,33,34,47,52]},"scoresAfter":[-32,-64]},{"ply":33,"player":"human","action":42,"playedCard":25,"placeType":"discard","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[11,12,21,25,27,41,58,59],"ai":[6,7,9,29,33,34,47,52]},"scoresAfter":[-32,-64]},{"ply":34,"player":"ai","action":36,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[11,12,18,21,27,41,58,59],"ai":[6,7,9,29,33,34,47,52]},"scoresAfter":[-32,-56]},{"ply":35,"player":"human","action":72,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[11,12,18,21,27,41,58,59],"ai":[6,7,9,33,34,35,47,52]},"scoresAfter":[-14,-56]},{"ply":36,"player":"ai","action":18,"playedCard":7,"placeType":"discard","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[11,12,18,19,21,27,41,59],"ai":[6,7,9,33,34,35,47,52]},"scoresAfter":[-14,-56]},{"ply":37,"player":"human","action":12,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[11,12,18,19,21,27,41,59],"ai":[6,9,14,33,34,35,47,52]},"scoresAfter":[-54,-56]},{"ply":38,"player":"ai","action":36,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[11,18,19,21,27,41,46,59],"ai":[6,9,14,33,34,35,47,52]},"scoresAfter":[-54,-40]},{"ply":39,"player":"human","action":73,"playedCard":46,"placeType":"play","drawSource":"discard_0","drawnCard":7,"handsBefore":{"human":[11,18,19,21,27,41,46,59],"ai":[6,9,14,34,35,43,47,52]},"scoresAfter":[-36,-40]},{"ply":40,"player":"ai","action":60,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[7,11,18,19,21,27,41,59],"ai":[6,9,14,34,35,43,47,52]},"scoresAfter":[-36,-34]},{"ply":41,"player":"human","action":26,"playedCard":18,"placeType":"play","drawSource":"discard_1","drawnCard":15,"handsBefore":{"human":[7,11,18,19,21,27,41,59],"ai":[6,9,14,34,35,39,47,52]},"scoresAfter":[-26,-34]},{"ply":42,"player":"ai","action":36,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[7,11,15,19,21,27,41,59],"ai":[6,9,14,34,35,39,47,52]},"scoresAfter":[-26,-16]},{"ply":43,"player":"human","action":41,"playedCard":19,"placeType":"play","drawSource":"discard_4","drawnCard":53,"handsBefore":{"human":[7,11,15,19,21,27,41,59],"ai":[6,9,14,35,39,47,48,52]},"scoresAfter":[-14,-16]},{"ply":44,"player":"ai","action":36,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[7,11,15,21,27,41,53,59],"ai":[6,9,14,35,39,47,48,52]},"scoresAfter":[-14,4]},{"ply":45,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[7,11,15,21,27,41,53,59],"ai":[6,9,13,14,39,47,48,52]},"scoresAfter":[6,4]},{"ply":46,"player":"ai","action":60,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[7,11,15,21,22,27,41,53],"ai":[6,9,13,14,39,47,48,52]},"scoresAfter":[6,14]},{"ply":47,"player":"human","action":41,"playedCard":21,"placeType":"play","drawSource":"discard_4","drawnCard":49,"handsBefore":{"human":[7,11,15,21,22,27,41,53],"ai":[6,9,13,14,23,39,48,52]},"scoresAfter":[22,14]},{"ply":48,"player":"ai","action":48,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[7,11,15,22,27,41,49,53],"ai":[6,9,13,14,23,39,48,52]},"scoresAfter":[22,24]}],"finalScores":[22,24],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[58,15,30,59,2,26,51,42,37,24,0,29,4,55,16,33,3,8,44,28,32,40,11,7,50,36,21,10,38,34,49,5,54,1,41,57,31,52,12,47,53,17,27,20,56,9,25,6,18,35,19,14,46,43,39,48,13,22,23,45],"drawPtr":60,"cardLoc":[5,5,5,5,4,5,2,1,4,2,4,1,3,2,2,1,4,4,3,3,4,3,1,4,4,5,3,1,4,4,3,3,3,4,4,4,5,5,3,2,4,1,3,4,3,2,3,4,2,1,3,3,2,1,3,4,3,4,3,3],"handPublic":[false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,true,false,false,false,false,false,false],"colTop":[[0,8,7,9,10],[9,10,10,10,8]],"colHandshakes":[[0,1,1,1,1],[0,0,1,0,0]],"colLength":[[0,4,4,4,6],[3,4,6,3,2]],"piles":[[2,3,0,5,1],[],[25],[37,36],[]],"toMove":0,"stepCount":48,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"6ff57738-2444-4d17-8f67-b90e24caea1b","seed":"wedkb8","startedAt":"2026-07-14T17:58:43.440Z","finishedAt":"2026-07-14T18:00:18.955Z","initialDeckOrder":[52,25,46,23,49,41,40,5,19,12,9,34,37,22,44,29,18,21,43,15,54,38,24,45,11,3,42,0,55,28,57,31,26,27,47,7,48,16,6,35,20,53,32,17,58,4,50,14,10,2,13,39,51,33,56,30,8,59,36,1],"moves":[{"ply":1,"player":"human","action":36,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[5,23,25,40,41,46,49,52],"ai":[9,12,19,22,29,34,37,44]},"scoresAfter":[-17,0]},{"ply":2,"player":"ai","action":12,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[5,18,23,25,41,46,49,52],"ai":[9,12,19,22,29,34,37,44]},"scoresAfter":[-17,-40]},{"ply":3,"player":"human","action":48,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[5,18,23,25,41,46,49,52],"ai":[9,19,21,22,29,34,37,44]},"scoresAfter":[-13,-40]},{"ply":4,"player":"ai","action":78,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[5,18,23,25,43,46,49,52],"ai":[9,19,21,22,29,34,37,44]},"scoresAfter":[-13,-40]},{"ply":5,"player":"human","action":48,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[5,18,23,25,43,46,49,52],"ai":[9,15,19,21,22,29,34,44]},"scoresAfter":[-7,-40]},{"ply":6,"player":"ai","action":12,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[5,18,23,25,46,49,52,54],"ai":[9,15,19,21,22,29,34,44]},"scoresAfter":[-7,-36]},{"ply":7,"player":"human","action":42,"playedCard":25,"placeType":"discard","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[5,18,23,25,46,49,52,54],"ai":[9,19,21,22,29,34,38,44]},"scoresAfter":[-7,-36]},{"ply":8,"player":"ai","action":78,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[5,18,23,24,46,49,52,54],"ai":[9,19,21,22,29,34,38,44]},"scoresAfter":[-7,-36]},{"ply":9,"player":"human","action":42,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[5,18,23,24,46,49,52,54],"ai":[9,19,21,22,29,34,44,45]},"scoresAfter":[-7,-36]},{"ply":10,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[5,11,18,23,46,49,52,54],"ai":[9,19,21,22,29,34,44,45]},"scoresAfter":[-7,-48]},{"ply":11,"player":"human","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[5,11,18,23,46,49,52,54],"ai":[3,19,21,22,29,34,44,45]},"scoresAfter":[-23,-48]},{"ply":12,"player":"ai","action":6,"playedCard":3,"placeType":"discard","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[11,18,23,42,46,49,52,54],"ai":[3,19,21,22,29,34,44,45]},"scoresAfter":[-23,-48]},{"ply":13,"player":"human","action":12,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[11,18,23,42,46,49,52,54],"ai":[0,19,21,22,29,34,44,45]},"scoresAfter":[-38,-48]},{"ply":14,"player":"ai","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[11,23,42,46,49,52,54,55],"ai":[0,19,21,22,29,34,44,45]},"scoresAfter":[-38,-48]},{"ply":15,"player":"human","action":48,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[11,23,42,46,49,52,54,55],"ai":[19,21,22,28,29,34,44,45]},"scoresAfter":[-78,-48]},{"ply":16,"player":"ai","action":75,"playedCard":44,"placeType":"play","drawSource":"discard_2","drawnCard":24,"handsBefore":{"human":[11,23,42,46,52,54,55,57],"ai":[19,21,22,28,29,34,44,45]},"scoresAfter":[-78,-61]},{"ply":17,"player":"human","action":48,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[11,23,42,46,52,54,55,57],"ai":[19,21,22,24,28,29,34,45]},"scoresAfter":[-72,-61]},{"ply":18,"player":"ai","action":3,"playedCard":19,"placeType":"play","drawSource":"discard_2","drawnCard":25,"handsBefore":{"human":[11,23,31,42,46,54,55,57],"ai":[19,21,22,24,28,29,34,45]},"scoresAfter":[-72,-49]},{"ply":19,"player":"human","action":60,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[11,23,31,42,46,54,55,57],"ai":[21,22,24,25,28,29,34,45]},"scoresAfter":[-62,-49]},{"ply":20,"player":"ai","action":84,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[11,23,26,31,42,46,55,57],"ai":[21,22,24,25,28,29,34,45]},"scoresAfter":[-62,-41]},{"ply":21,"player":"human","action":72,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[11,23,26,31,42,46,55,57],"ai":[21,22,24,25,27,28,29,34]},"scoresAfter":[-50,-41]},{"ply":22,"player":"ai","action":0,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[11,23,26,31,42,46,47,57],"ai":[21,22,24,25,27,28,29,34]},"scoresAfter":[-50,-25]},{"ply":23,"player":"human","action":84,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[11,23,26,31,42,46,47,57],"ai":[7,22,24,25,27,28,29,34]},"scoresAfter":[-34,-25]},{"ply":24,"player":"ai","action":6,"playedCard":7,"placeType":"discard","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[11,23,26,31,42,46,47,48],"ai":[7,22,24,25,27,28,29,34]},"scoresAfter":[-34,-25]},{"ply":25,"player":"human","action":60,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[11,23,26,31,42,46,47,48],"ai":[16,22,24,25,27,28,29,34]},"scoresAfter":[-25,-25]},{"ply":26,"player":"ai","action":6,"playedCard":16,"placeType":"discard","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[6,11,23,26,31,42,47,48],"ai":[16,22,24,25,27,28,29,34]},"scoresAfter":[-25,-25]},{"ply":27,"player":"human","action":72,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[6,11,23,26,31,42,47,48],"ai":[22,24,25,27,28,29,34,35]},"scoresAfter":[-15,-25]},{"ply":28,"player":"ai","action":0,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[6,11,20,23,26,31,42,48],"ai":[22,24,25,27,28,29,34,35]},"scoresAfter":[-15,-7]},{"ply":29,"player":"human","action":24,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[6,11,20,23,26,31,42,48],"ai":[24,25,27,28,29,34,35,53]},"scoresAfter":[-8,-7]},{"ply":30,"player":"ai","action":0,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[6,11,23,26,31,32,42,48],"ai":[24,25,27,28,29,34,35,53]},"scoresAfter":[-8,-47]},{"ply":31,"player":"human","action":1,"playedCard":6,"placeType":"play","drawSource":"discard_0","drawnCard":7,"handsBefore":{"human":[6,11,23,26,31,32,42,48],"ai":[17,25,27,28,29,34,35,53]},"scoresAfter":[-3,-47]},{"ply":32,"player":"ai","action":12,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[7,11,23,26,31,32,42,48],"ai":[17,25,27,28,29,34,35,53]},"scoresAfter":[-3,-67]},{"ply":33,"player":"human","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[7,11,23,26,31,32,42,48],"ai":[17,27,28,29,34,35,53,58]},"scoresAfter":[3,-67]},{"ply":34,"player":"ai","action":78,"playedCard":53,"placeType":"discard","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[4,11,23,26,31,32,42,48],"ai":[17,27,28,29,34,35,53,58]},"scoresAfter":[3,-67]},{"ply":35,"player":"human","action":90,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[4,11,23,26,31,32,42,48],"ai":[17,27,28,29,34,35,50,58]},"scoresAfter":[3,-67]},{"ply":36,"player":"ai","action":12,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[4,11,14,23,26,31,32,42],"ai":[17,27,28,29,34,35,50,58]},"scoresAfter":[3,-61]},{"ply":37,"player":"human","action":30,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[4,11,14,23,26,31,32,42],"ai":[10,17,28,29,34,35,50,58]},"scoresAfter":[3,-61]},{"ply":38,"player":"ai","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[2,4,11,23,26,31,32,42],"ai":[10,17,28,29,34,35,50,58]},"scoresAfter":[3,-52]},{"ply":39,"player":"human","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[2,4,11,23,26,31,32,42],"ai":[13,17,28,29,34,35,50,58]},"scoresAfter":[3,-52]},{"ply":40,"player":"ai","action":24,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[4,11,23,26,31,32,39,42],"ai":[13,17,28,29,34,35,50,58]},"scoresAfter":[3,-43]},{"ply":41,"player":"human","action":78,"playedCard":39,"placeType":"discard","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[4,11,23,26,31,32,39,42],"ai":[13,17,29,34,35,50,51,58]},"scoresAfter":[3,-43]},{"ply":42,"player":"ai","action":78,"playedCard":51,"placeType":"discard","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[4,11,23,26,31,32,33,42],"ai":[13,17,29,34,35,50,51,58]},"scoresAfter":[3,-43]},{"ply":43,"player":"human","action":24,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[4,11,23,26,31,32,33,42],"ai":[13,17,29,34,35,50,56,58]},"scoresAfter":[13,-43]},{"ply":44,"player":"ai","action":26,"playedCard":29,"placeType":"play","drawSource":"discard_1","drawnCard":14,"handsBefore":{"human":[4,11,26,30,31,32,33,42],"ai":[13,17,29,34,35,50,56,58]},"scoresAfter":[13,-31]},{"ply":45,"player":"human","action":26,"playedCard":26,"placeType":"play","drawSource":"discard_1","drawnCard":16,"handsBefore":{"human":[4,11,26,30,31,32,33,42],"ai":[13,14,17,34,35,50,56,58]},"scoresAfter":[-27,-31]},{"ply":46,"player":"ai","action":36,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[4,11,16,30,31,32,33,42],"ai":[13,14,17,34,35,50,56,58]},"scoresAfter":[-27,-4]},{"ply":47,"player":"human","action":49,"playedCard":31,"placeType":"play","drawSource":"discard_0","drawnCard":2,"handsBefore":{"human":[4,11,16,30,31,32,33,42],"ai":[8,13,14,17,35,50,56,58]},"scoresAfter":[-15,-4]},{"ply":48,"player":"ai","action":78,"playedCard":56,"placeType":"discard","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[2,4,11,16,30,32,33,42],"ai":[8,13,14,17,35,50,56,58]},"scoresAfter":[-15,-4]},{"ply":49,"player":"human","action":64,"playedCard":32,"placeType":"play","drawSource":"discard_3","drawnCard":39,"handsBefore":{"human":[2,4,11,16,30,32,33,42],"ai":[8,13,14,17,35,50,58,59]},"scoresAfter":[-1,-4]},{"ply":50,"player":"ai","action":52,"playedCard":35,"placeType":"play","drawSource":"discard_3","drawnCard":38,"handsBefore":{"human":[2,4,11,16,30,33,39,42],"ai":[8,13,14,17,35,50,58,59]},"scoresAfter":[-1,26]},{"ply":51,"player":"human","action":65,"playedCard":33,"placeType":"play","drawSource":"discard_4","drawnCard":56,"handsBefore":{"human":[2,4,11,16,30,33,39,42],"ai":[8,13,14,17,38,50,58,59]},"scoresAfter":[15,26]},{"ply":52,"player":"ai","action":66,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[2,4,11,16,30,39,42,56],"ai":[8,13,14,17,38,50,58,59]},"scoresAfter":[15,26]},{"ply":53,"player":"human","action":24,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[2,4,11,16,30,39,42,56],"ai":[8,13,14,17,36,38,58,59]},"scoresAfter":[25,26]}],"finalScores":[25,26],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[52,25,46,23,49,41,40,5,19,12,9,34,37,22,44,29,18,21,43,15,54,38,24,45,11,3,42,0,55,28,57,31,26,27,47,7,48,16,6,35,20,53,32,17,58,4,50,14,10,2,13,39,51,33,56,30,8,59,36,1],"drawPtr":60,"cardLoc":[5,1,1,5,1,3,3,3,2,4,4,3,4,2,2,4,1,2,3,4,3,4,4,3,4,4,3,4,4,4,1,3,3,3,4,4,2,5,2,1,3,3,1,3,4,4,3,3,5,3,5,5,3,5,3,3,1,3,2,2],"handPublic":[false,false,true,false,false,false,false,false,false,false,false,false,false,false,true,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false],"colTop":[[10,10,8,10,8],[9,9,10,8,0]],"colHandshakes":[[0,0,1,0,1],[0,1,2,0,0]],"colLength":[[4,3,4,5,5],[2,5,7,2,0]],"piles":[[3,0],[],[],[37],[53,48,51,50]],"toMove":1,"stepCount":53,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"7390b4d7-1bfa-4f5c-9d90-efa0eaee2b75","seed":"ksdhrt","startedAt":"2026-07-14T18:00:19.949Z","finishedAt":"2026-07-14T18:03:19.950Z","initialDeckOrder":[8,47,17,22,18,30,7,0,37,16,29,9,38,6,20,31,24,39,53,44,57,32,15,33,59,19,25,43,40,54,3,58,35,48,45,36,27,28,41,14,1,56,46,11,5,26,23,55,13,34,12,51,4,10,49,21,50,52,2,42],"moves":[{"ply":1,"player":"human","action":0,"playedCard":0,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[0,7,8,17,18,22,30,47],"ai":[6,9,16,20,29,31,37,38]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[7,8,17,18,22,24,30,47],"ai":[6,9,16,20,29,31,37,38]},"scoresAfter":[-40,-15]},{"ply":3,"player":"human","action":24,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[7,8,17,18,22,24,30,47],"ai":[9,16,20,29,31,37,38,39]},"scoresAfter":[-56,-15]},{"ply":4,"player":"ai","action":12,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[7,8,18,22,24,30,47,53],"ai":[9,16,20,29,31,37,38,39]},"scoresAfter":[-56,-32]},{"ply":5,"player":"human","action":24,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[7,8,18,22,24,30,47,53],"ai":[9,20,29,31,37,38,39,44]},"scoresAfter":[-51,-32]},{"ply":6,"player":"ai","action":48,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[7,8,22,24,30,47,53,57],"ai":[9,20,29,31,37,38,39,44]},"scoresAfter":[-51,-72]},{"ply":7,"player":"human","action":72,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[7,8,22,24,30,47,53,57],"ai":[9,20,29,31,32,38,39,44]},"scoresAfter":[-67,-72]},{"ply":8,"player":"ai","action":60,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[7,8,15,22,24,30,47,57],"ai":[9,20,29,31,32,38,39,44]},"scoresAfter":[-67,-92]},{"ply":9,"player":"human","action":30,"playedCard":15,"placeType":"discard","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[7,8,15,22,24,30,47,57],"ai":[9,20,29,31,32,33,39,44]},"scoresAfter":[-67,-92]},{"ply":10,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[7,8,22,24,30,47,57,59],"ai":[9,20,29,31,32,33,39,44]},"scoresAfter":[-67,-84]},{"ply":11,"player":"human","action":42,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[7,8,22,24,30,47,57,59],"ai":[19,20,29,31,32,33,39,44]},"scoresAfter":[-67,-84]},{"ply":12,"player":"ai","action":0,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[7,8,22,25,30,47,57,59],"ai":[19,20,29,31,32,33,39,44]},"scoresAfter":[-67,-78]},{"ply":13,"player":"human","action":42,"playedCard":25,"placeType":"discard","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[7,8,22,25,30,47,57,59],"ai":[20,29,31,32,33,39,43,44]},"scoresAfter":[-67,-78]},{"ply":14,"player":"ai","action":3,"playedCard":20,"placeType":"play","drawSource":"discard_2","drawnCard":25,"handsBefore":{"human":[7,8,22,30,40,47,57,59],"ai":[20,29,31,32,33,39,43,44]},"scoresAfter":[-67,-71]},{"ply":15,"player":"human","action":48,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[7,8,22,30,40,47,57,59],"ai":[25,29,31,32,33,39,43,44]},"scoresAfter":[-84,-71]},{"ply":16,"player":"ai","action":93,"playedCard":44,"placeType":"discard","drawSource":"discard_2","drawnCard":24,"handsBefore":{"human":[7,8,22,30,47,54,57,59],"ai":[25,29,31,32,33,39,43,44]},"scoresAfter":[-84,-71]},{"ply":17,"player":"human","action":60,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[7,8,22,30,47,54,57,59],"ai":[24,25,29,31,32,33,39,43]},"scoresAfter":[-79,-71]},{"ply":18,"player":"ai","action":4,"playedCard":24,"placeType":"play","drawSource":"discard_3","drawnCard":44,"handsBefore":{"human":[3,7,8,22,30,47,57,59],"ai":[24,25,29,31,32,33,39,43]},"scoresAfter":[-79,-111]},{"ply":19,"player":"human","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[3,7,8,22,30,47,57,59],"ai":[25,29,31,32,33,39,43,44]},"scoresAfter":[-75,-111]},{"ply":20,"player":"ai","action":60,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[7,8,22,30,47,57,58,59],"ai":[25,29,31,32,33,39,43,44]},"scoresAfter":[-75,-105]},{"ply":21,"player":"human","action":60,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[7,8,22,30,47,57,58,59],"ai":[25,29,31,32,33,35,43,44]},"scoresAfter":[-67,-105]},{"ply":22,"player":"ai","action":72,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[7,8,22,30,47,48,58,59],"ai":[25,29,31,32,33,35,43,44]},"scoresAfter":[-67,-87]},{"ply":23,"player":"human","action":72,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[7,8,22,30,47,48,58,59],"ai":[25,29,31,32,33,35,44,45]},"scoresAfter":[-58,-87]},{"ply":24,"player":"ai","action":72,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[7,8,22,30,36,47,48,59],"ai":[25,29,31,32,33,35,44,45]},"scoresAfter":[-58,-66]},{"ply":25,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[7,8,22,30,36,47,48,59],"ai":[25,27,29,31,32,33,35,45]},"scoresAfter":[-48,-66]},{"ply":26,"player":"ai","action":84,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[7,8,22,28,30,36,47,48],"ai":[25,27,29,31,32,33,35,45]},"scoresAfter":[-48,-42]},{"ply":27,"player":"human","action":66,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[7,8,22,28,30,36,47,48],"ai":[25,27,29,31,32,33,35,41]},"scoresAfter":[-48,-42]},{"ply":28,"player":"ai","action":0,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[7,8,14,22,28,30,47,48],"ai":[25,27,29,31,32,33,35,41]},"scoresAfter":[-48,-62]},{"ply":29,"player":"human","action":30,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[7,8,14,22,28,30,47,48],"ai":[1,27,29,31,32,33,35,41]},"scoresAfter":[-48,-62]},{"ply":30,"player":"ai","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[7,8,22,28,30,47,48,56],"ai":[1,27,29,31,32,33,35,41]},"scoresAfter":[-48,-62]},{"ply":31,"player":"human","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[7,8,22,28,30,47,48,56],"ai":[27,29,31,32,33,35,41,46]},"scoresAfter":[-36,-62]},{"ply":32,"player":"ai","action":0,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[8,11,22,28,30,47,48,56],"ai":[27,29,31,32,33,35,41,46]},"scoresAfter":[-36,-56]},{"ply":33,"player":"human","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[8,11,22,28,30,47,48,56],"ai":[5,29,31,32,33,35,41,46]},"scoresAfter":[-22,-56]},{"ply":34,"player":"ai","action":12,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[11,22,26,28,30,47,48,56],"ai":[5,29,31,32,33,35,41,46]},"scoresAfter":[-22,-44]},{"ply":35,"player":"human","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[11,22,26,28,30,47,48,56],"ai":[5,23,31,32,33,35,41,46]},"scoresAfter":[-2,-44]},{"ply":36,"player":"ai","action":12,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[22,26,28,30,47,48,55,56],"ai":[5,23,31,32,33,35,41,46]},"scoresAfter":[-2,-34]},{"ply":37,"player":"human","action":18,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[22,26,28,30,47,48,55,56],"ai":[5,13,31,32,33,35,41,46]},"scoresAfter":[-2,-34]},{"ply":38,"player":"ai","action":87,"playedCard":46,"placeType":"play","drawSource":"discard_2","drawnCard":26,"handsBefore":{"human":[22,28,30,34,47,48,55,56],"ai":[5,13,31,32,33,35,41,46]},"scoresAfter":[-2,-7]},{"ply":39,"player":"human","action":0,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[22,28,30,34,47,48,55,56],"ai":[5,13,26,31,32,33,35,41]},"scoresAfter":[7,-7]},{"ply":40,"player":"ai","action":18,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[12,28,30,34,47,48,55,56],"ai":[5,13,26,31,32,33,35,41]},"scoresAfter":[7,-7]},{"ply":41,"player":"human","action":12,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[12,28,30,34,47,48,55,56],"ai":[5,26,31,32,33,35,41,51]},"scoresAfter":[-10,-7]},{"ply":42,"player":"ai","action":94,"playedCard":51,"placeType":"discard","drawSource":"discard_3","drawnCard":36,"handsBefore":{"human":[4,12,30,34,47,48,55,56],"ai":[5,26,31,32,33,35,41,51]},"scoresAfter":[-10,-7]},{"ply":43,"player":"human","action":24,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[4,12,30,34,47,48,55,56],"ai":[5,26,31,32,33,35,36,41]},"scoresAfter":[-5,-7]},{"ply":44,"player":"ai","action":24,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[4,10,12,34,47,48,55,56],"ai":[5,26,31,32,33,35,36,41]},"scoresAfter":[-5,11]},{"ply":45,"player":"human","action":48,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[4,10,12,34,47,48,55,56],"ai":[5,26,32,33,35,36,41,49]},"scoresAfter":[5,11]},{"ply":46,"player":"ai","action":26,"playedCard":32,"placeType":"play","drawSource":"discard_1","drawnCard":13,"handsBefore":{"human":[4,10,12,21,34,48,55,56],"ai":[5,26,32,33,35,36,41,49]},"scoresAfter":[5,32]},{"ply":47,"player":"human","action":48,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[4,10,12,21,34,48,55,56],"ai":[5,13,26,33,35,36,41,49]},"scoresAfter":[14,32]},{"ply":48,"player":"ai","action":38,"playedCard":33,"placeType":"play","drawSource":"discard_1","drawnCard":14,"handsBefore":{"human":[4,10,12,21,48,50,55,56],"ai":[5,13,26,33,35,36,41,49]},"scoresAfter":[14,56]},{"ply":49,"player":"human","action":30,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[4,10,12,21,48,50,55,56],"ai":[5,13,14,26,35,36,41,49]},"scoresAfter":[14,56]},{"ply":50,"player":"ai","action":50,"playedCard":35,"placeType":"play","drawSource":"discard_1","drawnCard":12,"handsBefore":{"human":[4,10,21,48,50,52,55,56],"ai":[5,13,14,26,35,36,41,49]},"scoresAfter":[14,106]},{"ply":51,"player":"human","action":66,"playedCard":52,"placeType":"discard","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[4,10,21,48,50,52,55,56],"ai":[5,12,13,14,26,36,41,49]},"scoresAfter":[14,106]},{"ply":52,"player":"ai","action":6,"playedCard":5,"placeType":"discard","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[2,4,10,21,48,50,55,56],"ai":[5,12,13,14,26,36,41,49]},"scoresAfter":[14,106]}],"finalScores":[14,106],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[8,47,17,22,18,30,7,0,37,16,29,9,38,6,20,31,24,39,53,44,57,32,15,33,59,19,25,43,40,54,3,58,35,48,45,36,27,28,41,14,1,56,46,11,5,26,23,55,13,34,12,51,4,10,49,21,50,52,2,42],"drawPtr":60,"cardLoc":[3,5,1,3,1,5,4,3,3,4,1,3,2,2,2,5,4,3,3,4,4,1,3,4,4,4,2,4,3,4,3,4,4,4,3,4,2,4,4,4,3,2,2,4,4,4,4,3,1,2,1,5,5,3,3,1,1,3,3,3],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,true,true,true,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,9,9,10,10],[8,10,10,9,0]],"colHandshakes":[[1,0,0,0,0],[0,0,2,2,0]],"colLength":[[5,3,3,2,5],[2,4,8,7,0]],"piles":[[1,5],[15],[],[],[51,52]],"toMove":0,"stepCount":52,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"2319fc40-7a18-4955-a004-241ca6750687","seed":"38oao4","startedAt":"2026-07-14T18:03:20.867Z","finishedAt":"2026-07-14T18:06:14.415Z","initialDeckOrder":[5,16,55,9,19,0,42,51,41,57,34,45,20,49,36,56,15,58,6,44,30,33,52,29,31,54,38,27,40,22,39,3,7,24,48,21,11,59,4,46,32,18,25,1,35,8,14,50,10,26,53,2,23,17,12,28,47,13,37,43],"moves":[{"ply":1,"player":"human","action":0,"playedCard":0,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[0,5,9,16,19,42,51,55],"ai":[20,34,36,41,45,49,56,57]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":60,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[5,9,15,16,19,42,51,55],"ai":[20,34,36,41,45,49,56,57]},"scoresAfter":[-40,-40]},{"ply":3,"player":"human","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[5,9,15,16,19,42,51,55],"ai":[20,34,36,41,45,56,57,58]},"scoresAfter":[-32,-40]},{"ply":4,"player":"ai","action":36,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[6,9,15,16,19,42,51,55],"ai":[20,34,36,41,45,56,57,58]},"scoresAfter":[-32,-56]},{"ply":5,"player":"human","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[6,9,15,16,19,42,51,55],"ai":[20,34,36,44,45,56,57,58]},"scoresAfter":[-22,-56]},{"ply":6,"player":"ai","action":36,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[9,15,16,19,30,42,51,55],"ai":[20,34,36,44,45,56,57,58]},"scoresAfter":[-22,-49]},{"ply":7,"player":"human","action":66,"playedCard":42,"placeType":"discard","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[9,15,16,19,30,42,51,55],"ai":[20,33,34,36,45,56,57,58]},"scoresAfter":[-22,-49]},{"ply":8,"player":"ai","action":48,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[9,15,16,19,30,51,52,55],"ai":[20,33,34,36,45,56,57,58]},"scoresAfter":[-22,-41]},{"ply":9,"player":"human","action":60,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[9,15,16,19,30,51,52,55],"ai":[20,29,33,34,36,56,57,58]},"scoresAfter":[-40,-41]},{"ply":10,"player":"ai","action":54,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[9,15,16,19,30,31,52,55],"ai":[20,29,33,34,36,56,57,58]},"scoresAfter":[-40,-41]},{"ply":11,"player":"human","action":72,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[9,15,16,19,30,31,52,55],"ai":[20,29,33,34,54,56,57,58]},"scoresAfter":[-37,-41]},{"ply":12,"player":"ai","action":0,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[9,15,16,19,30,31,38,55],"ai":[20,29,33,34,54,56,57,58]},"scoresAfter":[-37,-54]},{"ply":13,"player":"human","action":78,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[9,15,16,19,30,31,38,55],"ai":[27,29,33,34,54,56,57,58]},"scoresAfter":[-37,-54]},{"ply":14,"player":"ai","action":0,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[9,15,16,19,30,31,40,55],"ai":[27,29,33,34,54,56,57,58]},"scoresAfter":[-37,-72]},{"ply":15,"player":"human","action":78,"playedCard":40,"placeType":"discard","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[9,15,16,19,30,31,40,55],"ai":[22,29,33,34,54,56,57,58]},"scoresAfter":[-37,-72]},{"ply":16,"player":"ai","action":0,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[9,15,16,19,30,31,39,55],"ai":[22,29,33,34,54,56,57,58]},"scoresAfter":[-37,-63]},{"ply":17,"player":"human","action":78,"playedCard":39,"placeType":"discard","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[9,15,16,19,30,31,39,55],"ai":[3,29,33,34,54,56,57,58]},"scoresAfter":[-37,-63]},{"ply":18,"player":"ai","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[7,9,15,16,19,30,31,55],"ai":[3,29,33,34,54,56,57,58]},"scoresAfter":[-37,-81]},{"ply":19,"player":"human","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[7,9,15,16,19,30,31,55],"ai":[24,29,33,34,54,56,57,58]},"scoresAfter":[-25,-81]},{"ply":20,"player":"ai","action":12,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[9,15,16,19,30,31,48,55],"ai":[24,29,33,34,54,56,57,58]},"scoresAfter":[-25,-77]},{"ply":21,"player":"human","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[9,15,16,19,30,31,48,55],"ai":[21,24,33,34,54,56,57,58]},"scoresAfter":[-9,-77]},{"ply":22,"player":"ai","action":6,"playedCard":21,"placeType":"discard","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[11,15,16,19,30,31,48,55],"ai":[21,24,33,34,54,56,57,58]},"scoresAfter":[-9,-77]},{"ply":23,"player":"human","action":2,"playedCard":11,"placeType":"play","drawSource":"discard_1","drawnCard":21,"handsBefore":{"human":[11,15,16,19,30,31,48,55],"ai":[24,33,34,54,56,57,58,59]},"scoresAfter":[11,-77]},{"ply":24,"player":"ai","action":12,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[15,16,19,21,30,31,48,55],"ai":[24,33,34,54,56,57,58,59]},"scoresAfter":[11,-69]},{"ply":25,"player":"human","action":0,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[15,16,19,21,30,31,48,55],"ai":[4,24,34,54,56,57,58,59]},"scoresAfter":[-7,-69]},{"ply":26,"player":"ai","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[16,19,21,30,31,46,48,55],"ai":[4,24,34,54,56,57,58,59]},"scoresAfter":[-7,-66]},{"ply":27,"player":"human","action":0,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[16,19,21,30,31,46,48,55],"ai":[24,32,34,54,56,57,58,59]},"scoresAfter":[-4,-66]},{"ply":28,"player":"ai","action":24,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[18,19,21,30,31,46,48,55],"ai":[24,32,34,54,56,57,58,59]},"scoresAfter":[-4,-57]},{"ply":29,"player":"human","action":0,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[18,19,21,30,31,46,48,55],"ai":[24,25,32,54,56,57,58,59]},"scoresAfter":[1,-57]},{"ply":30,"player":"ai","action":6,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[1,19,21,30,31,46,48,55],"ai":[24,25,32,54,56,57,58,59]},"scoresAfter":[1,-57]},{"ply":31,"player":"human","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[1,19,21,30,31,46,48,55],"ai":[25,32,35,54,56,57,58,59]},"scoresAfter":[1,-57]},{"ply":32,"player":"ai","action":24,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[8,19,21,30,31,46,48,55],"ai":[25,32,35,54,56,57,58,59]},"scoresAfter":[1,-47]},{"ply":33,"player":"human","action":12,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[8,19,21,30,31,46,48,55],"ai":[14,25,32,54,56,57,58,59]},"scoresAfter":[7,-47]},{"ply":34,"player":"ai","action":6,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[8,21,30,31,46,48,50,55],"ai":[14,25,32,54,56,57,58,59]},"scoresAfter":[7,-47]},{"ply":35,"player":"human","action":12,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[8,21,30,31,46,48,50,55],"ai":[10,25,32,54,56,57,58,59]},"scoresAfter":[15,-47]},{"ply":36,"player":"ai","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[8,26,30,31,46,48,50,55],"ai":[10,25,32,54,56,57,58,59]},"scoresAfter":[15,-38]},{"ply":37,"player":"human","action":30,"playedCard":30,"placeType":"discard","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[8,26,30,31,46,48,50,55],"ai":[25,32,53,54,56,57,58,59]},"scoresAfter":[15,-38]},{"ply":38,"player":"ai","action":24,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[2,8,26,31,46,48,50,55],"ai":[25,32,53,54,56,57,58,59]},"scoresAfter":[15,-30]},{"ply":39,"player":"human","action":30,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[2,8,26,31,46,48,50,55],"ai":[23,25,32,54,56,57,58,59]},"scoresAfter":[15,-30]},{"ply":40,"player":"ai","action":50,"playedCard":56,"placeType":"play","drawSource":"discard_1","drawnCard":14,"handsBefore":{"human":[2,8,17,31,46,48,50,55],"ai":[23,25,32,54,56,57,58,59]},"scoresAfter":[15,-16]},{"ply":41,"player":"human","action":42,"playedCard":31,"placeType":"discard","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[2,8,17,31,46,48,50,55],"ai":[14,23,25,32,54,57,58,59]},"scoresAfter":[15,-16]},{"ply":42,"player":"ai","action":16,"playedCard":23,"placeType":"play","drawSource":"discard_3","drawnCard":39,"handsBefore":{"human":[2,8,12,17,46,48,50,55],"ai":[14,23,25,32,54,57,58,59]},"scoresAfter":[15,-6]},{"ply":43,"player":"human","action":30,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[2,8,12,17,46,48,50,55],"ai":[14,25,32,39,54,57,58,59]},"scoresAfter":[15,-6]},{"ply":44,"player":"ai","action":62,"playedCard":57,"placeType":"play","drawSource":"discard_1","drawnCard":12,"handsBefore":{"human":[2,8,17,28,46,48,50,55],"ai":[14,25,32,39,54,57,58,59]},"scoresAfter":[15,10]},{"ply":45,"player":"human","action":84,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[2,8,17,28,46,48,50,55],"ai":[12,14,25,32,39,54,58,59]},"scoresAfter":[21,10]},{"ply":46,"player":"ai","action":76,"playedCard":58,"placeType":"play","drawSource":"discard_3","drawnCard":40,"handsBefore":{"human":[2,8,17,28,46,47,48,50],"ai":[12,14,25,32,39,54,58,59]},"scoresAfter":[21,28]},{"ply":47,"player":"human","action":42,"playedCard":28,"placeType":"discard","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[2,8,17,28,46,47,48,50],"ai":[12,14,25,32,39,40,54,59]},"scoresAfter":[21,28]},{"ply":48,"player":"ai","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[2,8,13,17,46,47,48,50],"ai":[12,14,25,32,39,40,54,59]},"scoresAfter":[21,48]},{"ply":49,"player":"human","action":30,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[2,8,13,17,46,47,48,50],"ai":[12,14,25,32,37,39,40,54]},"scoresAfter":[21,48]}],"finalScores":[21,48],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[5,16,55,9,19,0,42,51,41,57,34,45,20,49,36,56,15,58,6,44,30,33,52,29,31,54,38,27,40,22,39,3,7,24,48,21,11,59,4,46,32,18,25,1,35,8,14,50,10,26,53,2,23,17,12,28,47,13,37,43],"drawPtr":60,"cardLoc":[3,5,1,4,4,3,3,3,1,3,4,3,2,5,2,3,3,1,3,3,4,3,4,4,5,2,5,4,5,4,5,5,2,4,4,4,5,2,5,2,2,4,5,1,4,4,1,1,1,4,1,3,3,4,2,3,4,4,4,4],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,true,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,8,0,0,6],[9,10,10,8,10]],"colHandshakes":[[1,0,0,0,0],[0,0,0,0,1]],"colLength":[[6,5,0,0,3],[3,3,5,3,6]],"piles":[[1],[13],[24,30,26,31,28],[42,36,38],[]],"toMove":1,"stepCount":49,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"5459ee04-79ef-4069-be56-bb1778c2c665","seed":"92bfyw","startedAt":"2026-07-14T18:06:15.528Z","finishedAt":"2026-07-14T18:07:23.029Z","initialDeckOrder":[14,12,7,44,18,24,9,55,1,32,13,37,58,23,0,4,47,38,45,33,51,11,53,52,46,2,19,22,50,31,8,27,15,26,54,56,43,35,59,20,28,40,16,5,48,57,29,25,36,41,39,6,49,30,17,3,21,42,10,34],"moves":[{"ply":1,"player":"human","action":24,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[7,9,12,14,18,24,44,55],"ai":[0,1,4,13,23,32,37,58]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[7,9,14,18,24,44,47,55],"ai":[0,1,4,13,23,32,37,58]},"scoresAfter":[-40,0]},{"ply":3,"player":"human","action":24,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[7,9,14,18,24,44,47,55],"ai":[1,4,13,23,32,37,38,58]},"scoresAfter":[-60,0]},{"ply":4,"player":"ai","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[7,9,18,24,44,45,47,55],"ai":[1,4,13,23,32,37,38,58]},"scoresAfter":[-60,-40]},{"ply":5,"player":"human","action":42,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[7,9,18,24,44,45,47,55],"ai":[4,13,23,32,33,37,38,58]},"scoresAfter":[-60,-40]},{"ply":6,"player":"ai","action":72,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[7,9,18,44,45,47,51,55],"ai":[4,13,23,32,33,37,38,58]},"scoresAfter":[-60,-80]},{"ply":7,"player":"human","action":36,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[7,9,18,44,45,47,51,55],"ai":[4,11,13,23,32,33,37,58]},"scoresAfter":[-73,-80]},{"ply":8,"player":"ai","action":72,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[7,9,18,45,47,51,53,55],"ai":[4,11,13,23,32,33,37,58]},"scoresAfter":[-73,-100]},{"ply":9,"player":"human","action":36,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[7,9,18,45,47,51,53,55],"ai":[4,11,13,23,32,33,52,58]},"scoresAfter":[-65,-100]},{"ply":10,"player":"ai","action":72,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[7,9,18,46,47,51,53,55],"ai":[4,11,13,23,32,33,52,58]},"scoresAfter":[-65,-117]},{"ply":11,"player":"human","action":36,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[7,9,18,46,47,51,53,55],"ai":[2,4,11,13,23,32,33,58]},"scoresAfter":[-56,-117]},{"ply":12,"player":"ai","action":0,"playedCard":2,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[7,9,18,19,47,51,53,55],"ai":[2,4,11,13,23,32,33,58]},"scoresAfter":[-56,-137]},{"ply":13,"player":"human","action":48,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[7,9,18,19,47,51,53,55],"ai":[4,11,13,22,23,32,33,58]},"scoresAfter":[-46,-137]},{"ply":14,"player":"ai","action":24,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[7,9,18,19,50,51,53,55],"ai":[4,11,13,22,23,32,33,58]},"scoresAfter":[-46,-177]},{"ply":15,"player":"human","action":48,"playedCard":50,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[7,9,18,19,50,51,53,55],"ai":[4,11,22,23,31,32,33,58]},"scoresAfter":[-86,-177]},{"ply":16,"player":"ai","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[7,8,9,18,19,51,53,55],"ai":[4,11,22,23,31,32,33,58]},"scoresAfter":[-86,-168]},{"ply":17,"player":"human","action":60,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[7,8,9,18,19,51,53,55],"ai":[11,22,23,27,31,32,33,58]},"scoresAfter":[-82,-168]},{"ply":18,"player":"ai","action":36,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[7,8,9,15,18,19,53,55],"ai":[11,22,23,27,31,32,33,58]},"scoresAfter":[-82,-186]},{"ply":19,"player":"human","action":72,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[7,8,9,15,18,19,53,55],"ai":[11,22,23,26,31,32,33,58]},"scoresAfter":[-74,-186]},{"ply":20,"player":"ai","action":48,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[7,8,9,15,18,19,54,55],"ai":[11,22,23,26,31,32,33,58]},"scoresAfter":[-74,-180]},{"ply":21,"player":"human","action":72,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[7,8,9,15,18,19,54,55],"ai":[11,22,23,26,32,33,56,58]},"scoresAfter":[-64,-180]},{"ply":22,"player":"ai","action":72,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[7,8,9,15,18,19,43,55],"ai":[11,22,23,26,32,33,56,58]},"scoresAfter":[-64,-173]},{"ply":23,"player":"human","action":84,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[7,8,9,15,18,19,43,55],"ai":[11,22,23,26,32,33,35,58]},"scoresAfter":[-52,-173]},{"ply":24,"player":"ai","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[7,8,9,15,18,19,43,59],"ai":[11,22,23,26,32,33,35,58]},"scoresAfter":[-52,-164]},{"ply":25,"player":"human","action":36,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[7,8,9,15,18,19,43,59],"ai":[11,20,22,23,26,32,33,35]},"scoresAfter":[-46,-164]},{"ply":26,"player":"ai","action":60,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[7,8,9,18,19,28,43,59],"ai":[11,20,22,23,26,32,33,35]},"scoresAfter":[-46,-157]},{"ply":27,"player":"human","action":67,"playedCard":28,"placeType":"discard","drawSource":"discard_0","drawnCard":0,"handsBefore":{"human":[7,8,9,18,19,28,43,59],"ai":[11,20,22,23,26,33,35,40]},"scoresAfter":[-46,-157]},{"ply":28,"player":"ai","action":84,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[0,7,8,9,18,19,43,59],"ai":[11,20,22,23,26,33,35,40]},"scoresAfter":[-46,-148]},{"ply":29,"player":"human","action":0,"playedCard":0,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[0,7,8,9,18,19,43,59],"ai":[11,16,20,22,23,26,33,35]},"scoresAfter":[-86,-148]},{"ply":30,"player":"ai","action":84,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[5,7,8,9,18,19,43,59],"ai":[11,16,20,22,23,26,33,35]},"scoresAfter":[-86,-138]},{"ply":31,"player":"human","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[5,7,8,9,18,19,43,59],"ai":[11,16,20,22,23,26,33,48]},"scoresAfter":[-78,-138]},{"ply":32,"player":"ai","action":90,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[7,8,9,18,19,43,57,59],"ai":[11,16,20,22,23,26,33,48]},"scoresAfter":[-78,-138]},{"ply":33,"player":"human","action":72,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[7,8,9,18,19,43,57,59],"ai":[11,16,20,22,23,26,29,33]},"scoresAfter":[-62,-138]},{"ply":34,"player":"ai","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[7,8,9,18,19,25,43,59],"ai":[11,16,20,22,23,26,29,33]},"scoresAfter":[-62,-108]},{"ply":35,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[7,8,9,18,19,25,43,59],"ai":[16,20,22,23,26,29,33,36]},"scoresAfter":[-42,-108]},{"ply":36,"player":"ai","action":90,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[7,8,9,18,19,25,41,43],"ai":[16,20,22,23,26,29,33,36]},"scoresAfter":[-42,-108]},{"ply":37,"player":"human","action":36,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[7,8,9,18,19,25,41,43],"ai":[16,20,22,23,26,29,33,39]},"scoresAfter":[-27,-108]},{"ply":38,"player":"ai","action":0,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[6,7,8,9,19,25,41,43],"ai":[16,20,22,23,26,29,33,39]},"scoresAfter":[-27,-102]},{"ply":39,"player":"human","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[6,7,8,9,19,25,41,43],"ai":[20,22,23,26,29,33,39,49]},"scoresAfter":[-17,-102]},{"ply":40,"player":"ai","action":0,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[7,8,9,19,25,30,41,43],"ai":[20,22,23,26,29,33,39,49]},"scoresAfter":[-17,-88]},{"ply":41,"player":"human","action":5,"playedCard":7,"placeType":"play","drawSource":"discard_4","drawnCard":48,"handsBefore":{"human":[7,8,9,19,25,30,41,43],"ai":[17,22,23,26,29,33,39,49]},"scoresAfter":[-5,-88]},{"ply":42,"player":"ai","action":12,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[8,9,19,25,30,41,43,48],"ai":[17,22,23,26,29,33,39,49]},"scoresAfter":[-5,-70]},{"ply":43,"player":"human","action":4,"playedCard":8,"placeType":"play","drawSource":"discard_3","drawnCard":36,"handsBefore":{"human":[8,9,19,25,30,41,43,48],"ai":[3,17,23,26,29,33,39,49]},"scoresAfter":[9,-70]},{"ply":44,"player":"ai","action":24,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[9,19,25,30,36,41,43,48],"ai":[3,17,23,26,29,33,39,49]},"scoresAfter":[9,-50]},{"ply":45,"player":"human","action":3,"playedCard":9,"placeType":"play","drawSource":"discard_2","drawnCard":28,"handsBefore":{"human":[9,19,25,30,36,41,43,48],"ai":[3,17,21,26,29,33,39,49]},"scoresAfter":[25,-50]},{"ply":46,"player":"ai","action":54,"playedCard":29,"placeType":"discard","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[19,25,28,30,36,41,43,48],"ai":[3,17,21,26,29,33,39,49]},"scoresAfter":[25,-50]},{"ply":47,"player":"human","action":0,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[19,25,28,30,36,41,43,48],"ai":[3,17,21,26,33,39,42,49]},"scoresAfter":[43,-50]},{"ply":48,"player":"ai","action":72,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[10,25,28,30,36,41,43,48],"ai":[3,17,21,26,33,39,42,49]},"scoresAfter":[43,-35]}],"finalScores":[43,-35],"outcome":"YOU WIN","finalState":{"deckOrder":[14,12,7,44,18,24,9,55,1,32,13,37,58,23,0,4,47,38,45,33,51,11,53,52,46,2,19,22,50,31,8,27,15,26,54,56,43,35,59,20,28,40,16,5,48,57,29,25,36,41,39,6,49,30,17,3,21,42,10,34],"drawPtr":60,"cardLoc":[3,4,4,2,4,3,3,3,3,3,1,4,3,4,3,3,4,2,3,3,4,2,4,4,5,1,2,4,1,5,1,4,4,2,2,4,1,4,4,2,4,1,4,1,3,3,3,3,1,2,3,3,4,3,3,3,4,3,4,3],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[8,6,0,10,10],[10,10,10,5,9]],"colHandshakes":[[1,2,0,0,1],[2,1,0,2,0]],"colLength":[[6,5,0,4,7],[4,5,4,4,3]],"piles":[[],[],[24,29],[],[]],"toMove":0,"stepCount":48,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"7e464cd8-fbc8-4412-93e9-029a7886cc46","seed":"xbhxnh","startedAt":"2026-07-14T18:08:35.507Z","finishedAt":"2026-07-14T18:10:18.732Z","initialDeckOrder":[37,42,31,58,19,36,4,59,24,48,46,56,57,39,34,50,8,29,5,52,21,12,41,44,6,18,14,53,49,22,32,1,25,45,55,7,33,15,27,13,47,43,0,10,28,23,26,40,54,9,17,20,2,38,16,3,30,11,51,35],"moves":[{"ply":1,"player":"human","action":54,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[4,19,31,36,37,42,58,59],"ai":[24,34,39,46,48,50,56,57]},"scoresAfter":[0,0]},{"ply":2,"player":"ai","action":48,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[4,8,19,31,36,42,58,59],"ai":[24,34,39,46,48,50,56,57]},"scoresAfter":[0,-40]},{"ply":3,"player":"human","action":54,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[4,8,19,31,36,42,58,59],"ai":[24,29,34,39,46,50,56,57]},"scoresAfter":[0,-40]},{"ply":4,"player":"ai","action":60,"playedCard":50,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[4,5,8,19,31,42,58,59],"ai":[24,29,34,39,46,50,56,57]},"scoresAfter":[0,-60]},{"ply":5,"player":"human","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[4,5,8,19,31,42,58,59],"ai":[24,29,34,39,46,52,56,57]},"scoresAfter":[-17,-60]},{"ply":6,"player":"ai","action":0,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[5,8,19,21,31,42,58,59],"ai":[24,29,34,39,46,52,56,57]},"scoresAfter":[-17,-100]},{"ply":7,"player":"human","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[5,8,19,21,31,42,58,59],"ai":[12,29,34,39,46,52,56,57]},"scoresAfter":[-13,-100]},{"ply":8,"player":"ai","action":36,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[8,19,21,31,41,42,58,59],"ai":[12,29,34,39,46,52,56,57]},"scoresAfter":[-13,-118]},{"ply":9,"player":"human","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[8,19,21,31,41,42,58,59],"ai":[12,29,34,44,46,52,56,57]},"scoresAfter":[-6,-118]},{"ply":10,"player":"ai","action":36,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[6,19,21,31,41,42,58,59],"ai":[12,29,34,44,46,52,56,57]},"scoresAfter":[-6,-111]},{"ply":11,"player":"human","action":54,"playedCard":41,"placeType":"discard","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[6,19,21,31,41,42,58,59],"ai":[12,18,29,34,46,52,56,57]},"scoresAfter":[-6,-111]},{"ply":12,"player":"ai","action":0,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[6,14,19,21,31,42,58,59],"ai":[12,18,29,34,46,52,56,57]},"scoresAfter":[-6,-151]},{"ply":13,"player":"human","action":66,"playedCard":42,"placeType":"discard","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[6,14,19,21,31,42,58,59],"ai":[18,29,34,46,52,53,56,57]},"scoresAfter":[-6,-151]},{"ply":14,"player":"ai","action":36,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[6,14,19,21,31,49,58,59],"ai":[18,29,34,46,52,53,56,57]},"scoresAfter":[-6,-142]},{"ply":15,"player":"human","action":12,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[6,14,19,21,31,49,58,59],"ai":[18,22,29,34,52,53,56,57]},"scoresAfter":[-46,-142]},{"ply":16,"player":"ai","action":0,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[6,19,21,31,32,49,58,59],"ai":[18,22,29,34,52,53,56,57]},"scoresAfter":[-46,-132]},{"ply":17,"player":"human","action":60,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[6,19,21,31,32,49,58,59],"ai":[1,22,29,34,52,53,56,57]},"scoresAfter":[-86,-132]},{"ply":18,"player":"ai","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[6,19,21,25,31,32,58,59],"ai":[1,22,29,34,52,53,56,57]},"scoresAfter":[-86,-132]},{"ply":19,"player":"human","action":36,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[6,19,21,25,31,32,58,59],"ai":[22,29,34,45,52,53,56,57]},"scoresAfter":[-126,-132]},{"ply":20,"player":"ai","action":48,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[6,19,21,31,32,55,58,59],"ai":[22,29,34,45,52,53,56,57]},"scoresAfter":[-126,-123]},{"ply":21,"player":"human","action":60,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[6,19,21,31,32,55,58,59],"ai":[7,22,29,34,45,53,56,57]},"scoresAfter":[-114,-123]},{"ply":22,"player":"ai","action":60,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[6,19,21,31,32,33,58,59],"ai":[7,22,29,34,45,53,56,57]},"scoresAfter":[-114,-111]},{"ply":23,"player":"human","action":36,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[6,19,21,31,32,33,58,59],"ai":[7,15,22,29,34,45,56,57]},"scoresAfter":[-102,-111]},{"ply":24,"player":"ai","action":72,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[6,19,21,27,32,33,58,59],"ai":[7,15,22,29,34,45,56,57]},"scoresAfter":[-102,-90]},{"ply":25,"player":"human","action":48,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[6,19,21,27,32,33,58,59],"ai":[7,13,15,22,29,34,45,57]},"scoresAfter":[-88,-90]},{"ply":26,"player":"ai","action":18,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[6,19,21,27,33,47,58,59],"ai":[7,13,15,22,29,34,45,57]},"scoresAfter":[-88,-90]},{"ply":27,"player":"human","action":48,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[6,19,21,27,33,47,58,59],"ai":[7,15,22,29,34,43,45,57]},"scoresAfter":[-72,-90]},{"ply":28,"player":"ai","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[0,6,19,21,27,47,58,59],"ai":[7,15,22,29,34,43,45,57]},"scoresAfter":[-72,-104]},{"ply":29,"player":"human","action":18,"playedCard":6,"placeType":"discard","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[0,6,19,21,27,47,58,59],"ai":[10,15,22,29,34,43,45,57]},"scoresAfter":[-72,-104]},{"ply":30,"player":"ai","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[0,19,21,27,28,47,58,59],"ai":[10,15,22,29,34,43,45,57]},"scoresAfter":[-72,-95]},{"ply":31,"player":"human","action":72,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[0,19,21,27,28,47,58,59],"ai":[15,22,23,29,34,43,45,57]},"scoresAfter":[-54,-95]},{"ply":32,"player":"ai","action":36,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[0,19,21,26,27,28,47,59],"ai":[15,22,23,29,34,43,45,57]},"scoresAfter":[-54,-87]},{"ply":33,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[0,19,21,26,27,28,47,59],"ai":[15,22,23,34,40,43,45,57]},"scoresAfter":[-34,-87]},{"ply":34,"player":"ai","action":84,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[0,19,21,26,27,28,47,54],"ai":[15,22,23,34,40,43,45,57]},"scoresAfter":[-34,-63]},{"ply":35,"player":"human","action":54,"playedCard":27,"placeType":"discard","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[0,19,21,26,27,28,47,54],"ai":[9,15,22,23,34,40,43,45]},"scoresAfter":[-34,-63]},{"ply":36,"player":"ai","action":48,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[0,17,19,21,26,28,47,54],"ai":[9,15,22,23,34,40,43,45]},"scoresAfter":[-34,-45]},{"ply":37,"player":"human","action":66,"playedCard":28,"placeType":"discard","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[0,17,19,21,26,28,47,54],"ai":[9,15,20,22,23,40,43,45]},"scoresAfter":[-34,-45]},{"ply":38,"player":"ai","action":24,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[0,2,17,19,21,26,47,54],"ai":[9,15,20,22,23,40,43,45]},"scoresAfter":[-34,-31]},{"ply":39,"player":"human","action":24,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[0,2,17,19,21,26,47,54],"ai":[9,15,22,23,38,40,43,45]},"scoresAfter":[-26,-31]},{"ply":40,"player":"ai","action":24,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[0,2,16,19,21,26,47,54],"ai":[9,15,22,23,38,40,43,45]},"scoresAfter":[-26,-13]},{"ply":41,"player":"human","action":36,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[0,2,16,19,21,26,47,54],"ai":[3,9,15,23,38,40,43,45]},"scoresAfter":[-14,-13]},{"ply":42,"player":"ai","action":36,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[0,2,16,21,26,30,47,54],"ai":[3,9,15,23,38,40,43,45]},"scoresAfter":[-14,7]},{"ply":43,"player":"human","action":36,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[0,2,16,21,26,30,47,54],"ai":[3,9,11,15,38,40,43,45]},"scoresAfter":[2,7]},{"ply":44,"player":"ai","action":24,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[0,2,16,26,30,47,51,54],"ai":[3,9,11,15,38,40,43,45]},"scoresAfter":[2,17]}],"finalScores":[2,17],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[37,42,31,58,19,36,4,59,24,48,46,56,57,39,34,50,8,29,5,52,21,12,41,44,6,18,14,53,49,22,32,1,25,45,55,7,33,15,27,13,47,43,0,10,28,23,26,40,54,9,17,20,2,38,16,3,30,11,51,35],"drawPtr":60,"cardLoc":[1,5,1,2,3,3,5,4,3,2,4,4,4,5,3,2,1,3,4,3,4,3,4,4,4,3,1,5,5,4,1,3,3,3,4,2,5,5,2,4,2,5,5,2,4,2,4,1,4,3,4,1,4,4,1,3,4,4,3,3],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[7,8,8,0,10],[10,10,9,9,8]],"colHandshakes":[[0,1,1,0,1],[0,1,1,0,2]],"colLength":[[3,4,4,0,4],[3,5,3,3,6]],"piles":[[1,6],[13],[27,28],[37,36,41,42],[]],"toMove":0,"stepCount":44,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"99eecbbe-cf00-4bcc-a76b-e9a9932c45f0","seed":"8g2a4o","startedAt":"2026-07-14T18:10:19.831Z","finishedAt":"2026-07-14T18:12:13.486Z","initialDeckOrder":[58,32,11,25,49,5,3,34,52,13,0,47,2,56,55,48,51,18,24,16,46,6,28,20,14,37,39,19,22,31,59,53,41,45,30,26,43,7,50,44,54,42,36,12,1,4,27,21,57,10,23,35,8,17,29,33,9,38,40,15],"moves":[{"ply":1,"player":"human","action":36,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[3,5,11,25,32,34,49,58],"ai":[0,2,13,47,48,52,55,56]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":12,"playedCard":2,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[3,5,11,32,34,49,51,58],"ai":[0,2,13,47,48,52,55,56]},"scoresAfter":[-40,-40]},{"ply":3,"player":"human","action":60,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[3,5,11,32,34,49,51,58],"ai":[0,13,18,47,48,52,55,56]},"scoresAfter":[-80,-40]},{"ply":4,"player":"ai","action":48,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[3,5,11,24,32,34,51,58],"ai":[0,13,18,47,48,52,55,56]},"scoresAfter":[-80,-80]},{"ply":5,"player":"human","action":72,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[3,5,11,24,32,34,51,58],"ai":[0,13,16,18,47,52,55,56]},"scoresAfter":[-76,-80]},{"ply":6,"player":"ai","action":12,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[3,5,11,24,32,34,46,58],"ai":[0,13,16,18,47,52,55,56]},"scoresAfter":[-76,-120]},{"ply":7,"player":"human","action":36,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[3,5,11,24,32,34,46,58],"ai":[0,6,16,18,47,52,55,56]},"scoresAfter":[-96,-120]},{"ply":8,"player":"ai","action":0,"playedCard":0,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[3,5,11,28,32,34,46,58],"ai":[0,6,16,18,47,52,55,56]},"scoresAfter":[-96,-140]},{"ply":9,"player":"human","action":36,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[3,5,11,28,32,34,46,58],"ai":[6,16,18,20,47,52,55,56]},"scoresAfter":[-87,-140]},{"ply":10,"player":"ai","action":60,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[3,5,11,14,32,34,46,58],"ai":[6,16,18,20,47,52,55,56]},"scoresAfter":[-87,-134]},{"ply":11,"player":"human","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[3,5,11,14,32,34,46,58],"ai":[6,16,18,20,37,47,55,56]},"scoresAfter":[-105,-134]},{"ply":12,"player":"ai","action":48,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[5,11,14,32,34,39,46,58],"ai":[6,16,18,20,37,47,55,56]},"scoresAfter":[-105,-174]},{"ply":13,"player":"human","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[5,11,14,32,34,39,46,58],"ai":[6,16,18,19,20,47,55,56]},"scoresAfter":[-101,-174]},{"ply":14,"player":"ai","action":72,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[11,14,22,32,34,39,46,58],"ai":[6,16,18,19,20,47,55,56]},"scoresAfter":[-101,-162]},{"ply":15,"player":"human","action":18,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[11,14,22,32,34,39,46,58],"ai":[6,16,18,19,20,31,47,56]},"scoresAfter":[-101,-162]},{"ply":16,"player":"ai","action":62,"playedCard":31,"placeType":"play","drawSource":"discard_1","drawnCard":14,"handsBefore":{"human":[11,22,32,34,39,46,58,59],"ai":[6,16,18,19,20,31,47,56]},"scoresAfter":[-101,-176]},{"ply":17,"player":"human","action":54,"playedCard":39,"placeType":"discard","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[11,22,32,34,39,46,58,59],"ai":[6,14,16,18,19,20,47,56]},"scoresAfter":[-101,-176]},{"ply":18,"player":"ai","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[11,22,32,34,46,53,58,59],"ai":[6,14,16,18,19,20,47,56]},"scoresAfter":[-101,-161]},{"ply":19,"player":"human","action":60,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[11,22,32,34,46,53,58,59],"ai":[14,16,18,19,20,41,47,56]},"scoresAfter":[-93,-161]},{"ply":20,"player":"ai","action":0,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[11,22,32,34,45,46,58,59],"ai":[14,16,18,19,20,41,47,56]},"scoresAfter":[-93,-181]},{"ply":21,"player":"human","action":24,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[11,22,32,34,45,46,58,59],"ai":[16,18,19,20,30,41,47,56]},"scoresAfter":[-72,-181]},{"ply":22,"player":"ai","action":84,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[11,22,26,34,45,46,58,59],"ai":[16,18,19,20,30,41,47,56]},"scoresAfter":[-72,-167]},{"ply":23,"player":"human","action":30,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[11,22,26,34,45,46,58,59],"ai":[16,18,19,20,30,41,43,47]},"scoresAfter":[-72,-167]},{"ply":24,"player":"ai","action":60,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[7,11,22,34,45,46,58,59],"ai":[16,18,19,20,30,41,43,47]},"scoresAfter":[-72,-159]},{"ply":25,"player":"human","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[7,11,22,34,45,46,58,59],"ai":[16,18,19,20,30,43,47,50]},"scoresAfter":[-66,-159]},{"ply":26,"player":"ai","action":60,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[11,22,34,44,45,46,58,59],"ai":[16,18,19,20,30,43,47,50]},"scoresAfter":[-66,-147]},{"ply":27,"player":"human","action":36,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[11,22,34,44,45,46,58,59],"ai":[16,18,19,20,30,47,50,54]},"scoresAfter":[-79,-147]},{"ply":28,"player":"ai","action":54,"playedCard":30,"placeType":"discard","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[11,22,34,42,45,46,58,59],"ai":[16,18,19,20,30,47,50,54]},"scoresAfter":[-79,-147]},{"ply":29,"player":"human","action":48,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[11,22,34,42,45,46,58,59],"ai":[16,18,19,20,36,47,50,54]},"scoresAfter":[-71,-147]},{"ply":30,"player":"ai","action":60,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[11,12,22,34,42,46,58,59],"ai":[16,18,19,20,36,47,50,54]},"scoresAfter":[-71,-127]},{"ply":31,"player":"human","action":60,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[11,12,22,34,42,46,58,59],"ai":[1,16,18,19,20,36,50,54]},"scoresAfter":[-62,-127]},{"ply":32,"player":"ai","action":12,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[4,11,12,22,34,42,58,59],"ai":[1,16,18,19,20,36,50,54]},"scoresAfter":[-62,-118]},{"ply":33,"player":"human","action":48,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[4,11,12,22,34,42,58,59],"ai":[1,18,19,20,27,36,50,54]},"scoresAfter":[-35,-118]},{"ply":34,"player":"ai","action":12,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[4,11,12,21,22,42,58,59],"ai":[1,18,19,20,27,36,50,54]},"scoresAfter":[-35,-103]},{"ply":35,"player":"human","action":24,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[4,11,12,21,22,42,58,59],"ai":[1,19,20,27,36,50,54,57]},"scoresAfter":[-75,-103]},{"ply":36,"player":"ai","action":12,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[4,10,11,21,22,42,58,59],"ai":[1,19,20,27,36,50,54,57]},"scoresAfter":[-75,-85]},{"ply":37,"player":"human","action":12,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[4,10,11,21,22,42,58,59],"ai":[1,20,23,27,36,50,54,57]},"scoresAfter":[-66,-85]},{"ply":38,"player":"ai","action":84,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[4,11,21,22,35,42,58,59],"ai":[1,20,23,27,36,50,54,57]},"scoresAfter":[-66,-69]},{"ply":39,"player":"human","action":48,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[4,11,21,22,35,42,58,59],"ai":[1,8,20,23,27,36,50,54]},"scoresAfter":[-36,-69]},{"ply":40,"player":"ai","action":12,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[4,11,17,21,22,42,58,59],"ai":[1,8,20,23,27,36,50,54]},"scoresAfter":[-36,-48]},{"ply":41,"player":"human","action":76,"playedCard":58,"placeType":"play","drawSource":"discard_3","drawnCard":39,"handsBefore":{"human":[4,11,17,21,22,42,58,59],"ai":[1,20,23,27,29,36,50,54]},"scoresAfter":[-18,-48]},{"ply":42,"player":"ai","action":12,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[4,11,17,21,22,39,42,59],"ai":[1,20,23,27,29,36,50,54]},"scoresAfter":[-18,-27]},{"ply":43,"player":"human","action":27,"playedCard":17,"placeType":"play","drawSource":"discard_2","drawnCard":30,"handsBefore":{"human":[4,11,17,21,22,39,42,59],"ai":[1,23,27,29,33,36,50,54]},"scoresAfter":[-10,-27]},{"ply":44,"player":"ai","action":48,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[4,11,21,22,30,39,42,59],"ai":[1,23,27,29,33,36,50,54]},"scoresAfter":[-10,-19]},{"ply":45,"player":"human","action":27,"playedCard":21,"placeType":"play","drawSource":"discard_2","drawnCard":26,"handsBefore":{"human":[4,11,21,22,30,39,42,59],"ai":[1,9,23,27,29,36,50,54]},"scoresAfter":[6,-19]},{"ply":46,"player":"ai","action":12,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[4,11,22,26,30,39,42,59],"ai":[1,9,23,27,29,36,50,54]},"scoresAfter":[6,5]},{"ply":47,"player":"human","action":24,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[4,11,22,26,30,39,42,59],"ai":[1,23,27,29,36,38,50,54]},"scoresAfter":[24,5]},{"ply":48,"player":"ai","action":12,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[4,11,26,30,39,40,42,59],"ai":[1,23,27,29,36,38,50,54]},"scoresAfter":[24,35]}],"finalScores":[24,35],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[58,32,11,25,49,5,3,34,52,13,0,47,2,56,55,48,51,18,24,16,46,6,28,20,14,37,39,19,22,31,59,53,41,45,30,26,43,7,50,44,54,42,36,12,1,4,27,21,57,10,23,35,8,17,29,33,9,38,40,15],"drawPtr":60,"cardLoc":[4,2,4,3,1,3,4,3,4,4,3,1,3,4,4,2,4,3,4,4,4,3,3,4,3,3,1,2,3,2,1,4,3,4,3,3,2,4,2,1,1,4,1,4,3,3,3,4,4,3,2,3,4,3,2,4,4,4,3,1],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,true,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[9,9,10,9,9],[8,10,8,10,8]],"colHandshakes":[[0,1,2,0,1],[2,2,0,1,1]],"colLength":[[4,4,6,3,4],[5,7,2,4,5]],"piles":[[],[],[],[],[]],"toMove":0,"stepCount":48,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"102af78e-fde9-4ff2-a6bf-905e6f7f8c88","seed":"8zpoaa","startedAt":"2026-07-14T18:12:14.281Z","finishedAt":"2026-07-14T18:14:14.892Z","initialDeckOrder":[13,29,24,18,3,36,52,42,6,2,17,26,23,5,27,46,44,56,12,50,20,32,59,19,10,49,53,11,33,54,8,51,31,16,55,37,57,48,1,41,39,40,28,9,45,21,43,7,30,4,35,22,25,38,15,14,0,58,34,47],"moves":[{"ply":1,"player":"human","action":60,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[3,13,18,24,29,36,42,52],"ai":[2,5,6,17,23,26,27,46]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":0,"playedCard":2,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[3,13,18,24,29,42,44,52],"ai":[2,5,6,17,23,26,27,46]},"scoresAfter":[-40,-40]},{"ply":3,"player":"human","action":60,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[3,13,18,24,29,42,44,52],"ai":[5,6,17,23,26,27,46,56]},"scoresAfter":[-30,-40]},{"ply":4,"player":"ai","action":48,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[3,12,13,18,24,29,44,52],"ai":[5,6,17,23,26,27,46,56]},"scoresAfter":[-30,-80]},{"ply":5,"player":"human","action":54,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[3,12,13,18,24,29,44,52],"ai":[5,6,17,23,27,46,50,56]},"scoresAfter":[-30,-80]},{"ply":6,"player":"ai","action":48,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[3,12,13,18,20,29,44,52],"ai":[5,6,17,23,27,46,50,56]},"scoresAfter":[-30,-76]},{"ply":7,"player":"human","action":24,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[3,12,13,18,20,29,44,52],"ai":[5,6,17,23,32,46,50,56]},"scoresAfter":[-70,-76]},{"ply":8,"player":"ai","action":48,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[3,12,18,20,29,44,52,59],"ai":[5,6,17,23,32,46,50,56]},"scoresAfter":[-70,-62]},{"ply":9,"player":"human","action":12,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[3,12,18,20,29,44,52,59],"ai":[5,6,17,19,23,46,50,56]},"scoresAfter":[-90,-62]},{"ply":10,"player":"ai","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[3,10,18,20,29,44,52,59],"ai":[5,6,17,19,23,46,50,56]},"scoresAfter":[-90,-54]},{"ply":11,"player":"human","action":60,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[3,10,18,20,29,44,52,59],"ai":[6,17,19,23,46,49,50,56]},"scoresAfter":[-76,-54]},{"ply":12,"player":"ai","action":78,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[3,10,18,20,29,52,53,59],"ai":[6,17,19,23,46,49,50,56]},"scoresAfter":[-76,-54]},{"ply":13,"player":"human","action":29,"playedCard":18,"placeType":"play","drawSource":"discard_4","drawnCard":50,"handsBefore":{"human":[3,10,18,20,29,52,53,59],"ai":[6,11,17,19,23,46,49,56]},"scoresAfter":[-61,-54]},{"ply":14,"player":"ai","action":24,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[3,10,20,29,50,52,53,59],"ai":[6,11,17,19,23,46,49,56]},"scoresAfter":[-61,-70]},{"ply":15,"player":"human","action":48,"playedCard":50,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[3,10,20,29,50,52,53,59],"ai":[6,11,19,23,33,46,49,56]},"scoresAfter":[-101,-70]},{"ply":16,"player":"ai","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[3,10,20,29,52,53,54,59],"ai":[6,11,19,23,33,46,49,56]},"scoresAfter":[-101,-60]},{"ply":17,"player":"human","action":48,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[3,10,20,29,52,53,54,59],"ai":[8,11,19,23,33,46,49,56]},"scoresAfter":[-95,-60]},{"ply":18,"player":"ai","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[3,10,20,29,51,53,54,59],"ai":[8,11,19,23,33,46,49,56]},"scoresAfter":[-95,-46]},{"ply":19,"player":"human","action":60,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[3,10,20,29,51,53,54,59],"ai":[11,19,23,31,33,46,49,56]},"scoresAfter":[-87,-46]},{"ply":20,"player":"ai","action":72,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[3,10,16,20,29,51,54,59],"ai":[11,19,23,31,33,46,49,56]},"scoresAfter":[-87,-86]},{"ply":21,"player":"human","action":72,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[3,10,16,20,29,51,54,59],"ai":[11,19,23,31,33,46,55,56]},"scoresAfter":[-77,-86]},{"ply":22,"player":"ai","action":72,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[3,10,16,20,29,37,51,59],"ai":[11,19,23,31,33,46,55,56]},"scoresAfter":[-77,-74]},{"ply":23,"player":"human","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[3,10,16,20,29,37,51,59],"ai":[11,19,23,31,33,46,56,57]},"scoresAfter":[-95,-74]},{"ply":24,"player":"ai","action":72,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[10,16,20,29,37,48,51,59],"ai":[11,19,23,31,33,46,56,57]},"scoresAfter":[-95,-60]},{"ply":25,"player":"human","action":66,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[10,16,20,29,37,48,51,59],"ai":[1,11,19,23,31,33,46,57]},"scoresAfter":[-95,-60]},{"ply":26,"player":"ai","action":84,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[10,16,20,29,37,41,51,59],"ai":[1,11,19,23,31,33,46,57]},"scoresAfter":[-95,-44]},{"ply":27,"player":"human","action":78,"playedCard":51,"placeType":"discard","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[10,16,20,29,37,41,51,59],"ai":[1,11,19,23,31,33,39,46]},"scoresAfter":[-95,-44]},{"ply":28,"player":"ai","action":12,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[10,16,20,29,37,40,41,59],"ai":[1,11,19,23,31,33,39,46]},"scoresAfter":[-95,-24]},{"ply":29,"player":"human","action":18,"playedCard":16,"placeType":"discard","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[10,16,20,29,37,40,41,59],"ai":[1,19,23,28,31,33,39,46]},"scoresAfter":[-95,-24]},{"ply":30,"player":"ai","action":12,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[9,10,20,29,37,40,41,59],"ai":[1,19,23,28,31,33,39,46]},"scoresAfter":[-95,-18]},{"ply":31,"player":"human","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[9,10,20,29,37,40,41,59],"ai":[1,23,28,31,33,39,45,46]},"scoresAfter":[-87,-18]},{"ply":32,"player":"ai","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[10,20,21,29,37,40,41,59],"ai":[1,23,28,31,33,39,45,46]},"scoresAfter":[-87,-18]},{"ply":33,"player":"human","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[10,20,21,29,37,40,41,59],"ai":[23,28,31,33,39,43,45,46]},"scoresAfter":[-78,-18]},{"ply":34,"player":"ai","action":0,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[7,20,21,29,37,40,41,59],"ai":[23,28,31,33,39,43,45,46]},"scoresAfter":[-78,-8]},{"ply":35,"player":"human","action":12,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[7,20,21,29,37,40,41,59],"ai":[28,30,31,33,39,43,45,46]},"scoresAfter":[-57,-8]},{"ply":36,"player":"ai","action":60,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[4,7,21,29,37,40,41,59],"ai":[28,30,31,33,39,43,45,46]},"scoresAfter":[-57,-22]},{"ply":37,"player":"human","action":24,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[4,7,21,29,37,40,41,59],"ai":[28,30,31,33,35,39,45,46]},"scoresAfter":[-33,-22]},{"ply":38,"player":"ai","action":72,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[4,7,22,29,37,40,41,59],"ai":[28,30,31,33,35,39,45,46]},"scoresAfter":[-33,-14]},{"ply":39,"player":"human","action":24,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[4,7,22,29,37,40,41,59],"ai":[25,28,30,31,33,35,39,46]},"scoresAfter":[-6,-14]},{"ply":40,"player":"ai","action":84,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[4,7,29,37,38,40,41,59],"ai":[25,28,30,31,33,35,39,46]},"scoresAfter":[-6,-5]},{"ply":41,"player":"human","action":42,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[4,7,29,37,38,40,41,59],"ai":[15,25,28,30,31,33,35,39]},"scoresAfter":[-6,-5]},{"ply":42,"player":"ai","action":64,"playedCard":33,"placeType":"play","drawSource":"discard_3","drawnCard":37,"handsBefore":{"human":[4,7,14,29,38,40,41,59],"ai":[15,25,28,30,31,33,35,39]},"scoresAfter":[-6,11]},{"ply":43,"player":"human","action":30,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[4,7,14,29,38,40,41,59],"ai":[15,25,28,30,31,35,37,39]},"scoresAfter":[-6,11]},{"ply":44,"player":"ai","action":60,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[0,4,7,29,38,40,41,59],"ai":[15,25,28,30,31,35,37,39]},"scoresAfter":[-6,31]},{"ply":45,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[0,4,7,29,38,40,41,59],"ai":[15,25,28,30,31,37,39,58]},"scoresAfter":[14,31]},{"ply":46,"player":"ai","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[0,4,7,29,34,38,40,41],"ai":[15,25,28,30,31,37,39,58]},"scoresAfter":[14,49]}],"finalScores":[14,49],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[13,29,24,18,3,36,52,42,6,2,17,26,23,5,27,46,44,56,12,50,20,32,59,19,10,49,53,11,33,54,8,51,31,16,55,37,57,48,1,41,39,40,28,9,45,21,43,7,30,4,35,22,25,38,15,14,0,58,34,47],"drawPtr":60,"cardLoc":[1,5,4,3,1,4,4,1,4,3,3,4,3,3,5,2,5,4,3,4,3,3,3,4,5,2,4,4,2,1,2,2,4,4,1,4,3,2,1,2,1,1,3,4,3,4,4,2,5,4,3,5,3,3,3,4,4,4,4,3],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[9,9,0,7,10],[10,10,10,9,9]],"colHandshakes":[[0,2,0,1,1],[1,0,1,0,1]],"colLength":[[3,6,0,3,5],[5,3,5,3,5]],"piles":[[1],[16,14],[24],[],[48,51]],"toMove":0,"stepCount":46,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"4c5a8f51-5da9-4602-9b4e-49ef4c08c403","seed":"nm9y69","startedAt":"2026-07-14T18:14:15.860Z","finishedAt":"2026-07-14T18:15:48.669Z","initialDeckOrder":[28,52,8,3,11,16,44,41,7,35,50,19,14,25,45,12,17,4,48,10,36,46,51,54,5,58,26,0,32,18,31,27,21,20,47,42,39,57,23,24,55,40,6,22,34,15,9,59,1,43,2,29,13,37,56,33,53,30,49,38],"moves":[{"ply":1,"player":"human","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[3,8,11,16,28,41,44,52],"ai":[7,12,14,19,25,35,45,50]},"scoresAfter":[-18,0]},{"ply":2,"player":"ai","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[8,11,16,17,28,41,44,52],"ai":[7,12,14,19,25,35,45,50]},"scoresAfter":[-18,-14]},{"ply":3,"player":"human","action":60,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[8,11,16,17,28,41,44,52],"ai":[4,12,14,19,25,35,45,50]},"scoresAfter":[-34,-14]},{"ply":4,"player":"ai","action":6,"playedCard":4,"placeType":"discard","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[8,11,16,17,28,44,48,52],"ai":[4,12,14,19,25,35,45,50]},"scoresAfter":[-34,-14]},{"ply":5,"player":"human","action":24,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[8,11,16,17,28,44,48,52],"ai":[10,12,14,19,25,35,45,50]},"scoresAfter":[-51,-14]},{"ply":6,"player":"ai","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[8,11,17,28,36,44,48,52],"ai":[10,12,14,19,25,35,45,50]},"scoresAfter":[-51,-5]},{"ply":7,"player":"human","action":24,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[8,11,17,28,36,44,48,52],"ai":[12,14,19,25,35,45,46,50]},"scoresAfter":[-47,-5]},{"ply":8,"player":"ai","action":0,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[8,11,28,36,44,48,51,52],"ai":[12,14,19,25,35,45,46,50]},"scoresAfter":[-47,-45]},{"ply":9,"player":"human","action":60,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[8,11,28,36,44,48,51,52],"ai":[14,19,25,35,45,46,50,54]},"scoresAfter":[-87,-45]},{"ply":10,"player":"ai","action":84,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[5,8,11,28,36,44,51,52],"ai":[14,19,25,35,45,46,50,54]},"scoresAfter":[-87,-60]},{"ply":11,"player":"human","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[5,8,11,28,36,44,51,52],"ai":[14,19,25,35,45,46,50,58]},"scoresAfter":[-83,-60]},{"ply":12,"player":"ai","action":0,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[8,11,26,28,36,44,51,52],"ai":[14,19,25,35,45,46,50,58]},"scoresAfter":[-83,-80]},{"ply":13,"player":"human","action":72,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[8,11,26,28,36,44,51,52],"ai":[0,19,25,35,45,46,50,58]},"scoresAfter":[-79,-80]},{"ply":14,"player":"ai","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[8,11,26,28,32,36,44,52],"ai":[0,19,25,35,45,46,50,58]},"scoresAfter":[-79,-80]},{"ply":15,"player":"human","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[8,11,26,28,32,36,44,52],"ai":[18,19,25,35,45,46,50,58]},"scoresAfter":[-72,-80]},{"ply":16,"player":"ai","action":78,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[11,26,28,31,32,36,44,52],"ai":[18,19,25,35,45,46,50,58]},"scoresAfter":[-72,-80]},{"ply":17,"player":"human","action":24,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[11,26,28,31,32,36,44,52],"ai":[18,19,25,27,35,45,46,58]},"scoresAfter":[-89,-80]},{"ply":18,"player":"ai","action":24,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[11,21,26,31,32,36,44,52],"ai":[18,19,25,27,35,45,46,58]},"scoresAfter":[-89,-120]},{"ply":19,"player":"human","action":36,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[11,21,26,31,32,36,44,52],"ai":[18,19,20,27,35,45,46,58]},"scoresAfter":[-83,-120]},{"ply":20,"player":"ai","action":60,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[11,21,26,32,36,44,47,52],"ai":[18,19,20,27,35,45,46,58]},"scoresAfter":[-83,-132]},{"ply":21,"player":"human","action":36,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[11,21,26,32,36,44,47,52],"ai":[18,19,20,27,35,42,46,58]},"scoresAfter":[-76,-132]},{"ply":22,"player":"ai","action":72,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[11,21,26,36,39,44,47,52],"ai":[18,19,20,27,35,42,46,58]},"scoresAfter":[-76,-123]},{"ply":23,"player":"human","action":60,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[11,21,26,36,39,44,47,52],"ai":[18,19,20,27,35,42,57,58]},"scoresAfter":[-69,-123]},{"ply":24,"player":"ai","action":72,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[11,21,23,26,36,39,47,52],"ai":[18,19,20,27,35,42,57,58]},"scoresAfter":[-69,-115]},{"ply":25,"player":"human","action":84,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[11,21,23,26,36,39,47,52],"ai":[18,19,20,24,27,35,42,58]},"scoresAfter":[-63,-115]},{"ply":26,"player":"ai","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[11,21,23,26,36,39,47,55],"ai":[18,19,20,24,27,35,42,58]},"scoresAfter":[-63,-106]},{"ply":27,"player":"human","action":84,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[11,21,23,26,36,39,47,55],"ai":[18,19,20,24,27,35,40,42]},"scoresAfter":[-51,-106]},{"ply":28,"player":"ai","action":78,"playedCard":40,"placeType":"discard","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[6,11,21,23,26,36,39,47],"ai":[18,19,20,24,27,35,40,42]},"scoresAfter":[-51,-106]},{"ply":29,"player":"human","action":24,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[6,11,21,23,26,36,39,47],"ai":[18,19,20,22,24,27,35,42]},"scoresAfter":[-43,-106]},{"ply":30,"player":"ai","action":72,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[6,11,23,26,34,36,39,47],"ai":[18,19,20,22,24,27,35,42]},"scoresAfter":[-43,-86]},{"ply":31,"player":"human","action":48,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[6,11,23,26,34,36,39,47],"ai":[15,18,19,20,22,24,27,42]},"scoresAfter":[-34,-86]},{"ply":32,"player":"ai","action":0,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[6,9,11,23,26,36,39,47],"ai":[15,18,19,20,22,24,27,42]},"scoresAfter":[-34,-80]},{"ply":33,"player":"human","action":12,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[6,9,11,23,26,36,39,47],"ai":[18,19,20,22,24,27,42,59]},"scoresAfter":[-26,-80]},{"ply":34,"player":"ai","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[1,6,11,23,26,36,39,47],"ai":[18,19,20,22,24,27,42,59]},"scoresAfter":[-26,-70]},{"ply":35,"player":"human","action":24,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[1,6,11,23,26,36,39,47],"ai":[18,19,20,22,24,27,42,43]},"scoresAfter":[-16,-70]},{"ply":36,"player":"ai","action":0,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[1,2,6,23,26,36,39,47],"ai":[18,19,20,22,24,27,42,43]},"scoresAfter":[-16,-55]},{"ply":37,"player":"human","action":36,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[1,2,6,23,26,36,39,47],"ai":[19,20,22,24,27,29,42,43]},"scoresAfter":[-6,-55]},{"ply":38,"player":"ai","action":0,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[1,2,6,13,26,36,39,47],"ai":[19,20,22,24,27,29,42,43]},"scoresAfter":[-6,-37]},{"ply":39,"player":"human","action":84,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[1,2,6,13,26,36,39,47],"ai":[20,22,24,27,29,37,42,43]},"scoresAfter":[4,-37]},{"ply":40,"player":"ai","action":0,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[1,2,6,13,26,36,39,56],"ai":[20,22,24,27,29,37,42,43]},"scoresAfter":[4,-16]},{"ply":41,"player":"human","action":84,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[1,2,6,13,26,36,39,56],"ai":[22,24,27,29,33,37,42,43]},"scoresAfter":[18,-16]},{"ply":42,"player":"ai","action":1,"playedCard":22,"placeType":"play","drawSource":"discard_0","drawnCard":0,"handsBefore":{"human":[1,2,6,13,26,36,39,53],"ai":[22,24,27,29,33,37,42,43]},"scoresAfter":[18,11]},{"ply":43,"player":"human","action":90,"playedCard":53,"placeType":"discard","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[1,2,6,13,26,36,39,53],"ai":[0,24,27,29,33,37,42,43]},"scoresAfter":[18,11]},{"ply":44,"player":"ai","action":78,"playedCard":42,"placeType":"discard","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[1,2,6,13,26,30,36,39],"ai":[0,24,27,29,33,37,42,43]},"scoresAfter":[18,11]},{"ply":45,"player":"human","action":66,"playedCard":30,"placeType":"discard","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[1,2,6,13,26,30,36,39],"ai":[0,24,27,29,33,37,43,49]},"scoresAfter":[18,11]}],"finalScores":[18,11],"outcome":"YOU WIN","finalState":{"deckOrder":[28,52,8,3,11,16,44,41,7,35,50,19,14,25,45,12,17,4,48,10,36,46,51,54,5,58,26,0,32,18,31,27,21,20,47,42,39,57,23,24,55,40,6,22,34,15,9,59,1,43,2,29,13,37,56,33,53,30,49,38],"drawPtr":60,"cardLoc":[2,1,1,3,5,3,1,4,3,3,4,3,4,1,4,4,3,3,4,4,4,3,4,3,2,4,1,2,3,2,5,3,3,2,3,4,1,2,1,1,5,3,5,2,3,4,4,3,3,2,5,3,3,5,4,3,3,4,4,4],"handPublic":[true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,10,9,10,7],[9,9,10,9,10]],"colHandshakes":[[0,0,0,0,1],[0,2,1,0,0]],"colLength":[[5,4,4,3,5],[2,7,2,2,4]],"piles":[[4],[],[30],[40,42],[50,53]],"toMove":1,"stepCount":45,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"0b3fe6b1-f10c-4622-bc79-09f18d05c6ef","seed":"tfj6iq","startedAt":"2026-07-14T18:15:49.850Z","finishedAt":"2026-07-14T18:18:24.900Z","initialDeckOrder":[57,22,21,11,9,25,37,6,26,53,41,44,49,31,7,2,24,34,42,47,39,54,52,5,3,30,56,36,51,12,8,35,33,46,0,1,4,19,45,23,10,50,40,38,27,28,15,13,14,29,48,43,17,18,20,16,58,32,55,59],"moves":[{"ply":1,"player":"human","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[6,9,11,21,22,25,37,57],"ai":[2,7,26,31,41,44,49,53]},"scoresAfter":[-15,0]},{"ply":2,"player":"ai","action":24,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[9,11,21,22,24,25,37,57],"ai":[2,7,26,31,41,44,49,53]},"scoresAfter":[-15,-40]},{"ply":3,"player":"human","action":54,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[9,11,21,22,24,25,37,57],"ai":[2,7,31,34,41,44,49,53]},"scoresAfter":[-15,-40]},{"ply":4,"player":"ai","action":78,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[9,11,21,22,25,37,42,57],"ai":[2,7,31,34,41,44,49,53]},"scoresAfter":[-15,-40]},{"ply":5,"player":"human","action":54,"playedCard":25,"placeType":"discard","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[9,11,21,22,25,37,42,57],"ai":[2,7,31,34,41,44,47,53]},"scoresAfter":[-15,-40]},{"ply":6,"player":"ai","action":84,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[9,11,21,22,37,39,42,57],"ai":[2,7,31,34,41,44,47,53]},"scoresAfter":[-15,-56]},{"ply":7,"player":"human","action":48,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[9,11,21,22,37,39,42,57],"ai":[2,7,31,34,41,44,47,54]},"scoresAfter":[-55,-56]},{"ply":8,"player":"ai","action":48,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[9,11,21,22,39,42,52,57],"ai":[2,7,31,34,41,44,47,54]},"scoresAfter":[-55,-72]},{"ply":9,"player":"human","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[9,11,21,22,39,42,52,57],"ai":[2,5,7,31,34,44,47,54]},"scoresAfter":[-47,-72]},{"ply":10,"player":"ai","action":0,"playedCard":2,"placeType":"play","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[3,11,21,22,39,42,52,57],"ai":[2,5,7,31,34,44,47,54]},"scoresAfter":[-47,-112]},{"ply":11,"player":"human","action":53,"playedCard":39,"placeType":"play","drawSource":"discard_4","drawnCard":49,"handsBefore":{"human":[3,11,21,22,39,42,52,57],"ai":[5,7,30,31,34,44,47,54]},"scoresAfter":[-43,-112]},{"ply":12,"player":"ai","action":63,"playedCard":44,"placeType":"play","drawSource":"discard_2","drawnCard":25,"handsBefore":{"human":[3,11,21,22,42,49,52,57],"ai":[5,7,30,31,34,44,47,54]},"scoresAfter":[-43,-105]},{"ply":13,"player":"human","action":60,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[3,11,21,22,42,49,52,57],"ai":[5,7,25,30,31,34,47,54]},"scoresAfter":[-83,-105]},{"ply":14,"player":"ai","action":75,"playedCard":47,"placeType":"play","drawSource":"discard_2","drawnCard":24,"handsBefore":{"human":[3,11,21,22,42,52,56,57],"ai":[5,7,25,30,31,34,47,54]},"scoresAfter":[-83,-95]},{"ply":15,"player":"human","action":60,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[3,11,21,22,42,52,56,57],"ai":[5,7,24,25,30,31,34,54]},"scoresAfter":[-77,-95]},{"ply":16,"player":"ai","action":84,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[3,11,21,22,36,42,56,57],"ai":[5,7,24,25,30,31,34,54]},"scoresAfter":[-77,-90]},{"ply":17,"player":"human","action":60,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[3,11,21,22,36,42,56,57],"ai":[5,7,24,25,30,31,34,51]},"scoresAfter":[-67,-90]},{"ply":18,"player":"ai","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[3,11,12,21,22,36,56,57],"ai":[5,7,24,25,30,31,34,51]},"scoresAfter":[-67,-82]},{"ply":19,"player":"human","action":24,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[3,11,12,21,22,36,56,57],"ai":[7,8,24,25,30,31,34,51]},"scoresAfter":[-107,-82]},{"ply":20,"player":"ai","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[3,11,21,22,35,36,56,57],"ai":[7,8,24,25,30,31,34,51]},"scoresAfter":[-107,-70]},{"ply":21,"player":"human","action":12,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[3,11,21,22,35,36,56,57],"ai":[8,24,25,30,31,33,34,51]},"scoresAfter":[-97,-70]},{"ply":22,"player":"ai","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[3,21,22,35,36,46,56,57],"ai":[8,24,25,30,31,33,34,51]},"scoresAfter":[-97,-56]},{"ply":23,"player":"human","action":72,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[3,21,22,35,36,46,56,57],"ai":[0,24,25,30,31,33,34,51]},"scoresAfter":[-83,-56]},{"ply":24,"player":"ai","action":12,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[1,3,21,22,35,36,46,57],"ai":[0,24,25,30,31,33,34,51]},"scoresAfter":[-83,-76]},{"ply":25,"player":"human","action":84,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[1,3,21,22,35,36,46,57],"ai":[0,4,25,30,31,33,34,51]},"scoresAfter":[-67,-76]},{"ply":26,"player":"ai","action":18,"playedCard":4,"placeType":"discard","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[1,3,19,21,22,35,36,46],"ai":[0,4,25,30,31,33,34,51]},"scoresAfter":[-67,-76]},{"ply":27,"player":"human","action":24,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[1,3,19,21,22,35,36,46],"ai":[0,25,30,31,33,34,45,51]},"scoresAfter":[-55,-76]},{"ply":28,"player":"ai","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[1,3,21,22,23,35,36,46],"ai":[0,25,30,31,33,34,45,51]},"scoresAfter":[-55,-76]},{"ply":29,"player":"human","action":24,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[1,3,21,22,23,35,36,46],"ai":[10,25,30,31,33,34,45,51]},"scoresAfter":[-39,-76]},{"ply":30,"player":"ai","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[1,3,22,23,35,36,46,50],"ai":[10,25,30,31,33,34,45,51]},"scoresAfter":[-39,-58]},{"ply":31,"player":"human","action":24,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[1,3,22,23,35,36,46,50],"ai":[25,30,31,33,34,40,45,51]},"scoresAfter":[-21,-58]},{"ply":32,"player":"ai","action":0,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[1,3,23,35,36,38,46,50],"ai":[25,30,31,33,34,40,45,51]},"scoresAfter":[-21,-78]},{"ply":33,"player":"human","action":24,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[1,3,23,35,36,38,46,50],"ai":[27,30,31,33,34,40,45,51]},"scoresAfter":[-1,-78]},{"ply":34,"player":"ai","action":0,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[1,3,28,35,36,38,46,50],"ai":[27,30,31,33,34,40,45,51]},"scoresAfter":[-1,-70]},{"ply":35,"player":"human","action":18,"playedCard":3,"placeType":"discard","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[1,3,28,35,36,38,46,50],"ai":[15,30,31,33,34,40,45,51]},"scoresAfter":[-1,-70]},{"ply":36,"player":"ai","action":0,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[1,13,28,35,36,38,46,50],"ai":[15,30,31,33,34,40,45,51]},"scoresAfter":[-1,-88]},{"ply":37,"player":"human","action":18,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[1,13,28,35,36,38,46,50],"ai":[14,30,31,33,34,40,45,51]},"scoresAfter":[-1,-88]},{"ply":38,"player":"ai","action":12,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[1,28,29,35,36,38,46,50],"ai":[14,30,31,33,34,40,45,51]},"scoresAfter":[-1,-68]},{"ply":39,"player":"human","action":6,"playedCard":1,"placeType":"discard","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[1,28,29,35,36,38,46,50],"ai":[14,31,33,34,40,45,48,51]},"scoresAfter":[-1,-68]},{"ply":40,"player":"ai","action":12,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[28,29,35,36,38,43,46,50],"ai":[14,31,33,34,40,45,48,51]},"scoresAfter":[-1,-44]},{"ply":41,"player":"human","action":60,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[28,29,35,36,38,43,46,50],"ai":[14,17,33,34,40,45,48,51]},"scoresAfter":[11,-44]},{"ply":42,"player":"ai","action":24,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[18,28,29,35,36,38,46,50],"ai":[14,17,33,34,40,45,48,51]},"scoresAfter":[11,-12]},{"ply":43,"player":"human","action":18,"playedCard":28,"placeType":"discard","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[18,28,29,35,36,38,46,50],"ai":[14,17,20,34,40,45,48,51]},"scoresAfter":[11,-12]},{"ply":44,"player":"ai","action":24,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[16,18,29,35,36,38,46,50],"ai":[14,17,20,34,40,45,48,51]},"scoresAfter":[11,-5]},{"ply":45,"player":"human","action":30,"playedCard":29,"placeType":"discard","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[16,18,29,35,36,38,46,50],"ai":[14,17,34,40,45,48,51,58]},"scoresAfter":[11,-5]},{"ply":46,"player":"ai","action":24,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[16,18,32,35,36,38,46,50],"ai":[14,17,34,40,45,48,51,58]},"scoresAfter":[11,51]},{"ply":47,"player":"human","action":72,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[16,18,32,35,36,38,46,50],"ai":[14,17,40,45,48,51,55,58]},"scoresAfter":[29,51]}],"finalScores":[29,51],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[57,22,21,11,9,25,37,6,26,53,41,44,49,31,7,2,24,34,42,47,39,54,52,5,3,30,56,36,51,12,8,35,33,46,0,1,4,19,45,23,10,50,40,38,27,28,15,13,14,29,48,43,17,18,20,16,58,32,55,59],"drawPtr":60,"cardLoc":[5,5,4,5,5,4,3,4,4,3,4,3,3,5,2,4,1,2,1,3,4,3,3,3,4,4,4,4,5,5,4,4,1,4,4,1,1,3,1,3,2,4,3,3,4,2,3,4,2,3,1,2,3,4,4,2,3,3,2,1],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,10,0,9,8],[9,7,9,10,5]],"colHandshakes":[[0,1,0,1,1],[1,0,3,0,0]],"colLength":[[3,5,0,5,4],[5,2,8,3,2]],"piles":[[4,0,3,1],[13],[28,29],[],[]],"toMove":1,"stepCount":47,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"309958c2-0d9d-4874-baf2-4b9f3cfc0af6","seed":"rw42jg","startedAt":"2026-07-14T18:18:25.728Z","finishedAt":"2026-07-14T18:21:44.749Z","initialDeckOrder":[0,15,42,48,32,1,57,25,53,23,52,18,38,12,56,4,27,24,55,43,17,50,58,39,41,28,45,5,59,16,35,14,29,44,33,6,8,26,7,10,30,36,11,40,51,13,20,22,47,19,54,9,34,37,21,49,3,2,31,46],"moves":[{"ply":1,"player":"human","action":72,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[0,1,15,25,32,42,48,57],"ai":[4,12,18,23,38,52,53,56]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":72,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[0,1,15,25,27,32,42,57],"ai":[4,12,18,23,38,52,53,56]},"scoresAfter":[-40,-16]},{"ply":3,"player":"human","action":36,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[0,1,15,25,27,32,42,57],"ai":[4,12,18,23,24,38,52,56]},"scoresAfter":[-80,-16]},{"ply":4,"player":"ai","action":66,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[0,1,15,27,32,42,55,57],"ai":[4,12,18,23,24,38,52,56]},"scoresAfter":[-80,-16]},{"ply":5,"player":"human","action":36,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[0,1,15,27,32,42,55,57],"ai":[4,12,18,23,24,43,52,56]},"scoresAfter":[-76,-16]},{"ply":6,"player":"ai","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[0,1,15,17,32,42,55,57],"ai":[4,12,18,23,24,43,52,56]},"scoresAfter":[-76,-33]},{"ply":7,"player":"human","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[0,1,15,17,32,42,55,57],"ai":[12,18,23,24,43,50,52,56]},"scoresAfter":[-76,-33]},{"ply":8,"player":"ai","action":66,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[1,15,17,32,42,55,57,58],"ai":[12,18,23,24,43,50,52,56]},"scoresAfter":[-76,-33]},{"ply":9,"player":"human","action":11,"playedCard":1,"placeType":"discard","drawSource":"discard_4","drawnCard":50,"handsBefore":{"human":[1,15,17,32,42,55,57,58],"ai":[12,18,23,24,39,43,52,56]},"scoresAfter":[-76,-33]},{"ply":10,"player":"ai","action":66,"playedCard":43,"placeType":"discard","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[15,17,32,42,50,55,57,58],"ai":[12,18,23,24,39,43,52,56]},"scoresAfter":[-76,-33]},{"ply":11,"player":"human","action":48,"playedCard":50,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[15,17,32,42,50,55,57,58],"ai":[12,18,23,24,39,41,52,56]},"scoresAfter":[-96,-33]},{"ply":12,"player":"ai","action":60,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[15,17,28,32,42,55,57,58],"ai":[12,18,23,24,39,41,52,56]},"scoresAfter":[-96,-49]},{"ply":13,"player":"human","action":24,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[15,17,28,32,42,55,57,58],"ai":[12,18,23,24,39,45,52,56]},"scoresAfter":[-90,-49]},{"ply":14,"player":"ai","action":78,"playedCard":52,"placeType":"discard","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[5,15,17,32,42,55,57,58],"ai":[12,18,23,24,39,45,52,56]},"scoresAfter":[-90,-49]},{"ply":15,"player":"human","action":23,"playedCard":15,"placeType":"discard","drawSource":"discard_4","drawnCard":52,"handsBefore":{"human":[5,15,17,32,42,55,57,58],"ai":[12,18,23,24,39,45,56,59]},"scoresAfter":[-90,-49]},{"ply":16,"player":"ai","action":0,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[5,17,32,42,52,55,57,58],"ai":[12,18,23,24,39,45,56,59]},"scoresAfter":[-90,-89]},{"ply":17,"player":"human","action":52,"playedCard":52,"placeType":"play","drawSource":"discard_3","drawnCard":43,"handsBefore":{"human":[5,17,32,42,52,55,57,58],"ai":[16,18,23,24,39,45,56,59]},"scoresAfter":[-81,-89]},{"ply":18,"player":"ai","action":60,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[5,17,32,42,43,55,57,58],"ai":[16,18,23,24,39,45,56,59]},"scoresAfter":[-81,-81]},{"ply":19,"player":"human","action":42,"playedCard":42,"placeType":"discard","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[5,17,32,42,43,55,57,58],"ai":[16,18,23,24,35,39,56,59]},"scoresAfter":[-81,-81]},{"ply":20,"player":"ai","action":72,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[5,14,17,32,43,55,57,58],"ai":[16,18,23,24,35,39,56,59]},"scoresAfter":[-81,-74]},{"ply":21,"player":"human","action":54,"playedCard":43,"placeType":"discard","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[5,14,17,32,43,55,57,58],"ai":[16,18,23,24,29,35,39,59]},"scoresAfter":[-81,-74]},{"ply":22,"player":"ai","action":48,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[5,14,17,32,44,55,57,58],"ai":[16,18,23,24,29,35,39,59]},"scoresAfter":[-81,-90]},{"ply":23,"player":"human","action":18,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[5,14,17,32,44,55,57,58],"ai":[16,18,23,24,33,35,39,59]},"scoresAfter":[-81,-90]},{"ply":24,"player":"ai","action":48,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[5,6,17,32,44,55,57,58],"ai":[16,18,23,24,33,35,39,59]},"scoresAfter":[-81,-82]},{"ply":25,"player":"human","action":54,"playedCard":44,"placeType":"discard","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[5,6,17,32,44,55,57,58],"ai":[8,16,18,23,24,35,39,59]},"scoresAfter":[-81,-82]},{"ply":26,"player":"ai","action":60,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[5,6,17,26,32,55,57,58],"ai":[8,16,18,23,24,35,39,59]},"scoresAfter":[-81,-72]},{"ply":27,"player":"human","action":60,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[5,6,17,26,32,55,57,58],"ai":[7,8,16,18,23,24,39,59]},"scoresAfter":[-63,-72]},{"ply":28,"player":"ai","action":78,"playedCard":39,"placeType":"discard","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[5,6,10,17,26,32,57,58],"ai":[7,8,16,18,23,24,39,59]},"scoresAfter":[-63,-72]},{"ply":29,"player":"human","action":72,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[5,6,10,17,26,32,57,58],"ai":[7,8,16,18,23,24,30,59]},"scoresAfter":[-39,-72]},{"ply":30,"player":"ai","action":2,"playedCard":7,"placeType":"play","drawSource":"discard_1","drawnCard":14,"handsBefore":{"human":[5,6,10,17,26,32,36,58],"ai":[7,8,16,18,23,24,30,59]},"scoresAfter":[-39,-66]},{"ply":31,"player":"human","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[5,6,10,17,26,32,36,58],"ai":[8,14,16,18,23,24,30,59]},"scoresAfter":[-12,-66]},{"ply":32,"player":"ai","action":2,"playedCard":8,"placeType":"play","drawSource":"discard_1","drawnCard":15,"handsBefore":{"human":[5,6,10,11,17,26,32,36],"ai":[8,14,16,18,23,24,30,59]},"scoresAfter":[-12,-59]},{"ply":33,"player":"human","action":67,"playedCard":26,"placeType":"discard","drawSource":"discard_0","drawnCard":1,"handsBefore":{"human":[5,6,10,11,17,26,32,36],"ai":[14,15,16,18,23,24,30,59]},"scoresAfter":[-12,-59]},{"ply":34,"player":"ai","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[1,5,6,10,11,17,32,36],"ai":[14,15,16,18,23,24,30,59]},"scoresAfter":[-12,-49]},{"ply":35,"player":"human","action":91,"playedCard":36,"placeType":"discard","drawSource":"discard_0","drawnCard":0,"handsBefore":{"human":[1,5,6,10,11,17,32,36],"ai":[14,15,16,18,23,24,30,40]},"scoresAfter":[-12,-49]},{"ply":36,"player":"ai","action":90,"playedCard":40,"placeType":"discard","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[0,1,5,6,10,11,17,32],"ai":[14,15,16,18,23,24,30,40]},"scoresAfter":[-12,-49]},{"ply":37,"player":"human","action":0,"playedCard":0,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[0,1,5,6,10,11,17,32],"ai":[14,15,16,18,23,24,30,51]},"scoresAfter":[-52,-49]},{"ply":38,"player":"ai","action":90,"playedCard":51,"placeType":"discard","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[1,5,6,10,11,13,17,32],"ai":[14,15,16,18,23,24,30,51]},"scoresAfter":[-52,-49]},{"ply":39,"player":"human","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[1,5,6,10,11,13,17,32],"ai":[14,15,16,18,20,23,24,30]},"scoresAfter":[-72,-49]},{"ply":40,"player":"ai","action":0,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[5,6,10,11,13,17,22,32],"ai":[14,15,16,18,20,23,24,30]},"scoresAfter":[-72,-69]},{"ply":41,"player":"human","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[5,6,10,11,13,17,22,32],"ai":[15,16,18,20,23,24,30,47]},"scoresAfter":[-60,-69]},{"ply":42,"player":"ai","action":0,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[6,10,11,13,17,19,22,32],"ai":[15,16,18,20,23,24,30,47]},"scoresAfter":[-60,-63]},{"ply":43,"player":"human","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[6,10,11,13,17,19,22,32],"ai":[16,18,20,23,24,30,47,54]},"scoresAfter":[-45,-63]},{"ply":44,"player":"ai","action":0,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[9,10,11,13,17,19,22,32],"ai":[16,18,20,23,24,30,47,54]},"scoresAfter":[-45,-54]},{"ply":45,"player":"human","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[9,10,11,13,17,19,22,32],"ai":[18,20,23,24,30,34,47,54]},"scoresAfter":[-21,-54]},{"ply":46,"player":"ai","action":4,"playedCard":18,"placeType":"play","drawSource":"discard_3","drawnCard":40,"handsBefore":{"human":[10,11,13,17,19,22,32,37],"ai":[18,20,23,24,30,34,47,54]},"scoresAfter":[-21,-39]},{"ply":47,"player":"human","action":3,"playedCard":10,"placeType":"play","drawSource":"discard_2","drawnCard":26,"handsBefore":{"human":[10,11,13,17,19,22,32,37],"ai":[20,23,24,30,34,40,47,54]},"scoresAfter":[6,-39]},{"ply":48,"player":"ai","action":72,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[11,13,17,19,22,26,32,37],"ai":[20,23,24,30,34,40,47,54]},"scoresAfter":[6,-29]},{"ply":49,"player":"human","action":4,"playedCard":11,"placeType":"play","drawSource":"discard_3","drawnCard":36,"handsBefore":{"human":[11,13,17,19,22,26,32,37],"ai":[20,21,23,24,30,34,40,54]},"scoresAfter":[36,-29]},{"ply":50,"player":"ai","action":4,"playedCard":20,"placeType":"play","drawSource":"discard_3","drawnCard":39,"handsBefore":{"human":[13,17,19,22,26,32,36,37],"ai":[20,21,23,24,30,34,40,54]},"scoresAfter":[36,-8]},{"ply":51,"player":"human","action":4,"playedCard":13,"placeType":"play","drawSource":"discard_3","drawnCard":44,"handsBefore":{"human":[13,17,19,22,26,32,36,37],"ai":[21,23,24,30,34,39,40,54]},"scoresAfter":[-4,-8]},{"ply":52,"player":"ai","action":0,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[17,19,22,26,32,36,37,44],"ai":[21,23,24,30,34,39,40,54]},"scoresAfter":[-4,16]},{"ply":53,"player":"human","action":4,"playedCard":17,"placeType":"play","drawSource":"discard_3","drawnCard":43,"handsBefore":{"human":[17,19,22,26,32,36,37,44],"ai":[23,24,30,34,39,40,49,54]},"scoresAfter":[4,16]},{"ply":54,"player":"ai","action":0,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[19,22,26,32,36,37,43,44],"ai":[23,24,30,34,39,40,49,54]},"scoresAfter":[4,66]},{"ply":55,"player":"human","action":4,"playedCard":19,"placeType":"play","drawSource":"discard_3","drawnCard":42,"handsBefore":{"human":[19,22,26,32,36,37,43,44],"ai":[3,24,30,34,39,40,49,54]},"scoresAfter":[16,66]},{"ply":56,"player":"ai","action":6,"playedCard":3,"placeType":"discard","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[22,26,32,36,37,42,43,44],"ai":[3,24,30,34,39,40,49,54]},"scoresAfter":[16,66]},{"ply":57,"player":"human","action":29,"playedCard":32,"placeType":"play","drawSource":"discard_4","drawnCard":51,"handsBefore":{"human":[22,26,32,36,37,42,43,44],"ai":[2,24,30,34,39,40,49,54]},"scoresAfter":[30,66]},{"ply":58,"player":"ai","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[22,26,36,37,42,43,44,51],"ai":[2,24,30,34,39,40,49,54]},"scoresAfter":[30,66]},{"ply":59,"player":"human","action":0,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[22,26,36,37,42,43,44,51],"ai":[24,30,31,34,39,40,49,54]},"scoresAfter":[48,66]}],"finalScores":[48,66],"outcome":"THE RIVAL WINS","finalState":{"deckOrder":[0,15,42,48,32,1,57,25,53,23,52,18,38,12,56,4,27,24,55,43,17,50,58,39,41,28,45,5,59,16,35,14,29,44,33,6,8,26,7,10,30,36,11,40,51,13,20,22,47,19,54,9,34,37,21,49,3,2,31,46],"drawPtr":60,"cardLoc":[3,3,5,5,4,3,3,4,4,3,3,3,4,3,4,4,4,3,4,3,4,4,3,4,2,3,1,3,3,4,2,2,3,4,2,4,1,1,5,2,2,4,1,1,1,4,1,4,3,2,3,1,3,4,2,3,4,3,3,4],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,true,false,false,true,true,false,true,true,true,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false],"colTop":[[10,9,7,0,9],[7,10,10,10,10]],"colHandshakes":[[2,1,1,0,2],[0,2,0,0,0]],"colLength":[[7,4,4,0,6],[3,8,3,3,3]],"piles":[[3,2],[],[],[38],[]],"toMove":1,"stepCount":59,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"ba17c591-f8bf-4ca1-a4ab-32a757b6e217","seed":"2lmoaa","startedAt":"2026-07-14T18:21:45.623Z","finishedAt":"2026-07-14T18:24:07.060Z","initialDeckOrder":[37,8,29,23,15,24,57,59,30,40,22,33,48,11,18,49,54,41,9,43,21,56,25,39,58,50,16,3,46,27,38,5,6,42,31,10,2,51,35,26,7,52,4,19,17,0,14,32,34,45,44,20,12,13,53,28,47,55,1,36],"moves":[{"ply":1,"player":"human","action":66,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[8,15,23,24,29,37,57,59],"ai":[11,18,22,30,33,40,48,49]},"scoresAfter":[0,0]},{"ply":2,"player":"ai","action":72,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[8,15,23,24,29,54,57,59],"ai":[11,18,22,30,33,40,48,49]},"scoresAfter":[0,-40]},{"ply":3,"player":"human","action":42,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[8,15,23,24,29,54,57,59],"ai":[11,18,22,30,33,40,41,49]},"scoresAfter":[0,-40]},{"ply":4,"player":"ai","action":60,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[8,9,15,23,29,54,57,59],"ai":[11,18,22,30,33,40,41,49]},"scoresAfter":[0,-57]},{"ply":5,"player":"human","action":24,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[8,9,15,23,29,54,57,59],"ai":[11,18,22,30,33,41,43,49]},"scoresAfter":[-18,-57]},{"ply":6,"player":"ai","action":60,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[8,9,21,23,29,54,57,59],"ai":[11,18,22,30,33,41,43,49]},"scoresAfter":[-18,-53]},{"ply":7,"player":"human","action":54,"playedCard":29,"placeType":"discard","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[8,9,21,23,29,54,57,59],"ai":[11,18,22,30,33,43,49,56]},"scoresAfter":[-18,-53]},{"ply":8,"player":"ai","action":60,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[8,9,21,23,25,54,57,59],"ai":[11,18,22,30,33,43,49,56]},"scoresAfter":[-18,-47]},{"ply":9,"player":"human","action":54,"playedCard":25,"placeType":"discard","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[8,9,21,23,25,54,57,59],"ai":[11,18,22,30,33,39,49,56]},"scoresAfter":[-18,-47]},{"ply":10,"player":"ai","action":72,"playedCard":49,"placeType":"play","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[8,9,21,23,54,57,58,59],"ai":[11,18,22,30,33,39,49,56]},"scoresAfter":[-18,-67]},{"ply":11,"player":"human","action":48,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[8,9,21,23,54,57,58,59],"ai":[11,18,22,30,33,39,50,56]},"scoresAfter":[-33,-67]},{"ply":12,"player":"ai","action":72,"playedCard":50,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[8,9,16,21,23,57,58,59],"ai":[11,18,22,30,33,39,50,56]},"scoresAfter":[-33,-87]},{"ply":13,"player":"human","action":24,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[8,9,16,21,23,57,58,59],"ai":[3,11,18,22,30,33,39,56]},"scoresAfter":[-30,-87]},{"ply":14,"player":"ai","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[8,9,21,23,46,57,58,59],"ai":[3,11,18,22,30,33,39,56]},"scoresAfter":[-30,-105]},{"ply":15,"player":"human","action":60,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[8,9,21,23,46,57,58,59],"ai":[11,18,22,27,30,33,39,56]},"scoresAfter":[-22,-105]},{"ply":16,"player":"ai","action":78,"playedCard":39,"placeType":"discard","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[8,9,21,23,38,46,58,59],"ai":[11,18,22,27,30,33,39,56]},"scoresAfter":[-22,-105]},{"ply":17,"player":"human","action":54,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[8,9,21,23,38,46,58,59],"ai":[5,11,18,22,27,30,33,56]},"scoresAfter":[-22,-105]},{"ply":18,"player":"ai","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[6,8,9,21,23,46,58,59],"ai":[5,11,18,22,27,30,33,56]},"scoresAfter":[-22,-101]},{"ply":19,"player":"human","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[6,8,9,21,23,46,58,59],"ai":[11,18,22,27,30,33,42,56]},"scoresAfter":[-37,-101]},{"ply":20,"player":"ai","action":78,"playedCard":42,"placeType":"discard","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[8,9,21,23,31,46,58,59],"ai":[11,18,22,27,30,33,42,56]},"scoresAfter":[-37,-101]},{"ply":21,"player":"human","action":72,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[8,9,21,23,31,46,58,59],"ai":[10,11,18,22,27,30,33,56]},"scoresAfter":[-28,-101]},{"ply":22,"player":"ai","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[2,8,9,21,23,31,46,59],"ai":[10,11,18,22,27,30,33,56]},"scoresAfter":[-28,-92]},{"ply":23,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[2,8,9,21,23,31,46,59],"ai":[11,18,22,27,30,33,51,56]},"scoresAfter":[-18,-92]},{"ply":24,"player":"ai","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[2,8,9,21,23,31,35,46],"ai":[11,18,22,27,30,33,51,56]},"scoresAfter":[-18,-82]},{"ply":25,"player":"human","action":12,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[2,8,9,21,23,31,35,46],"ai":[18,22,26,27,30,33,51,56]},"scoresAfter":[-11,-82]},{"ply":26,"player":"ai","action":0,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[2,7,9,21,23,31,35,46],"ai":[18,22,26,27,30,33,51,56]},"scoresAfter":[-11,-97]},{"ply":27,"player":"human","action":24,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[2,7,9,21,23,31,35,46],"ai":[22,26,27,30,33,51,52,56]},"scoresAfter":[-3,-97]},{"ply":28,"player":"ai","action":0,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[2,4,7,21,23,31,35,46],"ai":[22,26,27,30,33,51,52,56]},"scoresAfter":[-3,-88]},{"ply":29,"player":"human","action":21,"playedCard":4,"placeType":"discard","drawSource":"discard_2","drawnCard":25,"handsBefore":{"human":[2,4,7,21,23,31,35,46],"ai":[19,26,27,30,33,51,52,56]},"scoresAfter":[-3,-88]},{"ply":30,"player":"ai","action":72,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[2,7,21,23,25,31,35,46],"ai":[19,26,27,30,33,51,52,56]},"scoresAfter":[-3,-76]},{"ply":31,"player":"human","action":27,"playedCard":21,"placeType":"play","drawSource":"discard_2","drawnCard":29,"handsBefore":{"human":[2,7,21,23,25,31,35,46],"ai":[17,19,26,27,30,33,51,56]},"scoresAfter":[5,-76]},{"ply":32,"player":"ai","action":18,"playedCard":19,"placeType":"discard","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[2,7,23,25,29,31,35,46],"ai":[17,19,26,27,30,33,51,56]},"scoresAfter":[5,-76]},{"ply":33,"player":"human","action":36,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[2,7,23,25,29,31,35,46],"ai":[0,17,26,27,30,33,51,56]},"scoresAfter":[-35,-76]},{"ply":34,"player":"ai","action":18,"playedCard":17,"placeType":"discard","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[2,7,14,23,29,31,35,46],"ai":[0,17,26,27,30,33,51,56]},"scoresAfter":[-35,-76]},{"ply":35,"player":"human","action":36,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[2,7,14,23,29,31,35,46],"ai":[0,26,27,30,32,33,51,56]},"scoresAfter":[-25,-76]},{"ply":36,"player":"ai","action":12,"playedCard":26,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[2,7,14,29,31,34,35,46],"ai":[0,26,27,30,32,33,51,56]},"scoresAfter":[-25,-116]},{"ply":37,"player":"human","action":33,"playedCard":14,"placeType":"discard","drawSource":"discard_2","drawnCard":24,"handsBefore":{"human":[2,7,14,29,31,34,35,46],"ai":[0,27,30,32,33,45,51,56]},"scoresAfter":[-25,-116]},{"ply":38,"player":"ai","action":84,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[2,7,24,29,31,34,35,46],"ai":[0,27,30,32,33,45,51,56]},"scoresAfter":[-25,-88]},{"ply":39,"player":"human","action":24,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[2,7,24,29,31,34,35,46],"ai":[0,27,30,32,33,44,45,51]},"scoresAfter":[-45,-88]},{"ply":40,"player":"ai","action":12,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[2,7,20,29,31,34,35,46],"ai":[0,27,30,32,33,44,45,51]},"scoresAfter":[-45,-84]},{"ply":41,"player":"human","action":36,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[2,7,20,29,31,34,35,46],"ai":[0,12,30,32,33,44,45,51]},"scoresAfter":[-33,-84]},{"ply":42,"player":"ai","action":24,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[2,7,13,20,31,34,35,46],"ai":[0,12,30,32,33,44,45,51]},"scoresAfter":[-33,-74]},{"ply":43,"player":"human","action":48,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[2,7,13,20,31,34,35,46],"ai":[0,12,32,33,44,45,51,53]},"scoresAfter":[-15,-74]},{"ply":44,"player":"ai","action":24,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[2,7,13,20,28,34,35,46],"ai":[0,12,32,33,44,45,51,53]},"scoresAfter":[-15,-60]},{"ply":45,"player":"human","action":60,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[2,7,13,20,28,34,35,46],"ai":[0,12,33,44,45,47,51,53]},"scoresAfter":[12,-60]},{"ply":46,"player":"ai","action":40,"playedCard":44,"placeType":"play","drawSource":"discard_3","drawnCard":42,"handsBefore":{"human":[2,7,13,20,28,35,46,55],"ai":[0,12,33,44,45,47,51,53]},"scoresAfter":[12,-53]},{"ply":47,"player":"human","action":60,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[2,7,13,20,28,35,46,55],"ai":[0,12,33,42,45,47,51,53]},"scoresAfter":[42,-53]},{"ply":48,"player":"ai","action":25,"playedCard":33,"placeType":"play","drawSource":"discard_0","drawnCard":4,"handsBefore":{"human":[1,2,7,13,20,28,46,55],"ai":[0,12,33,42,45,47,51,53]},"scoresAfter":[42,-37]},{"ply":49,"player":"human","action":30,"playedCard":7,"placeType":"discard","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[1,2,7,13,20,28,46,55],"ai":[0,4,12,42,45,47,51,53]},"scoresAfter":[42,-37]}],"finalScores":[42,-37],"outcome":"YOU WIN","finalState":{"deckOrder":[37,8,29,23,15,24,57,59,30,40,22,33,48,11,18,49,54,41,9,43,21,56,25,39,58,50,16,3,46,27,38,5,6,42,31,10,2,51,35,26,7,52,4,19,17,0,14,32,34,45,44,20,12,13,53,28,47,55,1,36],"drawPtr":60,"cardLoc":[2,1,1,4,2,4,3,5,3,3,4,4,2,1,5,3,3,5,4,5,1,3,4,3,3,3,4,4,1,3,4,3,4,4,3,3,1,5,5,5,4,4,2,4,4,2,1,2,4,4,4,2,4,2,3,1,4,3,3,3],"handPublic":[false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[8,10,10,0,10],[10,9,8,7,7]],"colHandshakes":[[0,0,2,0,0],[0,0,1,0,3]],"colLength":[[3,4,6,0,4],[4,2,5,4,5]],"piles":[[7],[19,17,14],[],[37,39,38],[]],"toMove":1,"stepCount":49,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"92721f9e-43a3-4f59-9eaa-f7f7b90a1198","seed":"ax7dwx","startedAt":"2026-07-14T18:24:08.112Z","finishedAt":"2026-07-14T18:26:39.680Z","initialDeckOrder":[56,31,16,29,39,33,23,42,53,20,7,22,9,36,40,50,58,8,44,51,2,55,15,27,41,6,59,38,34,46,17,49,11,21,26,37,24,10,54,52,18,30,35,47,3,43,1,0,48,25,45,5,19,57,13,4,12,14,28,32],"moves":[{"ply":1,"player":"human","action":0,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[16,23,29,31,33,39,42,56],"ai":[7,9,20,22,36,40,50,53]},"scoresAfter":[-17,0]},{"ply":2,"player":"ai","action":54,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":8,"handsBefore":{"human":[23,29,31,33,39,42,56,58],"ai":[7,9,20,22,36,40,50,53]},"scoresAfter":[-17,0]},{"ply":3,"player":"human","action":12,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[23,29,31,33,39,42,56,58],"ai":[7,8,9,20,22,40,50,53]},"scoresAfter":[-33,0]},{"ply":4,"player":"ai","action":66,"playedCard":40,"placeType":"discard","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[23,31,33,39,42,44,56,58],"ai":[7,8,9,20,22,40,50,53]},"scoresAfter":[-33,0]},{"ply":5,"player":"human","action":36,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[23,31,33,39,42,44,56,58],"ai":[7,8,9,20,22,50,51,53]},"scoresAfter":[-51,0]},{"ply":6,"player":"ai","action":72,"playedCard":51,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[2,23,31,33,42,44,56,58],"ai":[7,8,9,20,22,50,51,53]},"scoresAfter":[-51,-18]},{"ply":7,"player":"human","action":24,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[2,23,31,33,42,44,56,58],"ai":[7,8,9,20,22,50,53,55]},"scoresAfter":[-45,-18]},{"ply":8,"player":"ai","action":72,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[2,15,23,33,42,44,56,58],"ai":[7,8,9,20,22,50,53,55]},"scoresAfter":[-45,-14]},{"ply":9,"player":"human","action":48,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[2,15,23,33,42,44,56,58],"ai":[7,8,9,20,22,27,50,55]},"scoresAfter":[-40,-14]},{"ply":10,"player":"ai","action":84,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[2,15,23,33,41,44,56,58],"ai":[7,8,9,20,22,27,50,55]},"scoresAfter":[-40,-8]},{"ply":11,"player":"human","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[2,15,23,33,41,44,56,58],"ai":[6,7,8,9,20,22,27,50]},"scoresAfter":[-40,-8]},{"ply":12,"player":"ai","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":38,"handsBefore":{"human":[15,23,33,41,44,56,58,59],"ai":[6,7,8,9,20,22,27,50]},"scoresAfter":[-40,-23]},{"ply":13,"player":"human","action":60,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[15,23,33,41,44,56,58,59],"ai":[7,8,9,20,22,27,38,50]},"scoresAfter":[-53,-23]},{"ply":14,"player":"ai","action":78,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[15,23,33,34,41,44,58,59],"ai":[7,8,9,20,22,27,38,50]},"scoresAfter":[-53,-23]},{"ply":15,"player":"human","action":24,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[15,23,33,34,41,44,58,59],"ai":[7,8,9,20,22,27,46,50]},"scoresAfter":[-45,-23]},{"ply":16,"player":"ai","action":90,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[15,17,23,34,41,44,58,59],"ai":[7,8,9,20,22,27,46,50]},"scoresAfter":[-45,-23]},{"ply":17,"player":"human","action":12,"playedCard":17,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[15,17,23,34,41,44,58,59],"ai":[7,8,9,20,22,27,46,49]},"scoresAfter":[-41,-23]},{"ply":18,"player":"ai","action":90,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[11,15,23,34,41,44,58,59],"ai":[7,8,9,20,22,27,46,49]},"scoresAfter":[-41,-23]},{"ply":19,"player":"human","action":72,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[11,15,23,34,41,44,58,59],"ai":[7,8,9,20,21,22,27,46]},"scoresAfter":[-32,-23]},{"ply":20,"player":"ai","action":78,"playedCard":27,"placeType":"discard","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[11,15,23,26,34,41,44,59],"ai":[7,8,9,20,21,22,27,46]},"scoresAfter":[-32,-23]},{"ply":21,"player":"human","action":48,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[11,15,23,26,34,41,44,59],"ai":[7,8,9,20,21,22,37,46]},"scoresAfter":[-23,-23]},{"ply":22,"player":"ai","action":4,"playedCard":7,"placeType":"play","drawSource":"discard_3","drawnCard":38,"handsBefore":{"human":[11,15,23,24,26,41,44,59],"ai":[7,8,9,20,21,22,37,46]},"scoresAfter":[-23,-17]},{"ply":23,"player":"human","action":42,"playedCard":24,"placeType":"discard","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[11,15,23,24,26,41,44,59],"ai":[8,9,20,21,22,37,38,46]},"scoresAfter":[-23,-17]},{"ply":24,"player":"ai","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[10,11,15,23,26,41,44,59],"ai":[8,9,20,21,22,37,38,46]},"scoresAfter":[-23,-10]},{"ply":25,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[10,11,15,23,26,41,44,59],"ai":[9,20,21,22,37,38,46,54]},"scoresAfter":[-13,-10]},{"ply":26,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[10,11,15,23,26,41,44,52],"ai":[9,20,21,22,37,38,46,54]},"scoresAfter":[-13,-2]},{"ply":27,"player":"human","action":90,"playedCard":52,"placeType":"discard","drawSource":"deck","drawnCard":30,"handsBefore":{"human":[10,11,15,23,26,41,44,52],"ai":[18,20,21,22,37,38,46,54]},"scoresAfter":[-13,-2]},{"ply":28,"player":"ai","action":54,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[10,11,15,23,26,30,41,44],"ai":[18,20,21,22,37,38,46,54]},"scoresAfter":[-13,-2]},{"ply":29,"player":"human","action":30,"playedCard":15,"placeType":"discard","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[10,11,15,23,26,30,41,44],"ai":[18,20,21,22,35,38,46,54]},"scoresAfter":[-13,-2]},{"ply":30,"player":"ai","action":92,"playedCard":54,"placeType":"discard","drawSource":"discard_1","drawnCard":15,"handsBefore":{"human":[10,11,23,26,30,41,44,47],"ai":[18,20,21,22,35,38,46,54]},"scoresAfter":[-13,-2]},{"ply":31,"player":"human","action":72,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[10,11,23,26,30,41,44,47],"ai":[15,18,20,21,22,35,38,46]},"scoresAfter":[-6,-2]},{"ply":32,"player":"ai","action":0,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[3,10,11,23,26,30,41,47],"ai":[15,18,20,21,22,35,38,46]},"scoresAfter":[-6,-20]},{"ply":33,"player":"human","action":67,"playedCard":30,"placeType":"discard","drawSource":"discard_0","drawnCard":2,"handsBefore":{"human":[3,10,11,23,26,30,41,47],"ai":[18,20,21,22,35,38,43,46]},"scoresAfter":[-6,-20]},{"ply":34,"player":"ai","action":0,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[2,3,10,11,23,26,41,47],"ai":[18,20,21,22,35,38,43,46]},"scoresAfter":[-6,-15]},{"ply":35,"player":"human","action":0,"playedCard":2,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[2,3,10,11,23,26,41,47],"ai":[1,20,21,22,35,38,43,46]},"scoresAfter":[-46,-15]},{"ply":36,"player":"ai","action":12,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[0,3,10,11,23,26,41,47],"ai":[1,20,21,22,35,38,43,46]},"scoresAfter":[-46,-8]},{"ply":37,"player":"human","action":0,"playedCard":0,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[0,3,10,11,23,26,41,47],"ai":[1,21,22,35,38,43,46,48]},"scoresAfter":[-66,-8]},{"ply":38,"player":"ai","action":12,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[3,10,11,23,25,26,41,47],"ai":[1,21,22,35,38,43,46,48]},"scoresAfter":[-66,0]},{"ply":39,"player":"human","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[3,10,11,23,25,26,41,47],"ai":[1,22,35,38,43,45,46,48]},"scoresAfter":[-60,0]},{"ply":40,"player":"ai","action":12,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[5,10,11,23,25,26,41,47],"ai":[1,22,35,38,43,45,46,48]},"scoresAfter":[-60,9]},{"ply":41,"player":"human","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[5,10,11,23,25,26,41,47],"ai":[1,19,35,38,43,45,46,48]},"scoresAfter":[-48,9]},{"ply":42,"player":"ai","action":24,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[10,11,23,25,26,41,47,57],"ai":[1,19,35,38,43,45,46,48]},"scoresAfter":[-48,-1]},{"ply":43,"player":"human","action":77,"playedCard":47,"placeType":"play","drawSource":"discard_4","drawnCard":54,"handsBefore":{"human":[10,11,23,25,26,41,47,57],"ai":[1,13,19,38,43,45,46,48]},"scoresAfter":[-38,-1]},{"ply":44,"player":"ai","action":36,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[10,11,23,25,26,41,54,57],"ai":[1,13,19,38,43,45,46,48]},"scoresAfter":[-38,-41]},{"ply":45,"player":"human","action":5,"playedCard":10,"placeType":"play","drawSource":"discard_4","drawnCard":52,"handsBefore":{"human":[10,11,23,25,26,41,54,57],"ai":[1,4,13,19,43,45,46,48]},"scoresAfter":[-11,-41]},{"ply":46,"player":"ai","action":52,"playedCard":43,"placeType":"play","drawSource":"discard_3","drawnCard":37,"handsBefore":{"human":[11,23,25,26,41,52,54,57],"ai":[1,4,13,19,43,45,46,48]},"scoresAfter":[-11,-29]},{"ply":47,"player":"human","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[11,23,25,26,41,52,54,57],"ai":[1,4,13,19,37,45,46,48]},"scoresAfter":[19,-29]},{"ply":48,"player":"ai","action":65,"playedCard":45,"placeType":"play","drawSource":"discard_4","drawnCard":49,"handsBefore":{"human":[12,23,25,26,41,52,54,57],"ai":[1,4,13,19,37,45,46,48]},"scoresAfter":[19,-13]},{"ply":49,"player":"human","action":6,"playedCard":12,"placeType":"discard","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[12,23,25,26,41,52,54,57],"ai":[1,4,13,19,37,46,48,49]},"scoresAfter":[19,-13]},{"ply":50,"player":"ai","action":60,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[14,23,25,26,41,52,54,57],"ai":[1,4,13,19,37,46,48,49]},"scoresAfter":[19,5]},{"ply":51,"player":"human","action":12,"playedCard":23,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[14,23,25,26,41,52,54,57],"ai":[1,4,13,19,28,37,48,49]},"scoresAfter":[29,5]}],"finalScores":[29,5],"outcome":"YOU WIN","finalState":{"deckOrder":[56,31,16,29,39,33,23,42,53,20,7,22,9,36,40,50,58,8,44,51,2,55,15,27,41,6,59,38,34,46,17,49,11,21,26,37,24,10,54,52,18,30,35,47,3,43,1,0,48,25,45,5,19,57,13,4,12,14,28,32],"drawPtr":60,"cardLoc":[3,2,3,3,2,3,4,4,4,4,3,3,5,2,1,4,3,3,4,2,4,4,4,3,5,1,1,5,2,3,5,3,1,3,3,4,5,2,4,3,5,1,3,4,3,4,4,3,2,2,5,4,1,4,1,4,3,1,3,3],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,true,false,false,true,false,true,false,false,false,false,false],"colTop":[[10,10,9,10,10],[8,9,10,9,6]],"colHandshakes":[[2,0,0,0,0],[0,0,0,1,0]],"colLength":[[6,3,4,4,3],[4,5,1,4,3]],"piles":[[],[12],[27,24,30],[36,40],[50]],"toMove":1,"stepCount":51,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"e9721b0c-8d8a-4432-a25e-98412ade6c13","seed":"3op2kh","startedAt":"2026-07-14T18:26:40.782Z","finishedAt":"2026-07-14T18:28:15.367Z","initialDeckOrder":[1,8,52,3,29,30,38,2,15,14,37,50,31,10,24,46,48,12,57,22,21,4,54,55,6,27,41,53,44,35,33,7,34,32,18,13,28,43,42,5,25,39,9,40,56,16,58,19,59,23,26,17,11,49,36,51,47,0,20,45],"moves":[{"ply":1,"player":"human","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[1,2,3,8,29,30,38,52],"ai":[10,14,15,24,31,37,46,50]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":90,"playedCard":50,"placeType":"discard","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[2,3,8,29,30,38,48,52],"ai":[10,14,15,24,31,37,46,50]},"scoresAfter":[-40,0]},{"ply":3,"player":"human","action":0,"playedCard":2,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[2,3,8,29,30,38,48,52],"ai":[10,12,14,15,24,31,37,46]},"scoresAfter":[-60,0]},{"ply":4,"player":"ai","action":72,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[3,8,29,30,38,48,52,57],"ai":[10,12,14,15,24,31,37,46]},"scoresAfter":[-60,-40]},{"ply":5,"player":"human","action":60,"playedCard":48,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[3,8,29,30,38,48,52,57],"ai":[10,12,14,15,22,24,31,46]},"scoresAfter":[-100,-40]},{"ply":6,"player":"ai","action":12,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[3,8,21,29,30,38,52,57],"ai":[10,12,14,15,22,24,31,46]},"scoresAfter":[-100,-80]},{"ply":7,"player":"human","action":71,"playedCard":38,"placeType":"discard","drawSource":"discard_4","drawnCard":50,"handsBefore":{"human":[3,8,21,29,30,38,52,57],"ai":[4,10,14,15,22,24,31,46]},"scoresAfter":[-100,-80]},{"ply":8,"player":"ai","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[3,8,21,29,30,50,52,57],"ai":[4,10,14,15,22,24,31,46]},"scoresAfter":[-100,-97]},{"ply":9,"player":"human","action":60,"playedCard":50,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[3,8,21,29,30,50,52,57],"ai":[10,14,15,22,24,31,46,54]},"scoresAfter":[-120,-97]},{"ply":10,"player":"ai","action":84,"playedCard":54,"placeType":"play","drawSource":"deck","drawnCard":6,"handsBefore":{"human":[3,8,21,29,30,52,55,57],"ai":[10,14,15,22,24,31,46,54]},"scoresAfter":[-120,-112]},{"ply":11,"player":"human","action":60,"playedCard":52,"placeType":"play","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[3,8,21,29,30,52,55,57],"ai":[6,10,14,15,22,24,31,46]},"scoresAfter":[-111,-112]},{"ply":12,"player":"ai","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[3,8,21,27,29,30,55,57],"ai":[6,10,14,15,22,24,31,46]},"scoresAfter":[-111,-107]},{"ply":13,"player":"human","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[3,8,21,27,29,30,55,57],"ai":[10,14,15,22,24,31,41,46]},"scoresAfter":[-105,-107]},{"ply":14,"player":"ai","action":12,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[8,21,27,29,30,53,55,57],"ai":[10,14,15,22,24,31,41,46]},"scoresAfter":[-105,-127]},{"ply":15,"player":"human","action":60,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[8,21,27,29,30,53,55,57],"ai":[10,15,22,24,31,41,44,46]},"scoresAfter":[-93,-127]},{"ply":16,"player":"ai","action":36,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[8,21,27,29,30,35,55,57],"ai":[10,15,22,24,31,41,44,46]},"scoresAfter":[-93,-167]},{"ply":17,"player":"human","action":72,"playedCard":55,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[8,21,27,29,30,35,55,57],"ai":[10,15,22,31,33,41,44,46]},"scoresAfter":[-75,-167]},{"ply":18,"player":"ai","action":4,"playedCard":10,"placeType":"play","drawSource":"discard_3","drawnCard":38,"handsBefore":{"human":[7,8,21,27,29,30,35,57],"ai":[10,15,22,31,33,41,44,46]},"scoresAfter":[-75,-158]},{"ply":19,"player":"human","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[7,8,21,27,29,30,35,57],"ai":[15,22,31,33,38,41,44,46]},"scoresAfter":[-57,-158]},{"ply":20,"player":"ai","action":48,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[8,21,27,29,30,34,35,57],"ai":[15,22,31,33,38,41,44,46]},"scoresAfter":[-57,-178]},{"ply":21,"player":"human","action":84,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[8,21,27,29,30,34,35,57],"ai":[15,22,31,32,33,41,44,46]},"scoresAfter":[-33,-178]},{"ply":22,"player":"ai","action":24,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":13,"handsBefore":{"human":[8,18,21,27,29,30,34,35],"ai":[15,22,31,32,33,41,44,46]},"scoresAfter":[-33,-166]},{"ply":23,"player":"human","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":28,"handsBefore":{"human":[8,18,21,27,29,30,34,35],"ai":[13,15,22,32,33,41,44,46]},"scoresAfter":[-12,-166]},{"ply":24,"player":"ai","action":36,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[18,21,27,28,29,30,34,35],"ai":[13,15,22,32,33,41,44,46]},"scoresAfter":[-12,-152]},{"ply":25,"player":"human","action":24,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[18,21,27,28,29,30,34,35],"ai":[13,15,22,33,41,43,44,46]},"scoresAfter":[-30,-152]},{"ply":26,"player":"ai","action":36,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[18,21,28,29,30,34,35,42],"ai":[13,15,22,33,41,43,44,46]},"scoresAfter":[-30,-136]},{"ply":27,"player":"human","action":24,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[18,21,28,29,30,34,35,42],"ai":[5,13,15,22,41,43,44,46]},"scoresAfter":[-27,-136]},{"ply":28,"player":"ai","action":6,"playedCard":5,"placeType":"discard","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[18,21,25,29,30,34,35,42],"ai":[5,13,15,22,41,43,44,46]},"scoresAfter":[-27,-136]},{"ply":29,"player":"human","action":36,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[18,21,25,29,30,34,35,42],"ai":[13,15,22,39,41,43,44,46]},"scoresAfter":[-23,-136]},{"ply":30,"player":"ai","action":36,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[9,18,21,25,30,34,35,42],"ai":[13,15,22,39,41,43,44,46]},"scoresAfter":[-23,-130]},{"ply":31,"player":"human","action":48,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[9,18,21,25,30,34,35,42],"ai":[13,15,22,40,41,43,44,46]},"scoresAfter":[-18,-130]},{"ply":32,"player":"ai","action":48,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[9,18,21,25,34,35,42,56],"ai":[13,15,22,40,41,43,44,46]},"scoresAfter":[-18,-118]},{"ply":33,"player":"human","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[9,18,21,25,34,35,42,56],"ai":[13,15,16,22,40,43,44,46]},"scoresAfter":[6,-118]},{"ply":34,"player":"ai","action":60,"playedCard":43,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[18,21,25,34,35,42,56,58],"ai":[13,15,16,22,40,43,44,46]},"scoresAfter":[6,-100]},{"ply":35,"player":"human","action":84,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[18,21,25,34,35,42,56,58],"ai":[13,15,16,19,22,40,44,46]},"scoresAfter":[33,-100]},{"ply":36,"player":"ai","action":24,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[18,21,25,34,35,42,56,59],"ai":[13,15,16,19,22,40,44,46]},"scoresAfter":[33,-91]},{"ply":37,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[18,21,25,34,35,42,56,59],"ai":[13,15,19,22,23,40,44,46]},"scoresAfter":[83,-91]},{"ply":38,"player":"ai","action":24,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[18,21,25,26,34,35,42,56],"ai":[13,15,19,22,23,40,44,46]},"scoresAfter":[83,-73]},{"ply":39,"player":"human","action":48,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[18,21,25,26,34,35,42,56],"ai":[13,15,17,22,23,40,44,46]},"scoresAfter":[92,-73]},{"ply":40,"player":"ai","action":36,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[11,18,21,25,26,35,42,56],"ai":[13,15,17,22,23,40,44,46]},"scoresAfter":[92,-46]},{"ply":41,"player":"human","action":60,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[11,18,21,25,26,35,42,56],"ai":[13,15,17,23,40,44,46,49]},"scoresAfter":[102,-46]},{"ply":42,"player":"ai","action":37,"playedCard":23,"placeType":"play","drawSource":"discard_0","drawnCard":5,"handsBefore":{"human":[11,18,21,25,26,36,42,56],"ai":[13,15,17,23,40,44,46,49]},"scoresAfter":[102,-16]},{"ply":43,"player":"human","action":0,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[11,18,21,25,26,36,42,56],"ai":[5,13,15,17,40,44,46,49]},"scoresAfter":[132,-16]},{"ply":44,"player":"ai","action":60,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[18,21,25,26,36,42,51,56],"ai":[5,13,15,17,40,44,46,49]},"scoresAfter":[132,5]},{"ply":45,"player":"human","action":30,"playedCard":25,"placeType":"discard","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[18,21,25,26,36,42,51,56],"ai":[5,13,15,17,40,46,47,49]},"scoresAfter":[132,5]},{"ply":46,"player":"ai","action":63,"playedCard":46,"placeType":"play","drawSource":"discard_2","drawnCard":25,"handsBefore":{"human":[0,18,21,26,36,42,51,56],"ai":[5,13,15,17,40,46,47,49]},"scoresAfter":[132,32]},{"ply":47,"player":"human","action":6,"playedCard":0,"placeType":"discard","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[0,18,21,26,36,42,51,56],"ai":[5,13,15,17,25,40,47,49]},"scoresAfter":[132,32]},{"ply":48,"player":"ai","action":72,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[18,20,21,26,36,42,51,56],"ai":[5,13,15,17,25,40,47,49]},"scoresAfter":[132,82]}],"finalScores":[132,82],"outcome":"YOU WIN","finalState":{"deckOrder":[1,8,52,3,29,30,38,2,15,14,37,50,31,10,24,46,48,12,57,22,21,4,54,55,6,27,41,53,44,35,33,7,34,32,18,13,28,43,42,5,25,39,9,40,56,16,58,19,59,23,26,17,11,49,36,51,47,0,20,45],"drawPtr":60,"cardLoc":[5,3,3,3,4,2,4,3,3,3,4,3,4,2,4,2,4,2,1,4,1,1,4,4,4,2,1,3,3,3,3,4,4,4,3,3,1,4,4,4,2,4,1,4,4,2,4,4,3,2,3,1,3,3,4,3,1,3,3,3],"handPublic":[false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"colTop":[[10,0,10,0,10],[9,10,8,10,5]],"colHandshakes":[[2,0,0,0,2],[0,2,1,2,0]],"colLength":[[7,0,6,0,8],[3,6,4,8,1]],"piles":[[0],[],[],[],[]],"toMove":0,"stepCount":48,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"38ed0756-4a90-4d2e-a697-b64ff27f35ec","seed":"ir0nps","startedAt":"2026-07-14T20:25:34.950Z","finishedAt":"2026-07-14T20:29:17.902Z","initialDeckOrder":[27,3,30,38,18,4,9,36,28,8,19,13,47,25,6,7,37,1,49,42,32,31,12,34,51,53,20,56,24,40,43,55,39,15,16,14,11,26,46,22,21,41,48,44,59,33,17,2,57,35,0,54,29,45,58,23,10,52,50,5],"moves":[{"ply":1,"player":"human","action":0,"playedCard":3,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[3,4,9,18,27,30,36,38],"ai":[6,7,8,13,19,25,28,47]},"scoresAfter":[-18,0]},{"ply":2,"player":"ai","action":48,"playedCard":19,"placeType":"play","drawSource":"deck","drawnCard":1,"handsBefore":{"human":[4,9,18,27,30,36,37,38],"ai":[6,7,8,13,19,25,28,47]},"scoresAfter":[-18,-14]},{"ply":3,"player":"human","action":0,"playedCard":4,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[4,9,18,27,30,36,37,38],"ai":[1,6,7,8,13,25,28,47]},"scoresAfter":[-15,-14]},{"ply":4,"player":"ai","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":42,"handsBefore":{"human":[9,18,27,30,36,37,38,49],"ai":[1,6,7,8,13,25,28,47]},"scoresAfter":[-15,-54]},{"ply":5,"player":"human","action":54,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":32,"handsBefore":{"human":[9,18,27,30,36,37,38,49],"ai":[6,7,8,13,25,28,42,47]},"scoresAfter":[-15,-54]},{"ply":6,"player":"ai","action":0,"playedCard":6,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[9,18,27,30,32,37,38,49],"ai":[6,7,8,13,25,28,42,47]},"scoresAfter":[-15,-44]},{"ply":7,"player":"human","action":66,"playedCard":37,"placeType":"discard","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[9,18,27,30,32,37,38,49],"ai":[7,8,13,25,28,31,42,47]},"scoresAfter":[-15,-44]},{"ply":8,"player":"ai","action":0,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[9,12,18,27,30,32,38,49],"ai":[7,8,13,25,28,31,42,47]},"scoresAfter":[-15,-32]},{"ply":9,"player":"human","action":78,"playedCard":38,"placeType":"discard","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[9,12,18,27,30,32,38,49],"ai":[8,13,25,28,31,34,42,47]},"scoresAfter":[-15,-32]},{"ply":10,"player":"ai","action":0,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":53,"handsBefore":{"human":[9,12,18,27,30,32,49,51],"ai":[8,13,25,28,31,34,42,47]},"scoresAfter":[-15,-18]},{"ply":11,"player":"human","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[9,12,18,27,30,32,49,51],"ai":[13,25,28,31,34,42,47,53]},"scoresAfter":[-7,-18]},{"ply":12,"player":"ai","action":84,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[12,18,20,27,30,32,49,51],"ai":[13,25,28,31,34,42,47,53]},"scoresAfter":[-7,-34]},{"ply":13,"player":"human","action":0,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[12,18,20,27,30,32,49,51],"ai":[13,25,28,31,34,42,47,56]},"scoresAfter":[-47,-34]},{"ply":14,"player":"ai","action":84,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[18,20,24,27,30,32,49,51],"ai":[13,25,28,31,34,42,47,56]},"scoresAfter":[-47,-27]},{"ply":15,"player":"human","action":24,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[18,20,24,27,30,32,49,51],"ai":[13,25,28,31,34,40,42,47]},"scoresAfter":[-87,-27]},{"ply":16,"player":"ai","action":12,"playedCard":25,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[18,20,27,30,32,43,49,51],"ai":[13,25,28,31,34,40,42,47]},"scoresAfter":[-87,-67]},{"ply":17,"player":"human","action":24,"playedCard":27,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[18,20,27,30,32,43,49,51],"ai":[13,28,31,34,40,42,47,55]},"scoresAfter":[-83,-67]},{"ply":18,"player":"ai","action":16,"playedCard":28,"placeType":"play","drawSource":"discard_3","drawnCard":38,"handsBefore":{"human":[18,20,30,32,39,43,49,51],"ai":[13,28,31,34,40,42,47,55]},"scoresAfter":[-83,-61]},{"ply":19,"player":"human","action":24,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[18,20,30,32,39,43,49,51],"ai":[13,31,34,38,40,42,47,55]},"scoresAfter":[-73,-61]},{"ply":20,"player":"ai","action":90,"playedCard":55,"placeType":"discard","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[15,18,20,32,39,43,49,51],"ai":[13,31,34,38,40,42,47,55]},"scoresAfter":[-73,-61]},{"ply":21,"player":"human","action":0,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":14,"handsBefore":{"human":[15,18,20,32,39,43,49,51],"ai":[13,16,31,34,38,40,42,47]},"scoresAfter":[-69,-61]},{"ply":22,"player":"ai","action":6,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[14,18,20,32,39,43,49,51],"ai":[13,16,31,34,38,40,42,47]},"scoresAfter":[-69,-61]},{"ply":23,"player":"human","action":6,"playedCard":14,"placeType":"discard","drawSource":"deck","drawnCard":26,"handsBefore":{"human":[14,18,20,32,39,43,49,51],"ai":[11,16,31,34,38,40,42,47]},"scoresAfter":[-69,-61]},{"ply":24,"player":"ai","action":4,"playedCard":11,"placeType":"play","drawSource":"discard_3","drawnCard":37,"handsBefore":{"human":[18,20,26,32,39,43,49,51],"ai":[11,16,31,34,38,40,42,47]},"scoresAfter":[-69,-41]},{"ply":25,"player":"human","action":30,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":46,"handsBefore":{"human":[18,20,26,32,39,43,49,51],"ai":[16,31,34,37,38,40,42,47]},"scoresAfter":[-69,-41]},{"ply":26,"player":"ai","action":16,"playedCard":31,"placeType":"play","drawSource":"discard_3","drawnCard":36,"handsBefore":{"human":[18,20,32,39,43,46,49,51],"ai":[16,31,34,37,38,40,42,47]},"scoresAfter":[-69,-29]},{"ply":27,"player":"human","action":36,"playedCard":39,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[18,20,32,39,43,46,49,51],"ai":[16,34,36,37,38,40,42,47]},"scoresAfter":[-87,-29]},{"ply":28,"player":"ai","action":36,"playedCard":37,"placeType":"play","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[18,20,22,32,43,46,49,51],"ai":[16,34,36,37,38,40,42,47]},"scoresAfter":[-87,-69]},{"ply":29,"player":"human","action":0,"playedCard":18,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[18,20,22,32,43,46,49,51],"ai":[16,21,34,36,38,40,42,47]},"scoresAfter":[-77,-69]},{"ply":30,"player":"ai","action":12,"playedCard":21,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[20,22,32,41,43,46,49,51],"ai":[16,21,34,36,38,40,42,47]},"scoresAfter":[-77,-61]},{"ply":31,"player":"human","action":0,"playedCard":20,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[20,22,32,41,43,46,49,51],"ai":[16,34,36,38,40,42,47,48]},"scoresAfter":[-63,-61]},{"ply":32,"player":"ai","action":12,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":59,"handsBefore":{"human":[22,32,41,43,44,46,49,51],"ai":[16,34,36,38,40,42,47,48]},"scoresAfter":[-63,-43]},{"ply":33,"player":"human","action":0,"playedCard":22,"placeType":"play","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[22,32,41,43,44,46,49,51],"ai":[16,36,38,40,42,47,48,59]},"scoresAfter":[-45,-43]},{"ply":34,"player":"ai","action":12,"playedCard":36,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[32,33,41,43,44,46,49,51],"ai":[16,36,38,40,42,47,48,59]},"scoresAfter":[-45,-63]},{"ply":35,"player":"human","action":0,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[32,33,41,43,44,46,49,51],"ai":[16,17,38,40,42,47,48,59]},"scoresAfter":[-31,-63]},{"ply":36,"player":"ai","action":24,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[2,33,41,43,44,46,49,51],"ai":[16,17,38,40,42,47,48,59]},"scoresAfter":[-31,-83]},{"ply":37,"player":"human","action":12,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[2,33,41,43,44,46,49,51],"ai":[16,17,40,42,47,48,57,59]},"scoresAfter":[-15,-83]},{"ply":38,"player":"ai","action":72,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[2,35,41,43,44,46,49,51],"ai":[16,17,40,42,47,48,57,59]},"scoresAfter":[-15,-75]},{"ply":39,"player":"human","action":12,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[2,35,41,43,44,46,49,51],"ai":[0,16,17,40,42,47,48,59]},"scoresAfter":[5,-75]},{"ply":40,"player":"ai","action":36,"playedCard":40,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[2,41,43,44,46,49,51,54],"ai":[0,16,17,40,42,47,48,59]},"scoresAfter":[5,-63]},{"ply":41,"player":"human","action":12,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[2,41,43,44,46,49,51,54],"ai":[0,16,17,29,42,47,48,59]},"scoresAfter":[9,-63]},{"ply":42,"player":"ai","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[2,43,44,45,46,49,51,54],"ai":[0,16,17,29,42,47,48,59]},"scoresAfter":[9,-53]},{"ply":43,"player":"human","action":17,"playedCard":43,"placeType":"play","drawSource":"discard_4","drawnCard":55,"handsBefore":{"human":[2,43,44,45,46,49,51,54],"ai":[0,16,17,29,42,47,48,58]},"scoresAfter":[15,-53]},{"ply":44,"player":"ai","action":48,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":23,"handsBefore":{"human":[2,44,45,46,49,51,54,55],"ai":[0,16,17,29,42,47,48,58]},"scoresAfter":[15,-33]},{"ply":45,"player":"human","action":12,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[2,44,45,46,49,51,54,55],"ai":[0,16,17,23,29,47,48,58]},"scoresAfter":[22,-33]},{"ply":46,"player":"ai","action":39,"playedCard":23,"placeType":"play","drawSource":"discard_2","drawnCard":26,"handsBefore":{"human":[2,10,45,46,49,51,54,55],"ai":[0,16,17,23,29,47,48,58]},"scoresAfter":[22,-23]},{"ply":47,"player":"human","action":26,"playedCard":45,"placeType":"play","drawSource":"discard_1","drawnCard":14,"handsBefore":{"human":[2,10,45,46,49,51,54,55],"ai":[0,16,17,26,29,47,48,58]},"scoresAfter":[30,-23]},{"ply":48,"player":"ai","action":62,"playedCard":47,"placeType":"play","drawSource":"discard_1","drawnCard":13,"handsBefore":{"human":[2,10,14,46,49,51,54,55],"ai":[0,16,17,26,29,47,48,58]},"scoresAfter":[30,17]},{"ply":49,"player":"human","action":36,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[2,10,14,46,49,51,54,55],"ai":[0,13,16,17,26,29,48,58]},"scoresAfter":[39,17]},{"ply":50,"player":"ai","action":18,"playedCard":13,"placeType":"discard","drawSource":"deck","drawnCard":50,"handsBefore":{"human":[2,10,14,49,51,52,54,55],"ai":[0,13,16,17,26,29,48,58]},"scoresAfter":[39,17]},{"ply":51,"player":"human","action":12,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[2,10,14,49,51,52,54,55],"ai":[0,16,17,26,29,48,50,58]},"scoresAfter":[48,17]}],"finalScores":[48,17],"outcome":"YOU WIN","finalState":{"deckOrder":[27,3,30,38,18,4,9,36,28,8,19,13,47,25,6,7,37,1,49,42,32,31,12,34,51,53,20,56,24,40,43,55,39,15,16,14,11,26,46,22,21,41,48,44,59,33,17,2,57,35,0,54,29,45,58,23,10,52,50,5],"drawPtr":60,"cardLoc":[2,4,1,3,3,1,4,4,4,3,3,4,3,5,1,3,2,2,3,4,3,4,3,4,3,4,2,3,4,2,3,4,3,3,4,3,4,4,4,3,4,3,4,3,3,3,3,4,2,1,2,1,1,4,1,1,4,4,2,4],"handPublic":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false],"colTop":[[9,9,10,9,0],[10,10,9,10,10]],"colHandshakes":[[0,1,1,0,0],[1,0,1,3,0]],"colLength":[[4,5,6,6,0],[5,3,4,6,4]],"piles":[[],[13],[],[],[]],"toMove":1,"stepCount":51,"done":true},"policy":"WASM · FINAL PPO"} +{"format":"lost-cities-web-game-v1","gameId":"4eb1e5fb-f7da-429c-9032-6629db6ed35d","seed":"vyudm0","startedAt":"2026-07-14T20:29:18.767Z","finishedAt":"2026-07-14T20:31:17.120Z","initialDeckOrder":[50,8,59,46,6,32,1,42,13,26,38,53,30,23,14,28,57,10,56,41,2,45,5,58,44,48,9,35,49,24,16,29,22,47,36,17,18,4,43,37,19,31,12,40,55,7,33,54,15,11,20,3,0,21,34,39,51,27,52,25],"moves":[{"ply":1,"player":"human","action":0,"playedCard":1,"placeType":"play","drawSource":"deck","drawnCard":57,"handsBefore":{"human":[1,6,8,32,42,46,50,59],"ai":[13,14,23,26,28,30,38,53]},"scoresAfter":[-40,0]},{"ply":2,"player":"ai","action":90,"playedCard":53,"placeType":"discard","drawSource":"deck","drawnCard":10,"handsBefore":{"human":[6,8,32,42,46,50,57,59],"ai":[13,14,23,26,28,30,38,53]},"scoresAfter":[-40,0]},{"ply":3,"player":"human","action":60,"playedCard":50,"placeType":"play","drawSource":"deck","drawnCard":56,"handsBefore":{"human":[6,8,32,42,46,50,57,59],"ai":[10,13,14,23,26,28,30,38]},"scoresAfter":[-80,0]},{"ply":4,"player":"ai","action":24,"playedCard":14,"placeType":"play","drawSource":"deck","drawnCard":41,"handsBefore":{"human":[6,8,32,42,46,56,57,59],"ai":[10,13,14,23,26,28,30,38]},"scoresAfter":[-80,-40]},{"ply":5,"player":"human","action":5,"playedCard":6,"placeType":"play","drawSource":"discard_4","drawnCard":53,"handsBefore":{"human":[6,8,32,42,46,56,57,59],"ai":[10,13,23,26,28,30,38,41]},"scoresAfter":[-70,-40]},{"ply":6,"player":"ai","action":72,"playedCard":38,"placeType":"play","drawSource":"deck","drawnCard":2,"handsBefore":{"human":[8,32,42,46,53,56,57,59],"ai":[10,13,23,26,28,30,38,41]},"scoresAfter":[-70,-80]},{"ply":7,"player":"human","action":48,"playedCard":53,"placeType":"play","drawSource":"deck","drawnCard":45,"handsBefore":{"human":[8,32,42,46,53,56,57,59],"ai":[2,10,13,23,26,28,30,41]},"scoresAfter":[-62,-80]},{"ply":8,"player":"ai","action":6,"playedCard":2,"placeType":"discard","drawSource":"deck","drawnCard":5,"handsBefore":{"human":[8,32,42,45,46,56,57,59],"ai":[2,10,13,23,26,28,30,41]},"scoresAfter":[-62,-80]},{"ply":9,"player":"human","action":24,"playedCard":42,"placeType":"play","drawSource":"deck","drawnCard":58,"handsBefore":{"human":[8,32,42,45,46,56,57,59],"ai":[5,10,13,23,26,28,30,41]},"scoresAfter":[-77,-80]},{"ply":10,"player":"ai","action":84,"playedCard":41,"placeType":"play","drawSource":"deck","drawnCard":44,"handsBefore":{"human":[8,32,45,46,56,57,58,59],"ai":[5,10,13,23,26,28,30,41]},"scoresAfter":[-77,-72]},{"ply":11,"player":"human","action":48,"playedCard":56,"placeType":"play","drawSource":"deck","drawnCard":48,"handsBefore":{"human":[8,32,45,46,56,57,58,59],"ai":[5,10,13,23,26,28,30,44]},"scoresAfter":[-63,-72]},{"ply":12,"player":"ai","action":84,"playedCard":44,"placeType":"play","drawSource":"deck","drawnCard":9,"handsBefore":{"human":[8,32,45,46,48,57,58,59],"ai":[5,10,13,23,26,28,30,44]},"scoresAfter":[-63,-58]},{"ply":13,"player":"human","action":60,"playedCard":57,"placeType":"play","drawSource":"deck","drawnCard":35,"handsBefore":{"human":[8,32,45,46,48,57,58,59],"ai":[5,9,10,13,23,26,28,30]},"scoresAfter":[-47,-58]},{"ply":14,"player":"ai","action":0,"playedCard":5,"placeType":"play","drawSource":"deck","drawnCard":49,"handsBefore":{"human":[8,32,35,45,46,48,58,59],"ai":[5,9,10,13,23,26,28,30]},"scoresAfter":[-47,-74]},{"ply":15,"player":"human","action":72,"playedCard":58,"placeType":"play","drawSource":"deck","drawnCard":24,"handsBefore":{"human":[8,32,35,45,46,48,58,59],"ai":[9,10,13,23,26,28,30,49]},"scoresAfter":[-29,-74]},{"ply":16,"player":"ai","action":90,"playedCard":49,"placeType":"discard","drawSource":"deck","drawnCard":16,"handsBefore":{"human":[8,24,32,35,45,46,48,59],"ai":[9,10,13,23,26,28,30,49]},"scoresAfter":[-29,-74]},{"ply":17,"player":"human","action":84,"playedCard":59,"placeType":"play","drawSource":"deck","drawnCard":29,"handsBefore":{"human":[8,24,32,35,45,46,48,59],"ai":[9,10,13,16,23,26,28,30]},"scoresAfter":[-9,-74]},{"ply":18,"player":"ai","action":24,"playedCard":13,"placeType":"play","drawSource":"deck","drawnCard":22,"handsBefore":{"human":[8,24,29,32,35,45,46,48],"ai":[9,10,13,16,23,26,28,30]},"scoresAfter":[-9,-94]},{"ply":19,"player":"human","action":12,"playedCard":24,"placeType":"play","drawSource":"deck","drawnCard":47,"handsBefore":{"human":[8,24,29,32,35,45,46,48],"ai":[9,10,16,22,23,26,28,30]},"scoresAfter":[-49,-94]},{"ply":20,"player":"ai","action":72,"playedCard":28,"placeType":"play","drawSource":"deck","drawnCard":36,"handsBefore":{"human":[8,29,32,35,45,46,47,48],"ai":[9,10,16,22,23,26,28,30]},"scoresAfter":[-49,-111]},{"ply":21,"player":"human","action":48,"playedCard":45,"placeType":"play","drawSource":"deck","drawnCard":17,"handsBefore":{"human":[8,29,32,35,45,46,47,48],"ai":[9,10,16,22,23,26,30,36]},"scoresAfter":[-41,-111]},{"ply":22,"player":"ai","action":90,"playedCard":36,"placeType":"discard","drawSource":"deck","drawnCard":18,"handsBefore":{"human":[8,17,29,32,35,46,47,48],"ai":[9,10,16,22,23,26,30,36]},"scoresAfter":[-41,-111]},{"ply":23,"player":"human","action":60,"playedCard":46,"placeType":"play","drawSource":"deck","drawnCard":4,"handsBefore":{"human":[8,17,29,32,35,46,47,48],"ai":[9,10,16,18,22,23,26,30]},"scoresAfter":[-32,-111]},{"ply":24,"player":"ai","action":0,"playedCard":9,"placeType":"play","drawSource":"deck","drawnCard":43,"handsBefore":{"human":[4,8,17,29,32,35,47,48],"ai":[9,10,16,18,22,23,26,30]},"scoresAfter":[-32,-103]},{"ply":25,"player":"human","action":72,"playedCard":47,"placeType":"play","drawSource":"deck","drawnCard":37,"handsBefore":{"human":[4,8,17,29,32,35,47,48],"ai":[10,16,18,22,23,26,30,43]},"scoresAfter":[-22,-103]},{"ply":26,"player":"ai","action":72,"playedCard":30,"placeType":"play","drawSource":"deck","drawnCard":19,"handsBefore":{"human":[4,8,17,29,32,35,37,48],"ai":[10,16,18,22,23,26,30,43]},"scoresAfter":[-22,-98]},{"ply":27,"player":"human","action":36,"playedCard":29,"placeType":"play","drawSource":"deck","drawnCard":31,"handsBefore":{"human":[4,8,17,29,32,35,37,48],"ai":[10,16,18,19,22,23,26,43]},"scoresAfter":[-14,-98]},{"ply":28,"player":"ai","action":0,"playedCard":10,"placeType":"play","drawSource":"deck","drawnCard":12,"handsBefore":{"human":[4,8,17,31,32,35,37,48],"ai":[10,16,18,19,22,23,26,43]},"scoresAfter":[-14,-89]},{"ply":29,"player":"human","action":36,"playedCard":31,"placeType":"play","drawSource":"deck","drawnCard":40,"handsBefore":{"human":[4,8,17,31,32,35,37,48],"ai":[12,16,18,19,22,23,26,43]},"scoresAfter":[-2,-89]},{"ply":30,"player":"ai","action":0,"playedCard":12,"placeType":"play","drawSource":"deck","drawnCard":55,"handsBefore":{"human":[4,8,17,32,35,37,40,48],"ai":[12,16,18,19,22,23,26,43]},"scoresAfter":[-2,-109]},{"ply":31,"player":"human","action":36,"playedCard":32,"placeType":"play","drawSource":"deck","drawnCard":7,"handsBefore":{"human":[4,8,17,32,35,37,40,48],"ai":[16,18,19,22,23,26,43,55]},"scoresAfter":[12,-109]},{"ply":32,"player":"ai","action":90,"playedCard":55,"placeType":"discard","drawSource":"deck","drawnCard":33,"handsBefore":{"human":[4,7,8,17,35,37,40,48],"ai":[16,18,19,22,23,26,43,55]},"scoresAfter":[12,-109]},{"ply":33,"player":"human","action":12,"playedCard":7,"placeType":"play","drawSource":"deck","drawnCard":54,"handsBefore":{"human":[4,7,8,17,35,37,40,48],"ai":[16,18,19,22,23,26,33,43]},"scoresAfter":[24,-109]},{"ply":34,"player":"ai","action":72,"playedCard":33,"placeType":"play","drawSource":"deck","drawnCard":15,"handsBefore":{"human":[4,8,17,35,37,40,48,54],"ai":[16,18,19,22,23,26,33,43]},"scoresAfter":[24,-101]},{"ply":35,"player":"human","action":12,"playedCard":8,"placeType":"play","drawSource":"deck","drawnCard":11,"handsBefore":{"human":[4,8,17,35,37,40,48,54],"ai":[15,16,18,19,22,23,26,43]},"scoresAfter":[38,-101]},{"ply":36,"player":"ai","action":0,"playedCard":15,"placeType":"play","drawSource":"deck","drawnCard":20,"handsBefore":{"human":[4,11,17,35,37,40,48,54],"ai":[15,16,18,19,22,23,26,43]},"scoresAfter":[38,-93]},{"ply":37,"player":"human","action":66,"playedCard":40,"placeType":"discard","drawSource":"deck","drawnCard":3,"handsBefore":{"human":[4,11,17,35,37,40,48,54],"ai":[16,18,19,20,22,23,26,43]},"scoresAfter":[38,-93]},{"ply":38,"player":"ai","action":0,"playedCard":16,"placeType":"play","drawSource":"deck","drawnCard":0,"handsBefore":{"human":[3,4,11,17,35,37,48,54],"ai":[16,18,19,20,22,23,26,43]},"scoresAfter":[38,-81]},{"ply":39,"player":"human","action":6,"playedCard":3,"placeType":"discard","drawSource":"deck","drawnCard":21,"handsBefore":{"human":[3,4,11,17,35,37,48,54],"ai":[0,18,19,20,22,23,26,43]},"scoresAfter":[38,-81]},{"ply":40,"player":"ai","action":17,"playedCard":18,"placeType":"play","drawSource":"discard_4","drawnCard":55,"handsBefore":{"human":[4,11,17,21,35,37,48,54],"ai":[0,18,19,20,22,23,26,43]},"scoresAfter":[38,-61]},{"ply":41,"player":"human","action":12,"playedCard":11,"placeType":"play","drawSource":"deck","drawnCard":34,"handsBefore":{"human":[4,11,17,21,35,37,48,54],"ai":[0,19,20,22,23,26,43,55]},"scoresAfter":[58,-61]},{"ply":42,"player":"ai","action":13,"playedCard":19,"placeType":"play","drawSource":"discard_0","drawnCard":3,"handsBefore":{"human":[4,17,21,34,35,37,48,54],"ai":[0,19,20,22,23,26,43,55]},"scoresAfter":[58,-37]},{"ply":43,"player":"human","action":36,"playedCard":34,"placeType":"play","drawSource":"deck","drawnCard":39,"handsBefore":{"human":[4,17,21,34,35,37,48,54],"ai":[0,3,20,22,23,26,43,55]},"scoresAfter":[76,-37]},{"ply":44,"player":"ai","action":29,"playedCard":20,"placeType":"play","drawSource":"discard_4","drawnCard":49,"handsBefore":{"human":[4,17,21,35,37,39,48,54],"ai":[0,3,20,22,23,26,43,55]},"scoresAfter":[76,11]},{"ply":45,"player":"human","action":36,"playedCard":35,"placeType":"play","drawSource":"deck","drawnCard":51,"handsBefore":{"human":[4,17,21,35,37,39,48,54],"ai":[0,3,22,23,26,43,49,55]},"scoresAfter":[96,11]},{"ply":46,"player":"ai","action":28,"playedCard":22,"placeType":"play","drawSource":"discard_3","drawnCard":40,"handsBefore":{"human":[4,17,21,37,39,48,51,54],"ai":[0,3,22,23,26,43,49,55]},"scoresAfter":[96,47]},{"ply":47,"player":"human","action":66,"playedCard":48,"placeType":"discard","drawSource":"deck","drawnCard":27,"handsBefore":{"human":[4,17,21,37,39,48,51,54],"ai":[0,3,23,26,40,43,49,55]},"scoresAfter":[96,47]},{"ply":48,"player":"ai","action":28,"playedCard":23,"placeType":"play","drawSource":"discard_3","drawnCard":36,"handsBefore":{"human":[4,17,21,27,37,39,51,54],"ai":[0,3,23,26,40,43,49,55]},"scoresAfter":[96,87]},{"ply":49,"player":"human","action":42,"playedCard":27,"placeType":"discard","drawSource":"deck","drawnCard":52,"handsBefore":{"human":[4,17,21,27,37,39,51,54],"ai":[0,3,26,36,40,43,49,55]},"scoresAfter":[96,87]},{"ply":50,"player":"ai","action":30,"playedCard":26,"placeType":"discard","drawSource":"deck","drawnCard":25,"handsBefore":{"human":[4,17,21,37,39,51,52,54],"ai":[0,3,26,36,40,43,49,55]},"scoresAfter":[96,87]}],"finalScores":[96,87],"outcome":"YOU WIN","finalState":{"deckOrder":[50,8,59,46,6,32,1,42,13,26,38,53,30,23,14,28,57,10,56,41,2,45,5,58,44,48,9,35,49,24,16,29,22,47,36,17,18,4,43,37,19,31,12,40,55,7,33,54,15,11,20,3,0,21,34,39,51,27,52,25],"drawPtr":60,"cardLoc":[2,3,5,2,1,4,3,3,3,4,4,3,4,4,4,4,4,1,4,4,4,1,4,4,3,2,5,5,4,3,4,3,3,4,3,3,2,1,4,1,2,4,3,2,4,3,3,3,5,2,3,1,1,3,1,2,3,3,3,3],"handPublic":[false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,true,false,false,false,false,false,false,false,false,true,false,false,false,false,false,true,false,false,false,false],"colTop":[[10,0,10,10,10],[9,10,8,7,0]],"colHandshakes":[[1,0,1,0,1],[0,3,0,1,0]],"colLength":[[5,0,6,4,6],[3,10,3,3,0]],"piles":[[2],[],[27,26],[],[48]],"toMove":0,"stepCount":50,"done":true},"policy":"WASM · FINAL PPO"} diff --git a/data/models.json b/data/models.json new file mode 100644 index 0000000..4aef2ed --- /dev/null +++ b/data/models.json @@ -0,0 +1,43 @@ +{ + "_scheme": { + "naming": "Astronomical names, alphabetically ordered. The first letter is the generation; a new letter means the observation space broke, not that the model got better.", + "rule": "A codename never encodes quality. The record this replaces stored 'FINAL PPO', which stops meaning anything the moment there is a second final model.", + "identity": "The hash is the truth -- it is what actually played. The codename is for humans, and it is assigned here, not derived. Records should carry the hash; look the codename up.", + "next": "cygnus, deneb, ..." + }, + + "models": { + "altair": { + "hash": "e8241e305c01", + "hash_kind": "sha256 of web/public/models/jax-ppo.onnx", + "generation": "a", + "game": "single round", + "observation_size": 454, + "hidden_size": 512, + "num_layers": 3, + "trained": "self-play league, 122.6M learner actions", + "source": "/mnt/2tbhdd/coolrl-lost-cities-artifacts/league/2026-07-05_052325_jax-ppo-league-v1/latest", + "deployed": "web/public/models/jax-ppo.onnx", + "displayed_as": "WASM · FINAL PPO", + "note": "Every game in data/human-play/game-records.jsonl (format v1, 111 games, 2026-07-14) was played against this model. The v1 schema has no model field -- it stores the on-screen label -- so this line is the record of what they played." + }, + + "borealis": { + "hash": "4ae613b010ca", + "hash_kind": "sha256 over the orbax checkpoint files (no ONNX export yet)", + "generation": "b", + "game": "three-round match (classic rules)", + "observation_size": 501, + "critic_observation_size": 681, + "hidden_size": 512, + "num_layers": 3, + "trained": "self-play, 131.1M learner actions, linear total-score reward, both seats, privileged critic", + "source": "runs/jax-ppo-match/2026-07-15_031529_match-scaled/latest", + "deployed": null, + "results": { + "vs_altair_3round": "0.6094 win rate [0.599, 0.620], +22.0 points, 8192 duplicate matches", + "exploitability": "a from-scratch exploiter funded to 131M reaches 0.4657 against it, and 0.6295 against altair -- lower bound, neither exploiter had plateaued" + } + } + } +} diff --git a/docs/plans/lost-cities-classic-3round.md b/docs/plans/lost-cities-classic-3round.md new file mode 100644 index 0000000..07364e5 --- /dev/null +++ b/docs/plans/lost-cities-classic-3round.md @@ -0,0 +1,617 @@ +# Plan: 클래식 3라운드 로스트시티 에이전트 + +**Status:** Ready to execute (Fable 2차 검토 반영 완료) +**Priority:** High — 현재 스택은 **단판(1라운드)** 게임을 학습하는데, 원작 로스트시티는 +**3라운드 합산**이 승패를 가른다. 즉 지금 에이전트는 애초에 다른 게임을 배우고 있다. +**Background:** Fable 설계 검토 2회 (2026-07-15), 인간 대 AI 기보 +(`data/human-play/game-records.jsonl`, 계속 증가 중) + +## 목표 + +**원작 규칙 그대로의 로스트시티에서 가장 강한 에이전트.** 레거시 코드 호환은 고려하지 않는다. +env/obs/보상/학습 루프 재작성 모두 허용. + +## 확정된 규칙 (룰북 원문 검증 완료) + +코스모스 공식 영문 룰북(691820-02) 및 Board Game Arena 구현체로 교차 확인: + +- 3라운드를 두고 **누적 총점**이 높은 쪽이 매치 승리. +- 1라운드 선공: "가장 나이 많은 사람" → 게임 내적으로는 **임의**. +- **2·3라운드 선공: 누적 점수가 더 많은 쪽** ("The player who has more points begins.") + — 번갈아 가는 것이 아니다. +- **정확한 동점일 때의 선공은 룰북에 없다.** 공식 룰북·BGA 모두 침묵. + → **무작위(동전 던지기)로 정한다.** 결정론적 규칙은 대칭 제로섬 셀프플레이에 + 자리(seat) 비대칭을 주입해 착취 가능한 구멍이 된다. + +점수 계산(`(랭크합 − 20) × (1 + 악수) + (8장 이상 +20)`)과 "방금 버린 카드는 즉시 +회수 불가"(`just_discarded`)는 **현재 엔진이 이미 정확하다** +(`engine.py:244`, `engine.py:124`). + +### 선공이 중요한 이유: 덱 시계 + +라운드는 **덱의 마지막 카드를 뽑는 순간** 끝난다. 카드는 놓은 뒤에 뽑으므로 마지막 +카드를 뽑은 쪽은 그 카드를 쓰지 못한다. 총 턴 수가 홀수면 **선공이 한 장 더 놓는다**. +총 턴 수 = 44 + (버림패 드로우 횟수)이므로 **플레이어가 홀짝을 조작할 수 있다** +(실측 게임당 버림패 드로우 ≈6.6회). 선공권이 누적 점수에 달려 있으므로, 2라운드 +마진에는 **점수를 넘어 3라운드 선공권이라는 추가 가치**가 붙는다. + +### 측정된 사실: stalling은 정적 상대 착취이지 균형이 아니다 (Phase 1 사이징의 근거) + +버림패 드로우는 덱을 줄이지 않으므로, **양쪽이 계속 버림패만 뒤지면 라운드가 끝나지 +않는다.** 기존 학습 로그를 보면 이 착취가 실제로 학습된다: + +| 학습 체제 | 라운드 길이 추이 | 400수 상한 도달 | +|---|---|---| +| 정적 휴리스틱 상대 (`balanced.yaml`) | 82 → **116수** (eval greedy **168수**) | 0.4~0.7% | +| **셀프플레이 (league)** | 71 → **53.6수로 수렴** | **0%** | + +정적 약체 상대에게는 턴을 늘릴수록 원정 깊이·8장 보너스에서 강자가 이득이라 질질 끄는 +것이 합리적이다. 그러나 **셀프플레이에서는 상대도 똑같이 끌 수 있어 상쇄되고, 라운드가 +자연 길이(≈54수 = 44 덱 드로우 + ~10 버림패 드로우)로 수렴한다.** + +**결론:** 우리의 목표 체제는 셀프플레이/league이므로 **3라운드 매치 ≈ 160수**로 잡으면 +되고, 기존 `rollout_steps=400` 안에 여유롭게 들어간다. 단 두 가지를 유의한다: + +1. **정적 상대로 3라운드를 학습시키면 매치가 350~500수까지 늘어날 수 있다** — 정적 상대 + 워밍업 단계를 쓴다면 스캔 길이를 따로 잡아야 한다. +2. **라운드 상한(~120수)은 그 자체가 착취 가능한 구멍이다.** 앞선 쪽이 상한까지 끌면 + 라운드가 유리한 상태로 얼어붙는다. `max_steps_rate`를 게이트 지표로 계속 감시할 것 + (셀프플레이에서는 0이어야 정상). + +## 현재 코드의 결함 (Fable 2회 교차 검증 — 8건 전부 사실 확인) + +1. **env가 1라운드짜리** — `State`에 라운드/누적 점수 없음 (`types.py:46`), + `to_move=0` 하드코딩 (`engine.py:63`). +2. **롤아웃의 87%가 죽은 스텝** — 한 라운드는 실측 평균 50.6수(최대 56)인데 + `rollout_steps = MAX_STEPS = 400` (`ppo.py:66`)이고, 스캔 **안에는 리셋이 없다** + (`reset_done_envs`는 업데이트 사이에서만, `ppo.py:275`). +3. **GAE 부트스트랩 초기값이 0** (`ppo.py:691`). 지금은 모든 에피소드가 스캔 안에서 끝나 + 무해하나, **in-scan 리셋을 켜는 순간 편향**이 된다. +4. **shaping 어닐링 회계 버그** — `update * batch_games * rollout_steps` (`ppo.py:222`)로 + **죽은 스텝까지 세어서**, 5M 어닐링이 250 업데이트 중 2번째에 끝난다. league는 shaping을 + 아예 끈다 (`league.py:592`). + → **"shaping은 불필요하다"는 과거 결론이 있다면 무효다. 켜진 적이 없다.** +5. **obs에 `to_move`가 없다.** 그런데 value loss는 `active` 마스크로 학습되어 (`ppo.py:624`) + **상대 차례 상태에서도** 가치를 맞추라고 요구한다. critic이 차례를 구분할 단서가 + `step_count / 400`뿐 — MLP에게 부동소수점에서 홀짝을 뽑으라는 요구다. +6. **점수차 정규화가 ÷780** (`MAX_ABS_SCORE`, `obs.py:68`). ±50점 차가 ±0.06 → 사실상 + 안 보인다. +7. **셀프플레이에서 상대 자리 결정을 전부 버린다** (`stop_gradient`, `ppo.py:425`) — + 의사결정의 절반을 낭비. +8. **평가가 단판 승률** (`gates.py`) — 3라운드 개편의 성패를 측정할 자가 없다. + +## 핵심 설계 결정 + +### PRNG: 모든 무작위성을 `reset()`에서 미리 뽑는다 (필수) + +라운드 전환 리셔플과 동점 코인플립을 `step()` 안에서 샘플링하면 `step`이 확률적이 되어 +서명이 바뀌고, 모든 rollout/eval/gates 바디에 키를 꿰어야 하며 duplicate 미러링이 꼬인다. + +**`reset()`에서 3라운드 덱 순서 전부(3×60), 동점 코인플립 비트 2개, 1라운드 선공 비트 +1개를 미리 샘플링해 `State`에 저장한다.** `step()`은 결정론을 유지하고 라운드 전환은 +다음 덱 슬라이스로 스위치만 한다. 덤: **미러 매치(같은 3딜 + 자리 교대 + 같은 코인플립 +비트)가 공짜로 따라온다** — Phase 5의 antithetic 페어링이 그대로 성립. + +### 라운드 전환 vs 매치 리셋의 분리 + +- **라운드 전환은 엔진 `step()` 내부**에서 (`done=False` 유지, carry 갱신, 덱 슬라이스 전환) +- **매치 done 리셋은 rollout 바디**에서 (in-scan auto-reset) + +이러면 두 메커니즘이 깨끗이 분리된다. 단 위의 pre-sampled 덱 설계가 전제다. + +- `State`에 **라운드 스텝 카운터와 매치 스텝 카운터를 둘 다** 둔다 (forced-done은 라운드 + 단위, obs 정규화는 라운드 상대 진행도 + round 원-핫). +- 중간 라운드 forced-done(라운드 상한 초과) 시 **자연 종료와 동일하게 라운드 종료 → 전환**. + +### 보상 스케일에 대한 해소 (혼동 방지) + +`sign()`에 가까운 작은 scale은 **틀린 선택**이다 — 150수에 걸쳐 모든 수가 동일한 ±1을 +받아 크레딧 할당이 전부 critic에 떠넘겨지고, 5점 차 패배와 80점 차 패배의 그래디언트가 +같아진다. **scale 30~50의 tanh가 절충점**이다: |마진| ≳ 60에서는 `sign`을 근사하면서 +크레딧 그래디언트를 보존한다. 대신 5점 승과 80점 승을 여전히 구분하므로 순수 승률 +최적화 대비 **마진 쪽으로 약간 왜곡**된다 — 이 잔여 왜곡은 Phase 5의 후기 fine-tune으로 +scale을 낮춰서(예: 50 → 25) 제거한다. + +명시적 risk 항은 **넣지 않는다.** carry + round를 obs에 넣은 종료 보상이 올바른 리스크 +태도(뒤지면 도박, 앞서면 잠금)를 자동으로 유도한다. + +## 체크리스트 + +### Phase 0a — 학습 루프 수정 (최우선, 단판 체제에서 검증 가능) + +- [x] **GAE 부트스트랩 수정**: 잘린 에피소드를 `V(s_final)`로 부트스트랩 (`ppo.py:691`). +- [x] **in-scan auto-reset**: 롤아웃 스캔 안에서 done env 리셋 → 죽은 스텝 제거. + **실측(rollout_steps=400, batch_games=64, 3 업데이트):** main은 활성 17.3% + (learner 액션 2,221/업데이트), 수정 후 **활성 100% (12,842/업데이트) — 동일 연산량에 + 샘플 5.8배.** 활성 비율은 게임 길이에 비례하므로, 학습 초기 정책(~69수)에서 5.8배, + 학습된 정책(~50수)이면 8배에 가까워진다. 3라운드 매치(~150수)가 되면 약 2.7배로 + 줄지만 그때는 스캔 전체가 실제 매치로 채워진다. +- [x] **메트릭 파이프라인 재작업 (필수, 놓치면 조용히 오염됨)**: `rollout_metrics`는 + `final_env`에서 통계를 읽고 `episode_return = jnp.sum(transitions.reward, axis=0)`은 + **env당 에피소드 1개를 가정**한다 (`ppo.py:1069`). in-scan 리셋 후에는 final_env가 + 에피소드 중간이고 여러 에피소드의 보상이 합산된다 → **metrics.jsonl 전체가 쓰레기가 + 된다.** done 경계에서 누적하는 에피소드 단위 집계로 바꿀 것. +- [x] **league assignments를 scan carry로**: `learner_seat`/`opponent_index`/`use_mirror`가 + 업데이트 사이에서만 재샘플링된다 (`ppo.py:568`). in-scan 리셋을 켜면 리셋 시점에 + 스캔 내부에서 재샘플링해야 한다 — 안 하면 자리/상대가 에피소드 간 고정되어 편향. +- [x] **shaping 어닐링 회계 수정**: 패딩된 스캔 스텝이 아니라 **learner 액션 수** 기준 + (`ppo.py:222`). `shaping_coef`는 호스트에서 계산해 jit 함수에 넘기므로 + (`ppo.py:221`), 직전 업데이트의 액션 수를 호스트에서 누적하는 **1-업데이트 지연** + 구조가 된다 (무해). +- [x] **회귀 게이트 — 통과 (단, 게이트 설계를 고쳐야 했다).** + + **(1) "동일 learner-액션 예산"은 잘못된 게이트였다.** PPO 진척도는 샘플 수와 + **옵티마이저 스텝 수** 둘 다에 달려 있다. 샘플을 맞추면(64 vs 250 업데이트) 새 코드는 + 그래디언트 스텝이 1/4이 되어 덜 수렴한다. 업데이트당 연산량은 동일하므로 + **올바른 게이트는 250 대 250**(같은 컴퓨트·같은 그래디언트 스텝, 샘플만 5.8배)이다. + + **(2) 동일 컴퓨트 게이트 결과 (2만판 duplicate eval):** + + | 앵커 | 지표 | 베이스라인 | Phase 0a | + |---|---|---|---| + | **expert** (강함) | 승률 | 0.4525 | **0.5071** | + | **expert** | 평균 점수차 | −4.28 | **−0.56** | + | balanced (약함) | 승률 | 0.9866 | 0.9292 | + | balanced | 평균 점수차 | 116.8 | **128.1** | + + 학습 곡선은 **모든 업데이트 지점에서** 새 코드가 위(최종 return 0.963 vs 0.935). + + **(3) balanced 승률 하락은 전부 `MAX_STEPS=400` 아티팩트다.** 새 정책 2,048판 분해: + + | | 판수 | 패배율 | + |---|---|---| + | 자연 종료 | 1,214 | **0.08%** | + | 400수 상한 도달 | 834 (40.7%) | **20.62%** | + + **전체 패배의 99.4%가 상한에 부딪힌 판에서 발생.** 새 정책은 자연 종료 게임에서 + **99.92% 승률**이다. 샘플이 5.8배라 stalling 착취를 더 깊이 배웠고(greedy 225수), + 그 결과 40%가 인위적 벽에 박아 원정 미완성인 채 얼어붙는다. + + **결론:** Phase 0a는 성공. expert(=stalling을 허용하지 않는 앵커)에서 45%→51%로 + 실제 실력이 올랐다. + +### Phase 1 — 3라운드 env + +**구현: `src/lost_cities_jax/match.py` (커밋 `7cd299d`).** 단판 엔진을 고치지 않고 **감쌌다** +— `engine.py`는 TS 클라이언트와의 차분 테스트가 지키는 규칙 오라클이고, 라운드 자체는 +매치가 생겨도 변하지 않는다. `MatchState`가 내부에 단판 `State`를 든다. + +- [x] `MatchState`: `round`(단판 State), `deck_orders`(3×60), `coin_flips`(3,), + `round_idx`, `carry`(2, 플레이어별 누적 점수), `done`. + 별도 매치 스텝 카운터는 두지 않았다 — 매치는 3라운드가 끝나면 종료하므로 종료 판정에 + 불필요하고, 라운드 진행도는 내부 `State.step_count`(라운드마다 리셋)가 이미 준다. +- [x] `match_step()`: 덱 소진 시 라운드 < 3이면 carry 갱신 → 다음 덱 슬라이스 → `round_idx += 1`, + `done` 유지. 라운드 == 3이면 `done = True`. **보상은 3라운드 끝에서만.** +- [x] **선공 규칙**: `carry[0] > carry[1]` → p0, `<` → p1, `==` → pre-sampled 코인플립. + 1라운드는 특수 케이스가 **필요 없다** — carry가 (0,0)이라 동점 분기가 자동으로 코인을 + 뽑고, 그게 룰북의 "가장 나이 많은 사람"(= 임의)과 정확히 같다. +- [x] **PRNG**: 딜 3벌 + 코인 3개를 `match_reset`에서 전부 미리 뽑아 상태에 저장. + `match_step`은 결정론적이라 키를 rollout/eval/gates에 꿸 필요가 없고, **미러 매치가 + 자리 라벨 교체만으로 성립**한다 (Phase 5 antithetic 페어링이 여기 의존). +- [x] ~~라운드당 스텝 상한을 400 → ~120으로 분리~~ — **철회한다. 라운드 상한은 400을 유지.** + + **이 항목의 원래 명분이 사라졌다.** 근거는 "3라운드(~360수)가 400스텝 스캔에 들어가게" + 였는데, **Phase 0a의 GAE 절단 부트스트랩이 스캔 길이 제약을 없앴다.** 잘린 매치는 + 올바르게 부트스트랩되므로 스캔 길이는 이제 자유 파라미터다. + + **그리고 상한을 낮추면 아티팩트가 악화된다.** Phase 0a 실측: 400수 벽에 부딪힌 판의 + 20.6%가 패배로 뒤집혔고 **전체 패배의 99.4%가 거기서 발생**했다. 상한을 120으로 내리면 + **더 많은 판이 벽에 박고**, "앞선 쪽이 상한까지 끌어 라운드를 얼린다"는 착취가 훨씬 + 쉬워진다. 셀프플레이에서는 라운드가 54수로 수렴해 120이든 400이든 안 걸리므로, + **덜 걸리는 쪽을 두고 `max_steps_rate`를 감시**하는 것이 맞다. + +- [ ] **학습 파이프라인 배선** (원래 계획서에서 누락된 항목): `ppo.py`의 rollout/eval, + `gates.py`, `league.py`가 전부 단판 `State`를 받는다. `MatchState`를 받도록 배선한다. + - 매치용 obs 래퍼: 우선 `observation(state.round, player)`로 carry-blind하게 연결 + (carry/round 피처는 Phase 3에서 추가). + - `match_legal_action_mask`, `match_step`, `match_score`로 교체. + - 스캔 길이는 자유 파라미터가 되었으므로 셀프플레이 매치 길이(~160수) 기준으로 잡되, + 잘려도 부트스트랩이 처리한다. +- [ ] **league 풀 재구축**: 기존 스냅샷 멤버는 obs 변경으로 전부 무효화된다 — Phase 3 이후로 + 미룬다 (obs가 확정되기 전에 풀을 다시 채우면 두 번 일한다). +- [x] **테스트 12개** (`tests/lost_cities_jax/test_match.py`): 라운드당 덱 드로우 = 44 + + 버림패 드로우만큼 연장, `carry`가 각 라운드를 정확히 한 번씩 적립, 선공 규칙 3분기, + 1라운드 코인 공정성(≈50/50), 라운드 경계에서 누적 점수 불연속 없음(PBRS 전제), + 미러 매치 대칭성, 보상은 3라운드 끝에서만 지급. + +### Phase 0b — 측정 자 (첫 장기 3라운드 학습 **전에** 착지) + +- [ ] **매치 단위 평가**: 3딜 전부 미러링 + 자리 교대 + **동일 코인플립 비트**, + 매치 승률 + Wilson CI, 평균 총 마진. `gates.py`/`league.py`의 단판 기준을 대체. + **`gates.py:884`, `gates.py:961`의 `MAX_STEPS` 길이 단판 스캔 2곳 포팅 포함** — + exploiter 학습·평가 경로 전체가 3라운드로 가야 성공 기준 3을 잴 수 있다. +- [ ] **carry 조건부 프로브**: carry ∈ {−60, −25, −1, +1, +25, +60}을 주입한 3라운드 시작 + 위치에서 승률·행동 변화(원정 개수, 악수 비율, 덱 레이스 비율) 측정. +- [ ] **shuffle bank 포맷 확장**: 덱과 함께 코인플립·선공 비트도 뽑도록. 안 그러면 + `jax.random.PRNGKey(0)` 고정 eval(`ppo.py:1025`)의 재현성이 매치 정의와 얽힌다. +- [ ] **legacy obs 버전 보존**: 구 정책을 3라운드 매치에 투입해 베이스라인을 재려면 구 + obs(454차원)로 추론해야 하는데, `checkpoint_policy_from_params`는 전역 `observation`을 + 호출한다 (`ppo.py:802`) → obs 개편 후 구 체크포인트는 **로드 자체가 실패**한다. + policy 로더가 체크포인트별 obs 버전을 받도록 할 것. **성공 기준 2의 분모가 여기 달렸다.** + +### Phase 2 — 보상 + +- [ ] 종료 보상: 3라운드 끝에서만 `tanh(총_점수차 / scale)`, **scale = 30~50** + (근거는 위 "보상 스케일에 대한 해소" 절). +- [ ] 마진 shaping 부활: `Φ(s) = carry + 현재 보드 점수차`, **작은 계수**(종료 보상 스케일의 + 0.05~0.2). 현재의 계수 1.0 원점수 shaping은 ±1 종료 보상보다 10~30배 크다. + learner 스텝 기준으로 어닐링하되 **후반까지 정확히 0으로 내리지 않는다.** +- [ ] γ=1.0에서 `Φ(s') − Φ(s)`는 **올바른 PBRS 형태다** (γ 누락 아님 — 검토에서 확인). + +### Phase 3 — 관측 + +- [ ] `carry`: **÷75 스칼라 + 구간 원-핫**(약 9구간). 3라운드 정책은 "1점만 더" 임계값 + 근처에서 급격히 꺾여야 한다. 기존 `score_diff`의 ÷780 정규화도 같이 고친다. +- [ ] `round_idx` 원-핫 + 남은 라운드 수. +- [ ] **`to_move` 비트** + "내가 이번 라운드 선공인가" + "현재 홀짝에서 마지막 덱 카드를 + 누가 뽑는가"(덱 시계). +- [ ] 색깔별 **살아있는 점수 3분할**: 내 `col_top` 위로 아직 나올 수 있는 점수를 + (a) **내 손패**, (b) **버림패 더미**(공개돼 있고 회수 가능 — 빠뜨리기 쉬움), + (c) **미공개**(덱 ∪ 상대 은닉 손패)로 나눠 넣는다. 상대에 대해서도 동일 + (상대 `col_top`은 공개). MLP가 7×60 채널에서 뽑아내기 어려운 비선형 집계이고, + 모든 개시/연장/차단 판단을 좌우한다. + +### Phase 4 — 학습 효율 + +- [ ] **전지적 critic (CTDE)**: critic에만 상대 손패 + 덱 구성을 준다. 행동과 무관한 + 정보이므로 정책 그래디언트를 편향시키지 않는다. 딜 운 분산을 정면으로 깎는다. + **가치 경로를 정책 트렁크에서 분리해야 한다** (현재 공유 트렁크, `ppo.py:104`) — + 특권 정보가 정책 로짓으로 새면 안 된다. + → 이 critic은 나중에 **PIMC 탐색의 리프 평가기로 그대로 재활용**된다. +- [ ] **양쪽 자리 학습**: `stop_gradient`된 상대 자리 전이(`ppo.py:425`)도 학습에 쓴다 + (샘플 효율 2배). 같은 게임의 두 자리는 반상관이므로 같은 배치에 두고 advantage + 정규화에 맡긴다. +- [ ] `gae_lambda` 재검토: 0.95는 150수 지평에서 너무 짧다(중반 수 직접 가중치 0.02). + 전지적 critic이 있으면 유지, 없으면 0.97~0.99. **λ=1은 금지**(딜 분산). +- [ ] `entropy_coef` **스윕으로 재결정**. (주의: "0.01이 원점수 shaping 기준으로 잡혔다"는 + 추론은 **틀렸다** — league는 shaping을 끄고 학습했으므로 0.01은 이미 ±1 tanh 체제에서 + 동작해온 값이다. 다만 3라운드에서 보상 빈도가 1/150로 희석되고 작은 shaping이 + 추가되므로 재튜닝 자체는 타당하다. **근거 없이 10배 낮추면 과소탐색으로 직행한다.**) + +### Phase 5 (나중) — 최종 강함 + +- [ ] **후기 fine-tune**: 학습 말미에 종료 보상 scale을 낮춰(50 → 25) 마진 왜곡을 제거하고 + 순수 승률 쪽으로 당긴다. +- [ ] 페어드 antithetic 딜(같은 3딜 + 자리 교대 + 같은 코인플립 비트)을 **학습에** 도입. + 단순 포함이 아니라 **쌍으로 묶어** control variate로 써야 효과가 있다. + (Phase 1의 pre-sampled PRNG 설계 덕에 사실상 공짜.) +- [ ] MMD식 정규화 셀프플레이 (loss에 ~20줄) — 2인 제로섬 근사 내시 보험. +- [ ] **추론 시점 탐색 (PIMC / ISMCTS)** — 최종 강함의 가장 큰 이득. 로스트시티는 블러핑 + 경제가 없는 저기만성 불완전정보 게임이라 결정화 탐색이 잘 맞는다. raw net 대 + net+search 맞대결로 측정. +- [ ] 네트워크 용량 A/B (512×3 → 1024×3 또는 residual) — **파이프라인 변경이 끝난 뒤에.** + +## 범위 밖 (명시적 동결) + +- **웹 클라이언트/ONNX는 별도 계획 전까지 레거시 단판 모델로 동결한다.** obs 개편 즉시 + export 파이프라인(`scripts/export_jax_ppo_onnx.py:70`, manifest `observation_size: 454`), + TS obs 빌더, TS 단판 엔진이 전부 비호환이 된다. 이 선언이 없으면 실행 중 스코프가 + 웹 재작성으로 샌다. +- **Deep CFR 복귀** — 이미 BC 천장을 쳤고, 3라운드는 트리만 키운다. PPO+league를 학습 + 백본으로 유지한다. +- 레거시 호환을 위한 타협. + +## 성공 기준 + +0. **(Phase 0a 게이트)** 루프 수정 후 단판 체제에서 동일 learner-액션 예산으로 기존 anchor + 성적 재현 ≥ 동등. **없으면 auto-reset 버그가 3라운드 결과에 섞여 원인 분리가 불가능해진다.** +1. **carry 프로브에서 행동이 단조롭게 변한다** — carry 6개 수준에 걸쳐 원정 개수/악수 비율의 + **단조 추세**(CI 포함). ("행동이 변한다"는 노이즈로도 통과 가능하므로 단조성으로 정의.) +2. **매치 승률이 구 정책(3라운드에 그대로 투입)을 이긴다** — 페어드 매치 **≥ 1만 쌍**, + 매치 승률 **Wilson 하한 > 0.5** *및* 평균 총 마진 **CI 하한 > 0**. +3. 착취자(exploiter) 승률이 악화되지 않는다. +4. **(anchor 비회귀)** 휴리스틱 anchor 상대 매치 승률·라운드당 마진이 구 정책 대비 악화되지 + 않는다. **기준 2의 구멍을 막는 항목**: carry-blind인 구 정책만 상대로 이기는 것은 + **카드 플레이가 퇴보해도 carry 착취만으로 달성 가능**하다. + + **단, anchor 선택에 주의:** Phase 0a에서 실증됐듯 **약한 anchor(`heuristic_balanced`)는 + 무한 stalling을 허용해서 신호를 오염시킨다** — 승률이 실력이 아니라 상한 도달률을 잰다. + **`heuristic_expert`처럼 stalling을 허용하지 않는 anchor**(게임이 자연 길이로 끝남)만 + 실력 지표로 쓰고, 약한 anchor는 **자연 종료 게임만 필터링해서** 보거나 `max_steps_rate`를 + 함께 보고할 것. + +--- + +## 실행 결과 (2026-07-15, 커밋 `9ba5a07`) + +### 동작하는 것 + +- **셀프플레이가 stalling을 스스로 제거한다.** 매치가 146.8수(라운드 ≈49수)로 수렴하고 + 덱 레이스 비율 91%. Phase 0a에서 정적 상대가 225수까지 끌던 것과 대조된다. +- **미러 매치 평가가 정확하다.** 셀프플레이 duplicate 승률 0.4968, **평균 lead 정확히 0.0** — + 같은 3딜 + 같은 코인 + 자리 교대가 딜 운을 완전히 상쇄한다. 미완료 0%. +- **전지적 critic이 격리돼 있다.** 특권 입력을 흔들어도 정책 로짓은 비트 단위로 동일하고, + 가치만 움직인다 (테스트로 고정). + +### 성공 기준 1 — **약하게만 충족. 사실상 미달.** + +carry 프로브(3라운드 시작 시 carry 주입)에서: + +| | scale 50 | scale 25 | scale 12 | +|---|---|---|---| +| 악수 스프레드 (carry −60 → +60) | 0.19 | 0.08 | **0.31** | +| 원정 개수 | 5.00 고정 | 4.99 고정 | **5.00 고정** | + +- **악수 사용은 6개 carry 수준 전체에서 단조**로 움직인다 (뒤지면 배수 베팅 ↑). 방향은 맞다. +- 그러나 **원정 개수는 carry와 무관하게 5.00에 붙어 있다.** 굳은 습관이지 조건부 플레이가 아니다. +- 효과 크기가 작다. + +### 확정된 진단 + +1. **shaping 가설은 틀렸다.** `potential_shaping_final=0.0`으로 완전히 꺼도 프로브는 평평했다. +2. **원인은 `terminal_scale`이다.** carry = −60에서 `tanh((margin − 60)/50)`의 인자는 현실적 + 마진 범위에서 **거의 선형**이고, 선형 구간에서 `E[tanh]` 최대화는 `E[margin]` 최대화와 같다 + → 도박할 이유가 없다. 위험 추구는 tanh가 **강하게 볼록한** 구간에서만 나오며 scale을 낮춰야 + 그 구간에 들어간다. scale 50 → 12에서 스프레드가 0.19 → 0.31로 커진 것이 이를 확인한다. +3. **프로브 설계 결함:** scale 12에서 `tanh(60/12) ≈ 1.0`이라 **±60은 포화 = 그래디언트 0**. + 거기서 정책은 학습된 바가 없다. **의미 있는 측정 구간은 `|carry| ≲ 2 × terminal_scale`.** + 프로브 수준을 scale에 맞춰 재설계해야 한다. + +### 다음에 할 일 + +- [ ] **프로브 재설계**: carry 수준을 `terminal_scale`에 맞춰 잡는다 (포화 구간 측정 금지). +- [ ] **학습 중 carry 분포 확인**: 셀프플레이에서 3라운드 진입 시 carry가 실제로 얼마나 + 퍼지는가. 좁으면 정책이 큰 deficit을 본 적이 없다는 뜻이고, 그게 진짜 원인일 수 있다. +- [ ] **"항상 5색 개시"가 정상인지 검증**: 인간 기보에서 AI는 4.81, 인간은 4.19를 열었다. + 5.00 고정은 의심스럽다. 셀프플레이 균형인지, 탐색 붕괴인지 (엔트로피 3.5 → 1.03). +- [ ] scale 스케줄(50 → 12 후기 fine-tune)이 처음부터 12로 학습하는 것보다 나은지 A/B. + +--- + +## 판정: 보상은 **선형 총점**이다 (2026-07-15, Fable 3차 검토 + 실측) + +사용자 제안("그냥 3판 총점이 크기만 하면 되는 것 아니냐")이 **맞았다. tanh 종료 보상은 +오버엔지니어링이었다.** + +### 근거 1 — 분해 논증 (실측) + +보상이 총점에 선형이면 라운드가 독립이므로 3라운드 게임이 3개의 독립 단판으로 분해된다. +셀프플레이 2,048매치 실측: `corr(m1, m2) = 0.004`, `corr(m1+m2, m3) = 0.05`. +라운드를 잇는 유일한 고리인 **선공 어드밴티지는 +0.73 ± 0.84점** — 0과 구분 불가. + +### 근거 2 — 리스크 태도는 값어치가 없다 (실측) + +Fable이 리스크 태도를 직접 구현해 greedy 클론과 duplicate 6,144판 맞대결: + +| 도박 정책 | 매치 승률 | +|---|---| +| 3R에서 20점 이상 뒤지면 온도 샘플링 | **0.482** (진다) | +| 40점 이상 뒤질 때만 | 0.498 (본전) | + +**일부러 도박을 시켜도 지거나 본전.** 로스트시티의 분산 레버(한계 악수 ≈ Δσ +1.7에 마진 +−2~3점)가 근본적으로 약해서, 분산을 사는 비용이 볼록성 이득을 먹는다. +carry 조건부 플레이의 가치 상한: **1승점 미만.** + +### 근거 3 — 맞대결에서 단순한 쪽이 **이겼다** + +duplicate 10,000판 (같은 3딜 + 같은 코인 + 자리 교대), 동일 컴퓨트 300 업데이트: + +| A | B | A 승률 | A 평균 총점차 | +|---|---|---|---| +| **선형 총점** | tanh(총점/12) | **0.5859** (CI 0.576–0.596) | **+20.3점** | + +버려도 손해가 없는 게 아니라 **버리니 더 강해졌다.** 이유는 리스크가 아니라 **신호 밀도**다: +tanh는 ~150수 매치에 포화된 ±1 하나를 주고, 선형은 매 수마다 그 수가 총점차를 움직인 만큼을 +준다. γ=1에서 후자의 합이 정확히 최종 총점차로 telescoping되므로 **목적함수는 동일한데 크레딧 +할당만 150배 조밀**하다. + +### 근거 4 — 탐색 붕괴가 아니었다 + +프로브가 평평했던 이유는 탐색 붕괴가 아니다. 샘플링 프로브에서도 원정 5.00 ± 0.05, +엔트로피 1.36나트(유효 행동 3.9개)로 정상 수렴. 그리고 **critic은 carry를 완벽히 읽고 있었다** +(3R 시작 가치 −0.87 → +0.86 단조). 신호는 있었고, **정책이 그걸로 살 수 있는 물건이 +없었을 뿐**이다. + +### 최종 설계 + +```python +# match_ppo.py 롤아웃 바디 +reward0 = jnp.where(active, (after - before) / cfg.reward.terminal_scale, 0.0) +``` + +- **성공 기준 1(carry 프로브 단조성)은 게이트에서 제거한다.** 최적 반응 자체가 이 게임에서 + 거의 존재하지 않는다는 것이 측정 결과다. 기준 2·4(맞대결 + anchor 비회귀)가 옳은 자다. +- `carry`는 obs에 **남긴다** (비용 0, 선공 규칙이 키로 쓰는 상태, critic이 잘 읽음). + +### 목적함수와 무관하게 살아남은 것 (전부 순이득) + +in-scan auto-reset + GAE 절단 부트스트랩(샘플 5.8배), 메트릭 재작업, **비대칭 CTDE critic**, +**양쪽 좌석 학습**, **duplicate 매치 평가**, pre-sampled PRNG/미러 설계, 그리고 match_obs의 +단판 결함 수정분(`to_move`, 덱 시계, ÷780 → ÷75, 살아있는 점수 3분할). + +**죽은 것은 tanh 종료 보상과 carry 구간 원-핫뿐이다.** + +--- + +## 신구 대결: 진짜 3라운드 클래식에서 (2026-07-15) + +**질문: "기존 학습 방법 대비 실제로 뭐가 나아졌나?"** + +duplicate 매치 8,192판(같은 3딜 + 같은 코인 + 자리 교대), 진짜 3라운드 게임: + +| 신(매치 스택) | 상대 | 신 승률 | 신 평균 총점차 | 상대 learner 액션 | +|---|---|---|---|---| +| 39.3M | 기존 baseline (정적 상대 학습) | 0.6077 | +19.5 | 104M | +| 39.3M | Phase 0a 게이트 (루프 수정만) | **0.5842** | +16.0 | **411M (10.5배)** | +| 39.3M | league (셀프플레이, 웹 배포판) | 0.3142 | −37.0 | 122.6M (3.1배) | +| **131M** | **league (셀프플레이, 웹 배포판)** | **0.6094** (CI 0.599–0.620) | **+22.0** | 122.6M | + +**결론:** + +1. **샘플 효율이 크게 올랐다.** 39.3M짜리가 **411M(10.5배)짜리를 이긴다.** +2. **동일 예산에서 기존 최강(league)을 이긴다** — 131M vs 122.6M에서 0.6094. +3. 39.3M에서 league에 졌던 것(0.3142)은 **약해서가 아니라 예산이 1/3이어서**였다. + +**남은 단서:** league는 **착취자(exploiter) 구조**를 포함한 런이다. 평균 강함은 우리가 이기지만 +**exploitability는 아직 재지 않았다.** "덜 착취당한다"는 증명되지 않았다. + +--- + +## 기여도 A/B (2026-07-15) + +각 조각을 하나씩 끄고 동일 컴퓨트(300 업데이트, batch 512)로 학습시킨 뒤, +full 스택과 duplicate 매치 8,192판 맞대결. **0.5 미만 = 그 조각이 기여하고 있었다.** + +| 제거한 것 | full 대비 승률 | 95% CI | 평균 총점차 | 판정 | +|---|---|---|---|---| +| **양쪽 좌석 학습** | **0.3317** | [0.322, 0.342] | −28.6 | **압도적 기여** | +| 매치 관측 (carry/to_move/덱시계/살아있는점수) | 0.4751 | [0.464, 0.486] | −4.0 | 유의하게 기여 | +| **전지적 critic (CTDE)** | **0.5160** | [0.505, 0.527] | +2.6 | **오히려 해가 된다** | + +### 1. 양쪽 좌석 학습 — 가장 큰 기여 + +끄면 승률이 0.33으로 무너진다. 같은 업데이트 수에서 learner 액션이 **정확히 절반**이 되므로 +상당 부분은 샘플 수 효과다 — 그러나 **그게 요점이다.** 셀프플레이에서 상대 좌석의 수는 같은 +네트워크가 둔 것인데 기존 트레이너는 `stop_gradient`로 버렸다. **공짜로 데이터가 2배**가 된다. + +### 2. 매치 관측 — 작지만 실재 + +0.4751 (CI 상한 0.486 < 0.5). `to_move`, 덱 시계, ÷780 → ÷75 스케일 수정, 살아있는 점수 +3분할이 합쳐서 약 2.5%p 값어치. carry 자체는 (분해 논증대로) 거의 기여하지 않으므로, +이 이득의 대부분은 **단판 obs의 결함 수정분**으로 보인다. + +### 3. 전지적 critic — **Fable의 최우선 권고가 틀렸다** + +Fable은 이것을 "가장 큰 누락 아이디어"로 꼽았다. 실측은 **반대**다: 끄면 오히려 +**0.5160 (CI 하한 0.505 > 0.5)** 으로 유의하게 **더 강해진다.** + +그럴듯한 이유: 특권 critic은 덱을 알기 때문에 가치를 아주 잘 맞추지만, 그 결과 +`V(전체상태) ≠ E[리턴 | 마스킹된 관측]`이 되어, **어드밴티지에 정책이 통제할 수 없는 성분**이 +섞인다. 액터 입장에서 그건 분산 감소가 아니라 노이즈다. 부분관측 환경에서 비대칭 critic이 +해가 되는 것은 알려진 현상이다. + +**조치: 전지적 critic을 기본에서 끈다.** (PIMC 탐색의 리프 평가기로 재활용한다는 계획은 +별개로 유효할 수 있으나, 정책 학습용으로는 손해다.) + +### 종합: 실제로 값어치 있었던 것 + +1. **in-scan auto-reset + GAE 절단 부트스트랩** — 샘플 5.8배, expert 0.4525 → 0.5071 +2. **양쪽 좌석 학습** — 데이터 2배, 단독으로 승률 0.33 → 0.5 +3. **선형 총점 보상** — tanh 대비 0.5859 (사용자 제안) +4. **매치 관측 결함 수정** — 약 2.5%p +5. ~~전지적 critic~~ — **해가 된다. 끈다.** + +### 정정: 전지적 critic의 가치는 **스케일에 따라 뒤집힌다** + +위 A/B는 39.3M learner 액션 규모에서 돌렸다. 실전 규모(131M)에서 동일 설정으로 둘을 직접 +맞붙이면 **결론이 반대로 나온다.** + +| 규모 | critic OFF의 승률 (critic ON 상대) | 판정 | +|---|---|---| +| 39.3M (A/B 규모) | **0.5160** [0.505, 0.527] | OFF가 낫다 | +| **131M (실전 규모)** | **0.4633** [0.453, 0.474] | **ON이 낫다** | + +**전지적 critic은 그것을 학습시킬 데이터가 충분해질 때 값어치를 한다.** 39.3M에서는 특권 +정보를 쓰는 큰 가치 트렁크를 제대로 못 맞춰서 어드밴티지에 노이즈만 얹었고, 131M에서는 +제대로 맞춰서 분산 감소가 실현된다. + +**교훈: 배포할 예산이 아닌 규모에서 ablation을 돌리면 결론이 뒤집힐 수 있다.** +`privileged_critic` 기본값은 **ON으로 되돌린다.** + +### 최종 순위 (진짜 3라운드 클래식, duplicate 8,192판) + +| 모델 | learner 액션 | vs league | +|---|---|---| +| **매치 스택 (critic ON)** | 131M | **0.6094** (+22.0점) | +| 매치 스택 (critic OFF) | 131M | 0.5526 (+10.9점) | +| league (기존 최강, 웹 배포판) | 122.6M | — | + +### 기여도 재측정: 동일 규모(131M)에서 + +39.3M A/B는 critic에게 가장 불리한 지점이었다. 두 조각을 **같은 131M 예산**에서 다시 쟀다: + +| 조각 | full의 승률 (그 조각 뺀 버전 상대) | 순이득 | +|---|---|---| +| **양쪽 좌석 학습** | 0.6707 | **+17.1 %p** | +| **전지적 critic** | 0.5367 | **+3.7 %p** | + +**양쪽 좌석이 약 4.6배 크다.** 그리고 성격이 다르다: + +| 규모 | 양쪽 좌석 | 전지적 critic | +|---|---|---| +| 39.3M | +16.8 %p | **−1.6 %p** | +| 131M | **+17.1 %p** | +3.7 %p | + +**양쪽 좌석은 규모와 무관하게 안정적**(+17%p). **critic은 규모를 탄다.** + +이유: 양쪽 좌석은 **데이터를 2배로** 만든다(65.5M → 131M, 같은 컴퓨트에서). critic은 데이터를 +안 늘리고 **채점 정확도만** 올리는데, 코치가 배울 게 많아져서 데이터가 부족하면 오히려 +엉터리 채점을 한다. + +**Fable은 critic을 "가장 큰 누락 아이디어" 1순위로, 양쪽 좌석을 4순위로 꼽았다. 정확히 거꾸로였다.** + +--- + +## Exploitability: 우리가 league보다 **덜 착취당한다** (2026-07-15) + +**남겨뒀던 단서를 해소했다.** 평균 실력에서 이기는 것과 "파먹을 약점이 없는 것"은 다른 +속성이다. 가위바위보에서 바위를 60% 내는 놈은 아무한테나 이길 수도 있지만, 그 습관을 +알아챈 놈에게는 매번 진다. + +**측정 방법:** 정책을 얼려놓고, **오직 그놈만 이기도록 특화된 새 정책을 처음부터 학습**시킨다 +(`src/lost_cities_jax/exploit.py`). 착취자가 도달한 승률이 곧 그 정책이 못 막아낸 습관의 크기다. + +**동일 착취자 예산 (250 업데이트 × batch 1024 = 32.5M learner 액션):** + +| 얼려놓은 정책 | 착취자 승률 | 95% CI | +|---|---|---| +| **우리 매치 스택 (131M)** | **0.2278** | [0.219, 0.237] | +| league (웹 배포판, 122.6M) | **0.3213** | [0.311, 0.331] | + +**league가 9.4%p 더 털린다.** 그리고 둘 다 0.5에서 한참 멀다 — 어느 쪽도 만만한 상대는 아니다. + +### 최종 정리: 두 축 모두에서 이긴다 + +| 축 | 결과 | +|---|---| +| **평균 실력** (정면 대결) | 0.6094, +22.0점 ✅ | +| **약점 적음** (exploitability) | 0.2278 vs 0.3213 ✅ | + +### 단서 + +1. **하한선이다.** 더 세거나 더 오래 학습한 착취자는 더 찾아낼 수 있다. **절대값이 아니라 + 동일 예산에서의 비교로만 의미가 있다.** +2. **착취자 예산이 목표의 약 1/4에 불과하다 (32.5M vs 131M).** 약한 공격자다. + 따라서 **"우리는 22.8%밖에 안 털린다"고 말할 수 없다** — 그건 이 약한 공격자 기준일 뿐이다. + 살아남는 주장은 **"동일 예산에서 league가 더 털린다"** 하나뿐이다. + 착취자를 목표와 같은 예산(131M)으로 키워서 **순서가 유지되는지** 확인해야 한다. +3. league는 단판 정책이라 3라운드 게임에선 다소 제 물이 아니다 — 다만 carry가 무의미하다는 + 것이 이미 증명됐으므로 큰 불리함은 아니다. + +**흥미로운 점:** 우리는 **순수 셀프플레이**이고 league는 **착취자 구조를 학습에 넣은** 런인데, +그런데도 우리가 덜 착취당한다. 착취자 구조가 exploitability를 낮춰줄 것이라는 기대가 +이 게임에서는 확인되지 않았다. + +### 착취자에 제대로 자금을 대고 재측정 (131M, 목표와 동일 예산) + +앞선 32.5M 측정은 **공격자가 목표보다 4배 부족**했다. 예산을 목표와 맞춰 다시 쟀다. +실측 확인: 착취자 learner 액션 **130.4M** (우리 상대) / **131.1M** (league 상대). + +| 얼려놓은 정책 | 착취자 승률 | 95% CI | 착취자 평균 마진 | 이전(32.5M) | +|---|---|---|---|---| +| **우리 매치 스택** (131.1M 학습) | **0.4657** | [0.455, 0.477] | **−5.5점** | 0.2278 | +| league (122.6M 학습) | **0.6295** | [0.619, 0.640] | **+28.8점** | 0.3213 | + +**CI가 전혀 겹치지 않고, 격차가 오히려 벌어졌다 (0.094 → 0.164).** + +**질적으로 선을 넘었다:** 제대로 자금 댄 전담 공격자는 **league를 아예 이긴다**(0.63, +28.8점). +반면 **우리는 여전히 못 뚫는다**(0.47, −5.5점). + +#### 우리에게 불리한 단서 (반드시 함께 읽을 것) + +- **둘 다 1000 업데이트 끝까지 정체 없이 오르고 있었다. 이 수치도 여전히 하한선이다.** +- **우리 쪽 착취자의 말단 기울기가 더 가파르다** (+0.031 vs +0.016 / 100 업데이트). + league 착취자 곡선은 꺾이기 시작했는데 우리 쪽은 아직 갈 길이 남았다. + **공격자 예산을 크게 더 키우면 격차가 좁혀질 수 있고, 뒤집힐 가능성도 배제 못 한다.** + +#### 구조적 교란 (순수한 "학습법 A vs B"가 아니다) + +1. **league는 단판 정책이다.** carry도 매치 점수도 모른다. 더 털리는 것의 일부는 + **학습 방법이 아니라 구조적 맹점** 때문일 수 있다. +2. **둘 다 greedy(argmax)로 뒀다.** 결정론적 정책은 **정의상 최대로 착취당한다.** + 양쪽을 똑같이 대우했으니 비교는 공정하나, **절대값은 부풀려져 있다.** + +#### 살아남는 주장 / 못 하는 주장 + +- ✅ **"동일 예산의 전담 공격자 앞에서 league는 뚫리고 우리는 안 뚫린다."** +- ❌ "우리 정책은 착취 불가능하다." — 하한선일 뿐이고, 우리 쪽 곡선은 아직 오르는 중이다. diff --git a/scripts/ablate_match.py b/scripts/ablate_match.py new file mode 100644 index 0000000..b83a9c8 --- /dev/null +++ b/scripts/ablate_match.py @@ -0,0 +1,148 @@ +#!/usr/bin/env python3 +"""What is each piece of the match stack worth? + +Train one variant per switch at identical compute, then play each against the full +stack in duplicate matches -- same three deals, same coins, both seats -- so deal +luck cancels and only the policy difference is left. + +The variants do not share an observation shape (dropping the privileged critic or +the match features changes the input dims), so this carries its own head-to-head +rather than reusing match_eval's, which assumes one architecture. +""" + +from __future__ import annotations + +import json +from pathlib import Path + +import jax +import jax.numpy as jnp +import numpy as np + +from lost_cities_jax.match import ( + match_legal_action_mask, + match_reset_from, + match_score, + match_step, +) +from lost_cities_jax.match_eval import MATCH_SCAN_STEPS, _wilson, match_bank +from lost_cities_jax.match_ppo import ( + Ablation, + MatchActorCritic, + _seat_views, + create_match_train_state, + match_train, +) +from lost_cities_jax.ppo import load_config, mask_logits, restore_checkpoint + +VARIANTS = [ + Ablation(privileged_critic=False), + Ablation(both_seats=False), + Ablation(match_obs=False), +] +MATCHES = 4096 +FULL_CHECKPOINT = Path("runs/jax-ppo-match/2026-07-15_030152_match-linear/latest") + + +def _load(cfg, checkpoint: Path, ablation: Ablation): + state = create_match_train_state(cfg, jax.random.PRNGKey(0), ablation) + return restore_checkpoint(checkpoint, state).params + + +def _existing_run(label: str) -> Path | None: + runs = sorted(Path("runs/jax-ppo-match").glob(f"*ablate-{label}")) + for run in reversed(runs): + if (run / "latest").exists(): + return run + return None + + +def duel(cfg, params_a, ablation_a, params_b, ablation_b, *, matches: int) -> dict: + """A vs B over duplicate matches. Each side sees the world its own way.""" + + decks, coins = match_bank(20260719, matches) + model = MatchActorCritic(cfg.network.hidden_size, cfg.network.num_layers) + seats = jnp.arange(2, dtype=jnp.int32) + + @jax.jit + def run(env, a_seat): + def body(carry, _): + env, _unused = carry + to_move = env.round.to_move.astype(jnp.int32) + mask = jax.vmap(match_legal_action_mask)(env) + + def act(params, ablation): + obs, critic = _seat_views(env, seats, ablation) + idx = to_move[None, :, None] + seat_obs = jnp.take_along_axis(obs, idx, axis=0)[0] + seat_critic = jnp.take_along_axis(critic, idx, axis=0)[0] + logits, _ = model.apply(params, seat_obs, seat_critic) + return jnp.argmax(mask_logits(logits, mask), axis=-1).astype(jnp.int32) + + action = jnp.where( + to_move == a_seat, act(params_a, ablation_a), act(params_b, ablation_b) + ) + env, _, _ = jax.vmap(match_step, in_axes=(0, 0))(env, action) + return (env, _unused), None + + (env, _), _ = jax.lax.scan(body, (env, jnp.int32(0)), xs=None, length=MATCH_SCAN_STEPS) + return env + + leads = [] + for seat in (0, 1): + env = jax.vmap(match_reset_from)(decks, coins) + final = run(env, jnp.full((matches,), seat, dtype=jnp.int32)) + totals = np.asarray(jax.vmap(match_score)(final)) + leads.append(totals[:, seat] - totals[:, 1 - seat]) + + lead = np.concatenate(leads) + games = float(lead.size) + wins = float((lead > 0).sum()) + low, high = _wilson(wins, games) + return { + "matches": games, + "a_win_rate": wins / games, + "wilson_low": low, + "wilson_high": high, + "a_mean_lead": float(lead.mean()), + } + + +def main() -> None: + cfg = load_config("configs/jax_ppo/match-selfplay.yaml") + full = _load(cfg, FULL_CHECKPOINT, Ablation()) + + rows = [] + for ablation in VARIANTS: + label = ablation.label() + run_dir = _existing_run(label) + if run_dir is None: + print(f"\n===== training {label} =====", flush=True) + cfg = load_config("configs/jax_ppo/match-selfplay.yaml") + cfg.run.experiment_name = f"ablate-{label}" + run_dir = match_train(cfg, ablation=ablation) + else: + print(f"\n===== reusing {run_dir} =====", flush=True) + + cfg = load_config("configs/jax_ppo/match-selfplay.yaml") + params = _load(cfg, run_dir / "latest", ablation) + # The ablated net plays seat A, the full stack answers. Below 0.5 means + # the piece we removed was carrying weight. + result = duel(cfg, params, ablation, full, Ablation(), matches=MATCHES) + rows.append({"ablation": label, **result}) + print(f" {label}: win rate vs full = {result['a_win_rate']:.4f}", flush=True) + + print("\n\n==================== ablation ====================") + print(f"{'removed':<26}{'win rate vs full':>18}{'95% CI':>22}{'mean lead':>12}") + print("-" * 78) + for row in rows: + ci = f"[{row['wilson_low']:.3f}, {row['wilson_high']:.3f}]" + print( + f"{row['ablation']:<26}{row['a_win_rate']:>18.4f}{ci:>22}{row['a_mean_lead']:>+12.1f}" + ) + print("\nbelow 0.5 = the removed piece was carrying weight") + Path("runs/jax-ppo-match/ablation.json").write_text(json.dumps(rows, indent=2, sort_keys=True)) + + +if __name__ == "__main__": + main() diff --git a/scripts/export_match_onnx.py b/scripts/export_match_onnx.py new file mode 100644 index 0000000..99fd0d6 --- /dev/null +++ b/scripts/export_match_onnx.py @@ -0,0 +1,138 @@ +#!/usr/bin/env python3 +"""Export a match policy's actor trunk to ONNX for the browser. + +Only the actor ships. The critic exists to grade moves during training and never +plays, so its trunk -- and the privileged view of the opponent's hand and the deck +that feeds it -- is dropped here rather than shipped and then not used. That also +means the exported graph physically cannot leak hidden state, which is a stronger +guarantee than promising not to call it. + +MatchActorCritic lays the actor out as Dense_0..Dense_{num_layers} exactly as the +single-round model does, so the graph construction is the same; only the input +width and the checkpoint loader differ. +""" + +from __future__ import annotations + +import argparse +import hashlib +import json +from pathlib import Path + +import jax +import jax.numpy as jnp +import numpy as np + +from lost_cities_jax.match_obs import MATCH_CRITIC_OBS_DIM, MATCH_OBS_DIM +from lost_cities_jax.match_ppo import Ablation, MatchActorCritic, create_match_train_state +from lost_cities_jax.ppo import load_config, restore_checkpoint +from lost_cities_jax.types import N_ACTIONS + + +def build_argparser() -> argparse.ArgumentParser: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--checkpoint", type=Path, required=True) + parser.add_argument("--config", type=Path, default=Path("configs/jax_ppo/match-selfplay.yaml")) + parser.add_argument("--output", type=Path, required=True) + parser.add_argument("--codename", required=True, help="see data/models.json") + return parser + + +def export_model(checkpoint: Path, config: Path, output: Path, codename: str) -> None: + try: + import onnx + from onnx import TensorProto, helper, numpy_helper + from onnx.reference import ReferenceEvaluator + except ImportError as exc: + raise SystemExit("onnx is required; run with `uv run --with onnx ...`") from exc + + cfg = load_config(config) + state = restore_checkpoint( + checkpoint, create_match_train_state(cfg, jax.random.PRNGKey(0), Ablation()) + ) + params = state.params + dense = params["params"] + + nodes = [] + initializers = [] + previous = "obs" + for index in range(cfg.network.num_layers): + layer = dense[f"Dense_{index}"] + weight, bias = f"dense_{index}.weight", f"dense_{index}.bias" + initializers.extend( + [ + numpy_helper.from_array(np.asarray(layer["kernel"], dtype=np.float32), weight), + numpy_helper.from_array(np.asarray(layer["bias"], dtype=np.float32), bias), + ] + ) + nodes.append(helper.make_node("Gemm", [previous, weight, bias], [f"dense_{index}.linear"])) + nodes.append(helper.make_node("Relu", [f"dense_{index}.linear"], [f"dense_{index}.relu"])) + previous = f"dense_{index}.relu" + + actor = dense[f"Dense_{cfg.network.num_layers}"] + initializers.extend( + [ + numpy_helper.from_array(np.asarray(actor["kernel"], dtype=np.float32), "actor.weight"), + numpy_helper.from_array(np.asarray(actor["bias"], dtype=np.float32), "actor.bias"), + ] + ) + nodes.append(helper.make_node("Gemm", [previous, "actor.weight", "actor.bias"], ["logits"])) + + graph = helper.make_graph( + nodes, + f"coolrl-lost-cities-match-actor-{codename}", + [helper.make_tensor_value_info("obs", TensorProto.FLOAT, [None, MATCH_OBS_DIM])], + [helper.make_tensor_value_info("logits", TensorProto.FLOAT, [None, N_ACTIONS])], + initializer=initializers, + ) + model = helper.make_model( + graph, producer_name="coolrl-lost-cities", opset_imports=[helper.make_opsetid("", 17)] + ) + model.ir_version = 8 + onnx.checker.check_model(model) + + # The exported graph has to agree with the trained one, not merely load. + rng = np.random.default_rng(20260715) + sample = rng.normal(size=(8, MATCH_OBS_DIM)).astype(np.float32) + critic_stub = jnp.zeros((8, MATCH_CRITIC_OBS_DIM), dtype=jnp.float32) + flax_model = MatchActorCritic(cfg.network.hidden_size, cfg.network.num_layers) + expected, _ = flax_model.apply(params, jnp.asarray(sample), critic_stub) + actual = ReferenceEvaluator(model).run(None, {"obs": sample})[0] + np.testing.assert_allclose(actual, np.asarray(expected), rtol=2e-5, atol=2e-5) + np.testing.assert_array_equal( + np.argmax(actual, axis=1), np.argmax(np.asarray(expected), axis=1) + ) + + output.parent.mkdir(parents=True, exist_ok=True) + onnx.save(model, output) + model_bytes = output.read_bytes() + manifest = { + "format": "coolrl-lost-cities-match-onnx-v1", + "codename": codename, + "model_file": output.name, + "model_size_bytes": len(model_bytes), + "model_sha256": hashlib.sha256(model_bytes).hexdigest(), + "source_checkpoint": str(checkpoint), + "source_config": config.name, + "observation_size": MATCH_OBS_DIM, + "action_size": N_ACTIONS, + "hidden_size": cfg.network.hidden_size, + "num_layers": cfg.network.num_layers, + "dtype": "float32", + "validation_max_abs_error": float(np.max(np.abs(actual - np.asarray(expected)))), + } + output.with_suffix(".json").write_text(json.dumps(manifest, indent=2) + "\n") + print(f"exported {codename} -> {output} ({output.stat().st_size:,} bytes)") + print( + f" sha256 {manifest['model_sha256'][:12]} obs {MATCH_OBS_DIM} max err " + f"{manifest['validation_max_abs_error']:.2e}" + ) + + +def main() -> None: + args = build_argparser().parse_args() + export_model(args.checkpoint, args.config, args.output, args.codename) + + +if __name__ == "__main__": + main() diff --git a/scripts/generate_match_parity_fixture.py b/scripts/generate_match_parity_fixture.py new file mode 100644 index 0000000..fd62510 --- /dev/null +++ b/scripts/generate_match_parity_fixture.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python3 +"""Generate match states and their observations so TypeScript can be checked against JAX. + +The two observation builders must agree to the bit. A mismatch does not throw -- +the ONNX policy consumes a wrong vector quite happily and plays worse for reasons +nobody can see. So the port is not trusted; it is checked. + +States are drawn from real random play so the fixture covers the awkward parts: +mid-round, both seats to move, past a round roll-over, with a non-zero carry. +""" + +from __future__ import annotations + +import json +from pathlib import Path + +import jax +import numpy as np + +from lost_cities_jax.match import MatchState, match_reset_from, match_step +from lost_cities_jax.match_obs import MATCH_OBS_DIM, match_observation +from lost_cities_jax.opponents import random_legal_action +from lost_cities_jax.types import N_CARDS + +OUTPUT = Path(__file__).resolve().parents[1] / "web" / "src" / "game" / "match-parity-fixture.json" +N_ROUNDS = 3 + + +def match_json(match: MatchState) -> dict: + round_state = match.round + return { + "round": { + "deckOrder": np.asarray(round_state.deck_order).astype(int).tolist(), + "drawPtr": int(round_state.draw_ptr), + "cardLoc": np.asarray(round_state.card_loc).astype(int).tolist(), + "handPublic": np.asarray(round_state.hand_public).astype(bool).tolist(), + "colTop": np.asarray(round_state.col_top).astype(int).tolist(), + "colHandshakes": np.asarray(round_state.col_hs).astype(int).tolist(), + "colLength": np.asarray(round_state.col_len).astype(int).tolist(), + "piles": [ + np.asarray(round_state.pile[color, : int(round_state.pile_len[color])]) + .astype(int) + .tolist() + for color in range(5) + ], + "toMove": int(round_state.to_move), + "stepCount": int(round_state.step_count), + "done": bool(round_state.done), + }, + "deckOrders": np.asarray(match.deck_orders).astype(int).tolist(), + "coinFlips": np.asarray(match.coin_flips).astype(int).tolist(), + "roundIdx": int(match.round_idx), + "carry": np.asarray(match.carry).astype(int).tolist(), + "done": bool(match.done), + } + + +def main() -> None: + rng = np.random.default_rng(20260715) + key = jax.random.PRNGKey(7) + rows = [] + + for match_index in range(6): + decks = np.stack([rng.permutation(N_CARDS) for _ in range(N_ROUNDS)]) + coins = rng.integers(0, 2, size=(N_ROUNDS,)) + match = match_reset_from(decks.astype(np.int8), coins.astype(np.int8)) + + # Sample the opening position and then every 17th ply, which lands in all + # three rounds and on both seats without hand-picking anything. + ply = 0 + while not bool(match.done) and ply < 400: + if ply % 17 == 0 or ply == 0: + for player in (0, 1): + obs = np.asarray(match_observation(match, player), dtype=np.float64) + assert obs.shape == (MATCH_OBS_DIM,) + rows.append( + { + "match": match_json(match), + "player": player, + "observation": [round(float(v), 7) for v in obs], + } + ) + key, step_key = jax.random.split(key) + action = int(random_legal_action(match.round, match.round.to_move, step_key)) + match, _, _ = match_step(match, action) + ply += 1 + del match_index + + OUTPUT.write_text( + json.dumps({"format": "jax-web-match-parity-v1", "obsDim": MATCH_OBS_DIM, "rows": rows}) + + "\n" + ) + print(f"wrote {len(rows)} rows -> {OUTPUT}") + + +if __name__ == "__main__": + main() diff --git a/scripts/measure_exploitability.py b/scripts/measure_exploitability.py new file mode 100644 index 0000000..9953e54 --- /dev/null +++ b/scripts/measure_exploitability.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python3 +"""Freeze each policy, train an exploiter against it on the same budget, compare. + +Winning the head-to-head says a policy is strong on average. It does not say the +policy is hard to beat. This does: whatever the exploiter reaches is a habit the +frozen policy could not defend. +""" + +from __future__ import annotations + +import argparse +import json +from pathlib import Path + +import jax +import numpy as np + +from lost_cities_jax.exploit import ( + match_frozen_policy, + single_round_frozen_policy, + train_exploiter, +) +from lost_cities_jax.match import match_reset_from, match_score +from lost_cities_jax.match_eval import MATCH_SCAN_STEPS, _wilson, match_bank +from lost_cities_jax.match_ppo import Ablation, create_match_train_state +from lost_cities_jax.ppo import create_train_state, load_config, restore_checkpoint + +OURS = Path("runs/jax-ppo-match/2026-07-15_031529_match-scaled/latest") +LEAGUE = Path( + "/mnt/2tbhdd/coolrl-lost-cities-artifacts/league/2026-07-05_052325_jax-ppo-league-v1/latest" +) +MATCHES = 4096 + + +def _final_score(cfg, exploiter_params, frozen, matches: int) -> dict: + """Play the trained exploiter against the frozen policy, both seats.""" + import jax.numpy as jnp + + from lost_cities_jax.exploit import match_frozen_policy as _mk + from lost_cities_jax.match import match_step + + attacker = _mk(cfg, exploiter_params, Ablation()) + decks, coins = match_bank(20260722, matches) + + @jax.jit + def run(env, a_seat): + def body(carry, _): + env, _u = carry + action = jnp.where( + env.round.to_move.astype(jnp.int32) == a_seat, + attacker(env, a_seat), + frozen(env, 1 - a_seat), + ) + env, _, _ = jax.vmap(match_step, in_axes=(0, 0))(env, action) + return (env, _u), None + + (env, _), _ = jax.lax.scan(body, (env, jnp.int32(0)), xs=None, length=MATCH_SCAN_STEPS) + return env + + leads = [] + for seat in (0, 1): + env = jax.vmap(match_reset_from)(decks, coins) + final = run(env, jnp.full((matches,), seat, dtype=jnp.int32)) + totals = np.asarray(jax.vmap(match_score)(final)) + leads.append(totals[:, seat] - totals[:, 1 - seat]) + + lead = np.concatenate(leads) + games = float(lead.size) + wins = float((lead > 0).sum()) + low, high = _wilson(wins, games) + return { + "exploiter_win_rate": wins / games, + "wilson_low": low, + "wilson_high": high, + "exploiter_mean_lead": float(lead.mean()), + "matches": games, + } + + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument("--updates", type=int, default=250, help="exploiter training updates") + parser.add_argument("--batch-games", type=int, default=1024) + parser.add_argument("--tag", default="", help="suffix for the run dir, to keep runs apart") + args = parser.parse_args() + + match_cfg = load_config("configs/jax_ppo/match-selfplay.yaml") + old_cfg = load_config("configs/jax_ppo/balanced.yaml") + + ours = restore_checkpoint( + OURS, create_match_train_state(match_cfg, jax.random.PRNGKey(0), Ablation()) + ).params + league = restore_checkpoint(LEAGUE, create_train_state(old_cfg, jax.random.PRNGKey(0))).params + + targets = { + "ours (match stack, 131M)": match_frozen_policy(match_cfg, ours, Ablation()), + "league (web-deployed)": single_round_frozen_policy(old_cfg, league), + } + + rows = [] + for name, frozen in targets.items(): + print(f"\n===== training an exploiter against: {name} =====", flush=True) + cfg = load_config("configs/jax_ppo/match-selfplay.yaml") + cfg.ppo.batch_games = args.batch_games + cfg.run.total_updates = args.updates + cfg.run.log_every = max(1, args.updates // 10) + slug = name.split()[0] + args.tag + state = train_exploiter(cfg, frozen, Path(f"runs/jax-ppo-match/exploit-{slug}")) + result = _final_score(cfg, state.params, frozen, MATCHES) + rows.append({"target": name, **result}) + print(f" exploiter reached {result['exploiter_win_rate']:.4f} vs {name}", flush=True) + + print("\n\n============ exploitability (same exploiter budget) ============") + print(f"{'frozen policy':<28}{'exploiter win rate':>20}{'95% CI':>22}") + print("-" * 72) + for row in rows: + ci = f"[{row['wilson_low']:.3f}, {row['wilson_high']:.3f}]" + print(f"{row['target']:<28}{row['exploiter_win_rate']:>20.4f}{ci:>22}") + print("\nhigher = the frozen policy had more to farm. 0.5 = nothing found.") + Path(f"runs/jax-ppo-match/exploitability{args.tag}.json").write_text(json.dumps(rows, indent=2)) + + +if __name__ == "__main__": + main() diff --git a/scripts/serve_web_with_logs.py b/scripts/serve_web_with_logs.py new file mode 100644 index 0000000..94781a4 --- /dev/null +++ b/scripts/serve_web_with_logs.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python3 +"""Serve the production web client and append completed games to JSONL.""" + +from __future__ import annotations + +import argparse +import json +from http import HTTPStatus +from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer +from pathlib import Path +from typing import Any + +MAX_RECORD_BYTES = 6_000_000 + +# v2 adds the opponent's identity (codename + hash) and the match layer -- three +# deals, the coin flips, and which round each move belongs to. v1 is still +# accepted because 111 games were recorded under it; they are all altair, which +# data/models.json records since v1 has nowhere to say so. +SUPPORTED_FORMATS = frozenset({"lost-cities-web-game-v1", "lost-cities-web-game-v2"}) + + +def parse_record(body: bytes) -> dict[str, Any]: + if len(body) > MAX_RECORD_BYTES: + raise ValueError("record is too large") + value = json.loads(body) + if not isinstance(value, dict) or value.get("format") not in SUPPORTED_FORMATS: + raise ValueError("unsupported game record") + if not isinstance(value.get("gameId"), str) or not isinstance(value.get("moves"), list): + raise ValueError("invalid game record") + return value + + +def make_handler(dist: Path, output: Path): + seen_ids: set[str] = set() + if output.exists(): + for line in output.read_text(encoding="utf-8").splitlines(): + try: + game_id = json.loads(line).get("gameId") + if isinstance(game_id, str): + seen_ids.add(game_id) + except (json.JSONDecodeError, AttributeError): + continue + + class Handler(SimpleHTTPRequestHandler): + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, directory=str(dist), **kwargs) + + def do_POST(self) -> None: # noqa: N802 + if self.path != "/api/game-records": + self.send_error(HTTPStatus.NOT_FOUND) + return + try: + length = int(self.headers.get("content-length", "0")) + record = parse_record(self.rfile.read(length)) + except (ValueError, json.JSONDecodeError) as error: + self.send_error(HTTPStatus.BAD_REQUEST, str(error)) + return + game_id = record["gameId"] + if game_id not in seen_ids: + output.parent.mkdir(parents=True, exist_ok=True) + with output.open("a", encoding="utf-8") as stream: + stream.write( + json.dumps(record, ensure_ascii=False, separators=(",", ":")) + "\n" + ) + seen_ids.add(game_id) + self.send_response(HTTPStatus.NO_CONTENT) + self.end_headers() + + return Handler + + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument("--host", default="0.0.0.0") + parser.add_argument("--port", type=int, default=5173) + parser.add_argument("--dist", type=Path, default=Path("web/dist")) + parser.add_argument("--output", type=Path, default=Path("data/human-play/game-records.jsonl")) + args = parser.parse_args() + server = ThreadingHTTPServer((args.host, args.port), make_handler(args.dist, args.output)) + print(f"Serving {args.dist} on http://{args.host}:{args.port}", flush=True) + print(f"Writing game records to {args.output}", flush=True) + server.serve_forever() + + +if __name__ == "__main__": + main() diff --git a/scripts/train_match.py b/scripts/train_match.py new file mode 100644 index 0000000..e3dbecd --- /dev/null +++ b/scripts/train_match.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 +"""Train the classic three-round agent by self-play, then measure it.""" + +from __future__ import annotations + +import argparse +import json +from pathlib import Path + +import jax + +from lost_cities_jax.match_eval import carry_probe, match_evaluate +from lost_cities_jax.match_ppo import create_match_train_state, match_train +from lost_cities_jax.ppo import load_config, restore_checkpoint + + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument("--config", default="configs/jax_ppo/match-selfplay.yaml") + parser.add_argument("--eval-only", type=Path, default=None) + parser.add_argument("--matches", type=int, default=1024) + parser.add_argument("--set", action="append", default=[]) + args = parser.parse_args() + + cfg = load_config(args.config) + for override in args.set: + path, _, raw = override.partition("=") + section, _, field = path.partition(".") + target = getattr(cfg, section) + current = getattr(target, field) + value = type(current)(raw) if not isinstance(current, bool) else raw == "true" + setattr(target, field, value) + + if args.eval_only is None: + run_dir = match_train(cfg) + checkpoint = run_dir / "latest" + else: + checkpoint = args.eval_only + + state = create_match_train_state(cfg, jax.random.PRNGKey(0)) + state = restore_checkpoint(Path(checkpoint), state) + + result = match_evaluate(cfg, state.params, matches=args.matches) + print("\n== duplicate match eval (self-play) ==") + print(json.dumps(result, indent=2, sort_keys=True)) + + print("\n== carry probe: does round-three play react to the deficit? ==") + rows = carry_probe(cfg, state.params, matches=args.matches // 2) + header = f"{'carry':>7}{'win_rate':>10}{'opened':>9}{'wagers':>9}{'deck_race':>11}{'plies':>8}" + print(header) + for row in rows: + print( + f"{row['carry']:>7}{row['win_rate']:>10.3f}{row['opened_colors']:>9.2f}" + f"{row['wagers_played']:>9.2f}{row['deck_race_rate']:>11.3f}{row['mean_plies']:>8.0f}" + ) + Path(checkpoint).parent.joinpath("carry_probe.json").write_text( + json.dumps({"eval": result, "probe": rows}, indent=2, sort_keys=True) + ) + + +if __name__ == "__main__": + main() diff --git a/src/lost_cities_jax/engine.py b/src/lost_cities_jax/engine.py index 033bad8..1a916e2 100644 --- a/src/lost_cities_jax/engine.py +++ b/src/lost_cities_jax/engine.py @@ -36,11 +36,14 @@ def reset(rng: jax.Array) -> State: return reset_from_order(deck_order) -def reset_from_order(deck_order: jax.Array) -> State: +def reset_from_order(deck_order: jax.Array, first_player: jax.Array | int = 0) -> State: """Return an initial state using an explicit 60-card deck permutation. The first eight cards are dealt to player 0 and the next eight to player 1. The remaining cards are drawn in array order starting at ``draw_ptr == 16``. + + ``first_player`` moves first. Rounds two and three of a classic match are led + by whoever is ahead on points, so the match layer sets this per round. """ deck_order = jnp.asarray(deck_order, dtype=jnp.int8) @@ -60,7 +63,7 @@ def reset_from_order(deck_order: jax.Array) -> State: col_len=jnp.zeros((2, N_COLORS), dtype=jnp.int8), pile=jnp.full((N_COLORS, MAX_PILE_SIZE), NO_CARD, dtype=jnp.int8), pile_len=jnp.zeros((N_COLORS,), dtype=jnp.int8), - to_move=jnp.asarray(0, dtype=jnp.int8), + to_move=jnp.asarray(first_player, dtype=jnp.int8), just_discarded=jnp.asarray(NO_CARD, dtype=jnp.int8), step_count=jnp.asarray(0, dtype=jnp.int32), done=jnp.asarray(False), diff --git a/src/lost_cities_jax/exploit.py b/src/lost_cities_jax/exploit.py new file mode 100644 index 0000000..db43c0b --- /dev/null +++ b/src/lost_cities_jax/exploit.py @@ -0,0 +1,244 @@ +"""How exploitable is a frozen policy? + +Beating an opponent on average and being hard to beat are different properties. +A policy can win the head-to-head and still have a habit a dedicated opponent can +farm -- rock-paper-scissors throwing rock 60% of the time beats a lot of people +and loses every time to anyone who noticed. + +So: freeze the policy, train a fresh one from scratch whose only job is to beat +*that* policy, and see how far it gets. Near 0.5 means there was nothing to find. +Well above it means there was. + +PPO self-play carries no Nash guarantee, so this is not a formality. The number it +produces is a lower bound on exploitability -- a stronger exploiter might find +more -- so it is only meaningful compared against the same exploiter budget spent +on another policy. +""" + +from __future__ import annotations + +import json +import time +from collections.abc import Callable +from pathlib import Path + +import jax +import jax.numpy as jnp + +from lost_cities_jax.match import MatchState, match_legal_action_mask, match_reset, match_step +from lost_cities_jax.match_ppo import ( + FULL, + N_SEATS, + Ablation, + MatchActorCritic, + MatchTransition, + _seat_views, + create_match_train_state, + match_lead, + match_ppo_update, +) +from lost_cities_jax.obs import observation +from lost_cities_jax.ppo import ( + ActorCritic, + JaxPPOConfig, + TrainState, + _append_jsonl, + _broadcast_done, + action_log_prob, + categorical_entropy, + compute_gae, + mask_logits, + masked_mean, +) +from lost_cities_jax.types import PLAY + +FrozenPolicy = Callable[[MatchState, jax.Array], jax.Array] +"""(env batch, seat batch) -> greedy actions. Whatever architecture, hidden here.""" + + +def match_frozen_policy(cfg: JaxPPOConfig, params, ablation: Ablation = FULL) -> FrozenPolicy: + model = MatchActorCritic(cfg.network.hidden_size, cfg.network.num_layers) + seats = jnp.arange(N_SEATS, dtype=jnp.int32) + + def policy(env: MatchState, seat: jax.Array) -> jax.Array: + obs, critic = _seat_views(env, seats, ablation) + idx = seat[None, :, None] + logits, _ = model.apply( + params, + jnp.take_along_axis(obs, idx, axis=0)[0], + jnp.take_along_axis(critic, idx, axis=0)[0], + ) + mask = jax.vmap(match_legal_action_mask)(env) + return jnp.argmax(mask_logits(logits, mask), axis=-1).astype(jnp.int32) + + return policy + + +def single_round_frozen_policy(cfg: JaxPPOConfig, params) -> FrozenPolicy: + """The old stack: it sees one round at a time and has never heard of carry.""" + model = ActorCritic(cfg.network.hidden_size, cfg.network.num_layers) + + def policy(env: MatchState, seat: jax.Array) -> jax.Array: + logits, _ = model.apply(params, jax.vmap(observation)(env.round, seat)) + mask = jax.vmap(match_legal_action_mask)(env) + return jnp.argmax(mask_logits(logits, mask), axis=-1).astype(jnp.int32) + + return policy + + +def _reset_done(env: MatchState, seat: jax.Array, rng: jax.Array, batch: int): + env_key, seat_key = jax.random.split(rng) + fresh = jax.vmap(match_reset)(jax.random.split(env_key, batch)) + next_env = jax.tree_util.tree_map( + lambda old, new: jnp.where(_broadcast_done(env.done, old), new, old), env, fresh + ) + # Redraw the exploiter's seat too, so it learns to beat the frozen policy from + # either side rather than only the one it started in. + fresh_seat = jax.random.bernoulli(seat_key, 0.5, shape=(batch,)).astype(jnp.int32) + return next_env, jnp.where(env.done, fresh_seat, seat) + + +def make_exploiter_rollout_fn(cfg: JaxPPOConfig, frozen: FrozenPolicy): + batch = cfg.ppo.batch_games + seats = jnp.arange(N_SEATS, dtype=jnp.int32) + ablation = FULL + + @jax.jit + def rollout_fn(state: TrainState, env: MatchState, seat: jax.Array, rng: jax.Array): + def body(carry, _): + env, seat, key = carry + key, act_key, reset_key = jax.random.split(key, 3) + + obs, critic_obs = _seat_views(env, seats, ablation) + idx = seat[None, :, None] + my_obs = jnp.take_along_axis(obs, idx, axis=0)[0] + my_critic = jnp.take_along_axis(critic_obs, idx, axis=0)[0] + legal = jax.vmap(match_legal_action_mask)(env) + + logits, value = state.apply_fn(state.params, my_obs, my_critic) + masked = mask_logits(logits, legal) + mine = jax.random.categorical(act_key, masked, axis=-1).astype(jnp.int32) + theirs = jax.lax.stop_gradient(frozen(env, 1 - seat)) + + to_move = env.round.to_move.astype(jnp.int32) + active = ~env.done + my_turn = to_move == seat + actions = jnp.where(my_turn, mine, theirs) + + before = jax.vmap(match_lead)(env) + next_env, _, _ = jax.vmap(match_step, in_axes=(0, 0))(env, actions) + after = jax.vmap(match_lead)(next_env) + + # match_lead is seat 0's view; flip it when the exploiter sits in 1. + sign = jnp.where(seat == 0, 1.0, -1.0) + reward = jnp.where(active, sign * (after - before) / cfg.reward.terminal_scale, 0.0) + + actor_mask = active & my_turn + transition = MatchTransition( + obs=my_obs, + critic_obs=my_critic, + legal_mask=legal, + action=actions, + log_prob=action_log_prob(masked, mine), + value=value, + reward=reward, + done=next_env.done, + active=active, + actor_mask=actor_mask, + entropy=categorical_entropy(masked), + play_action=((actions % 12) // 6 == PLAY) & actor_mask, + ) + + done = next_env.done + final_lead = sign * jax.vmap(match_lead)(next_env) + won = (done & active & (final_lead > 0)).astype(jnp.float32) + finished = (done & active).astype(jnp.float32) + + next_env, seat = _reset_done(next_env, seat, reset_key, batch) + return (next_env, seat, key), (transition, won, finished) + + (next_env, seat, rng), (transitions, won, finished) = jax.lax.scan( + body, (env, seat, rng), xs=None, length=cfg.ppo.rollout_steps + ) + + obs, critic_obs = _seat_views(next_env, seats, ablation) + idx = seat[None, :, None] + _, last_value = state.apply_fn( + state.params, + jnp.take_along_axis(obs, idx, axis=0)[0], + jnp.take_along_axis(critic_obs, idx, axis=0)[0], + ) + + played = jnp.sum(finished) + metrics = { + "exploiter_win_rate": jnp.sum(won) / jnp.maximum(played, 1.0), + "matches_completed": played, + "learner_actions": jnp.sum(transitions.actor_mask), + "entropy_mean": masked_mean( + transitions.entropy, transitions.actor_mask.astype(jnp.float32) + ), + } + return next_env, seat, transitions, last_value, metrics + + return rollout_fn + + +def train_exploiter(cfg: JaxPPOConfig, frozen: FrozenPolicy, run_dir: Path) -> TrainState: + """Train a fresh policy whose only goal is to beat ``frozen``.""" + + rng = jax.random.PRNGKey(cfg.run.seed) + rng, init_key, reset_key, seat_key = jax.random.split(rng, 4) + state = create_match_train_state(cfg, init_key, Ablation()) + env = jax.jit(jax.vmap(match_reset))(jax.random.split(reset_key, cfg.ppo.batch_games)) + seat = jax.random.bernoulli(seat_key, 0.5, shape=(cfg.ppo.batch_games,)).astype(jnp.int32) + + rollout_fn = make_exploiter_rollout_fn(cfg, frozen) + + @jax.jit + def iteration(state, env, seat, rng): + rng, roll_key, update_key = jax.random.split(rng, 3) + env, seat, transitions, last_value, metrics = rollout_fn(state, env, seat, roll_key) + advantages, returns = compute_gae( + transitions.reward, + transitions.value, + transitions.done, + cfg.ppo.gamma, + cfg.ppo.gae_lambda, + last_value, + ) + state, update_metrics = match_ppo_update( + state, transitions, advantages, returns, update_key, cfg + ) + return state, env, seat, rng, {**metrics, **update_metrics} + + run_dir.mkdir(parents=True, exist_ok=True) + metrics_path = run_dir / "metrics.jsonl" + start = time.perf_counter() + for update in range(cfg.run.total_updates): + state, env, seat, rng, metrics = iteration(state, env, seat, rng) + jax.tree_util.tree_leaves(metrics)[0].block_until_ready() + row = {k: float(v) for k, v in metrics.items()} + row["update"] = update + row["elapsed_seconds"] = time.perf_counter() - start + _append_jsonl(metrics_path, row) + if update % cfg.run.log_every == 0: + print( + json.dumps( + { + "update": update, + "exploiter_win_rate": row["exploiter_win_rate"], + "matches": row["matches_completed"], + }, + sort_keys=True, + ), + flush=True, + ) + return state + + +__all__ = [ + "make_exploiter_rollout_fn", + "match_frozen_policy", + "single_round_frozen_policy", + "train_exploiter", +] diff --git a/src/lost_cities_jax/match.py b/src/lost_cities_jax/match.py new file mode 100644 index 0000000..7e5cfa0 --- /dev/null +++ b/src/lost_cities_jax/match.py @@ -0,0 +1,139 @@ +"""Classic Lost Cities: three rounds, scores summed, highest total wins. + +The single-round engine in ``engine.py`` is left alone -- it is the rules oracle +the TypeScript client is differential-tested against. This module wraps it. + +Two rules only exist at the match level, both from the Kosmos rulebook: + +- "If after three games you have the highest overall score, you win." +- "The player who has more points begins" the next game. Not alternating. The + rulebook says nothing about an exact tie, so we flip a coin: any deterministic + tie-break would hand one seat a standing edge in symmetric self-play, and the + agent would learn to steer for it. + +All randomness is drawn in ``match_reset`` and stored in the state, so +``match_step`` stays deterministic and needs no PRNG key. That keeps the step +signature clean through every rollout/eval body, and it means a mirrored match +(same three deals, seats swapped, same coin flips) is just a seat relabel. +""" + +from __future__ import annotations + +from typing import NamedTuple + +import jax +import jax.numpy as jnp + +from lost_cities_jax.engine import board_score, legal_action_mask, reset_from_order, step +from lost_cities_jax.types import N_CARDS, State + +N_ROUNDS = 3 + + +class MatchState(NamedTuple): + round: State + """The round being played right now.""" + + deck_orders: jax.Array + """(N_ROUNDS, N_CARDS) -- every deal of the match, shuffled up front.""" + + coin_flips: jax.Array + """(N_ROUNDS,) tie-breaking starters, used only when the scores are level.""" + + round_idx: jax.Array + carry: jax.Array + """(2,) points banked by each player in the rounds already finished.""" + + done: jax.Array + + +def match_reset(rng: jax.Array) -> MatchState: + deck_key, coin_key = jax.random.split(rng) + deck_keys = jax.random.split(deck_key, N_ROUNDS) + deck_orders = jax.vmap( + lambda key: jax.random.permutation(key, jnp.arange(N_CARDS, dtype=jnp.int32), axis=0) + )(deck_keys).astype(jnp.int8) + coin_flips = jax.random.bernoulli(coin_key, 0.5, shape=(N_ROUNDS,)).astype(jnp.int8) + return match_reset_from(deck_orders, coin_flips) + + +def match_reset_from(deck_orders: jax.Array, coin_flips: jax.Array) -> MatchState: + """Build a match from explicit deals and coin flips (mirrored eval, fixtures).""" + + deck_orders = jnp.asarray(deck_orders, dtype=jnp.int8) + coin_flips = jnp.asarray(coin_flips, dtype=jnp.int8) + carry = jnp.zeros((2,), dtype=jnp.int32) + round_idx = jnp.asarray(0, dtype=jnp.int32) + return MatchState( + round=reset_from_order(deck_orders[0], first_player=starting_player(carry, 0, coin_flips)), + deck_orders=deck_orders, + coin_flips=coin_flips, + round_idx=round_idx, + carry=carry, + done=jnp.asarray(False), + ) + + +def starting_player(carry: jax.Array, round_idx: jax.Array, coin_flips: jax.Array) -> jax.Array: + """Whoever has banked more points leads; level scores fall back to the coin. + + Round one needs no special case: ``carry`` is (0, 0) there, so the tie branch + already picks the coin flip, which is exactly the rulebook's arbitrary + "oldest player begins". + """ + + lead = carry[0] - carry[1] + coin = coin_flips[round_idx].astype(jnp.int8) + ahead = jnp.where(lead > 0, jnp.int8(0), jnp.int8(1)) + return jnp.where(lead == 0, coin, ahead) + + +def match_score(state: MatchState) -> jax.Array: + """(2,) running totals: rounds already banked plus the board in play.""" + + return state.carry + board_score(state.round).astype(jnp.int32) + + +def match_legal_action_mask(state: MatchState) -> jax.Array: + return legal_action_mask(state.round) & ~state.done + + +def match_step(state: MatchState, action: jax.Array) -> tuple[MatchState, jax.Array, jax.Array]: + """Play one ply. Rolls into the next round when the deck runs out. + + Reward is zero until the third round ends, then it is each player's match + total. Intermediate rounds pay nothing: only the sum decides the match. + """ + + played, _, _ = step(state.round, action) + round_over = played.done & ~state.done + is_final_round = state.round_idx >= N_ROUNDS - 1 + + advance = round_over & ~is_final_round + finished = round_over & is_final_round + + banked = state.carry + board_score(played).astype(jnp.int32) + next_carry = jnp.where(advance, banked, state.carry) + next_round_idx = jnp.where(advance, state.round_idx + 1, state.round_idx) + + # Dealt eagerly every ply; only kept on the plies that actually roll over. + fresh = reset_from_order( + state.deck_orders[next_round_idx], + first_player=starting_player(next_carry, next_round_idx, state.coin_flips), + ) + next_round = jax.tree_util.tree_map( + lambda new, old: jnp.where(advance, new, old), fresh, played + ) + + next_state = MatchState( + round=next_round, + deck_orders=state.deck_orders, + coin_flips=state.coin_flips, + round_idx=next_round_idx, + carry=next_carry, + done=state.done | finished, + ) + + total = state.carry + board_score(played).astype(jnp.int32) + reward = jnp.where(finished, total.astype(jnp.float32), jnp.zeros((2,), dtype=jnp.float32)) + return next_state, reward, next_state.done diff --git a/src/lost_cities_jax/match_eval.py b/src/lost_cities_jax/match_eval.py new file mode 100644 index 0000000..7d6cd6e --- /dev/null +++ b/src/lost_cities_jax/match_eval.py @@ -0,0 +1,250 @@ +"""Match-level evaluation, and the probe that says whether carry changed anything. + +Single-deal win rate cannot tell you if the three-round rework worked. Two things +can: + +- **Duplicate match play.** The same three deals and the same coin flips, played + from both seats. Deal luck cancels, so what is left is the policy difference. +- **The carry probe.** Drop the policy into round three holding a fixed deficit or + lead and watch what it does. A carry-blind policy plays a 60-point deficit + exactly like a 60-point lead. If the numbers below do not move with carry, the + rework bought nothing, no matter what the win rate says. +""" + +from __future__ import annotations + +import math + +import jax +import jax.numpy as jnp +import numpy as np + +from lost_cities_jax.engine import reset_from_order +from lost_cities_jax.match import ( + N_ROUNDS, + MatchState, + match_legal_action_mask, + match_reset_from, + match_score, + match_step, +) +from lost_cities_jax.match_obs import match_critic_observation, match_observation +from lost_cities_jax.match_ppo import MatchActorCritic, match_lead +from lost_cities_jax.ppo import JaxPPOConfig, mask_logits +from lost_cities_jax.types import DRAW_DECK, MAX_STEPS, N_CARDS + +MATCH_SCAN_STEPS = N_ROUNDS * MAX_STEPS + + +def match_bank(seed: int, matches: int) -> tuple[jnp.ndarray, jnp.ndarray]: + """Deterministic deals and coin flips, so runs are comparable.""" + rng = np.random.default_rng(seed) + decks = np.stack( + [np.stack([rng.permutation(N_CARDS) for _ in range(N_ROUNDS)]) for _ in range(matches)] + ) + coins = rng.integers(0, 2, size=(matches, N_ROUNDS)) + return jnp.asarray(decks, dtype=jnp.int8), jnp.asarray(coins, dtype=jnp.int8) + + +def _wilson(wins: float, games: float) -> tuple[float, float]: + if games == 0: + return 0.0, 0.0 + z = 1.96 + p = wins / games + denom = 1 + z * z / games + centre = p + z * z / (2 * games) + margin = z * math.sqrt(p * (1 - p) / games + z * z / (4 * games * games)) + return (centre - margin) / denom, (centre + margin) / denom + + +def make_match_runner(cfg: JaxPPOConfig, opponent_policy=None): + """Play whole matches to the end. ``opponent_policy`` is a single-round policy.""" + + model = MatchActorCritic(cfg.network.hidden_size, cfg.network.num_layers) + + @jax.jit + def run(params, env: MatchState, learner_seat: jax.Array, rng: jax.Array): + def body(carry, _): + env, key, deck_draws, plies = carry + key, opp_key = jax.random.split(key) + + to_move = env.round.to_move.astype(jnp.int32) + obs = jax.vmap(match_observation)(env, to_move) + critic = jax.vmap(match_critic_observation)(env, to_move) + mask = jax.vmap(match_legal_action_mask)(env) + logits, _ = model.apply(params, obs, critic) + learner_action = jnp.argmax(mask_logits(logits, mask), axis=-1).astype(jnp.int32) + + if opponent_policy is None: + action = learner_action + else: + opp_keys = jax.random.split(opp_key, env.done.shape[0]) + opp_action = jax.vmap(opponent_policy, in_axes=(0, 0, 0))( + env.round, to_move, opp_keys + ) + action = jnp.where(to_move == learner_seat, learner_action, opp_action) + + live = ~env.done + is_deck = (action % 6) == DRAW_DECK + deck_draws = deck_draws + (is_deck & live).astype(jnp.int32) + plies = plies + live.astype(jnp.int32) + + env, _, _ = jax.vmap(match_step, in_axes=(0, 0))(env, action) + return (env, key, deck_draws, plies), None + + n = env.done.shape[0] + zeros = jnp.zeros((n,), dtype=jnp.int32) + (env, _, deck_draws, plies), _ = jax.lax.scan( + body, (env, rng, zeros, zeros), xs=None, length=MATCH_SCAN_STEPS + ) + return env, deck_draws, plies + + return run + + +def match_evaluate(cfg: JaxPPOConfig, params, *, matches: int = 2000, seed: int = 20260715) -> dict: + """Duplicate match play: every deal seen from both seats.""" + + decks, coins = match_bank(seed, matches) + runner = make_match_runner(cfg) + + results = [] + for seat in (0, 1): + env = jax.vmap(match_reset_from)(decks, coins) + seats = jnp.full((matches,), seat, dtype=jnp.int32) + final, deck_draws, plies = runner(params, env, seats, jax.random.PRNGKey(0)) + totals = np.asarray(jax.vmap(match_score)(final)) + lead = totals[:, seat] - totals[:, 1 - seat] + results.append( + { + "lead": lead, + "plies": np.asarray(plies), + "deck_share": np.asarray(deck_draws) / np.maximum(np.asarray(plies), 1), + "done": np.asarray(final.done), + } + ) + + lead = np.concatenate([r["lead"] for r in results]) + games = float(lead.size) + wins = float((lead > 0).sum()) + ties = float((lead == 0).sum()) + low, high = _wilson(wins, games) + return { + "matches": games, + "wins": wins, + "ties": ties, + "losses": games - wins - ties, + "match_win_rate": wins / games, + "wilson_low": low, + "wilson_high": high, + "mean_total_lead": float(lead.mean()), + "mean_plies": float(np.concatenate([r["plies"] for r in results]).mean()), + "unfinished_rate": float( + 1.0 - np.concatenate([r["done"] for r in results]).astype(np.float32).mean() + ), + } + + +def head_to_head( + cfg: JaxPPOConfig, params_a, params_b, *, matches: int = 4096, seed: int = 20260717 +) -> dict: + """Duplicate matches between two policies: same deals, same coins, both seats. + + Every deal is played twice with the seats swapped, so deal luck cancels and + what is left is the difference between the two policies. + """ + + decks, coins = match_bank(seed, matches) + model = MatchActorCritic(cfg.network.hidden_size, cfg.network.num_layers) + + @jax.jit + def run(env: MatchState, a_seat: jax.Array): + def body(carry, _): + env, _unused = carry + to_move = env.round.to_move.astype(jnp.int32) + obs = jax.vmap(match_observation)(env, to_move) + critic = jax.vmap(match_critic_observation)(env, to_move) + mask = jax.vmap(match_legal_action_mask)(env) + + logits_a, _ = model.apply(params_a, obs, critic) + logits_b, _ = model.apply(params_b, obs, critic) + act_a = jnp.argmax(mask_logits(logits_a, mask), axis=-1).astype(jnp.int32) + act_b = jnp.argmax(mask_logits(logits_b, mask), axis=-1).astype(jnp.int32) + + action = jnp.where(to_move == a_seat, act_a, act_b) + env, _, _ = jax.vmap(match_step, in_axes=(0, 0))(env, action) + return (env, _unused), None + + (env, _), _ = jax.lax.scan(body, (env, jnp.int32(0)), xs=None, length=MATCH_SCAN_STEPS) + return env + + leads = [] + for seat in (0, 1): + env = jax.vmap(match_reset_from)(decks, coins) + final = run(env, jnp.full((matches,), seat, dtype=jnp.int32)) + totals = np.asarray(jax.vmap(match_score)(final)) + leads.append(totals[:, seat] - totals[:, 1 - seat]) + + lead = np.concatenate(leads) + games = float(lead.size) + wins = float((lead > 0).sum()) + ties = float((lead == 0).sum()) + low, high = _wilson(wins, games) + return { + "matches": games, + "a_win_rate": wins / games, + "wilson_low": low, + "wilson_high": high, + "ties": ties, + "a_mean_lead": float(lead.mean()), + } + + +def carry_probe( + cfg: JaxPPOConfig, + params, + *, + carry_levels=(-60, -25, -1, 1, 25, 60), + matches: int = 512, + seed: int = 20260716, +) -> list[dict]: + """Start the policy in round three holding ``carry`` and see what changes. + + A policy that reads carry should open more expeditions and lean on wagers when + it is behind (it has to swing), and shut down when it is ahead. Flat rows mean + the policy is ignoring the one thing the three-round rework added. + """ + + decks, coins = match_bank(seed, matches) + runner = make_match_runner(cfg) + rows = [] + + for level in carry_levels: + base = jax.vmap(match_reset_from)(decks, coins) + carry = jnp.tile(jnp.asarray([level, 0], dtype=jnp.int32), (matches, 1)) + round_idx = jnp.full((matches,), N_ROUNDS - 1, dtype=jnp.int32) + # Whoever is ahead leads the round, exactly as the match layer would. + first = jnp.int8(0 if level > 0 else 1) + rounds = jax.vmap(reset_from_order, in_axes=(0, None))(decks[:, N_ROUNDS - 1], first) + + env = base._replace(round=rounds, carry=carry, round_idx=round_idx) + final, deck_draws, plies = runner( + params, env, jnp.zeros((matches,), jnp.int32), jax.random.PRNGKey(1) + ) + + lead = np.asarray(jax.vmap(match_lead)(final)) + opened = np.asarray(jnp.sum(final.round.col_len[:, 0, :] > 0, axis=-1)) + wagers = np.asarray(jnp.sum(final.round.col_hs[:, 0, :], axis=-1)) + deck_share = np.asarray(deck_draws) / np.maximum(np.asarray(plies), 1) + + rows.append( + { + "carry": level, + "win_rate": float((lead > 0).mean()), + "opened_colors": float(opened.mean()), + "wagers_played": float(wagers.mean()), + "deck_race_rate": float(deck_share.mean()), + "mean_plies": float(np.asarray(plies).mean()), + } + ) + return rows diff --git a/src/lost_cities_jax/match_obs.py b/src/lost_cities_jax/match_obs.py new file mode 100644 index 0000000..d839177 --- /dev/null +++ b/src/lost_cities_jax/match_obs.py @@ -0,0 +1,198 @@ +"""Player-view observation for a three-round match. + +Everything the single-round observation had, plus the four things a match policy +cannot play without: + +- **carry**, as a scalar *and* a one-hot over bins. Round three is a threshold + problem -- "win by 41 or lose" plays nothing like "win by 39" -- and a lone + scalar makes the network learn a cliff from a smooth input. (The old + ``score_diff`` divided by ``MAX_ABS_SCORE`` = 780, which squashed a decisive + 50-point lead to 0.06. That scaling is fixed here too.) +- **which round it is**, and how many are left. +- **whose turn it is.** The single-round obs never had this, yet the critic is + trained on opponent-turn states as well, leaving it to recover turn parity + from ``step_count / 400``. +- **the deck clock.** A round ends when the last deck card is drawn, so turn + parity decides who gets the final placement -- and players bend that parity by + drawing from discard piles instead. + +Live points per colour are split by where the card is (hand / discard pile / +unseen) because a discard pile is public and recoverable: lumping it in with the +unseen cards hides the high cards sitting in plain view. +""" + +from __future__ import annotations + +import jax +import jax.numpy as jnp + +from lost_cities_jax.engine import board_score +from lost_cities_jax.match import N_ROUNDS, MatchState +from lost_cities_jax.obs import observation +from lost_cities_jax.types import ( + CARDS_PER_COLOR, + LOC_DECK, + LOC_DISCARD, + LOC_P0_HAND, + N_CARDS, + N_COLORS, + OBS_DIM, +) + +# Bin edges for the carry one-hot. Packed tightly around zero: that is where the +# round-three decision actually flips. +CARRY_BIN_EDGES = jnp.asarray([-60.0, -30.0, -12.0, -1.0, 1.0, 12.0, 30.0, 60.0]) +N_CARRY_BINS = CARRY_BIN_EDGES.shape[0] + 1 + +CARRY_SCALE = 75.0 +"""Typical round margin, not the theoretical 780 maximum.""" + +MAX_COLOR_POINTS = 54.0 +"""2+3+...+10, the most a single expedition can be worth before multipliers.""" + +N_MATCH_SCALARS = ( + 1 # carry, scaled + + N_CARRY_BINS # carry, binned + + N_ROUNDS # which round + + 1 # rounds left + + 1 # is it my turn + + 1 # did I lead this round + + 1 # do I take the last deck card at the current parity + + 2 * N_COLORS * 3 # live points: both players x colour x {hand, discard, unseen} +) +MATCH_OBS_DIM = OBS_DIM + N_MATCH_SCALARS + + +def _live_points(state, viewer: jax.Array, subject: jax.Array) -> jax.Array: + """Points still reachable for ``subject``, split by where the card sits. + + Returns ``float32[N_COLORS, 3]`` over {in hand, in a discard pile, unseen}. + Seen through ``viewer``'s eyes: a card in the opponent's hand only counts as + "in hand" if it is public, otherwise it is unseen. + """ + + ids = jnp.arange(N_CARDS, dtype=jnp.int32) + colors = ids // CARDS_PER_COLOR + slots = ids % CARDS_PER_COLOR + ranks = jnp.where(slots >= 3, slots - 1, 0).astype(jnp.float32) + + loc = state.card_loc.astype(jnp.int32) + subject_hand = loc == (LOC_P0_HAND + subject) + is_mine = subject == viewer + + # An ascending column can only take cards above its current top. + above_top = ranks > state.col_top[subject][colors].astype(jnp.float32) + + in_hand = subject_hand & (is_mine | state.hand_public) + in_discard = loc == LOC_DISCARD + unseen = (loc == LOC_DECK) | (subject_hand & ~is_mine & ~state.hand_public) + # Cards in the *other* player's hidden hand are unseen to the viewer too, but + # they are not reachable by the subject, so they are deliberately excluded. + + def by_color(mask: jax.Array) -> jax.Array: + weighted = jnp.where(mask & above_top, ranks, 0.0) + return jax.ops.segment_sum(weighted, colors, num_segments=N_COLORS) + + stacked = jnp.stack([by_color(in_hand), by_color(in_discard), by_color(unseen)], axis=1) + return stacked / MAX_COLOR_POINTS + + +def match_observation(state: MatchState, player: jax.Array) -> jax.Array: + """Return ``float32[MATCH_OBS_DIM]`` from ``player``'s seat.""" + + player = jnp.asarray(player, dtype=jnp.int32) + opponent = 1 - player + round_state = state.round + + base = observation(round_state, player) + + totals = state.carry + board_score(round_state).astype(jnp.int32) + lead = (totals[player] - totals[opponent]).astype(jnp.float32) + carry_scaled = jnp.clip(lead / CARRY_SCALE, -2.0, 2.0).reshape((1,)) + carry_bins = jax.nn.one_hot(jnp.digitize(lead, CARRY_BIN_EDGES), N_CARRY_BINS) + + round_onehot = jax.nn.one_hot(state.round_idx, N_ROUNDS) + rounds_left = ((N_ROUNDS - 1 - state.round_idx).astype(jnp.float32) / (N_ROUNDS - 1)).reshape( + (1,) + ) + + to_move = round_state.to_move.astype(jnp.int32) + my_turn = (to_move == player).astype(jnp.float32).reshape((1,)) + # to_move flips every ply, so the round's opener is recoverable from parity. + parity = round_state.step_count.astype(jnp.int32) & 1 + round_opener = to_move ^ parity + i_opened = (round_opener == player).astype(jnp.float32).reshape((1,)) + + # If both players drew from the deck from here, the last deck card falls to + # whoever is on move after `remaining - 1` more plies. + remaining = jnp.maximum(N_CARDS - round_state.draw_ptr, 1).astype(jnp.int32) + last_drawer = to_move ^ ((remaining - 1) & 1) + i_take_last = (last_drawer == player).astype(jnp.float32).reshape((1,)) + + live_me = _live_points(round_state, player, player).reshape((-1,)) + live_opp = _live_points(round_state, player, opponent).reshape((-1,)) + + extra = jnp.concatenate( + [ + carry_scaled, + carry_bins, + round_onehot, + rounds_left, + my_turn, + i_opened, + i_take_last, + live_me, + live_opp, + ], + axis=0, + ).astype(jnp.float32) + + return jnp.concatenate([base, extra], axis=0).reshape((MATCH_OBS_DIM,)) + + +CRITIC_EXTRA_CHANNELS = 3 +MATCH_CRITIC_OBS_DIM = MATCH_OBS_DIM + N_CARDS * CRITIC_EXTRA_CHANNELS + + +def match_critic_observation(state: MatchState, player: jax.Array) -> jax.Array: + """The same view, plus the hidden state. Training only -- never played from. + + A value baseline may condition on anything the action does not depend on + without biasing the policy gradient, and the deal is exactly the noise that + swamps a match-terminal reward. So the critic gets the opponent's hand and + the deck *in order* -- it knows what is coming -- while the actor keeps the + masked view. The two run on separate trunks so none of this can leak into + the logits. + """ + + player = jnp.asarray(player, dtype=jnp.int32) + opponent = 1 - player + round_state = state.round + loc = round_state.card_loc.astype(jnp.int32) + + opp_hand = (loc == (LOC_P0_HAND + opponent)).astype(jnp.float32) + in_deck = (loc == LOC_DECK).astype(jnp.float32) + + # Position of each card in the undrawn deck, so the critic can see the order + # rather than just the multiset. + deck_order = round_state.deck_order.astype(jnp.int32) + position = ( + jnp.zeros((N_CARDS,), dtype=jnp.int32) + .at[deck_order] + .set(jnp.arange(N_CARDS, dtype=jnp.int32)) + ) + depth = (position - round_state.draw_ptr).astype(jnp.float32) / N_CARDS + deck_depth = jnp.where(in_deck > 0, depth, 0.0) + + hidden = jnp.stack([opp_hand, in_deck, deck_depth], axis=1).reshape((-1,)) + base = match_observation(state, player) + return jnp.concatenate([base, hidden], axis=0).reshape((MATCH_CRITIC_OBS_DIM,)) + + +__all__ = [ + "MATCH_CRITIC_OBS_DIM", + "MATCH_OBS_DIM", + "N_CARRY_BINS", + "match_critic_observation", + "match_observation", +] diff --git a/src/lost_cities_jax/match_ppo.py b/src/lost_cities_jax/match_ppo.py new file mode 100644 index 0000000..f7bd4d1 --- /dev/null +++ b/src/lost_cities_jax/match_ppo.py @@ -0,0 +1,480 @@ +"""PPO over three-round matches. + +Three things differ from the single-round trainer beyond the env swap: + +**Asymmetric actor-critic.** The critic never plays, so it is fed the hidden +state (opponent's hand, deck in order) while the actor keeps the masked view. A +state-value baseline may condition on anything action-independent without biasing +the policy gradient, and deal luck is exactly what makes a match-terminal reward +hard to learn from. The trunks are separate so the privileged features cannot +reach the logits. + +**Both seats train.** In self-play one network picks both players' moves, but the +single-round trainer stop_gradients the opponent seat and throws those plies away +-- half of every game. Here every ply emits a transition for both seats, each +with its own seat-relative view, value and reward; the actor mask keeps the +policy loss on the seat that actually moved, while the critic learns from both. +Folding the seat axis into the batch keeps each seat's GAE chain independent. + +**Reward is the match total, paid densely.** Each ply pays the points by which it +moved the running match difference; at gamma=1 that telescopes to the final total +difference, so the objective is exactly the rulebook's -- score more across the +three rounds. + +This used to be ``tanh(total / terminal_scale)`` at the end of round three, to +optimise P(win match) rather than expected total. That was over-engineered. The +two differ only in risk attitude, and risk attitude is worth almost nothing here: +a policy told to gamble when it trails by 20 going into round three *loses* to a +greedy clone over 6144 duplicate matches (0.482), and one that gambles only when +it trails by 40 breaks even (0.498). Lost Cities' variance levers -- a marginal +wager, a marginal expedition -- cost more expected margin than the convexity they +buy. Measured ceiling on the whole carry-conditioning idea: under one win-rate +point. The dense linear reward also gives credit assignment every ply instead of +one bounded number per ~160. + +``carry`` stays in the observation: it costs nothing, it is the state the +start-player rule keys off, and the critic reads it cleanly. +""" + +from __future__ import annotations + +import json +import time +from dataclasses import asdict, dataclass +from pathlib import Path +from typing import NamedTuple + +import flax.linen as nn +import jax +import jax.numpy as jnp +import optax + +from lost_cities_jax.match import ( + MatchState, + match_legal_action_mask, + match_reset, + match_score, + match_step, +) +from lost_cities_jax.match_obs import ( + MATCH_CRITIC_OBS_DIM, + MATCH_OBS_DIM, + match_critic_observation, + match_observation, +) +from lost_cities_jax.obs import observation +from lost_cities_jax.ppo import ( + EpisodeEnd, + JaxPPOConfig, + TrainState, + _append_jsonl, + _broadcast_done, + _create_run_dir, + _write_json, + action_log_prob, + categorical_entropy, + compute_gae, + mask_logits, + masked_mean, + restore_checkpoint, + save_checkpoint, + shaping_coefficient, +) +from lost_cities_jax.types import MAX_STEPS, N_ACTIONS, OBS_DIM, PLAY + +N_SEATS = 2 + + +@dataclass +class Ablation: + """Switches for measuring what each piece of the match stack is worth.""" + + privileged_critic: bool = True + """On: the critic also sees the opponent's hand and the deck in order. + + Its worth flips with scale, so do not trust a cheap ablation here. Ablated at + 39.3M learner actions, switching it OFF *won* 0.5160 [0.505, 0.527] -- the + obvious reading being that a critic fitting V(full state) rather than + E[return | masked obs] hands the actor advantage noise it cannot act on. But + head to head at 131M, both sides trained identically, OFF *loses*: 0.4633 + [0.453, 0.474]. The privileged critic earns its keep once there is enough data + to fit it. Defaults on for that reason, and the small-scale result is kept as + a warning about ablating at a budget you do not intend to ship. + """ + + both_seats: bool = True + """Off: the opponent seat's plies are discarded, as the old trainer did.""" + + match_obs: bool = True + """Off: the actor gets the plain single-round observation, carry and all the + rest of the match features withheld.""" + + def actor_obs_dim(self) -> int: + return MATCH_OBS_DIM if self.match_obs else OBS_DIM + + def critic_obs_dim(self) -> int: + if not self.privileged_critic: + return self.actor_obs_dim() + return MATCH_CRITIC_OBS_DIM + + def label(self) -> str: + parts = [] + if self.privileged_critic: + parts.append("privileged_critic") + if not self.both_seats: + parts.append("no-both_seats") + if not self.match_obs: + parts.append("no-match_obs") + return "default" if not parts else "+".join(parts) + + +FULL = Ablation() + + +class MatchTransition(NamedTuple): + obs: jax.Array + critic_obs: jax.Array + legal_mask: jax.Array + action: jax.Array + log_prob: jax.Array + value: jax.Array + reward: jax.Array + done: jax.Array + active: jax.Array + actor_mask: jax.Array + entropy: jax.Array + play_action: jax.Array + + +class MatchActorCritic(nn.Module): + """Separate trunks, so the critic's privileged input cannot reach the logits.""" + + hidden_size: int = 512 + num_layers: int = 3 + + @nn.compact + def __call__(self, obs: jax.Array, critic_obs: jax.Array) -> tuple[jax.Array, jax.Array]: + x = obs + for _ in range(self.num_layers): + x = nn.relu(nn.Dense(self.hidden_size)(x)) + logits = nn.Dense(N_ACTIONS)(x) + + v = critic_obs + for _ in range(self.num_layers): + v = nn.relu(nn.Dense(self.hidden_size)(v)) + value = nn.Dense(1)(v) + return logits, jnp.squeeze(value, axis=-1) + + +def create_match_train_state( + cfg: JaxPPOConfig, rng: jax.Array, ablation: Ablation = FULL +) -> TrainState: + model = MatchActorCritic(cfg.network.hidden_size, cfg.network.num_layers) + params = model.init( + rng, + jnp.zeros((1, ablation.actor_obs_dim()), dtype=jnp.float32), + jnp.zeros((1, ablation.critic_obs_dim()), dtype=jnp.float32), + ) + tx = optax.chain( + optax.clip_by_global_norm(cfg.ppo.max_grad_norm), + optax.adam(cfg.ppo.learning_rate), + ) + return TrainState.create(apply_fn=model.apply, params=params, tx=tx) + + +def match_lead(env: MatchState) -> jax.Array: + """Running match total from seat 0's side, in raw points.""" + totals = match_score(env) + return (totals[0] - totals[1]).astype(jnp.float32) + + +def reset_done_matches(env: MatchState, rng: jax.Array, batch: int) -> MatchState: + fresh = jax.vmap(match_reset)(jax.random.split(rng, batch)) + return jax.tree_util.tree_map( + lambda old, new: jnp.where(_broadcast_done(env.done, old), new, old), env, fresh + ) + + +def _seat_views(env: MatchState, seats: jax.Array, ablation: Ablation = FULL): + actor_fn = match_observation if ablation.match_obs else (lambda m, p: observation(m.round, p)) + obs = jax.vmap(lambda s: jax.vmap(actor_fn, in_axes=(0, None))(env, s))(seats) + if not ablation.privileged_critic: + return obs, obs + critic = jax.vmap(lambda s: jax.vmap(match_critic_observation, in_axes=(0, None))(env, s))( + seats + ) + return obs, critic + + +def _episode_end(env: MatchState, terminal: jax.Array, episode_return: jax.Array) -> EpisodeEnd: + lead = jax.vmap(match_lead)(env) + opened = jnp.sum(env.round.col_len[:, 0, :] > 0, axis=-1) + return EpisodeEnd( + done=terminal, + episode_return=episode_return, + length=env.round.step_count, + opened_colors=opened, + positive_expeditions=lead.astype(jnp.int32), # final match lead, in points + hit_max_steps=env.round.step_count >= MAX_STEPS, + ) + + +def match_episode_metrics(transitions: MatchTransition, episodes: EpisodeEnd) -> dict: + done = episodes.done.astype(jnp.float32) + completed = jnp.sum(done) + denom = jnp.maximum(completed, 1.0) + actor_count = jnp.sum(transitions.actor_mask) + lead = episodes.positive_expeditions.astype(jnp.float32) + return { + "return_mean": jnp.sum(episodes.episode_return * done) / denom, + "match_lead_mean": jnp.sum(lead * done) / denom, + "match_win_rate": jnp.sum((lead > 0).astype(jnp.float32) * done) / denom, + "final_round_length_mean": jnp.sum(episodes.length.astype(jnp.float32) * done) / denom, + "max_steps_rate": jnp.sum(episodes.hit_max_steps.astype(jnp.float32) * done) / denom, + "play_action_rate": jnp.sum(transitions.play_action) / jnp.maximum(actor_count, 1), + "entropy_mean": masked_mean( + transitions.entropy, transitions.actor_mask.astype(jnp.float32) + ), + "learner_actions": actor_count, + "matches_completed": completed, + } + + +def make_match_rollout_fn(cfg: JaxPPOConfig, ablation: Ablation = FULL): + batch = cfg.ppo.batch_games + seats = jnp.arange(N_SEATS, dtype=jnp.int32) + + @jax.jit + def rollout_fn(state: TrainState, env: MatchState, rng: jax.Array, shaping_coef: jax.Array): + def body(carry, _): + env, episode_return, key = carry + key, act_key, reset_key = jax.random.split(key, 3) + + obs, critic_obs = _seat_views(env, seats, ablation) + legal = jax.vmap(match_legal_action_mask)(env) + legal_both = jnp.broadcast_to(legal, (N_SEATS, batch, N_ACTIONS)) + + logits, value = state.apply_fn(state.params, obs, critic_obs) + masked = mask_logits(logits, legal_both) + sampled = jax.random.categorical(act_key, masked, axis=-1).astype(jnp.int32) + log_prob = jax.vmap(action_log_prob)(masked, sampled) + entropy = jax.vmap(categorical_entropy)(masked) + + to_move = env.round.to_move.astype(jnp.int32) + active = ~env.done + actor_mask = (seats[:, None] == to_move[None, :]) & active[None, :] + if not ablation.both_seats: + # The old trainer kept one seat and stop_gradiented the other. + keep = (seats[:, None] == 0) & jnp.ones_like(active)[None, :] + actor_mask = actor_mask & keep + actions = jnp.take_along_axis(sampled, to_move[None, :], axis=0)[0] + + before = jax.vmap(match_lead)(env) + next_env, _, _ = jax.vmap(match_step, in_axes=(0, 0))(env, actions) + after = jax.vmap(match_lead)(next_env) + + done = next_env.done + terminal = active & done + # Every ply pays the points by which it moved the match total. At + # gamma=1 that telescopes to the final total difference, so the + # objective is exactly "score more across the three rounds" -- just + # handed out densely instead of once, 150 plies later. + reward0 = jnp.where(active, (after - before) / cfg.reward.terminal_scale, 0.0) + # Zero-sum: seat 1 sees exactly the negation. + reward = jnp.stack([reward0, -reward0], axis=0) + + played = ((actions % 12) // 6 == PLAY)[None, :] & actor_mask + transition = MatchTransition( + obs=obs, + critic_obs=critic_obs, + legal_mask=legal_both, + action=jnp.broadcast_to(actions, (N_SEATS, batch)), + log_prob=log_prob, + value=value, + reward=reward, + done=jnp.broadcast_to(done, (N_SEATS, batch)), + active=( + jnp.broadcast_to(active, (N_SEATS, batch)) + if ablation.both_seats + else jnp.broadcast_to(active, (N_SEATS, batch)) & (seats[:, None] == 0) + ), + actor_mask=actor_mask, + entropy=entropy, + play_action=played, + ) + + episode_return = episode_return + reward0 + episode = _episode_end(next_env, terminal, episode_return) + next_env = reset_done_matches(next_env, reset_key, batch) + episode_return = jnp.where(done, 0.0, episode_return) + return (next_env, episode_return, key), (transition, episode) + + init_return = jnp.zeros((batch,), dtype=jnp.float32) + (next_env, _, rng), (transitions, episodes) = jax.lax.scan( + body, (env, init_return, rng), xs=None, length=cfg.ppo.rollout_steps + ) + + # Fold the seat axis into the batch: each column is then an independent + # episode chain, which is exactly what GAE wants. + transitions = jax.tree_util.tree_map( + lambda x: x.reshape((x.shape[0], N_SEATS * batch, *x.shape[3:])), transitions + ) + final_obs, final_critic = _seat_views(next_env, seats, ablation) + _, last_value = state.apply_fn(state.params, final_obs, final_critic) + last_value = last_value.reshape((N_SEATS * batch,)) + + return next_env, transitions, last_value, match_episode_metrics(transitions, episodes) + + return rollout_fn + + +def match_ppo_update( + state: TrainState, + transitions: MatchTransition, + advantages: jax.Array, + returns: jax.Array, + rng: jax.Array, + cfg: JaxPPOConfig, +) -> tuple[TrainState, dict[str, jax.Array]]: + batch_size = int(transitions.reward.size) + minibatch_size = batch_size // cfg.ppo.minibatches + flat = jax.tree_util.tree_map(lambda x: x.reshape((-1, *x.shape[2:])), transitions) + flat_advantages = advantages.reshape((batch_size,)) + flat_returns = returns.reshape((batch_size,)) + + actor_mask = flat.actor_mask.astype(jnp.float32) + adv_mean = masked_mean(flat_advantages, actor_mask) + adv_std = jnp.sqrt(masked_mean((flat_advantages - adv_mean) ** 2, actor_mask) + 1.0e-8) + flat_advantages = (flat_advantages - adv_mean) / adv_std + + def loss_fn(params, mb, mb_adv, mb_returns): + logits, value = state.apply_fn(params, mb.obs, mb.critic_obs) + masked_logits = mask_logits(logits, mb.legal_mask) + log_prob = action_log_prob(masked_logits, mb.action) + entropy = categorical_entropy(masked_logits) + ratio = jnp.exp(log_prob - mb.log_prob) + actor_weight = mb.actor_mask.astype(jnp.float32) + active_weight = mb.active.astype(jnp.float32) + unclipped = ratio * mb_adv + clipped = jnp.clip(ratio, 1.0 - cfg.ppo.clip_epsilon, 1.0 + cfg.ppo.clip_epsilon) * mb_adv + actor_loss = -masked_mean(jnp.minimum(unclipped, clipped), actor_weight) + value_loss = masked_mean((mb_returns - value) ** 2, active_weight) + entropy_loss = masked_mean(entropy, actor_weight) + loss = actor_loss + cfg.ppo.value_coef * value_loss - cfg.ppo.entropy_coef * entropy_loss + return loss, { + "loss": loss, + "actor_loss": actor_loss, + "value_loss": value_loss, + "entropy_loss": entropy_loss, + "approx_kl": masked_mean(mb.log_prob - log_prob, actor_weight), + } + + def epoch_update(carry, key): + train_state = carry + permutation = jax.random.permutation(key, batch_size) + + def minibatch_update(carry, idx): + train_state, accum = carry + mb_idx = jax.lax.dynamic_slice(permutation, (idx * minibatch_size,), (minibatch_size,)) + mb = jax.tree_util.tree_map(lambda x: x[mb_idx], flat) + (_, metrics), grads = jax.value_and_grad(loss_fn, has_aux=True)( + train_state.params, mb, flat_advantages[mb_idx], flat_returns[mb_idx] + ) + train_state = train_state.apply_gradients(grads=grads) + accum = jax.tree_util.tree_map(lambda a, b: a + b, accum, metrics) + return (train_state, accum), None + + zeros = { + key: jnp.array(0.0) + for key in ("loss", "actor_loss", "value_loss", "entropy_loss", "approx_kl") + } + (train_state, metrics), _ = jax.lax.scan( + minibatch_update, (train_state, zeros), jnp.arange(cfg.ppo.minibatches) + ) + metrics = jax.tree_util.tree_map(lambda x: x / cfg.ppo.minibatches, metrics) + return train_state, metrics + + keys = jax.random.split(rng, cfg.ppo.epochs) + state, metrics = jax.lax.scan(epoch_update, state, keys) + return state, jax.tree_util.tree_map(lambda x: jnp.mean(x, axis=0), metrics) + + +def make_match_train_iteration(cfg: JaxPPOConfig, ablation: Ablation = FULL): + rollout_fn = make_match_rollout_fn(cfg, ablation) + + @jax.jit + def train_iteration( + state: TrainState, env: MatchState, rng: jax.Array, shaping_coef: jax.Array + ): + rng, rollout_key, update_key = jax.random.split(rng, 3) + env, transitions, last_value, stats = rollout_fn(state, env, rollout_key, shaping_coef) + advantages, returns = compute_gae( + transitions.reward, + transitions.value, + transitions.done, + cfg.ppo.gamma, + cfg.ppo.gae_lambda, + last_value, + ) + state, update_metrics = match_ppo_update( + state, transitions, advantages, returns, update_key, cfg + ) + return state, env, rng, {**stats, **update_metrics} + + return train_iteration + + +def match_train(cfg: JaxPPOConfig, *, resume: str | None = None, ablation: Ablation = FULL) -> Path: + run_dir = _create_run_dir(cfg) + _write_json(run_dir / "config.json", asdict(cfg)) + metrics_path = run_dir / "metrics.jsonl" + + rng = jax.random.PRNGKey(cfg.run.seed) + rng, init_key, reset_key = jax.random.split(rng, 3) + state = create_match_train_state(cfg, init_key, ablation) + if resume: + state = restore_checkpoint(Path(resume), state) + + env = jax.jit(jax.vmap(match_reset))(jax.random.split(reset_key, cfg.ppo.batch_games)) + train_iteration = make_match_train_iteration(cfg, ablation) + + start = time.perf_counter() + learner_actions_seen = 0 + for update in range(cfg.run.total_updates): + shaping_coef = jnp.asarray(shaping_coefficient(cfg, learner_actions_seen), jnp.float32) + iter_start = time.perf_counter() + state, env, rng, metrics = train_iteration(state, env, rng, shaping_coef) + jax.tree_util.tree_leaves(metrics)[0].block_until_ready() + + row = { + key: float(value) if getattr(value, "shape", ()) == () else value.tolist() + for key, value in metrics.items() + } + learner_actions_seen += int(row["learner_actions"]) + row.update( + update=update, + shaping_coef=float(shaping_coef), + learner_actions_total=learner_actions_seen, + iteration_seconds=time.perf_counter() - iter_start, + elapsed_seconds=time.perf_counter() - start, + ) + _append_jsonl(metrics_path, row) + if update % cfg.run.log_every == 0: + print( + json.dumps( + { + "update": update, + "match_win_rate": row["match_win_rate"], + "match_lead_mean": row["match_lead_mean"], + "matches_completed": row["matches_completed"], + "entropy_mean": row["entropy_mean"], + }, + sort_keys=True, + ), + flush=True, + ) + if cfg.run.checkpoint_every and (update + 1) % cfg.run.checkpoint_every == 0: + save_checkpoint(run_dir / "latest", state, cfg) + + save_checkpoint(run_dir / "latest", state, cfg) + return run_dir diff --git a/src/lost_cities_jax/ppo.py b/src/lost_cities_jax/ppo.py index 0f9266c..305a694 100644 --- a/src/lost_cities_jax/ppo.py +++ b/src/lost_cities_jax/ppo.py @@ -77,6 +77,14 @@ class PPOHyperConfig: @dataclass class RewardConfig: + """Terminal reward plus potential-based shaping on the score difference. + + ``potential_shaping_anneal_steps`` counts **learner actions**, not scan + steps. It used to be fed padded scan steps, which made a 5M-step anneal + expire inside the first two updates; any earlier conclusion that shaping + does not help was drawn with shaping effectively off. + """ + terminal_scale: float = 50.0 potential_shaping_initial: float = 1.0 potential_shaping_final: float = 0.0 @@ -134,6 +142,23 @@ class Transition(NamedTuple): play_action: jax.Array +class EpisodeEnd(NamedTuple): + """Per-step episode-completion records emitted by the rollout scan. + + With in-scan auto-reset an env slot hosts several episodes per rollout, so + ``final_env`` is mid-episode and summing rewards over the scan axis mixes + episodes. Every field here is masked by ``done``: read it only where + ``done`` is set. + """ + + done: jax.Array + episode_return: jax.Array + length: jax.Array + opened_colors: jax.Array + positive_expeditions: jax.Array + hit_max_steps: jax.Array + + class EvalBatch(NamedTuple): wins: jax.Array losses: jax.Array @@ -218,14 +243,20 @@ def train( train_iteration = make_train_iteration(cfg, opponent_policy) start = time.perf_counter() + # Anneal against learner actions taken, not scan steps issued: most scan + # steps used to be spent stepping already-done envs, which made the anneal + # finish within the first couple of updates. The count lags by one update + # because it comes back as a device metric. + learner_actions_seen = 0 + for update in range(cfg.run.total_updates): - shaping_coef = shaping_coefficient( - cfg, update * cfg.ppo.batch_games * cfg.ppo.rollout_steps - ) + shaping_coef = shaping_coefficient(cfg, learner_actions_seen) iter_start = time.perf_counter() state, env_state, rng, metrics = train_iteration(state, env_state, rng, shaping_coef) jax.tree_util.tree_leaves(metrics)[0].block_until_ready() row = _metrics_to_row(metrics, update, shaping_coef, cfg) + learner_actions_seen += int(row["learner_actions"]) + row["learner_actions_total"] = learner_actions_seen row["iteration_seconds"] = time.perf_counter() - iter_start row["elapsed_seconds"] = time.perf_counter() - start _append_jsonl(metrics_path, row) @@ -260,8 +291,10 @@ def make_train_iteration(cfg: JaxPPOConfig, opponent_policy): def train_iteration( state: TrainState, env_state: State, rng: jax.Array, shaping_coef: jax.Array ): - rng, rollout_key, update_key, reset_key = jax.random.split(rng, 4) - env_state, transitions, rollout_metrics = rollout_fn( + rng, rollout_key, update_key = jax.random.split(rng, 3) + # The rollout resets finished envs in-scan, so env_state never comes + # back done and needs no reset here. + env_state, transitions, last_value, rollout_stats = rollout_fn( state, env_state, rollout_key, shaping_coef ) advantages, returns = compute_gae( @@ -270,10 +303,10 @@ def make_train_iteration(cfg: JaxPPOConfig, opponent_policy): transitions.done, cfg.ppo.gamma, cfg.ppo.gae_lambda, + last_value, ) state, update_metrics = ppo_update(state, transitions, advantages, returns, update_key, cfg) - env_state = reset_done_envs(env_state, reset_key, cfg.ppo.batch_games) - return state, env_state, rng, {**rollout_metrics, **update_metrics} + return state, env_state, rng, {**rollout_stats, **update_metrics} return train_iteration @@ -299,8 +332,10 @@ def make_league_train_iteration( rng: jax.Array, shaping_coef: jax.Array, ): - rng, rollout_key, update_key, reset_key = jax.random.split(rng, 4) - env_state, transitions, rollout_metrics = rollout_fn( + rng, rollout_key, update_key = jax.random.split(rng, 3) + # The rollout resets finished envs and redraws their league assignments + # in-scan, so neither needs to be refreshed here. + env_state, assignments, transitions, last_value, rollout_stats = rollout_fn( state, env_state, assignments, rollout_key, shaping_coef ) advantages, returns = compute_gae( @@ -309,17 +344,10 @@ def make_league_train_iteration( transitions.done, cfg.ppo.gamma, cfg.ppo.gae_lambda, + last_value, ) state, update_metrics = ppo_update(state, transitions, advantages, returns, update_key, cfg) - env_state, assignments = reset_done_envs_with_assignments( - env_state, - assignments, - reset_key, - cfg.ppo.batch_games, - opponent_probs, - mirror_probability, - ) - return state, env_state, assignments, rng, {**rollout_metrics, **update_metrics} + return state, env_state, assignments, rng, {**rollout_stats, **update_metrics} return train_iteration @@ -328,11 +356,13 @@ def make_rollout_fn(cfg: JaxPPOConfig, opponent_policy): learner = jnp.asarray(cfg.run.learner_seat, dtype=jnp.int32) opponent = jnp.asarray(1 - cfg.run.learner_seat, dtype=jnp.int32) + learners = jnp.full((cfg.ppo.batch_games,), cfg.run.learner_seat, dtype=jnp.int32) + @jax.jit def rollout_fn(state: TrainState, env_state: State, rng: jax.Array, shaping_coef: jax.Array): def body(carry, _): - env, key = carry - key, learner_key, opponent_key = jax.random.split(key, 3) + env, episode_return, key = carry + key, learner_key, opponent_key, reset_key = jax.random.split(key, 4) obs = jax.vmap(observation, in_axes=(0, None))(env, learner) legal = jax.vmap(legal_action_mask)(env) logits, value = state.apply_fn(state.params, obs) @@ -355,7 +385,8 @@ def make_rollout_fn(cfg: JaxPPOConfig, opponent_policy): next_env, _, _ = jax.vmap(step, in_axes=(0, 0))(env, actions) after_diff = batch_score_diff(next_env, learner) terminal_reward = jnp.tanh(after_diff / cfg.reward.terminal_scale) - terminal = active & next_env.done + done = next_env.done + terminal = active & done reward = jnp.where(terminal, terminal_reward, 0.0) reward = reward + shaping_coef * (after_diff - before_diff) reward = jnp.where(active, reward, 0.0) @@ -369,19 +400,27 @@ def make_rollout_fn(cfg: JaxPPOConfig, opponent_policy): log_prob=log_prob, value=value, reward=reward, - done=next_env.done, + done=done, active=active, actor_mask=actor_mask, entropy=entropy, play_action=(place_type == PLAY) & actor_mask, ) - return (next_env, key), transition - (next_env, rng), transitions = jax.lax.scan( - body, (env_state, rng), xs=None, length=cfg.ppo.rollout_steps + episode_return = episode_return + reward + episode = _episode_end(next_env, learners, terminal, episode_return) + next_env = reset_done_envs(next_env, reset_key, cfg.ppo.batch_games) + episode_return = jnp.where(done, 0.0, episode_return) + return (next_env, episode_return, key), (transition, episode) + + init_return = jnp.zeros((cfg.ppo.batch_games,), dtype=jnp.float32) + (next_env, _, rng), (transitions, episodes) = jax.lax.scan( + body, (env_state, init_return, rng), xs=None, length=cfg.ppo.rollout_steps ) - metrics = rollout_metrics(transitions, next_env, learner) - return next_env, transitions, metrics + final_obs = jax.vmap(observation, in_axes=(0, None))(next_env, learner) + _, last_value = state.apply_fn(state.params, final_obs) + metrics = episode_metrics(transitions, episodes) + return next_env, transitions, last_value, metrics return rollout_fn @@ -405,8 +444,8 @@ def make_league_rollout_fn( shaping_coef: jax.Array, ): def body(carry, _): - env, key = carry - key, learner_key, mirror_key, pool_key = jax.random.split(key, 4) + env, assignments, episode_return, key = carry + key, learner_key, mirror_key, pool_key, reset_key = jax.random.split(key, 5) learner = assignments.learner_seat.astype(jnp.int32) opponent = 1 - learner @@ -449,7 +488,8 @@ def make_league_rollout_fn( next_env, _, _ = jax.vmap(step, in_axes=(0, 0))(env, actions) after_diff = batch_score_diff_for_players(next_env, learner) terminal_reward = jnp.tanh(after_diff / cfg.reward.terminal_scale) - terminal = active & next_env.done + done = next_env.done + terminal = active & done reward = jnp.where(terminal, terminal_reward, 0.0) reward = reward + shaping_coef * (after_diff - before_diff) reward = jnp.where(active, reward, 0.0) @@ -463,19 +503,37 @@ def make_league_rollout_fn( log_prob=log_prob, value=value, reward=reward, - done=next_env.done, + done=done, active=active, actor_mask=actor_mask, entropy=entropy, play_action=(place_type == PLAY) & actor_mask, ) - return (next_env, key), transition - (next_env, rng), transitions = jax.lax.scan( - body, (env_state, rng), xs=None, length=cfg.ppo.rollout_steps + episode_return = episode_return + reward + # Scored against the seat that just played the episode out, not the + # freshly drawn one. + episode = _episode_end(next_env, learner, terminal, episode_return) + next_env, assignments = reset_done_envs_with_assignments( + next_env, + assignments, + reset_key, + cfg.ppo.batch_games, + opponent_probs, + mirror_probability, + ) + episode_return = jnp.where(done, 0.0, episode_return) + return (next_env, assignments, episode_return, key), (transition, episode) + + init_return = jnp.zeros((cfg.ppo.batch_games,), dtype=jnp.float32) + (next_env, assignments, _, rng), (transitions, episodes) = jax.lax.scan( + body, (env_state, assignments, init_return, rng), xs=None, length=cfg.ppo.rollout_steps ) - metrics = rollout_metrics_for_players(transitions, next_env, assignments.learner_seat) - return next_env, transitions, metrics + final_learner = assignments.learner_seat.astype(jnp.int32) + final_obs = jax.vmap(observation, in_axes=(0, 0))(next_env, final_learner) + _, last_value = state.apply_fn(state.params, final_obs) + metrics = episode_metrics(transitions, episodes) + return next_env, assignments, transitions, last_value, metrics return rollout_fn @@ -487,11 +545,12 @@ def random_rollout(cfg: JaxPPOConfig) -> dict: env_state = jax.jit(jax.vmap(reset))(jax.random.split(reset_key, cfg.ppo.batch_games)) learner = jnp.asarray(cfg.run.learner_seat, dtype=jnp.int32) opponent = jnp.asarray(1 - cfg.run.learner_seat, dtype=jnp.int32) + learners = jnp.full((cfg.ppo.batch_games,), cfg.run.learner_seat, dtype=jnp.int32) @jax.jit def rollout(env_state: State, rng: jax.Array): def body(carry, _): - env, key = carry + env, episode_return, key = carry key, learner_key, opponent_key = jax.random.split(key, 3) learner_keys = jax.random.split(learner_key, cfg.ppo.batch_games) opponent_keys = jax.random.split(opponent_key, cfg.ppo.batch_games) @@ -508,6 +567,7 @@ def random_rollout(cfg: JaxPPOConfig) -> dict: next_env, _, _ = jax.vmap(step, in_axes=(0, 0))(env, actions) after_diff = batch_score_diff(next_env, learner) reward = jnp.where(active, after_diff - before_diff, 0.0) + terminal = active & next_env.done actor_mask = active & learner_turn place_type = (actions % 12) // 6 dummy_obs = jnp.zeros((cfg.ppo.batch_games, OBS_DIM), dtype=jnp.float32) @@ -525,12 +585,15 @@ def random_rollout(cfg: JaxPPOConfig) -> dict: entropy=jnp.zeros((cfg.ppo.batch_games,), dtype=jnp.float32), play_action=(place_type == PLAY) & actor_mask, ) - return (next_env, key), transition + episode_return = episode_return + reward + episode = _episode_end(next_env, learners, terminal, episode_return) + return (next_env, episode_return, key), (transition, episode) - (next_env, rng), transitions = jax.lax.scan( - body, (env_state, rng), xs=None, length=cfg.ppo.rollout_steps + init_return = jnp.zeros((cfg.ppo.batch_games,), dtype=jnp.float32) + (next_env, _, rng), (transitions, episodes) = jax.lax.scan( + body, (env_state, init_return, rng), xs=None, length=cfg.ppo.rollout_steps ) - return rng, rollout_metrics(transitions, next_env, learner) + return rng, episode_metrics(transitions, episodes) rng, metrics = rollout(env_state, rng) jax.tree_util.tree_leaves(metrics)[0].block_until_ready() @@ -679,7 +742,18 @@ def compute_gae( dones: jax.Array, gamma: float, gae_lambda: float, + last_value: jax.Array | None = None, ) -> tuple[jax.Array, jax.Array]: + """GAE over a rollout that may end mid-episode. + + ``last_value`` is V(s_T) for the state the scan stopped on. Episodes that + are cut by the rollout boundary bootstrap from it; leaving it at zero would + tell the critic every truncated episode is worth nothing. + """ + + if last_value is None: + last_value = jnp.zeros_like(values[-1]) + def body(carry, x): next_value, next_advantage = carry reward, value, done = x @@ -688,7 +762,7 @@ def compute_gae( advantage = delta + gamma * gae_lambda * nonterminal * next_advantage return (value, advantage), advantage - init = (jnp.zeros_like(values[-1]), jnp.zeros_like(values[-1])) + init = (last_value, jnp.zeros_like(values[-1])) _, advantages_rev = jax.lax.scan(body, init, (rewards[::-1], values[::-1], dones[::-1])) advantages = advantages_rev[::-1] return advantages, advantages + values @@ -1066,56 +1140,60 @@ def make_policy_match_batch_fn(learner_policy, opponent_policy): return eval_batch -def rollout_metrics( - transitions: Transition, final_env: State, learner: jax.Array -) -> dict[str, jax.Array]: - episode_return = jnp.sum(transitions.reward, axis=0) +def _episode_end( + next_env: State, + learners: jax.Array, + done: jax.Array, + episode_return: jax.Array, +) -> EpisodeEnd: + """Snapshot the finished-episode stats of ``next_env`` before it is reset.""" + + learners = jnp.broadcast_to(learners.astype(jnp.int32), done.shape) + color_scores = jax.vmap(color_scores_for_player, in_axes=(0, 0))(next_env, learners) + batch_idx = jnp.arange(done.shape[0]) + return EpisodeEnd( + done=done, + episode_return=episode_return, + length=next_env.step_count, + opened_colors=jnp.sum(next_env.col_len[batch_idx, learners, :] > 0, axis=-1), + positive_expeditions=jnp.sum(color_scores > 0, axis=-1), + hit_max_steps=next_env.step_count >= MAX_STEPS, + ) + + +def episode_metrics(transitions: Transition, episodes: EpisodeEnd) -> dict[str, jax.Array]: + """Aggregate over episodes that actually finished inside the rollout. + + Averaging over ``final_env`` instead would sample envs mid-episode, and + summing rewards along the scan axis would add up several episodes per slot. + """ + + done = episodes.done.astype(jnp.float32) + completed = jnp.sum(done) + denom = jnp.maximum(completed, 1.0) actor_count = jnp.sum(transitions.actor_mask) - active_count = jnp.sum(transitions.active) - color_scores = jax.vmap(color_scores_for_player, in_axes=(0, None))(final_env, learner) - opened = jnp.sum(final_env.col_len[:, learner, :] > 0, axis=-1) - positive = jnp.sum(color_scores > 0, axis=-1) + + returns = episodes.episode_return + return_mean = jnp.sum(returns * done) / denom + return_var = jnp.sum(((returns - return_mean) ** 2) * done) / denom + return { - "return_mean": jnp.mean(episode_return), - "return_std": jnp.std(episode_return), - "game_length_mean": jnp.mean(final_env.step_count.astype(jnp.float32)), - "game_length_max": jnp.max(final_env.step_count), - "max_steps_rate": jnp.mean(final_env.step_count >= MAX_STEPS), + "return_mean": return_mean, + "return_std": jnp.sqrt(jnp.maximum(return_var, 0.0)), + "game_length_mean": jnp.sum(episodes.length.astype(jnp.float32) * done) / denom, + "game_length_max": jnp.max(jnp.where(episodes.done, episodes.length, 0)), + "max_steps_rate": jnp.sum(episodes.hit_max_steps.astype(jnp.float32) * done) / denom, "play_action_rate": jnp.sum(transitions.play_action) / jnp.maximum(actor_count, 1), - "opened_colors_mean": jnp.mean(opened.astype(jnp.float32)), - "positive_expeditions_mean": jnp.mean(positive.astype(jnp.float32)), + "opened_colors_mean": jnp.sum(episodes.opened_colors.astype(jnp.float32) * done) / denom, + "positive_expeditions_mean": ( + jnp.sum(episodes.positive_expeditions.astype(jnp.float32) * done) / denom + ), "entropy_mean": masked_mean( transitions.entropy, transitions.actor_mask.astype(jnp.float32) ), - "active_steps": active_count, - "learner_actions": actor_count, - } - - -def rollout_metrics_for_players( - transitions: Transition, final_env: State, learners: jax.Array -) -> dict[str, jax.Array]: - episode_return = jnp.sum(transitions.reward, axis=0) - actor_count = jnp.sum(transitions.actor_mask) - active_count = jnp.sum(transitions.active) - color_scores = jax.vmap(color_scores_for_player, in_axes=(0, 0))(final_env, learners) - batch_idx = jnp.arange(learners.shape[0]) - opened = jnp.sum(final_env.col_len[batch_idx, learners.astype(jnp.int32), :] > 0, axis=-1) - positive = jnp.sum(color_scores > 0, axis=-1) - return { - "return_mean": jnp.mean(episode_return), - "return_std": jnp.std(episode_return), - "game_length_mean": jnp.mean(final_env.step_count.astype(jnp.float32)), - "game_length_max": jnp.max(final_env.step_count), - "max_steps_rate": jnp.mean(final_env.step_count >= MAX_STEPS), - "play_action_rate": jnp.sum(transitions.play_action) / jnp.maximum(actor_count, 1), - "opened_colors_mean": jnp.mean(opened.astype(jnp.float32)), - "positive_expeditions_mean": jnp.mean(positive.astype(jnp.float32)), - "entropy_mean": masked_mean( - transitions.entropy, transitions.actor_mask.astype(jnp.float32) - ), - "active_steps": active_count, + "active_steps": jnp.sum(transitions.active), "learner_actions": actor_count, + "episodes_completed": completed, } @@ -1179,11 +1257,11 @@ def _flatten_transitions(transitions: Transition) -> Transition: return jax.tree_util.tree_map(lambda x: x.reshape((-1, *x.shape[2:])), transitions) -def shaping_coefficient(cfg: JaxPPOConfig, env_steps: int) -> float: +def shaping_coefficient(cfg: JaxPPOConfig, learner_actions: int) -> float: reward_cfg = cfg.reward if reward_cfg.potential_shaping_anneal_steps <= 0: return reward_cfg.potential_shaping_final - progress = min(env_steps / reward_cfg.potential_shaping_anneal_steps, 1.0) + progress = min(learner_actions / reward_cfg.potential_shaping_anneal_steps, 1.0) return reward_cfg.potential_shaping_initial + progress * ( reward_cfg.potential_shaping_final - reward_cfg.potential_shaping_initial ) diff --git a/tests/lost_cities_jax/test_match.py b/tests/lost_cities_jax/test_match.py new file mode 100644 index 0000000..b704c38 --- /dev/null +++ b/tests/lost_cities_jax/test_match.py @@ -0,0 +1,179 @@ +"""Phase 1: the classic three-round match layer.""" + +import jax +import jax.numpy as jnp +import numpy as np +import pytest + +from lost_cities_jax.engine import board_score +from lost_cities_jax.match import ( + N_ROUNDS, + MatchState, + match_legal_action_mask, + match_reset, + match_reset_from, + match_score, + match_step, + starting_player, +) +from lost_cities_jax.opponents import random_legal_action +from lost_cities_jax.types import DECK_DRAWS, DRAW_DECK, N_CARDS + +MATCH_STEP_CAP = 1400 # 3 rounds x the engine's 400-ply safety cap, with slack + + +def _decks(seed: int) -> jnp.ndarray: + rng = np.random.default_rng(seed) + return jnp.asarray( + np.stack([rng.permutation(N_CARDS) for _ in range(N_ROUNDS)]), dtype=jnp.int8 + ) + + +def _play_match(state: MatchState, key: jax.Array): + """Drive a match to completion with random legal play, recording each ply.""" + plies = [] + while not bool(state.done): + key, step_key = jax.random.split(key) + action = random_legal_action(state.round, state.round.to_move, step_key) + assert bool(match_legal_action_mask(state)[action]) + prev = state + state, reward, _ = match_step(state, action) + plies.append((prev, int(action), state, np.asarray(reward))) + assert len(plies) < MATCH_STEP_CAP, "match failed to terminate" + return state, plies + + +# --- match structure ------------------------------------------------------- + + +def test_match_plays_exactly_three_rounds_and_then_ends(): + state = match_reset(jax.random.PRNGKey(0)) + final, plies = _play_match(state, jax.random.PRNGKey(1)) + + assert bool(final.done) + assert int(final.round_idx) == N_ROUNDS - 1 + # round_idx advances 0 -> 1 -> 2 and stops. + seen = {int(before.round_idx) for before, _, _, _ in plies} + assert seen == {0, 1, 2} + + +def test_reward_is_paid_only_when_the_third_round_ends(): + state = match_reset(jax.random.PRNGKey(2)) + final, plies = _play_match(state, jax.random.PRNGKey(3)) + + rewards = np.stack([reward for _, _, _, reward in plies]) + paid = np.flatnonzero(np.any(rewards != 0.0, axis=1)) + # Intermediate rounds bank points into carry but pay nothing. + assert paid.tolist() == [len(plies) - 1] + assert np.allclose(rewards[-1], np.asarray(match_score(final), dtype=np.float32)) + + +def test_each_round_runs_44_deck_draws_plus_one_ply_per_discard_draw(): + """The deck clock: only deck draws end a round, so discard draws extend it.""" + state = match_reset(jax.random.PRNGKey(4)) + _, plies = _play_match(state, jax.random.PRNGKey(5)) + + per_round: dict[int, list[int]] = {0: [], 1: [], 2: []} + for before, action, _, _ in plies: + per_round[int(before.round_idx)].append(action % 6) + + for round_idx, draws in per_round.items(): + deck_draws = sum(1 for src in draws if src == DRAW_DECK) + discard_draws = len(draws) - deck_draws + assert deck_draws == DECK_DRAWS, f"round {round_idx} drew {deck_draws} deck cards" + assert len(draws) == DECK_DRAWS + discard_draws + + +# --- carry ----------------------------------------------------------------- + + +def test_carry_banks_each_finished_round_exactly_once(): + state = match_reset(jax.random.PRNGKey(6)) + final, plies = _play_match(state, jax.random.PRNGKey(7)) + + deltas = [ + np.asarray(after.carry) - np.asarray(before.carry) + for before, _, after, _ in plies + if int(after.round_idx) != int(before.round_idx) + ] + + # Two roll-overs for three rounds, and carry is exactly their sum. + assert len(deltas) == N_ROUNDS - 1 + assert np.array_equal(np.asarray(final.carry), sum(deltas)) + + # The third round is still on the board, not yet banked. + board = np.asarray(board_score(final.round)).astype(np.int32) + assert np.array_equal(np.asarray(match_score(final)), np.asarray(final.carry) + board) + + +def test_match_score_does_not_jump_across_a_round_boundary(): + """Phi = carry + board diff must be continuous, or PBRS gets a free kick.""" + state = match_reset(jax.random.PRNGKey(8)) + _, plies = _play_match(state, jax.random.PRNGKey(9)) + + for before, _, after, _ in plies: + rolled_over = int(after.round_idx) != int(before.round_idx) + if not rolled_over: + continue + # The finished round's board is folded into carry and the new board is + # empty, so the running total is unchanged by the roll-over itself. + assert np.array_equal(np.asarray(after.carry), np.asarray(match_score(after))) + assert int(np.asarray(board_score(after.round)).sum()) == 0 + + +# --- the start-player rule ------------------------------------------------- + + +@pytest.mark.parametrize( + ("carry", "coin", "expected"), + [ + ((60, 10), 1, 0), # p0 ahead -> p0 leads, coin ignored + ((10, 60), 0, 1), # p1 ahead -> p1 leads, coin ignored + ((30, 30), 0, 0), # level -> coin + ((30, 30), 1, 1), # level -> coin + ], +) +def test_the_player_with_more_points_begins(carry, coin, expected): + coin_flips = jnp.asarray([coin, coin, coin], dtype=jnp.int8) + starter = starting_player(jnp.asarray(carry, dtype=jnp.int32), jnp.int32(1), coin_flips) + assert int(starter) == expected + + +def test_round_two_is_actually_led_by_whoever_is_ahead(): + state = match_reset(jax.random.PRNGKey(10)) + _, plies = _play_match(state, jax.random.PRNGKey(11)) + + for before, _, after, _ in plies: + if int(after.round_idx) == int(before.round_idx): + continue + carry = np.asarray(after.carry) + if carry[0] == carry[1]: + continue # coin flip, covered above + leader = 0 if carry[0] > carry[1] else 1 + assert int(after.round.to_move) == leader + + +def test_round_one_start_player_is_a_fair_coin(): + starts = [int(match_reset(jax.random.PRNGKey(seed)).round.to_move) for seed in range(400)] + share = sum(starts) / len(starts) + assert 0.4 < share < 0.6, f"round-1 starter is skewed: {share:.2f}" + + +# --- mirrored matches ------------------------------------------------------ + + +def test_mirroring_the_seats_negates_the_match_score(): + """Same deals, same coins, seats swapped: the result must flip sign exactly.""" + decks = _decks(21) + coins = jnp.asarray([0, 1, 0], dtype=jnp.int8) + + # Swapping seats == swapping the two dealt hands and the coin bits. + swapped = decks.at[:, :16].set(jnp.concatenate([decks[:, 8:16], decks[:, :8]], axis=1)) + flipped_coins = (1 - coins).astype(jnp.int8) + + a, _ = _play_match(match_reset_from(decks, coins), jax.random.PRNGKey(30)) + b, _ = _play_match(match_reset_from(swapped, flipped_coins), jax.random.PRNGKey(30)) + + # Both matches see identical information; only the seat labels differ, so the + # per-seat totals must be each other's mirror image. + assert np.array_equal(np.asarray(match_score(a)), np.asarray(match_score(b))[::-1]) diff --git a/tests/lost_cities_jax/test_match_ppo.py b/tests/lost_cities_jax/test_match_ppo.py new file mode 100644 index 0000000..eba28a6 --- /dev/null +++ b/tests/lost_cities_jax/test_match_ppo.py @@ -0,0 +1,200 @@ +"""Phases 2-4: match reward, match observation, asymmetric critic, both-seat training.""" + +import jax +import jax.numpy as jnp +import numpy as np +import pytest + +from lost_cities_jax.match import match_reset, match_score, match_step +from lost_cities_jax.match_obs import ( + MATCH_CRITIC_OBS_DIM, + MATCH_OBS_DIM, + match_critic_observation, + match_observation, +) +from lost_cities_jax.match_ppo import ( + Ablation, + create_match_train_state, + make_match_rollout_fn, + make_match_train_iteration, +) +from lost_cities_jax.opponents import random_legal_action +from lost_cities_jax.ppo import JaxPPOConfig +from lost_cities_jax.types import LOC_P0_HAND, N_CARDS + + +def _cfg(rollout_steps: int = 700, batch_games: int = 8) -> JaxPPOConfig: + cfg = JaxPPOConfig() + cfg.ppo.batch_games = batch_games + cfg.ppo.rollout_steps = rollout_steps + cfg.ppo.minibatches = 4 + cfg.ppo.epochs = 1 + cfg.network.hidden_size = 32 + cfg.network.num_layers = 1 + return cfg + + +# --- the asymmetric critic ------------------------------------------------- + + +def test_the_critic_sees_the_opponents_hand_and_the_actor_does_not(): + match = match_reset(jax.random.PRNGKey(0)) + loc = np.asarray(match.round.card_loc) + opp_hand = np.flatnonzero(loc == LOC_P0_HAND + 1) + + actor = np.asarray(match_observation(match, jnp.int32(0))) + critic = np.asarray(match_critic_observation(match, jnp.int32(0))) + + # Card-major, three channels each, matching the base observation's layout. + hidden = critic[MATCH_OBS_DIM:].reshape(N_CARDS, 3) + assert np.array_equal(np.flatnonzero(hidden[:, 0]), opp_hand) + + # The actor's view is a strict prefix of it and carries none of that. + assert np.array_equal(actor, critic[:MATCH_OBS_DIM]) + assert critic.shape == (MATCH_CRITIC_OBS_DIM,) + + +def test_privileged_input_cannot_move_the_policy_logits(): + """Separate trunks, or the critic's view of the deck leaks into play. + + The privileged critic is off by default -- it measured negative, see the + ablation in the plan -- but the isolation property still has to hold for + anyone who switches it on, and for its later reuse as a search evaluator. + """ + cfg = _cfg() + state = create_match_train_state(cfg, jax.random.PRNGKey(1), Ablation(privileged_critic=True)) + match = match_reset(jax.random.PRNGKey(2)) + + obs = match_observation(match, jnp.int32(0))[None, :] + critic_a = match_critic_observation(match, jnp.int32(0))[None, :] + critic_b = critic_a.at[0, MATCH_OBS_DIM:].set(1.0) # a totally different hidden state + + logits_a, value_a = state.apply_fn(state.params, obs, critic_a) + logits_b, value_b = state.apply_fn(state.params, obs, critic_b) + + assert np.array_equal(np.asarray(logits_a), np.asarray(logits_b)) + # ...and the value head must actually be using it, or the critic is pointless. + assert not np.allclose(np.asarray(value_a), np.asarray(value_b)) + + +# --- the match reward ------------------------------------------------------ + + +def test_reward_is_zero_sum(): + cfg = _cfg() + state = create_match_train_state(cfg, jax.random.PRNGKey(3)) + env = jax.jit(jax.vmap(match_reset))( + jax.random.split(jax.random.PRNGKey(4), cfg.ppo.batch_games) + ) + + rollout = make_match_rollout_fn(cfg) + _, transitions, _, metrics = rollout(state, env, jax.random.PRNGKey(5), jnp.asarray(1.0)) + + reward = np.asarray(transitions.reward) # (T, 2 * batch) + seat0, seat1 = reward[:, : cfg.ppo.batch_games], reward[:, cfg.ppo.batch_games :] + assert np.allclose(seat0, -seat1) + assert float(metrics["matches_completed"]) > 0 + + +def test_the_dense_reward_telescopes_to_the_match_total(): + """The whole justification for paying every ply: at gamma=1 the sum is the total. + + That is what makes "score more across three rounds" the objective, rather than + some shaped proxy for it. + """ + match = match_reset(jax.random.PRNGKey(6)) + key = jax.random.PRNGKey(7) + scale = 50.0 + + paid = 0.0 + while not bool(match.done): + key, step_key = jax.random.split(key) + action = random_legal_action(match.round, match.round.to_move, step_key) + before = np.asarray(match_score(match)) + match, _, _ = match_step(match, action) + after = np.asarray(match_score(match)) + paid += ((after[0] - after[1]) - (before[0] - before[1])) / scale + + final = np.asarray(match_score(match)) + total_lead = (final[0] - final[1]) / scale + # Every point banked along the way, and nothing else. + assert paid == pytest.approx(total_lead, abs=1e-4) + + +# --- both seats ------------------------------------------------------------ + + +def test_exactly_one_seat_acts_per_ply_but_both_are_trained(): + cfg = _cfg() + state = create_match_train_state(cfg, jax.random.PRNGKey(8)) + env = jax.jit(jax.vmap(match_reset))( + jax.random.split(jax.random.PRNGKey(9), cfg.ppo.batch_games) + ) + + rollout = make_match_rollout_fn(cfg) + _, transitions, last_value, _ = rollout(state, env, jax.random.PRNGKey(10), jnp.asarray(0.0)) + + batch = cfg.ppo.batch_games + actor = np.asarray(transitions.actor_mask) + seat0, seat1 = actor[:, :batch], actor[:, batch:] + + # One mover per ply while the match is live. + live = np.asarray(transitions.active)[:, :batch] + assert np.array_equal(seat0 ^ seat1, live) + + # But the critic gets both seats: every live ply is a value target on both. + assert np.asarray(transitions.active).sum() == 2 * live.sum() + assert transitions.value.shape == (cfg.ppo.rollout_steps, 2 * batch) + assert last_value.shape == (2 * batch,) + + +def test_self_play_is_balanced_and_a_train_step_stays_finite(): + cfg = _cfg(rollout_steps=700, batch_games=16) + state = create_match_train_state(cfg, jax.random.PRNGKey(11)) + env = jax.jit(jax.vmap(match_reset))(jax.random.split(jax.random.PRNGKey(12), 16)) + train_iteration = make_match_train_iteration(cfg) + + state, env, _, metrics = train_iteration(state, env, jax.random.PRNGKey(13), jnp.asarray(0.1)) + + assert bool(jnp.isfinite(metrics["loss"])) + assert float(metrics["matches_completed"]) > 0 + # One network on both sides: neither seat should be favoured. + assert 0.2 < float(metrics["match_win_rate"]) < 0.8 + + +# --- the match observation ------------------------------------------------- + + +def test_carry_reaches_the_observation_with_a_usable_scale(): + """The old score_diff divided by 780; a 50-point lead vanished into 0.06.""" + match = match_reset(jax.random.PRNGKey(14)) + behind = match._replace(carry=jnp.asarray([0, 50], dtype=jnp.int32)) + ahead = match._replace(carry=jnp.asarray([50, 0], dtype=jnp.int32)) + + obs_behind = np.asarray(match_observation(behind, jnp.int32(0))) + obs_ahead = np.asarray(match_observation(ahead, jnp.int32(0))) + + delta = np.abs(obs_ahead - obs_behind) + # A 100-point swing has to be plainly visible, not a rounding error. + assert delta.max() > 0.5 + assert (delta > 0.01).sum() >= 2 # the scalar and at least one bin flip + + +@pytest.mark.parametrize("round_idx", [0, 1, 2]) +def test_the_round_index_is_observable(round_idx): + match = match_reset(jax.random.PRNGKey(15))._replace( + round_idx=jnp.asarray(round_idx, dtype=jnp.int32) + ) + obs = np.asarray(match_observation(match, jnp.int32(0))) + assert obs.shape == (MATCH_OBS_DIM,) + assert np.isfinite(obs).all() + + +def test_whose_turn_it_is_is_observable(): + """The single-round obs never said; the critic had to read it off step_count.""" + match = match_reset(jax.random.PRNGKey(16)) + mover = int(match.round.to_move) + + from_mover = np.asarray(match_observation(match, jnp.int32(mover))) + from_waiter = np.asarray(match_observation(match, jnp.int32(1 - mover))) + assert not np.array_equal(from_mover, from_waiter) diff --git a/tests/lost_cities_jax/test_ppo_stack.py b/tests/lost_cities_jax/test_ppo_stack.py index 3aef0e7..35dcfba 100644 --- a/tests/lost_cities_jax/test_ppo_stack.py +++ b/tests/lost_cities_jax/test_ppo_stack.py @@ -61,7 +61,9 @@ def tiny_config(tmp_path) -> JaxPPOConfig: ), opponent=OpponentConfig(name="discard_only"), network=NetworkConfig(hidden_size=32, num_layers=1), - ppo=PPOHyperConfig(batch_games=8, rollout_steps=16, epochs=1, minibatches=2), + # A round runs at least 44 plies (one per deck draw), so a shorter + # rollout would finish no episodes and leave the episode metrics empty. + ppo=PPOHyperConfig(batch_games=8, rollout_steps=80, epochs=1, minibatches=2), ) @@ -305,9 +307,12 @@ def test_gate3_checkpoint_duplicate_self_mirror_score_diff_is_zero(): def test_random_rollout_smoke(tmp_path): row = random_rollout(tiny_config(tmp_path)) - assert row["env_steps"] == 8 * 16 + assert row["env_steps"] == 8 * 80 assert 0.0 <= row["play_action_rate"] <= 1.0 - assert row["game_length_mean"] > 0.0 + # Averaged over episodes that actually finished, so it must clear the + # 44-ply floor rather than report a mid-episode step count. + assert row["episodes_completed"] > 0 + assert row["game_length_mean"] >= 44.0 def test_train_checkpoint_and_eval_smoke(tmp_path): diff --git a/tests/lost_cities_jax/test_rollout_loop.py b/tests/lost_cities_jax/test_rollout_loop.py new file mode 100644 index 0000000..9e519fd --- /dev/null +++ b/tests/lost_cities_jax/test_rollout_loop.py @@ -0,0 +1,188 @@ +"""Phase 0a: GAE bootstrap, in-scan auto-reset, and episode-boundary metrics.""" + +import jax +import jax.numpy as jnp +import pytest + +from lost_cities_jax.engine import reset +from lost_cities_jax.opponents import policy_by_name +from lost_cities_jax.ppo import ( + EpisodeEnd, + JaxPPOConfig, + Transition, + compute_gae, + create_train_state, + episode_metrics, + make_rollout_fn, + shaping_coefficient, +) + + +def _cfg(**overrides) -> JaxPPOConfig: + cfg = JaxPPOConfig() + cfg.ppo.batch_games = 8 + cfg.ppo.rollout_steps = 120 + cfg.network.hidden_size = 16 + cfg.network.num_layers = 1 + for key, value in overrides.items(): + setattr(cfg.run, key, value) + return cfg + + +# --- GAE bootstrap --------------------------------------------------------- + + +def test_gae_bootstraps_truncated_episode_from_last_value(): + """A rollout that ends mid-episode must carry V(s_T), not zero.""" + rewards = jnp.zeros((3, 1)) + values = jnp.zeros((3, 1)) + dones = jnp.zeros((3, 1), dtype=bool) # never terminates inside the window + + _, returns_zero = compute_gae(rewards, values, dones, gamma=1.0, gae_lambda=1.0) + _, returns_boot = compute_gae( + rewards, values, dones, gamma=1.0, gae_lambda=1.0, last_value=jnp.array([5.0]) + ) + + # Without a bootstrap the truncated episode looks worthless. + assert jnp.allclose(returns_zero, 0.0) + # With it, every step inherits the tail value. + assert jnp.allclose(returns_boot, 5.0) + + +def test_gae_ignores_last_value_when_episode_terminates(): + """A terminal step must not bootstrap past the episode boundary.""" + rewards = jnp.array([[0.0], [1.0]]) + values = jnp.zeros((2, 1)) + dones = jnp.array([[False], [True]]) + + _, returns = compute_gae( + rewards, values, dones, gamma=1.0, gae_lambda=1.0, last_value=jnp.array([99.0]) + ) + # Terminal step sees only its own reward; the step before it sees that too. + assert jnp.allclose(returns, jnp.array([[1.0], [1.0]])) + + +def test_gae_done_flag_cuts_credit_between_episodes(): + """With in-scan resets two episodes share a slot; credit must not leak.""" + rewards = jnp.array([[1.0], [7.0]]) + values = jnp.zeros((2, 1)) + dones = jnp.array([[True], [False]]) # first step ends episode A + + _, returns = compute_gae(rewards, values, dones, gamma=1.0, gae_lambda=1.0) + # Episode A keeps its own reward; episode B's +7 must not flow backwards. + assert jnp.allclose(returns[0], 1.0) + assert jnp.allclose(returns[1], 7.0) + + +# --- episode-boundary metrics --------------------------------------------- + + +def _episodes(done, episode_return, length) -> EpisodeEnd: + shape = jnp.asarray(done).shape + return EpisodeEnd( + done=jnp.asarray(done), + episode_return=jnp.asarray(episode_return, dtype=jnp.float32), + length=jnp.asarray(length, dtype=jnp.int32), + opened_colors=jnp.zeros(shape, dtype=jnp.int32), + positive_expeditions=jnp.zeros(shape, dtype=jnp.int32), + hit_max_steps=jnp.zeros(shape, dtype=bool), + ) + + +def _transitions(steps: int, games: int) -> Transition: + zeros = jnp.zeros((steps, games), dtype=jnp.float32) + false = jnp.zeros((steps, games), dtype=bool) + return Transition( + obs=jnp.zeros((steps, games, 1)), + legal_mask=jnp.zeros((steps, games, 1), dtype=bool), + action=jnp.zeros((steps, games), dtype=jnp.int32), + log_prob=zeros, + value=zeros, + reward=zeros, + done=false, + active=~false, + actor_mask=~false, + entropy=zeros, + play_action=false, + ) + + +def test_episode_metrics_only_counts_finished_episodes(): + """Unfinished episodes carry a partial return; they must not be averaged in.""" + # Slot 0 finishes twice (returns 10 and 20); slot 1 never finishes. + done = jnp.array([[True, False], [False, False], [True, False]]) + episode_return = jnp.array([[10.0, 3.0], [0.0, 6.0], [20.0, 9.0]]) + length = jnp.array([[50, 1], [0, 2], [60, 3]]) + + metrics = episode_metrics(_transitions(3, 2), _episodes(done, episode_return, length)) + + assert float(metrics["episodes_completed"]) == 2.0 + assert float(metrics["return_mean"]) == pytest.approx(15.0) + assert float(metrics["game_length_mean"]) == pytest.approx(55.0) + assert int(metrics["game_length_max"]) == 60 + + +def test_episode_metrics_survives_a_rollout_with_no_completions(): + done = jnp.zeros((2, 2), dtype=bool) + metrics = episode_metrics( + _transitions(2, 2), _episodes(done, jnp.zeros((2, 2)), jnp.zeros((2, 2))) + ) + assert float(metrics["episodes_completed"]) == 0.0 + assert float(metrics["return_mean"]) == 0.0 # guarded denominator, not a NaN + + +# --- in-scan auto-reset ---------------------------------------------------- + + +def test_rollout_never_returns_a_done_env_and_completes_many_episodes(): + """The whole point of in-scan reset: no dead steps, several games per slot.""" + cfg = _cfg() + rng = jax.random.PRNGKey(0) + rng, init_key, reset_key, roll_key = jax.random.split(rng, 4) + state = create_train_state(cfg, init_key) + env_state = jax.jit(jax.vmap(reset))(jax.random.split(reset_key, cfg.ppo.batch_games)) + + rollout_fn = make_rollout_fn(cfg, policy_by_name("discard_only")) + next_env, transitions, last_value, metrics = rollout_fn( + state, env_state, roll_key, jnp.asarray(0.0, dtype=jnp.float32) + ) + + # Every slot is mid-episode, never parked on a finished game. + assert not bool(jnp.any(next_env.done)) + # 120 steps at ~50 plies a game means each of the 8 slots finished at least one. + assert float(metrics["episodes_completed"]) >= cfg.ppo.batch_games + # No step is wasted stepping an already-done env. + assert bool(jnp.all(transitions.active)) + assert int(metrics["active_steps"]) == cfg.ppo.rollout_steps * cfg.ppo.batch_games + assert last_value.shape == (cfg.ppo.batch_games,) + + +def test_rollout_game_length_matches_the_rules_clock(): + """A round is 44 deck draws plus one turn per discard-pile draw.""" + cfg = _cfg() + rng = jax.random.PRNGKey(1) + rng, init_key, reset_key, roll_key = jax.random.split(rng, 4) + state = create_train_state(cfg, init_key) + env_state = jax.jit(jax.vmap(reset))(jax.random.split(reset_key, cfg.ppo.batch_games)) + + rollout_fn = make_rollout_fn(cfg, policy_by_name("discard_only")) + _, _, _, metrics = rollout_fn(state, env_state, roll_key, jnp.asarray(0.0, dtype=jnp.float32)) + + # 44 deck draws is the floor; discard-pile draws only ever extend a round. + assert float(metrics["game_length_mean"]) >= 44.0 + assert float(metrics["max_steps_rate"]) == 0.0 + + +# --- shaping anneal accounting -------------------------------------------- + + +def test_shaping_anneal_tracks_learner_actions_not_padded_steps(): + cfg = _cfg() + cfg.reward.potential_shaping_initial = 1.0 + cfg.reward.potential_shaping_final = 0.0 + cfg.reward.potential_shaping_anneal_steps = 1_000 + + assert shaping_coefficient(cfg, 0) == pytest.approx(1.0) + assert shaping_coefficient(cfg, 500) == pytest.approx(0.5) + assert shaping_coefficient(cfg, 1_000) == pytest.approx(0.0) + assert shaping_coefficient(cfg, 10_000) == pytest.approx(0.0) diff --git a/tests/lost_cities_jax/test_web_log_server.py b/tests/lost_cities_jax/test_web_log_server.py new file mode 100644 index 0000000..80037fe --- /dev/null +++ b/tests/lost_cities_jax/test_web_log_server.py @@ -0,0 +1,34 @@ +import json + +import pytest + +from scripts.serve_web_with_logs import parse_record + + +def test_parse_record_accepts_analysis_record(): + record = {"format": "lost-cities-web-game-v1", "gameId": "game-1", "moves": []} + assert parse_record(json.dumps(record).encode()) == record + + +@pytest.mark.parametrize("record", [{}, {"format": "other"}, {"format": "lost-cities-web-game-v1"}]) +def test_parse_record_rejects_invalid_input(record): + with pytest.raises(ValueError): + parse_record(json.dumps(record).encode()) + + +def test_parse_record_accepts_the_match_schema(): + # v2 carries which model played and the three-round match; v1 had neither. + record = { + "format": "lost-cities-web-game-v2", + "gameId": "game-2", + "opponent": {"codename": "borealis", "hash": "13a25243de1c"}, + "mode": 3, + "moves": [], + } + assert parse_record(json.dumps(record).encode()) == record + + +def test_parse_record_still_accepts_v1(): + # 111 games were recorded under v1; refusing them now would orphan them. + record = {"format": "lost-cities-web-game-v1", "gameId": "game-1", "moves": []} + assert parse_record(json.dumps(record).encode()) == record diff --git a/web/.claude/skills/verify/SKILL.md b/web/.claude/skills/verify/SKILL.md new file mode 100644 index 0000000..7e1eea3 --- /dev/null +++ b/web/.claude/skills/verify/SKILL.md @@ -0,0 +1,68 @@ +--- +name: verify +description: Drive the Lost Cities web client in a real browser to observe a change working — model loading, a full match, the result card, records being written. +--- + +# Verifying the web client + +The client is where a silent bug hides best. `npm test` and `tsc` were both green +while the app was announcing the wrong winner and dropping every game record on +the floor. Neither throws. Run it. + +## Build and serve + +```bash +cd web && npm run build +cd .. && tmux new-session -d -s websrv \ + "uv run python scripts/serve_web_with_logs.py --host 127.0.0.1 --port 5199 \ + --dist web/dist --output /tmp/verify-records.jsonl" +``` + +Serve the **built dist**, not the vite dev server — the deploy builds from dist, +and the model is a static asset whose path only resolves there. Point `--output` +at a scratch file so verification runs never touch `data/human-play/`. + +## Drive it + +Playwright is deliberately **not** a dependency: the `playwright` package downloads +~114MB of Chromium on install, and `npm ci` runs in the deploy workflow. Install it +for the run and uninstall after. + +```bash +cd web +npm i -D playwright --no-fund --no-audit && npx playwright install chromium +# ... drive ... +npm uninstall playwright +``` + +## Selectors that actually work + +Found by dumping the DOM; guessing at them wasted two runs. + +| What | Selector | +|---|---| +| a hand card | `button.card:not([disabled])` | +| play onto an expedition | `button.lane__zone--mine.is-target` | +| discard | `button.lane__discard.is-target` | +| draw from deck | `button.deck-stack:not([disabled])` | +| which model loaded | `.score-plaque--rival small` | +| match progress | `.round-strip` | +| final scores | `.result-card` | + +A turn is three clicks: pick a card, choose where it goes, then draw. The place and +draw targets only appear **after** the card is selected, and only the legal ones are +enabled — so click the card first, then query. + +The rival answers on a 620ms timer plus inference; ~200ms of slack between plies is +enough. A full three-round match runs ~140 plies, so budget a few minutes. + +## Worth driving + +- **A whole match, not one round.** The round roll-over is where carry banks, and it + is where the result card got it wrong. +- **Check the record actually saved.** A schema bump on the client silently 400s + against `scripts/serve_web_with_logs.py` until its allowlist is updated too. +- **A stale save in localStorage.** Bump the key on a schema change; a half-migrated + save is worse than a fresh deal. +- **The same seed twice.** In match mode the seed fixes all three deals and the coin + flips, so a match is a pure function of it. diff --git a/web/BUGS.md b/web/BUGS.md new file mode 100644 index 0000000..66f5035 --- /dev/null +++ b/web/BUGS.md @@ -0,0 +1,21 @@ +# Web bug checklist + +- [ ] Prevent cards from launching more than once during initial loading. + - Implementation and automated checks complete; user visual acceptance pending. +- [ ] Stack Hint, Undo, and Redo vertically at the bottom-right, aligned with the hand row. + - Implementation and automated checks complete; user visual acceptance pending. +- [ ] Restore the latest game timeline and review position from local storage. + - Implementation and automated checks complete; user reload acceptance pending. +- [ ] Keep Hint, Undo, Redo, and Play From Here in fixed vertical positions. + - Play From Here remains visible but disabled when unavailable; user visual acceptance pending. +- [ ] Automatically record completed human-versus-AI games for later analysis. + - JSONL includes the full deal, both hands before every move, actions, draws, scores, and final state. + - Local production output: `data/human-play/game-records.jsonl` (was `runs/tmp/`, which is gitignored and documented as disposable). +- [ ] Support game-record IDs when LAN HTTP does not expose `crypto.randomUUID`. + - Uses `crypto.getRandomValues` with a compatibility fallback; user acceptance pending. + +Verification: + +- `cd web && npm test` +- `cd web && npm run build` +- Visual acceptance is performed by the user; do not run browser automation. diff --git a/web/public/models/borealis.json b/web/public/models/borealis.json new file mode 100644 index 0000000..164eb06 --- /dev/null +++ b/web/public/models/borealis.json @@ -0,0 +1,15 @@ +{ + "format": "coolrl-lost-cities-match-onnx-v1", + "codename": "borealis", + "model_file": "borealis.onnx", + "model_size_bytes": 3327043, + "model_sha256": "13a25243de1c0c4f27dcac348b072cc6ea8ffd283dc033b877a37099fd809415", + "source_checkpoint": "runs/jax-ppo-match/2026-07-15_031529_match-scaled/latest", + "source_config": "match-selfplay.yaml", + "observation_size": 501, + "action_size": 96, + "hidden_size": 512, + "num_layers": 3, + "dtype": "float32", + "validation_max_abs_error": 9.1552734375e-05 +} diff --git a/web/public/models/borealis.onnx b/web/public/models/borealis.onnx new file mode 100644 index 0000000..d92077f Binary files /dev/null and b/web/public/models/borealis.onnx differ diff --git a/web/src/App.tsx b/web/src/App.tsx index 5eeb31c..385b701 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -10,16 +10,35 @@ import { currentHandSorted, decodeAction, encodeAction, - legalActionMask, previewPlacement, - resetFromOrder, - step, } from "./game/engine"; -import { deckOrderFromSeed, normalizeSeed, randomSeed } from "./game/random"; -import { DRAW_DECK, N_CARDS, PLAY, type GameState, type PlaceType } from "./game/types"; +import { + N_ROUNDS, + matchFromOrders, + matchLegalActionMask, + matchScore, + matchStep, + type MatchState, +} from "./game/match"; +import { MODEL_CODENAME, MODEL_HASH } from "./model/policy"; +import { matchFromSeed, normalizeSeed, randomSeed } from "./game/random"; +import { parseSavedGame, SAVED_GAME_KEY, type SavedGame } from "./game/persistence"; +import { DRAW_DECK, N_CARDS, PLAY, type PlaceType } from "./game/types"; import { fallbackHeuristicPolicy, loadPolicy, type Policy } from "./model/policy"; import { useCardMotion } from "./ui/useCardMotion"; +/** One deal, or the classic three-round match decided on the summed total. */ +export type Mode = 1 | 3; + +const MODE_KEY = "lost-cities.mode"; + +function loadMode(): Mode { + const requested = new URLSearchParams(window.location.search).get("rounds"); + if (requested === "3") return 3; + if (requested === "1") return 1; + return window.localStorage.getItem(MODE_KEY) === "3" ? 3 : 1; +} + interface Hint { action: number; text: string; @@ -36,8 +55,9 @@ const EMPTY_SELECTION: Selection = { handSlot: null, placeType: null }; * makes a finished game reviewable ply by ply. */ interface Frame { - state: GameState; + state: MatchState; selection: Selection; + move?: { player: 0 | 1; action: number }; } // The hand row is centered, so the binding constraint is the score plaque @@ -66,15 +86,12 @@ function handCardStep(viewportWidth: number, count: number): number { return Math.max(minVisible, Math.min(relaxed, fitted)); } -/** A `?seed=` in the URL loads that exact deal, so a game can be shared or replayed. */ -function initialSeed(): string { - const fromUrl = new URLSearchParams(window.location.search).get("seed"); - const seed = fromUrl === null ? "" : normalizeSeed(fromUrl); - return seed === "" ? randomSeed() : seed; -} - -function openingFrame(seed: string): Frame { - return { state: resetFromOrder(deckOrderFromSeed(seed)), selection: EMPTY_SELECTION }; +/** A `?seed=` in the URL loads that exact deal, so a game can be shared or replayed. + * In match mode the seed fixes all three deals and the coin flips too, so the + * whole match is a pure function of it. */ +function openingFrame(seed: string, mode: Mode): Frame { + const { deckOrders, coinFlips } = matchFromSeed(seed); + return { state: matchFromOrders(deckOrders, coinFlips, mode), selection: EMPTY_SELECTION }; } /** Keep the address bar in sync so the current deal stays shareable. */ @@ -84,29 +101,66 @@ function publishSeed(seed: string): void { window.history.replaceState(null, "", url); } +function newGameId(): string { + if (typeof crypto.randomUUID === "function") return crypto.randomUUID(); + if (typeof crypto.getRandomValues === "function") { + const bytes = crypto.getRandomValues(new Uint8Array(16)); + bytes[6] = (bytes[6] & 0x0f) | 0x40; + bytes[8] = (bytes[8] & 0x3f) | 0x80; + const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join(""); + return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`; + } + return `game-${Date.now()}-${Math.random().toString(36).slice(2)}`; +} + +function initialGame(): Pick { + const requested = new URLSearchParams(window.location.search).get("seed"); + const mode = loadMode(); + const saved = parseSavedGame(window.localStorage.getItem(SAVED_GAME_KEY)); + const requestedSeed = requested === null ? null : normalizeSeed(requested); + // A saved game only resumes into the mode it was played in. + if (saved && saved.mode === mode && (requestedSeed === null || requestedSeed === saved.seed)) { + return saved; + } + const seed = requestedSeed || randomSeed(); + return { seed, mode, frames: [openingFrame(seed, mode)], cursor: 0, resultOpen: true }; +} + function App() { - const [seed, setSeed] = useState(initialSeed); - const [frames, setFrames] = useState(() => [openingFrame(seed)]); - const [cursor, setCursor] = useState(0); + const [initial] = useState(initialGame); + const [seed, setSeed] = useState(initial.seed); + const [mode, setMode] = useState(initial.mode as Mode); + const [frames, setFrames] = useState(initial.frames); + const [cursor, setCursor] = useState(initial.cursor); const [seedDraft, setSeedDraft] = useState(""); - const [resultOpen, setResultOpen] = useState(true); + const [resultOpen, setResultOpen] = useState(initial.resultOpen); const [policy, setPolicy] = useState(null); - const [modelMessage, setModelMessage] = useState("LOADING FINAL PPO"); + const [modelMessage, setModelMessage] = useState("LOADING BOREALIS"); const [thinking, setThinking] = useState(false); const [menuOpen, setMenuOpen] = useState(false); const [viewportWidth, setViewportWidth] = useState(() => window.innerWidth); const [hint, setHint] = useState(null); const [hintPending, setHintPending] = useState(false); const generation = useRef(0); + const gameId = useRef(newGameId()); + const startedAt = useRef(new Date().toISOString()); + const loggedGame = useRef(null); const { cardRef, deckRef, overlayRef, resetMotion } = useCardMotion(); - const { state, selection } = frames[cursor]; + const { state: match, selection } = frames[cursor]; + // The board on screen is the round in play; the match is what decides the game. + const state = match.round; const canUndo = cursor > 0; const canRedo = cursor < frames.length - 1; - const latestState = useRef(state); + const latestMatch = useRef(match); useEffect(() => { publishSeed(seed); }, [seed]); - useEffect(() => { latestState.current = state; }, [state]); + useEffect(() => { latestMatch.current = match; }, [match]); + useEffect(() => { window.localStorage.setItem(MODE_KEY, String(mode)); }, [mode]); + useEffect(() => { + const saved: SavedGame = { version: 2, seed, mode, frames, cursor, resultOpen }; + window.localStorage.setItem(SAVED_GAME_KEY, JSON.stringify(saved)); + }, [cursor, frames, mode, resultOpen, seed]); useEffect(() => { function onResize() { setViewportWidth(window.innerWidth); } @@ -116,7 +170,7 @@ function App() { const humanHand = useMemo(() => currentHandSorted(state, 0), [state]); const opponentHand = useMemo(() => currentHandSorted(state, 1), [state]); - const legal = useMemo(() => legalActionMask(state), [state]); + const legal = useMemo(() => matchLegalActionMask(match), [match]); const selectedCard = selection.handSlot === null ? null : humanHand[selection.handSlot]; const selectedColor = selectedCard === null ? null : cardColor(selectedCard); const displayState = useMemo( @@ -125,14 +179,23 @@ function App() { : previewPlacement(state, selection.handSlot, selection.placeType), [selection, state], ); - const scores = useMemo(() => boardScore(displayState), [displayState]); + /** This round's board. */ + const roundScores = useMemo(() => boardScore(displayState), [displayState]); + /** Rounds already banked plus the board in play — the number that decides a match. */ + const scores = useMemo( + (): [number, number] => [ + match.carry[0] + roundScores[0], + match.carry[1] + roundScores[1], + ], + [match.carry, roundScores], + ); useEffect(() => { let cancelled = false; loadPolicy().then(({ policy: loaded, warning }) => { if (cancelled) return; setPolicy(loaded); - setModelMessage(warning ?? `${loaded.provider.toUpperCase()} · FINAL PPO`); + setModelMessage(warning ?? `${loaded.provider.toUpperCase()} · BOREALIS`); }); return () => { cancelled = true; }; }, []); @@ -149,24 +212,28 @@ function App() { const rivalSuspended = canRedo; useEffect(() => { - if (!policy || rivalSuspended || state.done || state.toMove !== 1) return; + if (!policy || rivalSuspended || match.done || state.toMove !== 1) return; const currentGeneration = generation.current; const timer = window.setTimeout(async () => { setThinking(true); try { let action: number; try { - action = await policy.action(state); + action = await policy.action(match); } catch (error) { console.error("AI action failed; falling back to heuristic policy", error); const fallback = fallbackHeuristicPolicy(); - action = await fallback.action(state); + action = await fallback.action(match); if (generation.current !== currentGeneration) return; setPolicy(fallback); setModelMessage("HEURISTIC FALLBACK (MODEL ERROR)"); } if (generation.current !== currentGeneration) return; - pushFrame({ state: step(state, action), selection: EMPTY_SELECTION }); + pushFrame({ + state: matchStep(match, action), + selection: EMPTY_SELECTION, + move: { player: 1, action }, + }); } catch (error) { console.error("AI action failed even with heuristic fallback", error); setModelMessage("MODEL INFERENCE ERROR"); @@ -175,15 +242,19 @@ function App() { } }, 620); return () => window.clearTimeout(timer); - }, [policy, rivalSuspended, state]); + }, [policy, rivalSuspended, match, state.toMove]); /** Deal a game. Without a seed this rolls a fresh one; the same seed always * reproduces the same deal, so `restart(seed)` also replays the current one. */ - function restart(nextSeed: string = randomSeed()) { + function restart(nextSeed: string = randomSeed(), nextMode: Mode = mode) { generation.current += 1; resetMotion(); + gameId.current = newGameId(); + startedAt.current = new Date().toISOString(); + loggedGame.current = null; setSeed(nextSeed); - setFrames([openingFrame(nextSeed)]); + setMode(nextMode); + setFrames([openingFrame(nextSeed, nextMode)]); setCursor(0); setSeedDraft(""); setResultOpen(true); @@ -217,8 +288,8 @@ function App() { /** Ask the policy driving the rival what it would do in your seat. */ async function requestHint() { - if (!policy || state.done || state.toMove !== 0 || hintPending) return; - const position = state; + if (!policy || match.done || state.toMove !== 0 || hintPending) return; + const position = match; setHintPending(true); setMenuOpen(false); try { @@ -229,10 +300,10 @@ function App() { const [best] = ranked; // The position can move on while inference runs — a hint for a stale // position would point at the wrong hand slot. - if (best === undefined || latestState.current !== position) return; + if (best === undefined || latestMatch.current !== position) return; setHint({ action: best.action, - text: describeAction(position, best.action), + text: describeAction(position.round, best.action), probability: best.probability, }); } catch (error) { @@ -246,21 +317,21 @@ function App() { useEffect(() => { setHint(null); }, [cursor, frames]); function chooseCard(handSlot: number) { - if (state.toMove !== 0 || state.done) return; + if (state.toMove !== 0 || match.done) return; const next = selection.handSlot !== handSlot || selection.placeType !== null ? { handSlot, placeType: null } : EMPTY_SELECTION; - pushFrame({ state, selection: next }); + pushFrame({ state: match, selection: next }); } function choosePlace(placeType: PlaceType) { if (selection.handSlot === null) return; - pushFrame({ state, selection: { ...selection, placeType } }); + pushFrame({ state: match, selection: { ...selection, placeType } }); } function cancelPlace() { if (selection.handSlot === null || selection.placeType === null) return; - pushFrame({ state, selection: { ...selection, placeType: null } }); + pushFrame({ state: match, selection: { ...selection, placeType: null } }); } useEffect(() => { @@ -282,7 +353,11 @@ function App() { function commit(drawSource: number) { if (!legalDraw(drawSource) || selection.handSlot === null || selection.placeType === null) return; const action = encodeAction(selection.handSlot, selection.placeType, drawSource); - pushFrame({ state: step(state, action), selection: EMPTY_SELECTION }); + pushFrame({ + state: matchStep(match, action), + selection: EMPTY_SELECTION, + move: { player: 0, action }, + }); } // Cards actually drawn in the hand row (the selected card moves into the @@ -309,18 +384,83 @@ function App() { const hintConfidence = hint !== null && hint.probability !== null ? `${Math.round(hint.probability * 100)}%` : null; - const canHint = policy !== null && !state.done && state.toMove === 0; + const canHint = policy !== null && !match.done && state.toMove === 0; const outcome = scores[0] === scores[1] ? "DRAW" : scores[0] > scores[1] ? "YOU WIN" : "THE RIVAL WINS"; + + useEffect(() => { + if (!match.done || loggedGame.current === gameId.current) return; + loggedGame.current = gameId.current; + const moves = frames.flatMap((frame, index) => { + if (!frame.move || index === 0) return []; + const beforeMatch = frames[index - 1].state; + const afterMatch = frame.state; + const before = beforeMatch.round; + const after = afterMatch.round; + const decoded = decodeAction(frame.move.action); + const beforeHand = currentHandSorted(before, frame.move.player); + // A move that ends a round is followed by a fresh deal, so the drawn card + // has to be read from the hand it was drawn into, not from the next round's. + const rolledOver = afterMatch.roundIdx !== beforeMatch.roundIdx; + const afterHand = rolledOver ? beforeHand : currentHandSorted(after, frame.move.player); + return [{ + ply: before.stepCount + 1, + round: beforeMatch.roundIdx + 1, + player: frame.move.player === 0 ? "human" : "ai", + action: frame.move.action, + playedCard: beforeHand[decoded.handSlot], + placeType: decoded.placeType === PLAY ? "play" : "discard", + drawSource: decoded.drawSource === DRAW_DECK ? "deck" : `discard_${decoded.drawSource - 1}`, + drawnCard: rolledOver + ? null + : afterHand.find((card) => !beforeHand.includes(card)) ?? null, + handsBefore: { + human: currentHandSorted(before, 0), + ai: currentHandSorted(before, 1), + }, + scoresAfter: matchScore(afterMatch), + }]; + }); + const record = { + format: "lost-cities-web-game-v2", + gameId: gameId.current, + seed, + // Which model actually played. The old records stored the on-screen label, + // which stops identifying anything the moment there is a second model. + opponent: { codename: MODEL_CODENAME, hash: MODEL_HASH }, + mode, + startedAt: startedAt.current, + finishedAt: new Date().toISOString(), + deckOrders: match.deckOrders.slice(0, mode), + coinFlips: match.coinFlips.slice(0, mode), + moves, + finalScores: scores, + roundScores: match.carry, + outcome, + finalState: match, + policy: modelMessage, + }; + void fetch("./api/game-records", { + method: "POST", + headers: { "content-type": "application/json" }, + body: JSON.stringify(record), + keepalive: true, + }).then((response) => { + if (!response.ok) throw new Error(`game log HTTP ${response.status}`); + }).catch((error) => { + loggedGame.current = null; + console.warn("Game record was not saved", error); + }); + }, [frames, match, mode, modelMessage, outcome, scores, seed, state.done]); // While the rival is paused on its own turn (or on the final position) nothing // will happen until the move is redone or play is resumed — say so. On your own // turn the normal prompt still applies: you can simply play on from here. - const reviewingRival = rivalSuspended && (state.done || state.toMove === 1); + const reviewingRival = rivalSuspended && (match.done || state.toMove === 1); const status = reviewingRival ? `Reviewing ply ${state.stepCount} — redo, or play on from here` - : state.done + : match.done ? outcome : state.toMove === 1 ? thinking ? "The rival is thinking ···" : "The rival's turn" @@ -350,6 +490,24 @@ function App() {
+
+ + +
+ + A MATCH IS DECIDED ON THE SUMMED TOTAL · WHOEVER LEADS ON POINTS + OPENS THE NEXT ROUND +