-
Notifications
You must be signed in to change notification settings - Fork 785
Nations donate troops now 💀 (In team games) #2984
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
Nations donate troops now 💀 (In team games) #2984
Conversation
WalkthroughAdds AI troop-donation into attack flow, enforces transport and shore guards for sea attacks, expands attack triggers (Bots, HvN), updates emoji win detection to use Game.getWinner(), and exposes Game.getWinner/getWinner state in GameImpl. Changes
Sequence Diagram(s)sequenceDiagram
participant AI as AiAttackBehavior
participant Game as Game
participant Queue as ExecutionQueue
participant TE as Teammate
participant EN as EnemyTarget
AI->>Game: evaluateAttackConditions()
Game-->>AI: returns state (mode, transports, shoreTiles, teammates, flags, winner)
alt winner exists
AI->>AI: set gameOver and stop casual emoji sends
end
alt donation applicable (team mode & flag & difficulty prob)
AI->>AI: donateTroops() selects teammate with lowest troop %
AI->>Queue: enqueue DonateTroopsExecution(to TE, amount)
Queue-->>Game: schedule troop transfer
else attempt attack
AI->>Game: check transport limits & shore tiles
alt boat attack allowed
AI->>Queue: enqueue AttackExecution(target EN via transport)
else boat blocked
AI->>AI: abort boat attack / fallback strategies
end
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 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: 2
🤖 Fix all issues with AI agents
In `@src/core/execution/utils/AiAttackBehavior.ts`:
- Around line 809-814: The team percentage calculation can divide by zero when
numTilesWithoutFallout is 0; inside the AiAttackBehavior code where
numTilesWithoutFallout is computed (using this.game.numLandTiles() -
this.game.numTilesWithFallout()), add a guard that checks if
numTilesWithoutFallout === 0 and return false (or otherwise short-circuit the
win-check) before computing teamPercent and comparing to
this.game.config().percentageTilesOwnedToWin(); this prevents the division by
zero while preserving the existing logic in the method.
- Around line 672-683: The shouldAttack method in AiAttackBehavior uses the
magic string "Humans Vs Nations" to check playerTeams; replace that literal with
the exported constant HumansVsNations (from src/core/game/Game.ts) to match
project conventions. Import HumansVsNations at the top of AiAttackBehavior and
update the condition (the check inside shouldAttack that compares
this.game.config().gameConfig().playerTeams) to use the HumansVsNations constant
instead of the string literal.
| const myTeam = this.player.team(); | ||
| if (myTeam !== null) { | ||
| let teamTiles = 0; | ||
| for (const player of this.game.players()) { | ||
| if (player.team() === myTeam) { | ||
| teamTiles += player.numTilesOwned(); | ||
| } | ||
| } | ||
| const numTilesWithoutFallout = | ||
| this.game.numLandTiles() - this.game.numTilesWithFallout(); | ||
| const teamPercent = (teamTiles / numTilesWithoutFallout) * 100; | ||
| if (teamPercent >= this.game.config().percentageTilesOwnedToWin()) { | ||
| return false; | ||
| } | ||
| } | ||
|
|
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.
instead add getWinner on Game
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.
oh thats a much easier solution. I removed the big check and removed an even bigger winner check from NationEmojiBehavior
| return false; | ||
| } | ||
|
|
||
| // Don't donate if our team has won (otherwise nations will keep donating forever, circularly) |
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.
should we stop donation if any team has won?
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.
makes sense
|
|
||
| // Find teammates | ||
| const teammates = this.game.players().filter((p) => { | ||
| if (p === this.player) return false; |
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.
this check isn't necessary, player.isOnSameTeam already checks this case.
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.
You are right :o
|
Warning: I didn't just address the feedback, but also added new things:
|
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 (1)
src/core/execution/nation/NationEmojiBehavior.ts (1)
111-137: Add explicit type guard for team-game winner to match FFA pattern.In team-game mode (line 120-124), the code assumes
winneris aTeamstring when comparing at line 122, but the type signature allowsPlayer | Teamfor all callers. Unlike the FFA branch (line 127) which checkstypeof winner === "string", the team branch has no guard. If a bug causesPlayerto be passed instead ofTeam, the comparison silently fails without error.Add the guard to match the FFA pattern:
Suggested fix
if (isTeamGame) { // Team game: all nations congratulate if another team won // Don't congratulate if it's our own team + if (typeof winner === "string") { + if (winner === this.player.team()) return; + } else { + // If winner is Player, congratulate (should not happen in team mode) + return; + } - if (winner === this.player.team()) return; this.sendEmoji(AllPlayers, EMOJI_CONGRATULATE);
🧹 Nitpick comments (1)
src/core/execution/utils/AiAttackBehavior.ts (1)
537-599: Optional: cache shore tiles once to avoid recompute in the loop.This avoids repeated
Array.from(...).filter(...)for every candidate.♻️ Possible tweak
- const sortedPlayers = filteredPlayers + const shoreTiles = Array.from(this.player.borderTiles()).filter((t) => + this.game.isOceanShore(t), + ); + const sortedPlayers = filteredPlayers .map((filteredPlayer) => { @@ - for (const entry of sortedPlayers) { + for (const entry of sortedPlayers) { const closest = closestTwoTiles( this.game, - Array.from(this.player.borderTiles()).filter((t) => - this.game.isOceanShore(t), - ), + shoreTiles, Array.from(entry.player.borderTiles()).filter((t) => this.game.isOceanShore(t), ), );
evanpelle
left a 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.
thanks!
Description:
For v29, balances the HvN winrate.
In team games, nations now donate troops to their weakest team members (if they have no attack options available).
How often they donate depends on the difficulty.
This PR also has some other little fixes:
shouldAttack()(make nations a bit more aggressive).attackWithRandomBoat()for performancefindNearestIslandEnemy()for performance AND to make sure nations which are encircled by friends don't run into this method (=> no donation happening!)Please complete the following:
Please put your Discord username so you can be contacted if a bug or regression is found:
FloPinguin