mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-05 01:46:04 +00:00
Make easy and medium nations less aggressive 📊 (#2671)
## Description: 1. Players complained that they have problems allying with nations in the earlygame. So I added an `isEarlygame()` check to `AllianceBehavior`. This should make the easier difficulties much easier :) 2. The attack order of nations now depends on the difficulty. Easy and medium nations got dumbed down, they now take nuked territory before retaliating against attacks again. 3. The attack rate now depends on the difficulty. Easy nations are reacting slower than impossible nations (to make sure the number of sent alliance requests stays the same I removed the difficulty check in `maybeSendAllianceRequests()`). 4. On easy and medium difficulty nations will sometimes just skip an attack if the enemy is a human (`shouldAttack()`). But this did not apply for the nuking logic. Now it does, which makes the easier difficulties a bit easier. 5. I tuned the `getBotAttackMaxParallelism()` method a bit. The nations are doing a bit less parallel bot attacks now, which makes the easier difficulties a bit easier. 6. The settings in MIRVBehavior now depend on the difficulty. On easy difficulty, nations will only send MIRVs very rarely. 7. Unrelated MIRVBehavior Cleanup: There was a 2 second cooldown and cache logic. But it was completely useless because `considerMIRV()` is only called every 4-8 seconds by NationExecution. So I removed it. 8. Unrelated little cleanup: I made a couple of methods `private` ## 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
This commit is contained in:
@@ -18,7 +18,12 @@ import { TileRef, euclDistFN } from "../game/GameMap";
|
||||
import { canBuildTransportShip } from "../game/TransportShipUtils";
|
||||
import { PseudoRandom } from "../PseudoRandom";
|
||||
import { GameID } from "../Schemas";
|
||||
import { boundingBoxTiles, calculateBoundingBox, simpleHash } from "../Util";
|
||||
import {
|
||||
assertNever,
|
||||
boundingBoxTiles,
|
||||
calculateBoundingBox,
|
||||
simpleHash,
|
||||
} from "../Util";
|
||||
import { ConstructionExecution } from "./ConstructionExecution";
|
||||
import { NationAllianceBehavior } from "./nation/NationAllianceBehavior";
|
||||
import { NationEmojiBehavior } from "./nation/NationEmojiBehavior";
|
||||
@@ -61,8 +66,6 @@ export class NationExecution implements Execution {
|
||||
this.random = new PseudoRandom(
|
||||
simpleHash(nation.playerInfo.id) + simpleHash(gameID),
|
||||
);
|
||||
this.attackRate = this.random.nextInt(40, 80);
|
||||
this.attackTick = this.random.nextInt(0, this.attackRate);
|
||||
this.triggerRatio = this.random.nextInt(50, 60) / 100;
|
||||
this.reserveRatio = this.random.nextInt(30, 40) / 100;
|
||||
this.expandRatio = this.random.nextInt(10, 20) / 100;
|
||||
@@ -70,9 +73,8 @@ export class NationExecution implements Execution {
|
||||
|
||||
init(mg: Game) {
|
||||
this.mg = mg;
|
||||
if (this.random.chance(10)) {
|
||||
// this.isTraitor = true
|
||||
}
|
||||
this.attackRate = this.getAttackRate();
|
||||
this.attackTick = this.random.nextInt(0, this.attackRate);
|
||||
|
||||
if (!this.mg.hasPlayer(this.nation.playerInfo.id)) {
|
||||
this.player = this.mg.addPlayer(this.nation.playerInfo);
|
||||
@@ -81,6 +83,22 @@ export class NationExecution implements Execution {
|
||||
}
|
||||
}
|
||||
|
||||
private getAttackRate(): number {
|
||||
const { difficulty } = this.mg.config().gameConfig();
|
||||
switch (difficulty) {
|
||||
case Difficulty.Easy:
|
||||
return this.random.nextInt(65, 80); // Slower reactions
|
||||
case Difficulty.Medium:
|
||||
return this.random.nextInt(55, 70);
|
||||
case Difficulty.Hard:
|
||||
return this.random.nextInt(45, 60);
|
||||
case Difficulty.Impossible:
|
||||
return this.random.nextInt(30, 50); // Faster reactions
|
||||
default:
|
||||
assertNever(difficulty);
|
||||
}
|
||||
}
|
||||
|
||||
tick(ticks: number) {
|
||||
// Ship tracking
|
||||
if (
|
||||
@@ -495,7 +513,7 @@ export class NationExecution implements Execution {
|
||||
);
|
||||
}
|
||||
|
||||
sendBoatRandomly(borderingEnemies: Player[] = []) {
|
||||
private sendBoatRandomly(borderingEnemies: Player[] = []) {
|
||||
if (this.player === null) throw new Error("not initialized");
|
||||
const oceanShore = Array.from(this.player.borderTiles()).filter((t) =>
|
||||
this.mg.isOceanShore(t),
|
||||
@@ -590,14 +608,16 @@ export class NationExecution implements Execution {
|
||||
}
|
||||
|
||||
private maybeSendNuke(other: Player | null) {
|
||||
if (this.player === null) throw new Error("not initialized");
|
||||
if (this.player === null || this.attackBehavior === null)
|
||||
throw new Error("not initialized");
|
||||
const silos = this.player.units(UnitType.MissileSilo);
|
||||
if (
|
||||
silos.length === 0 ||
|
||||
this.player.gold() < this.cost(UnitType.AtomBomb) ||
|
||||
other === null ||
|
||||
other.type() === PlayerType.Bot || // Don't nuke bots (as opposed to nations and humans)
|
||||
this.player.isOnSameTeam(other)
|
||||
this.player.isOnSameTeam(other) ||
|
||||
this.attackBehavior.shouldAttack(other) === false
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user