mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 11:10:42 +00:00
Fix non-human player never responding to alliance renewal request
This commit is contained in:
@@ -105,7 +105,11 @@ export class Executor {
|
||||
case "build_unit":
|
||||
return new ConstructionExecution(player, intent.unit, intent.tile);
|
||||
case "allianceExtension": {
|
||||
return new AllianceExtensionExecution(player, intent.recipient);
|
||||
return new AllianceExtensionExecution(
|
||||
this.gameID,
|
||||
player,
|
||||
intent.recipient,
|
||||
);
|
||||
}
|
||||
|
||||
case "upgrade_structure":
|
||||
|
||||
@@ -4,13 +4,22 @@ import {
|
||||
MessageType,
|
||||
Player,
|
||||
PlayerID,
|
||||
PlayerType,
|
||||
} from "../../game/Game";
|
||||
import { PseudoRandom } from "../../PseudoRandom";
|
||||
import { GameID } from "../../Schemas";
|
||||
import { simpleHash } from "../../Util";
|
||||
|
||||
export class AllianceExtensionExecution implements Execution {
|
||||
private random: PseudoRandom;
|
||||
|
||||
constructor(
|
||||
gameID: GameID,
|
||||
private readonly from: Player,
|
||||
private readonly toID: PlayerID,
|
||||
) {}
|
||||
) {
|
||||
this.random = new PseudoRandom(simpleHash(toID) + simpleHash(gameID));
|
||||
}
|
||||
|
||||
init(mg: Game, ticks: number): void {
|
||||
if (!mg.hasPlayer(this.toID)) {
|
||||
@@ -36,27 +45,26 @@ export class AllianceExtensionExecution implements Execution {
|
||||
return;
|
||||
}
|
||||
|
||||
// Mark this player's intent to extend
|
||||
alliance.addExtensionRequest(this.from);
|
||||
|
||||
if (alliance.canExtend()) {
|
||||
alliance.extend();
|
||||
|
||||
mg.displayMessage(
|
||||
"events_display.alliance_renewed",
|
||||
MessageType.ALLIANCE_ACCEPTED,
|
||||
this.from.id(),
|
||||
undefined,
|
||||
{ name: to.displayName() },
|
||||
);
|
||||
mg.displayMessage(
|
||||
"events_display.alliance_renewed",
|
||||
MessageType.ALLIANCE_ACCEPTED,
|
||||
this.toID,
|
||||
undefined,
|
||||
{ name: this.from.displayName() },
|
||||
);
|
||||
if (to.type() !== PlayerType.Human) {
|
||||
if (!this.random.chance(1.3)) return;
|
||||
} else {
|
||||
// Mark this player's intent to extend
|
||||
alliance.addExtensionRequest(this.from);
|
||||
if (!alliance.canExtend()) return;
|
||||
}
|
||||
|
||||
alliance.extend();
|
||||
|
||||
mg.displayMessage(
|
||||
"events_display.alliance_renewed",
|
||||
MessageType.ALLIANCE_ACCEPTED,
|
||||
this.from.id(),
|
||||
);
|
||||
mg.displayMessage(
|
||||
"events_display.alliance_renewed",
|
||||
MessageType.ALLIANCE_ACCEPTED,
|
||||
this.toID,
|
||||
);
|
||||
}
|
||||
|
||||
tick(ticks: number): void {
|
||||
|
||||
@@ -7,6 +7,8 @@ import { playerInfo, setup } from "./util/Setup";
|
||||
let game: Game;
|
||||
let player1: Player;
|
||||
let player2: Player;
|
||||
let player3: Player;
|
||||
const gameID = "1b3xq";
|
||||
|
||||
describe("AllianceExtensionExecution", () => {
|
||||
beforeEach(async () => {
|
||||
@@ -20,19 +22,23 @@ describe("AllianceExtensionExecution", () => {
|
||||
[
|
||||
playerInfo("player1", PlayerType.Human),
|
||||
playerInfo("player2", PlayerType.Human),
|
||||
playerInfo("player3", PlayerType.FakeHuman),
|
||||
],
|
||||
);
|
||||
|
||||
player1 = game.player("player1");
|
||||
player2 = game.player("player2");
|
||||
player3 = game.player("player3");
|
||||
|
||||
while (game.inSpawnPhase()) {
|
||||
game.executeNextTick();
|
||||
}
|
||||
});
|
||||
|
||||
test("Successfully extends existing alliance", () => {
|
||||
test("Successfully extends existing alliance between Humans", () => {
|
||||
jest.spyOn(player1, "canSendAllianceRequest").mockReturnValue(true);
|
||||
jest.spyOn(player2, "isAlive").mockReturnValue(true);
|
||||
jest.spyOn(player1, "isAlive").mockReturnValue(true);
|
||||
game.addExecution(new AllianceRequestExecution(player1, player2.id()));
|
||||
game.executeNextTick();
|
||||
game.executeNextTick();
|
||||
@@ -47,27 +53,69 @@ describe("AllianceExtensionExecution", () => {
|
||||
expect(player2.allianceWith(player1)).toBeTruthy();
|
||||
|
||||
const allianceBefore = player1.allianceWith(player2)!;
|
||||
const expirationBefore =
|
||||
allianceBefore.createdAt() + game.config().allianceDuration();
|
||||
const allianceSpy = jest.spyOn(allianceBefore, "extend");
|
||||
const expirationBefore = allianceBefore.expiresAt();
|
||||
|
||||
game.addExecution(new AllianceExtensionExecution(player1, player2.id()));
|
||||
game.addExecution(
|
||||
new AllianceExtensionExecution(gameID, player1, player2.id()),
|
||||
);
|
||||
game.executeNextTick();
|
||||
expect(allianceSpy).toHaveBeenCalledTimes(0); // both players must agree to extend
|
||||
game.addExecution(
|
||||
new AllianceExtensionExecution(gameID, player2, player1.id()),
|
||||
);
|
||||
game.executeNextTick();
|
||||
|
||||
const allianceAfter = player1.allianceWith(player2)!;
|
||||
|
||||
expect(allianceAfter.id()).toBe(allianceBefore.id());
|
||||
|
||||
const expirationAfter =
|
||||
allianceAfter.createdAt() + game.config().allianceDuration();
|
||||
const expirationAfter = allianceAfter.expiresAt();
|
||||
|
||||
expect(expirationAfter).toBeGreaterThanOrEqual(expirationBefore);
|
||||
expect(expirationAfter).toBeGreaterThan(expirationBefore);
|
||||
expect(allianceSpy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test("Fails gracefully if no alliance exists", () => {
|
||||
game.addExecution(new AllianceExtensionExecution(player1, player2.id()));
|
||||
game.addExecution(
|
||||
new AllianceExtensionExecution(gameID, player1, player2.id()),
|
||||
);
|
||||
game.executeNextTick();
|
||||
|
||||
expect(player1.allianceWith(player2)).toBeFalsy();
|
||||
expect(player2.allianceWith(player1)).toBeFalsy();
|
||||
});
|
||||
|
||||
test("Successfully extends existing alliance between Human and non-Human", () => {
|
||||
jest.spyOn(player1, "canSendAllianceRequest").mockReturnValue(true);
|
||||
jest.spyOn(player3, "isAlive").mockReturnValue(true);
|
||||
jest.spyOn(player1, "isAlive").mockReturnValue(true);
|
||||
|
||||
game.addExecution(new AllianceRequestExecution(player1, player3.id()));
|
||||
game.executeNextTick();
|
||||
game.executeNextTick();
|
||||
|
||||
game.addExecution(
|
||||
new AllianceRequestReplyExecution(player1.id(), player3, true),
|
||||
);
|
||||
game.executeNextTick();
|
||||
game.executeNextTick();
|
||||
|
||||
expect(player1.allianceWith(player3)).toBeTruthy();
|
||||
expect(player3.allianceWith(player1)).toBeTruthy();
|
||||
|
||||
const allianceBefore = player1.allianceWith(player3)!;
|
||||
const expirationBefore = allianceBefore.expiresAt();
|
||||
|
||||
const exec = new AllianceExtensionExecution(gameID, player1, player3.id());
|
||||
jest.spyOn(exec["random"], "chance").mockReturnValue(true);
|
||||
game.addExecution(exec);
|
||||
game.executeNextTick();
|
||||
|
||||
const allianceAfter = player1.allianceWith(player3)!;
|
||||
expect(allianceAfter.id()).toBe(allianceBefore.id());
|
||||
|
||||
const expirationAfter = allianceBefore.expiresAt();
|
||||
expect(expirationAfter).toBeGreaterThan(expirationBefore);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user