Add AI telemetry, SPRT, and baseline checks #13
No reviewers
Labels
No labels
bug
documentation
duplicate
enhancement
good first issue
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
pokebedrock/pokebedrock-showdown!13
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "improve-ai"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Expands the self-play harness with mirrored seeded teams, confidence intervals, SPRT early stopping, optional decision telemetry, JSON output, and baseline regression gating (plus a new
ai:baselinescript and committed tier baselines). Reworks strategic AI tuning and evaluation across heuristic/one-ply/MCTS paths to avoid immune/useless choices, improve status/setup valuation, and apply info-forgetting via foe-state views instead of score scaling. Also fixes team pack/unpack symmetry for PokeBedrock fields (uuid,currentHealth,status,movesInfo) and adds targeted tests for round-tripping, status-block handling, and decision-quality guarantees.Summary by CodeRabbit
Bugbot is not enabled for your account, so this pull request was not reviewed.
Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.
Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.
📝 Walkthrough
Walkthrough
The PR adds PokeBedrock team-state round trips, expands Strategic-AI move evaluation and difficulty tuning, introduces decision telemetry and statistical self-play analysis, and adds mirrored baseline checks, tests, CLI options, and roadmap documentation.
Changes
Strategic AI and evaluation
sim/tools/strategic-ai/policy/*,sim/tools/strategic-ai/engines/Engine.ts,sim/tools/strategic-ai/engines/HeuristicEngine.tssim/tools/strategic-ai/mechanics/*,sim/tools/strategic-ai/engines/LightHeuristicEngine.ts,MctsEngine.ts,OnePlySearchEngine.ts,test/sim/tools/strategic-ai/status-move-blocked.jssim/tools/strategic-ai/telemetry/DecisionStats.ts,sim/tools/player-ai.ts,test/sim/tools/strategic-ai/decision-quality.jssim/tools/ai-stats.ts,sim/tools/selfplay.tssim/tools/strategic-ai/baselines/*,sim/tools/strategic-ai/ROADMAP.md,package.jsonai:baselinescript, and Strategic-AI measurement and roadmap documentation.Team state
sim/teams.ts,test/sim/misc/teams-pack-roundtrip.jsEstimated code review effort: 5 (Critical) | ~120 minutes
Possibly related PRs
Suggested reviewers:
copilot🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
✨ Finishing Touches
📝 Generate docstrings
🧪 Generate unit tests (beta)
improve-aiThanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
❤️ Share
Comment
@coderabbitai helpto get the list of available commands.Actionable comments posted: 8
🧹 Nitpick comments (2)
🤖 Prompt for all review comments with AI agents
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID:
30178f3d-b041-42e7-92bf-d1e99a848662📥 Commits
Reviewing files that changed from the base of the PR and between
85d344dac7and5af8f6194f.📒 Files selected for processing (27)
package.jsonsim/teams.tssim/tools/ai-stats.tssim/tools/player-ai.tssim/tools/selfplay.tssim/tools/strategic-ai/ROADMAP.mdsim/tools/strategic-ai/baselines/README.mdsim/tools/strategic-ai/baselines/check.shsim/tools/strategic-ai/baselines/d1-vs-random.jsonsim/tools/strategic-ai/baselines/d2-vs-random.jsonsim/tools/strategic-ai/baselines/d3-vs-random.jsonsim/tools/strategic-ai/baselines/d4-vs-random.jsonsim/tools/strategic-ai/baselines/d5-vs-random.jsonsim/tools/strategic-ai/engines/Engine.tssim/tools/strategic-ai/engines/HeuristicEngine.tssim/tools/strategic-ai/engines/LightHeuristicEngine.tssim/tools/strategic-ai/engines/MctsEngine.tssim/tools/strategic-ai/engines/OnePlySearchEngine.tssim/tools/strategic-ai/mechanics/DamageCalc.tssim/tools/strategic-ai/mechanics/MoveEvaluator.tssim/tools/strategic-ai/mechanics/SwitchEvaluator.tssim/tools/strategic-ai/policy/DifficultyPolicy.tssim/tools/strategic-ai/policy/InfoForgetting.tssim/tools/strategic-ai/telemetry/DecisionStats.tstest/sim/misc/teams-pack-roundtrip.jstest/sim/tools/strategic-ai/decision-quality.jstest/sim/tools/strategic-ai/status-move-blocked.js@ -46,6 +46,7 @@"build-npm": "node build && npx tsc sim/global-types.ts sim/index.ts --declaration --emitDeclarationOnly --declarationDir dist/ --target es2020 --strict --moduleResolution node --types node --lib es2020","test-npm": "npx tsc sim/global-types.ts sim/index.ts --noEmit --target es2020 --strict --moduleResolution node --types node --lib es2020","tsc": "tsc","ai:baseline": "sh sim/tools/strategic-ai/baselines/check.sh",🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Build the current sources before running the baseline gate.
check.shassumesnode buildalready ran, but this npm entrypoint invokes it directly.npm run ai:baselinecan therefore fail on a clean checkout or compare baselines against staledistoutput after source changes.Proposed fix
Update the README to avoid documenting a redundant separate build step.
📝 Committable suggestion
🤖 Prompt for AI Agents
@ -173,0 +178,4 @@// status - @pokebedrockbuf += `|${set.status || ''}`;🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win
uuid/statusare written unescaped into a delimiter-separated stream.packNamestrips non-alphanumerics for name/item/ability precisely because|and]are field/set separators.set.uuid(externally supplied) andset.statusare appended raw, so a value containing|or]shifts every subsequent field of that set — andunpackwill then mis-assign item/ability/moves silently. Consider stripping those two characters (or asserting the UUID shape) on pack.🛡️ Proposed guard
📝 Committable suggestion
🤖 Prompt for AI Agents
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
Make telemetry slot-aware before recording multi-slot choices.
DecisionStats.recordSlotreceives each slot index but evaluatestracker.myActiveandtracker.foeActivewithout using it. In doubles/triples, later choices are measured against the wrong attacker and target, corrupting telemetry. Resolve both from the command’s slot/target, or limit collection to singles.🤖 Prompt for AI Agents
🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift
Propagate the hazy foe state into search models.
Line 314 only replaces
evalCtx.defender;evalCtx.trackerremains complete.OnePlySearchEngineandMctsEnginederive foe-move models from that raw tracker, so their configuredinfoForgettingdoes not actually hide revealed moves. Pass a per-decision foe view into those models instead.🤖 Prompt for AI Agents
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Corrosion is not accounted for in the poison-type gate.
STATUS_IMMUNE_TYPES.psn/toxblocks Steel and Poison targets unconditionally, but a Corrosion attacker (Salazzle) legally poisons both. As written, Salazzle's Toxic into a Steel wall scoresIMMUNE_MOVE_SCOREand is never clicked.🐛 Proposed fix
📝 Committable suggestion
🤖 Prompt for AI Agents
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Restore the random engine for difficulty 0.
Line 157 maps
0toheuristic, contradicting the publicPlayerAIOptionscontract that difficulty 0 maps toRandomEngine.Proposed fix
📝 Committable suggestion
🤖 Prompt for AI Agents
@ -0,0 +85,4 @@revealedMoves: forgetMoves ?new Set([...foe.revealedMoves].filter(() => prng.random() >= forgetting)) :foe.revealedMoves,item: forgetItem ? "" : foe.item,🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Do not forget items that make a move fail.
Line 88 can hide Safety Goggles, but
statusMoveBlockedByrelies on the item to reject powder moves. This reintroduces a knowingly ineffective choice; preserve move-blocking items (or stop forgetting items during move evaluation).🤖 Prompt for AI Agents
@ -0,0 +183,4 @@if (calc.avgDamage <= 0) this.counters.zeroDamageMoves++;else if (Dex.getEffectiveness(move.type, defender.types) < 0) this.counters.resistedMoves++;}}🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Attacker/defender ignore the
slotparameter — wrong Pokemon for doubles/triples telemetry.record()/recordSlot()iterate per-slot (for (let slot = 0; slot < parts.length; slot++)) specifically to support doubles/triples, per the comment at Line 102. But bothrecordSlot(Lines 166-167) andhadConnectingAlternative(Lines 206-207) pull the attacker fromtracker.myActive, which is hardcoded to slot 0:For a slot-1+ command in a multi-slot battle, this evaluates damage/immunity against the wrong attacker (always the slot-0 Pokemon instead of the Pokemon that actually made the choice), silently corrupting
immuneMoves/zeroDamageMoves/resistedMoves/avoidableImmuneMovescounts for that slot.BattleStateTracker.getActive(side, position)is already slot-aware and available for this.🐛 Proposed fix for the attacker lookup
(The foe-side defender is harder to resolve precisely without target data in doubles, but the attacker fix alone removes the primary misattribution.)
Also applies to: 199-229
🤖 Prompt for AI Agents
Source: Learnings