From 8ab9cef65bf995abecb073223292c099d25b20a0 Mon Sep 17 00:00:00 2001 From: FloPinguin <25036848+FloPinguin@users.noreply.github.com> Date: Mon, 2 Feb 2026 05:12:19 +0100 Subject: [PATCH] =?UTF-8?q?Various=20little=20nation=20improvements=20?= =?UTF-8?q?=F0=9F=A4=96=20(#3082)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description: - Maybe greet nearby players with a 👋 emoji in the earlygame (make nations feel a little bit more lively) - Destroying a transport ship / capturing a trade ship of a nation now updates the relation (mainly on higher difficulties) - On hard difficulty: Only lift embargos if we have a friendly relation. On impossible difficulty: Don't lift embargos - Improve totalPlayers calculation and return value of `hasTooManyAlliances` in `NationAllianceBehavior` ## Please complete the following: - [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 ## Please put your Discord username so you can be contacted if a bug or regression is found: FloPinguin --- src/core/execution/NationExecution.ts | 10 +++++++++- .../execution/nation/NationAllianceBehavior.ts | 10 ++++++++-- .../execution/nation/NationEmojiBehavior.ts | 18 ++++++++++++++++++ .../execution/nation/NationWarshipBehavior.ts | 15 ++++++++++++--- 4 files changed, 47 insertions(+), 6 deletions(-) diff --git a/src/core/execution/NationExecution.ts b/src/core/execution/NationExecution.ts index 854d07b03..25cc06b5a 100644 --- a/src/core/execution/NationExecution.ts +++ b/src/core/execution/NationExecution.ts @@ -360,7 +360,15 @@ export class NationExecution implements Execution { player.addEmbargo(other, false); } else if ( player.relation(other) >= Relation.Neutral && - player.hasEmbargoAgainst(other) + player.hasEmbargoAgainst(other) && + this.mg.config().gameConfig().difficulty !== Difficulty.Hard && + this.mg.config().gameConfig().difficulty !== Difficulty.Impossible + ) { + player.stopEmbargo(other); + } else if ( + player.relation(other) >= Relation.Friendly && + player.hasEmbargoAgainst(other) && + this.mg.config().gameConfig().difficulty !== Difficulty.Impossible ) { player.stopEmbargo(other); } diff --git a/src/core/execution/nation/NationAllianceBehavior.ts b/src/core/execution/nation/NationAllianceBehavior.ts index 5743b6d67..2cffd925f 100644 --- a/src/core/execution/nation/NationAllianceBehavior.ts +++ b/src/core/execution/nation/NationAllianceBehavior.ts @@ -143,10 +143,16 @@ export class NationAllianceBehavior { return false; } - const totalPlayers = this.game.players().length; + const totalPlayers = this.game + .players() + .filter((p) => p.type() !== PlayerType.Bot).length; const otherPlayerAlliances = otherPlayer.alliances().length; - return otherPlayerAlliances >= totalPlayers * 0.5; + if (difficulty !== Difficulty.Hard) { + return otherPlayerAlliances >= totalPlayers * 0.5; + } else { + return otherPlayerAlliances >= totalPlayers * 0.25; + } } private isConfused(): boolean { diff --git a/src/core/execution/nation/NationEmojiBehavior.ts b/src/core/execution/nation/NationEmojiBehavior.ts index e62515bfd..93ba8140a 100644 --- a/src/core/execution/nation/NationEmojiBehavior.ts +++ b/src/core/execution/nation/NationEmojiBehavior.ts @@ -42,6 +42,7 @@ export const EMOJI_BORED = (["🥱"] as const).map(emojiId); export const EMOJI_HANDSHAKE = (["🤝"] as const).map(emojiId); export const EMOJI_DONATION_OK = (["👍"] as const).map(emojiId); export const EMOJI_DONATION_TOO_SMALL = (["❓", "🥱"] as const).map(emojiId); +export const EMOJI_GREET = (["👋"] as const).map(emojiId); export class NationEmojiBehavior { private readonly lastEmojiSent = new Map(); @@ -63,6 +64,7 @@ export class NationEmojiBehavior { this.charmAllies(); this.annoyTraitors(); this.findRat(); + this.greetNearbyPlayers(); } private checkOverwhelmedByAttacks(): void { @@ -203,6 +205,22 @@ export class NationEmojiBehavior { this.sendEmoji(smallPlayer, EMOJI_RAT); } + private greetNearbyPlayers(): void { + if (this.game.ticks() > 600) return; // Only in the first minute + if (!this.random.chance(250)) return; + + const nearbyHumans = this.player + .neighbors() + .filter( + (p): p is Player => p.isPlayer() && p.type() === PlayerType.Human, + ); + + if (nearbyHumans.length === 0) return; + + const neighbor = this.random.randElement(nearbyHumans); + this.sendEmoji(neighbor, EMOJI_GREET); + } + maybeSendEmoji( otherPlayer: Player | typeof AllPlayers, emojisList: number[], diff --git a/src/core/execution/nation/NationWarshipBehavior.ts b/src/core/execution/nation/NationWarshipBehavior.ts index 5dc7b0344..d476e5653 100644 --- a/src/core/execution/nation/NationWarshipBehavior.ts +++ b/src/core/execution/nation/NationWarshipBehavior.ts @@ -99,7 +99,11 @@ export class NationWarshipBehavior { if (!ship.isActive()) { // Distinguish between arrival/retreat and enemy destruction if (ship.wasDestroyedByEnemy() && ship.destroyer() !== undefined) { - this.maybeRetaliateWithWarship(ship.tile(), ship.destroyer()!); + this.maybeRetaliateWithWarship( + ship.tile(), + ship.destroyer()!, + "transport", + ); } this.trackedTransportShips.delete(ship); } @@ -121,13 +125,17 @@ export class NationWarshipBehavior { } if (ship.owner().id() !== this.player.id()) { // Ship was ours and is now owned by someone else -> captured - this.maybeRetaliateWithWarship(ship.tile(), ship.owner()); + this.maybeRetaliateWithWarship(ship.tile(), ship.owner(), "trade"); this.trackedTradeShips.delete(ship); } } } - private maybeRetaliateWithWarship(tile: TileRef, enemy: Player): void { + private maybeRetaliateWithWarship( + tile: TileRef, + enemy: Player, + reason: "trade" | "transport", + ): void { // Don't send too many warships if (this.player.units(UnitType.Warship).length >= 10) { return; @@ -148,6 +156,7 @@ export class NationWarshipBehavior { new ConstructionExecution(this.player, UnitType.Warship, tile), ); this.emojiBehavior.maybeSendEmoji(enemy, EMOJI_WARSHIP_RETALIATION); + this.player.updateRelation(enemy, reason === "trade" ? -7.5 : -15); } }