mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-08-18 17:53:29 +00:00
Nations now gang up on players and prioritize traitors/AFK players 🤖 (+ other improvements) (#2730)
## Description: - **Nations now specifically target AFK players, traitors, and players who are already being attacked (they gang up on them).** Depends on the difficulty. - Added ally assistance directly to the attack order (instead of calling it separately beforehand). - Added ally assistance to `findBestNukeTarget`. - Removed some checks from `findBestNukeTarget` (not necessary; better checks will follow in a dedicated nuking PR). - Relation updates on attack now depend on difficulty (makes Easy & Medium nations a bit easier). - On betrayal, every nation in the game previously received a –40 relation penalty toward the betrayer. That was too extreme, so now this only applies only to neighbors. - Nations send fewer alliance requests now; it felt like too many before. - In team games, nations may now reject alliance requests more often (depending on difficulty). - To ensure there are enough non-friendly players to stop the crown with nukes, nations may now reject alliance requests if the other player has too many alliances (on Hard and Impossible difficulty). - Rebalanced nation emoji usage a bit. - Nations may now send an emoji when they get MIRVed. ## 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 --------- Co-authored-by: iamlewis <lewismmmm@gmail.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import {
|
||||
Difficulty,
|
||||
Game,
|
||||
GameMode,
|
||||
Player,
|
||||
PlayerType,
|
||||
Relation,
|
||||
@@ -59,7 +60,7 @@ export class NationAllianceBehavior {
|
||||
|
||||
for (const enemy of borderingEnemies) {
|
||||
if (
|
||||
this.random.chance(20) &&
|
||||
this.random.chance(30) &&
|
||||
isAcceptablePlayerType(enemy) &&
|
||||
this.player.canSendAllianceRequest(enemy) &&
|
||||
this.getAllianceDecision(enemy, false)
|
||||
@@ -86,18 +87,27 @@ export class NationAllianceBehavior {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// Reject if otherPlayer has allied with 50% or more of all players (Hard and Impossible only)
|
||||
// To make sure there are enough non-friendly players in the game to stop the crown with nukes
|
||||
if (this.hasTooManyAlliances(otherPlayer)) {
|
||||
return false;
|
||||
}
|
||||
// Before caring about the relation, first check if the otherPlayer is a threat
|
||||
// Easy (dumb) nations are blinded by hatred, they don't care about threats, they care about the relation
|
||||
// Impossible (smart) nations on the other hand are analyzing the facts
|
||||
if (this.isAlliancePartnerThreat(otherPlayer)) {
|
||||
if (!isResponse && this.random.chance(3)) {
|
||||
if (!isResponse && this.random.chance(6)) {
|
||||
this.emojiBehavior.sendEmoji(otherPlayer, EMOJI_SCARED_OF_THREAT);
|
||||
}
|
||||
if (isResponse && this.random.chance(3)) {
|
||||
if (isResponse && this.random.chance(6)) {
|
||||
this.emojiBehavior.sendEmoji(otherPlayer, EMOJI_LOVE);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// Maybe reject if we are in a team game (allying makes less sense there)
|
||||
if (this.shouldRejectInTeamGame()) {
|
||||
return false;
|
||||
}
|
||||
// Reject if relation is bad
|
||||
if (this.player.relation(otherPlayer) < Relation.Neutral) {
|
||||
if (isResponse && this.random.chance(3)) {
|
||||
@@ -124,6 +134,21 @@ export class NationAllianceBehavior {
|
||||
return this.isAlliancePartnerSimilarlyStrong(otherPlayer);
|
||||
}
|
||||
|
||||
private hasTooManyAlliances(otherPlayer: Player): boolean {
|
||||
const { difficulty } = this.game.config().gameConfig();
|
||||
if (
|
||||
difficulty !== Difficulty.Hard &&
|
||||
difficulty !== Difficulty.Impossible
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const totalPlayers = this.game.players().length;
|
||||
const otherPlayerAlliances = otherPlayer.alliances().length;
|
||||
|
||||
return otherPlayerAlliances >= totalPlayers * 0.5;
|
||||
}
|
||||
|
||||
private isConfused(): boolean {
|
||||
const { difficulty } = this.game.config().gameConfig();
|
||||
switch (difficulty) {
|
||||
@@ -207,6 +232,26 @@ export class NationAllianceBehavior {
|
||||
}
|
||||
}
|
||||
|
||||
private shouldRejectInTeamGame(): boolean {
|
||||
if (this.game.config().gameConfig().gameMode !== GameMode.Team) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const { difficulty } = this.game.config().gameConfig();
|
||||
switch (difficulty) {
|
||||
case Difficulty.Easy:
|
||||
return false; // 0% chance to reject on easy
|
||||
case Difficulty.Medium:
|
||||
return this.random.nextInt(0, 100) < 20; // 20% chance to reject on medium
|
||||
case Difficulty.Hard:
|
||||
return this.random.nextInt(0, 100) < 40; // 40% chance to reject on hard
|
||||
case Difficulty.Impossible:
|
||||
return this.random.nextInt(0, 100) < 60; // 60% chance to reject on impossible
|
||||
default:
|
||||
assertNever(difficulty);
|
||||
}
|
||||
}
|
||||
|
||||
private checkAlreadyEnoughAlliances(otherPlayer: Player): boolean {
|
||||
const { difficulty } = this.game.config().gameConfig();
|
||||
switch (difficulty) {
|
||||
|
||||
Reference in New Issue
Block a user