-
Notifications
You must be signed in to change notification settings - Fork 704
Feature: Strategic Economic Spending for FakeHumans (Nations) #2244
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Feature: Strategic Economic Spending for FakeHumans (Nations) #2244
Conversation
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
…etter control flow
…distance calculation
…ution with comments
…eamroll prevention and team victory denial
…eHuman MIRV tests
…or victory denial
…n in FakeHumanExecution
WalkthroughIntegrates MIRV strategy into FakeHumanExecution with cooldowns, target-selection (counter, victory-denial, steamroll), reserve-aware spending, and a dynamic build-order; adds MIRV target param typing and passes Changes
Sequence Diagram(s)sequenceDiagram
actor Tick as Game Tick
participant FH as FakeHumanExecution
participant MIRV as MIRV Logic
participant Build as Unit Builder / MirvExecution
participant Target as Target Selector
Tick->>FH: tick(game)
FH->>MIRV: considerMIRV(gameState)
rect #e8f3ff
MIRV->>MIRV: check cooldowns & reserves
MIRV->>Target: evaluate scenarios (counter / deny / steamroll)
end
alt Threat selected
Target->>Build: request MIRV spawn with `targetTile`
Build->>Build: buildUnit(type=MIRV, params={targetTile})
Build->>Target: confirm outbound MIRV
else No action
Note right of MIRV: continue normal spend/build flow
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/core/execution/MIRVExecution.ts (2)
71-88: Missing silo cooldown on MIRV launch (launch() not called).NukeExecution triggers silo.launch() when firing; MIRVExecution should too. Otherwise silos can chain‑fire MIRVs without cooldown. Add a launch call for the silo at the spawn tile.
Apply this diff:
this.nuke = this.player.buildUnit(UnitType.MIRV, spawn, { targetTile: this.dst, }); + // Put the launching silo into cooldown (mirrors NukeExecution behavior) + const silo = this.player + .units(UnitType.MissileSilo) + .find((u) => u.tile() === spawn); + if (silo) { + silo.launch(); + }
74-79: Bug: double x() call uses x‑coordinate as a TileRef.this.mg.x(this.mg.x(this.nuke.tile())) calls x() with a number, not a TileRef. Use the nuke’s tile directly.
Apply this diff:
- const x = Math.floor( - (this.mg.x(this.dst) + this.mg.x(this.mg.x(this.nuke.tile()))) / 2, - ); + const x = Math.floor( + (this.mg.x(this.dst) + this.mg.x(this.nuke.tile())) / 2, + );
🧹 Nitpick comments (8)
src/core/execution/FakeHumanExecution.ts (6)
437-448: Build order pipeline: clear; keep it data‑driven.Nice separation via getBuildOrder() and per‑type multipliers. Consider extracting the base array to a top‑level readonly constant and typing the multiplier as (ownedPlusOne: number) => number for readability.
Also applies to: 450-486
733-766: MIRV decision gate: OK; small enhancement.Logic is sound: silo present, has gold, cooldown window, hesitation odds, then target selection. Optional: short‑circuit earlier by checking a cheap canBuild(UnitType.MIRV, anyEnemyTile) before heavier scans.
1000-1039: BigInt/Number mixing may overflow later; prefer BigInt.Number(this.player.gold()) and comparisons to Number literals risk precision loss if gold scales up. Use BigInt literals (e.g., 10_000_000n) and compare with BigInt.
Apply this minimal diff:
- const gold = Number(this.player.gold()); - if (currentSilos < 2 && gold > 10_000_000 && territorySize > 50) { + const gold = this.player.gold(); + if (currentSilos < 2 && gold > 10_000_000n && territorySize > 50) { return true; }And similarly avoid Number() in other gold comparisons.
1045-1133: Dynamic reserve threshold: solid, but use BigInt end‑to‑end.The benchmarking math is thorough. However, converting Gold (bigint) to Number throughout can lose precision. Recommend:
- Keep other players’ gold as bigint; compute scaled thresholds using bigint arithmetic where possible; only convert to Number for ratios, then back once, clamped to a bigint maximum.
- Document the intended gold magnitude to justify any Number conversions.
I can provide a bigint‑safe helper module (sum/avg/topK, ratio via fixed‑point) if helpful.
Also applies to: 1138-1156
73-75: Unused constant.MIRV_SAVING_URGENCY_MULTIPLIER is declared but never used. Remove or wire it into reserve logic.
Apply this diff to remove:
- /** Game progression factor - how much more urgent MIRV saving becomes over time */ - private static readonly MIRV_SAVING_URGENCY_MULTIPLIER = 0.5;
436-448: handleUnits() returns boolean but the return value is ignored.Either consume the boolean in tick() or change return type to void to avoid confusion.
- private handleUnits() { + private handleUnits(): void { const buildOrder = this.getBuildOrder(); for (const { type, multiplier } of buildOrder) { if (type === UnitType.Warship) { - if (this.maybeSpawnWarship()) return true; + if (this.maybeSpawnWarship()) return; } else { - if (this.maybeSpawnStructure(type, multiplier)) return true; + if (this.maybeSpawnStructure(type, multiplier)) return; } } - return false; }tests/FakeHumanMIRV.test.ts (1)
99-120: Seed‑sweep to dodge hesitation odds: OK; reduce flakiness.Looping over 20 seeds is pragmatic. For determinism, consider injecting a fixed attackRate/attackTick via a test‑only constructor or setter, and tick the game each loop (executeNextTick) while calling testExecution.tick(game.ticks()) to keep clocks aligned.
Also applies to: 259-281, 415-433, 571-589
src/core/game/Game.ts (1)
266-269: Use TileRef consistently across all bomb units in UnitParamsMap.Construction path is confirmed: UnitImpl reads params.targetTile during construction (line 54). However, all four bomb types (AtomBomb, HydrogenBomb, MIRV, MIRVWarhead) at lines 236, 241, 267, 271 use
targetTile?: numberwhile the Unit interface and GameUpdates usetargetTile?: TileRef. Since TileRef is the semantic alias for tile references, update all four bomb unit params to usetargetTile?: TileReffor consistency and clarity.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/core/execution/FakeHumanExecution.ts(10 hunks)src/core/execution/MIRVExecution.ts(1 hunks)src/core/game/Game.ts(1 hunks)tests/FakeHumanMIRV.test.ts(1 hunks)
🧰 Additional context used
🧠 Learnings (8)
📓 Common learnings
Learnt from: sambokai
PR: openfrontio/OpenFrontIO#2225
File: src/core/execution/FakeHumanExecution.ts:172-173
Timestamp: 2025-10-18T17:54:01.293Z
Learning: In src/core/execution/FakeHumanExecution.ts, MIRVs and ground attacks should not be mutually exclusive. The considerMIRV() method should not short-circuit maybeAttack() - both actions can occur in the same tick.
📚 Learning: 2025-05-18T23:36:12.847Z
Learnt from: scottanderson
PR: openfrontio/OpenFrontIO#784
File: src/core/game/StatsImpl.ts:143-159
Timestamp: 2025-05-18T23:36:12.847Z
Learning: In this codebase, NukeType is a union type derived from UnitType values (specifically bomb-related values like AtomBomb, HydrogenBomb, MIRV, and MIRVWarhead) rather than a separate enum. This means comparing NukeType values against UnitType values in switch statements is valid and intentional.
Applied to files:
src/core/game/Game.ts
📚 Learning: 2025-05-18T23:36:12.847Z
Learnt from: scottanderson
PR: openfrontio/OpenFrontIO#784
File: src/core/game/StatsImpl.ts:143-159
Timestamp: 2025-05-18T23:36:12.847Z
Learning: In this codebase, NukeType is a union type derived from specific UnitType enum values (AtomBomb, HydrogenBomb, MIRV, MIRVWarhead). This means that comparisons in switch statements between a NukeType parameter and UnitType enum values are valid and will work correctly at runtime.
Applied to files:
src/core/game/Game.ts
📚 Learning: 2025-10-18T17:54:01.293Z
Learnt from: sambokai
PR: openfrontio/OpenFrontIO#2225
File: src/core/execution/FakeHumanExecution.ts:172-173
Timestamp: 2025-10-18T17:54:01.293Z
Learning: In src/core/execution/FakeHumanExecution.ts, MIRVs and ground attacks should not be mutually exclusive. The considerMIRV() method should not short-circuit maybeAttack() - both actions can occur in the same tick.
Applied to files:
tests/FakeHumanMIRV.test.tssrc/core/execution/FakeHumanExecution.tssrc/core/execution/MIRVExecution.ts
📚 Learning: 2025-10-20T20:15:28.833Z
Learnt from: sambokai
PR: openfrontio/OpenFrontIO#2225
File: src/core/execution/FakeHumanExecution.ts:51-51
Timestamp: 2025-10-20T20:15:28.833Z
Learning: In src/core/execution/FakeHumanExecution.ts, game balance constants like MIRV_COOLDOWN_TICKS, MIRV_HESITATION_ODDS, VICTORY_DENIAL_TEAM_THRESHOLD, VICTORY_DENIAL_INDIVIDUAL_THRESHOLD, and STEAMROLL_CITY_GAP_MULTIPLIER are experimental tuning parameters subject to frequent change during balance testing. Do not flag changes to these values as issues or compare them against previous values.
Applied to files:
tests/FakeHumanMIRV.test.tssrc/core/execution/FakeHumanExecution.ts
📚 Learning: 2025-10-20T11:02:16.949Z
Learnt from: sambokai
PR: openfrontio/OpenFrontIO#2225
File: src/core/execution/FakeHumanExecution.ts:57-57
Timestamp: 2025-10-20T11:02:16.949Z
Learning: In src/core/execution/FakeHumanExecution.ts, the correct MIRV victory denial thresholds are VICTORY_DENIAL_TEAM_THRESHOLD = 0.8 (80% for team games) and VICTORY_DENIAL_INDIVIDUAL_THRESHOLD = 0.65 (65% for individual players), not 0.85 and 0.7 as might be mentioned in some documentation.
Applied to files:
tests/FakeHumanMIRV.test.tssrc/core/execution/FakeHumanExecution.ts
📚 Learning: 2025-08-23T08:03:44.914Z
Learnt from: ElMelchizedek
PR: openfrontio/OpenFrontIO#1876
File: src/core/execution/FakeHumanExecution.ts:547-592
Timestamp: 2025-08-23T08:03:44.914Z
Learning: In OpenFrontIO, FakeHumanExecution is used for AI-controlled nations that simulate human behavior, which is distinct from PlayerType.Bot. FakeHumanExecution players are not PlayerType.Bot - they represent more sophisticated AI that mimics human nation behavior, while PlayerType.Bot represents basic AI players.
Applied to files:
src/core/execution/FakeHumanExecution.ts
📚 Learning: 2025-08-18T03:11:18.617Z
Learnt from: scottanderson
PR: openfrontio/OpenFrontIO#1851
File: src/core/execution/FakeHumanExecution.ts:433-441
Timestamp: 2025-08-18T03:11:18.617Z
Learning: In FakeHumanExecution.maybeSpawnStructure, the perceived cost multiplier (owned + 1, capped at 5) applied to structure costs is intentional. This makes AI nations build fewer structures than players could, saving gold for bombs/nukes rather than maxing out structures.
Applied to files:
src/core/execution/FakeHumanExecution.ts
🧬 Code graph analysis (2)
tests/FakeHumanMIRV.test.ts (5)
tests/util/Setup.ts (1)
setup(23-80)src/core/game/Game.ts (2)
PlayerInfo(397-417)Cell(304-326)src/core/execution/MIRVExecution.ts (1)
MirvExecution(16-192)tests/util/utils.ts (1)
executeTicks(32-36)src/core/execution/FakeHumanExecution.ts (2)
FakeHumanExecution(30-1165)tick(142-192)
src/core/execution/FakeHumanExecution.ts (7)
src/core/execution/utils/BotBehavior.ts (1)
BotBehavior(25-340)src/core/game/Game.ts (5)
Tick(22-22)PlayerID(21-21)Nation(296-302)Player(519-653)Gold(23-23)src/core/game/GameMap.ts (3)
TileRef(3-3)x(122-124)cost(248-250)src/core/game/PlayerImpl.ts (5)
type(200-202)team(740-742)tiles(278-280)target(514-517)gold(764-766)src/core/game/GameImpl.ts (5)
x(780-782)players(402-404)owner(165-167)target(574-580)cost(843-845)src/core/execution/MIRVExecution.ts (2)
owner(181-183)MirvExecution(16-192)src/core/execution/NukeExecution.ts (3)
owner(325-327)target(43-45)tick(104-183)
🔇 Additional comments (11)
src/core/execution/FakeHumanExecution.ts (7)
190-191: Order is correct: MIRV does not block ground attacks.considerMIRV() runs before maybeAttack() without early return, matching the “not mutually exclusive” guidance.
Based on learnings
288-296: Don’t nuke basic bots: good guard.Skipping nukes vs PlayerType.Bot aligns with FakeHuman vs Bot distinction and avoids wasting gold.
Based on learnings
498-502: Reserve‑aware spending: good integration.canAffordWithReserve() here enforces MIRV deterrence savings while building structures.
566-572: Warship spending respects MIRV reserve.Using canAffordWithReserve(warshipCost) is consistent with the economic strategy.
778-821: Team victory‑denial: targets largest team member correctly.Logic matches threshold guidance and selects the largest teammate only when team exceeds threshold.
Based on learnings
742-746: Cooldown queue logic: OK.Queue semantics and removal by tick age are correct; pushing a representative tile for cooldown is reasonable.
Also applies to: 965-973, 975-984
888-899: API verified and correctly used.The
GameMapinterface declareshasOwner(ref: TileRef): boolean, and the implementation inGameMap.tsline 176 returnsthis.ownerID(ref) !== 0. The code at line 894 uses this method correctly:this.mg.hasOwner(dst)follows the expected signature, and the method is consistently used throughout the codebase in similar contexts.tests/FakeHumanMIRV.test.ts (3)
83-87: Precondition check is meaningful.Verifying attacker’s MIRV is in flight before retaliation improves signal in failures.
516-560: Team victory‑denial: clear largest‑member expectation.The 3:1 bias and share > 0.8 check align with code logic and retrieved learnings.
Based on learnings
78-88: No issues found. The targetTile parameter is already propagated correctly.The code already implements the required behavior:
- MirvExecution passes
targetTile: this.dstwhen calling buildUnit- UnitImpl constructor correctly checks for
targetTilein params and initializes_targetTile- The test assertions will pass because the full propagation chain works as expected
The test guards the API shape correctly and requires no changes.
src/core/execution/MIRVExecution.ts (1)
71-73: Verified: MIRV targetTile parameter is correctly applied during unit construction.The code change is correct. When
buildUnitis called withtargetTile, the parameter is passed toUnitImplconstructor, which directly extracts and assigns it to_targetTile(UnitImpl.ts:53-54). The accessortargetTile()will return the correct value. The parameter is applied during construction, not viasetTargetTile(), but the result is the same—downstream logic can readMIRV.targetTile()without undefined issues.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
src/core/execution/FakeHumanExecution.ts (1)
439-451: Add explicit return type annotation.The method returns boolean but lacks a type annotation.
Apply this diff:
- private handleUnits() { + private handleUnits(): boolean { const buildOrder = this.getBuildOrder();
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/core/execution/FakeHumanExecution.ts(10 hunks)src/core/game/Game.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/core/game/Game.ts
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: sambokai
PR: openfrontio/OpenFrontIO#2225
File: src/core/execution/FakeHumanExecution.ts:172-173
Timestamp: 2025-10-18T17:54:01.311Z
Learning: In src/core/execution/FakeHumanExecution.ts, MIRVs and ground attacks should not be mutually exclusive. The considerMIRV() method should not short-circuit maybeAttack() - both actions can occur in the same tick.
Learnt from: sambokai
PR: openfrontio/OpenFrontIO#2225
File: src/core/execution/FakeHumanExecution.ts:770-795
Timestamp: 2025-10-27T09:47:26.376Z
Learning: In src/core/execution/FakeHumanExecution.ts, the selectSteamrollStopTarget() method intentionally allows MIRV targeting when secondHighest city count is 0 (e.g., nuclear endgame scenarios where structures are destroyed). This is valid game design—"if you can afford it, you're good to go"—and should not be flagged as requiring a guard condition.
Learnt from: sambokai
PR: openfrontio/OpenFrontIO#2225
File: src/core/execution/FakeHumanExecution.ts:711-723
Timestamp: 2025-10-17T19:16:57.699Z
Learning: In the OpenFrontIO game, MIRVs (Multiple Independently targetable Reentry Vehicles) have an area of effect with a radius of 1500 tiles around the aim point. To maximize efficiency, bots should aim at the center of the target player's territory rather than selecting random tiles. This differs from the initial understanding that MIRVs covered an entire player's territory regardless of aim point.
Learnt from: sambokai
PR: openfrontio/OpenFrontIO#2225
File: src/core/execution/FakeHumanExecution.ts:51-51
Timestamp: 2025-10-20T20:15:28.858Z
Learning: In src/core/execution/FakeHumanExecution.ts, game balance constants like MIRV_COOLDOWN_TICKS, MIRV_HESITATION_ODDS, VICTORY_DENIAL_TEAM_THRESHOLD, VICTORY_DENIAL_INDIVIDUAL_THRESHOLD, and STEAMROLL_CITY_GAP_MULTIPLIER are experimental tuning parameters subject to frequent change during balance testing. Do not flag changes to these values as issues or compare them against previous values.
📚 Learning: 2025-10-18T17:54:01.311Z
Learnt from: sambokai
PR: openfrontio/OpenFrontIO#2225
File: src/core/execution/FakeHumanExecution.ts:172-173
Timestamp: 2025-10-18T17:54:01.311Z
Learning: In src/core/execution/FakeHumanExecution.ts, MIRVs and ground attacks should not be mutually exclusive. The considerMIRV() method should not short-circuit maybeAttack() - both actions can occur in the same tick.
Applied to files:
src/core/execution/FakeHumanExecution.ts
📚 Learning: 2025-10-20T20:15:28.858Z
Learnt from: sambokai
PR: openfrontio/OpenFrontIO#2225
File: src/core/execution/FakeHumanExecution.ts:51-51
Timestamp: 2025-10-20T20:15:28.858Z
Learning: In src/core/execution/FakeHumanExecution.ts, game balance constants like MIRV_COOLDOWN_TICKS, MIRV_HESITATION_ODDS, VICTORY_DENIAL_TEAM_THRESHOLD, VICTORY_DENIAL_INDIVIDUAL_THRESHOLD, and STEAMROLL_CITY_GAP_MULTIPLIER are experimental tuning parameters subject to frequent change during balance testing. Do not flag changes to these values as issues or compare them against previous values.
Applied to files:
src/core/execution/FakeHumanExecution.ts
📚 Learning: 2025-10-27T09:47:26.376Z
Learnt from: sambokai
PR: openfrontio/OpenFrontIO#2225
File: src/core/execution/FakeHumanExecution.ts:770-795
Timestamp: 2025-10-27T09:47:26.376Z
Learning: In src/core/execution/FakeHumanExecution.ts, the selectSteamrollStopTarget() method intentionally allows MIRV targeting when secondHighest city count is 0 (e.g., nuclear endgame scenarios where structures are destroyed). This is valid game design—"if you can afford it, you're good to go"—and should not be flagged as requiring a guard condition.
Applied to files:
src/core/execution/FakeHumanExecution.ts
📚 Learning: 2025-10-20T11:02:16.969Z
Learnt from: sambokai
PR: openfrontio/OpenFrontIO#2225
File: src/core/execution/FakeHumanExecution.ts:57-57
Timestamp: 2025-10-20T11:02:16.969Z
Learning: In src/core/execution/FakeHumanExecution.ts, the correct MIRV victory denial thresholds are VICTORY_DENIAL_TEAM_THRESHOLD = 0.8 (80% for team games) and VICTORY_DENIAL_INDIVIDUAL_THRESHOLD = 0.65 (65% for individual players), not 0.85 and 0.7 as might be mentioned in some documentation.
Applied to files:
src/core/execution/FakeHumanExecution.ts
📚 Learning: 2025-08-23T08:03:44.914Z
Learnt from: ElMelchizedek
PR: openfrontio/OpenFrontIO#1876
File: src/core/execution/FakeHumanExecution.ts:547-592
Timestamp: 2025-08-23T08:03:44.914Z
Learning: In OpenFrontIO, FakeHumanExecution is used for AI-controlled nations that simulate human behavior, which is distinct from PlayerType.Bot. FakeHumanExecution players are not PlayerType.Bot - they represent more sophisticated AI that mimics human nation behavior, while PlayerType.Bot represents basic AI players.
Applied to files:
src/core/execution/FakeHumanExecution.ts
📚 Learning: 2025-08-18T03:11:18.617Z
Learnt from: scottanderson
PR: openfrontio/OpenFrontIO#1851
File: src/core/execution/FakeHumanExecution.ts:433-441
Timestamp: 2025-08-18T03:11:18.617Z
Learning: In FakeHumanExecution.maybeSpawnStructure, the perceived cost multiplier (owned + 1, capped at 5) applied to structure costs is intentional. This makes AI nations build fewer structures than players could, saving gold for bombs/nukes rather than maxing out structures.
Applied to files:
src/core/execution/FakeHumanExecution.ts
🧬 Code graph analysis (1)
src/core/execution/FakeHumanExecution.ts (5)
src/core/execution/utils/BotBehavior.ts (1)
BotBehavior(25-340)src/core/game/Game.ts (5)
Tick(22-22)PlayerID(21-21)Nation(299-305)Player(525-661)Gold(23-23)src/core/game/GameView.ts (8)
type(94-96)type(340-342)team(337-339)x(671-673)owner(109-111)owner(636-638)tile(106-108)gold(362-364)src/core/Schemas.ts (2)
GameID(24-24)Player(116-116)src/core/execution/MIRVExecution.ts (2)
owner(181-183)MirvExecution(16-192)
🔇 Additional comments (10)
src/core/execution/FakeHumanExecution.ts (10)
23-23: LGTM! Clean integration of MIRV infrastructure.The import, state tracking field, and strategic constants properly establish the foundation for MIRV decision-making. The lastMIRVSent array follows the same pattern as lastNukeSent for consistency.
Also applies to: 46-46, 49-75
191-191: LGTM! Correct integration of MIRV strategy.The considerMIRV() call is properly sequenced before maybeAttack(), allowing both MIRV launches and ground attacks to occur in the same tick as intended.
Based on learnings.
453-489: LGTM! Clean dynamic build order implementation.The priority-based build system elegantly handles strategic shifts (e.g., prioritizing Missile Silos in mid/late game) while maintaining a sensible base order. The conditional reordering is clear and maintainable.
501-504: LGTM! Reserve-aware spending properly integrated.The canAffordWithReserve() checks ensure bots maintain MIRV deterrence funds while making structure and unit decisions. Clean integration with existing spawn logic.
Also applies to: 569-575
737-824: LGTM! Well-structured MIRV decision system.The three-tiered target selection (counter-MIRV → victory denial → steamroll) provides strategic depth. The victory denial logic correctly handles both team-based and individual victory threats, and the severity scoring ensures the most critical target is prioritized.
826-938: LGTM! Efficient and strategic targeting implementation.The steamroll detection via city count gap is sound. The caching in getValidMirvTargetPlayers reduces repeated filtering overhead, and calculateTerritoryCenter correctly implements center-mass targeting to maximize MIRV coverage within its 1500-tile radius.
Based on learnings.
941-987: LGTM! Clean MIRV execution flow.The execution methods properly sequence cooldown tracking, territory center targeting, and fallback logic. The cooldown mechanism correctly enforces the MIRV_COOLDOWN_TICKS constraint.
994-1042: LGTM! Strategic silo prioritization well-designed.The multi-condition checks account for game progression, economic position, and competitive pressure. The thresholds (5 min, 10 min, 10M gold, 20M competitive threshold) provide reasonable guardrails for strategic timing.
1048-1136: LGTM! Sophisticated economic pressure analysis.The multi-factor reserve threshold calculation (top player gap, economic level, MIRV capability pressure) creates dynamic deterrence that scales with competitive state. The weighted benchmark (60% top players, 40% average) and progressive multipliers provide nuanced responses to different threat levels.
1141-1159: LGTM! Clean reserve-aware spending interface.The getSpendableGold() and canAffordWithReserve() methods provide a clear abstraction for reserve-aware budgeting, ensuring MIRV deterrence funds are maintained across all spending decisions.
…lly (#2225) ## Description: > [!IMPORTANT] > Try here: https://mirv-test.openfront.dev/ > [!NOTE] > Blocks PRs: > - #2244 > - #2263 ### Summary Implements intelligent MIRV usage for fakehuman players, enabling them to make strategic nuclear strikes based on game state analysis. ### Changes #### Core FakeHuman Strategy (`FakeHumanExecution.ts`) - **MIRV Decision System**: Added `considerMIRV()` method that evaluates game state and determines optimal MIRV usage - **Three Strategic Targeting Modes**: 1. **Counter-MIRV**: Retaliatory strikes against players actively launching MIRVs at the fakehuman 2. **Victory Denial**: Preemptive strikes against players approaching win conditions - Team threshold: n% of total land (configurable) - Individual threshold: n% of total land (configurable) 3. **Steamroll Prevention**: Strikes against players with dominant city counts (n% ahead of next competitor) #### FakeHuman Behavior Tuning - **Cooldown System**: n-minute cooldown between MIRV attempts (configurable) - **Failure Rate**: ~n% chance of cooldown trigger without launch (simulates human hesitation/resource management; configurable) - **Territory Targeting**: Centers MIRV strikes on enemy territory center-of-mass for maximum impact #### Technical Improvements - **Type Safety**: Updated `UnitParamsMap` to include `targetTile` parameter for MIRV units - **Execution Flow**: Integrated MIRV consideration into fakehuman tick cycle outside of standard attack logic, due to its holistic strategic nature ### Game Balance Impact - **FakeHuman Threat Level**: Increases late-game fakehuman competitiveness - **Endgame Dynamics**: Prevents runaway victories, extends game tension ### Breaking Changes None - purely additive feature ### Related GitHub Issues: - #2205 ------ ## Other - [x] I have added screenshots for all UI updates - [x] I process any text displayed to the user through translateText() and I've added it to the en.json file - [x] I have added relevant tests to the test directory - [x] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced Discord Username: samsammiliah --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: Evan <evanpelle@gmail.com>
Strategic Economic Spending for FakeHuman Bots
Caution
This is a work in progress. Please do not merge.
Description:
Summary
Implements sophisticated economic decision-making for FakeHuman bots that adapts spending behavior based on competitive board state and game progression. This makes bots more strategically challenging by forcing players to consider economic pressure and MIRV deterrence.
Warning
Blocked by
Expands on and includes unmerged changes from:
Other Related Issues and PRs:
Other
Discord
samsammiliah