mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 18:30:53 +00:00
2e442c9c29
## Description: - Create a new expand ratio that allows AI players to expand with a much lower reserve ratio than the normal attack reserve ratio. - Unify the implementation of the first attack between bots and nations. - Bugfix: Multiple attacks per tick could cause nations to full-send. - Improve the chance of finding a place to boat to by allowing nations to target non-shore land tiles. ## 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 - [x] I understand that submitting code with bugs that could have been caught through manual testing blocks releases and new features for all contributors
152 lines
4.0 KiB
TypeScript
152 lines
4.0 KiB
TypeScript
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();
|
|
});
|
|
});
|