import { BotBehavior } from "../src/core/execution/utils/BotBehavior"; import { AllianceRequest, Game, Player, PlayerInfo, PlayerType, Tick, } from "../src/core/game/Game"; import { PseudoRandom } from "../src/core/PseudoRandom"; import { setup } from "./util/Setup"; let game: Game; let player: Player; let requestor: Player; let botBehavior: BotBehavior; describe("BotBehavior.handleAllianceRequests", () => { beforeEach(async () => { game = await setup("big_plains", { infiniteGold: true, instantBuild: true, }); const playerInfo = new PlayerInfo( "player_id", PlayerType.Bot, null, "player_id", ); const requestorInfo = new PlayerInfo( "requestor_id", PlayerType.Human, null, "requestor_id", ); game.addPlayer(playerInfo); game.addPlayer(requestorInfo); player = game.player("player_id"); requestor = game.player("requestor_id"); const random = new PseudoRandom(42); botBehavior = new BotBehavior(random, game, player, 0.5, 0.5, 0.2); }); function setupAllianceRequest({ isTraitor = false, relationDelta = 2, numTilesPlayer = 10, numTilesRequestor = 10, alliancesCount = 0, } = {}) { if (isTraitor) requestor.markTraitor(); player.updateRelation(requestor, relationDelta); requestor.updateRelation(player, relationDelta); game.map().forEachTile((tile) => { if (game.map().isLand(tile)) { if (numTilesPlayer > 0) { player.conquer(tile); numTilesPlayer--; } else if (numTilesRequestor > 0) { requestor.conquer(tile); numTilesRequestor--; } } }); jest .spyOn(requestor, "alliances") .mockReturnValue(new Array(alliancesCount)); const mockRequest = { requestor: () => requestor, recipient: () => player, createdAt: () => 0 as unknown as Tick, accept: jest.fn(), reject: jest.fn(), } as unknown as AllianceRequest; jest .spyOn(player, "incomingAllianceRequests") .mockReturnValue([mockRequest]); return mockRequest; } test("should accept alliance when all conditions are met", () => { const request = setupAllianceRequest({}); botBehavior.handleAllianceRequests(); expect(request.accept).toHaveBeenCalled(); expect(request.reject).not.toHaveBeenCalled(); }); test("should reject alliance if requestor is a traitor", () => { const request = setupAllianceRequest({ isTraitor: true }); botBehavior.handleAllianceRequests(); expect(request.accept).not.toHaveBeenCalled(); expect(request.reject).toHaveBeenCalled(); }); test("should reject alliance if relation is malicious", () => { const request = setupAllianceRequest({ relationDelta: -2 }); botBehavior.handleAllianceRequests(); expect(request.accept).not.toHaveBeenCalled(); expect(request.reject).toHaveBeenCalled(); }); test("should accept alliance if requestor is much larger (> 3 times size of recipient) and has too many alliances (>= 3)", () => { const request = setupAllianceRequest({ numTilesRequestor: 40, alliancesCount: 4, }); botBehavior.handleAllianceRequests(); expect(request.accept).toHaveBeenCalled(); expect(request.reject).not.toHaveBeenCalled(); }); test("should accept alliance if requestor is much larger (> 3 times size of recipient) and does not have too many alliances (< 3)", () => { const request = setupAllianceRequest({ numTilesRequestor: 40, alliancesCount: 2, }); botBehavior.handleAllianceRequests(); expect(request.accept).toHaveBeenCalled(); expect(request.reject).not.toHaveBeenCalled(); }); test("should reject alliance if requestor is acceptably small (<= 3 times size of recipient) and has too many alliances (>= 3)", () => { const request = setupAllianceRequest({ alliancesCount: 3 }); botBehavior.handleAllianceRequests(); expect(request.accept).not.toHaveBeenCalled(); expect(request.reject).toHaveBeenCalled(); }); });