Skip to content

Commit

Permalink
Finally fixed bug with advance
Browse files Browse the repository at this point in the history
  • Loading branch information
xpmatteo committed Nov 5, 2023
1 parent 887521d commit 9af4d61
Show file tree
Hide file tree
Showing 7 changed files with 176 additions and 40 deletions.
14 changes: 3 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,6 @@ image to appear. The parameters are:
* iterations, playouts: configure AI parameters



# URGENT

Recently I tried to fix a bug: if a unit ignores flags and stays in its hex, it should battle back.

- now the AI is broken
- it is possible to keep ignoring flags and battling back multiple times!
- change Phase#onClick so that it returns a command to execute -- this will make it easier to test

# AI TESTS

- Early game
Expand Down Expand Up @@ -72,12 +63,13 @@ Recently I tried to fix a bug: if a unit ignores flags and stays in its hex, it

- evasion
- more cards
- advance after combat
- cavalry, chariot battle again after advance
- cavalry bonus movement
- cavalry, chariot bonus combat
- leaders
- terrain
- "if you don't have any X unit, order a unit of your choice"
- heavy chariot battles back with 3 dice not 4
- heavy chariot ignores one sword result
- warriors, elephants, other units


123 changes: 110 additions & 13 deletions src/ai/__snapshots__/mcts_player.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ exports[`2 on 2 1`] = `
333/1999: End phase -> Roman movement -> 1
333/1998: MacroCommand(Move [-1,6] to [0,5],Move [0,6] to [1,5]) -> Roman battle -> 3
CHANCE/49: Close Combat from [1,5] to [1,4] -> Roman battle -> 6
-8/8: Close Combat from [1,5] to [1,4] -> Roman retreat -> 2
-8/8: Close Combat from [1,5] to [1,4] -> Roman attacker retreat -> 2
-4/4: Retreat [1,5] to [0,6] -> Roman battle -> 2
-4/4: Retreat [1,5] to [1,6] -> Roman battle -> 2
-17/20: Close Combat from [1,5] to [1,4] -> Carthaginian retreat -> 2
0/0: Retreat [1,4] to [2,3] -> Roman advance after combat -> 0
17/20: Retreat [1,4] to [1,3] -> Roman advance after combat -> 2
-4/7: Close Combat from [1,5] to [1,4] -> Roman retreat -> 2
-4/7: Close Combat from [1,5] to [1,4] -> Roman attacker retreat -> 2
-2/5: Retreat [1,5] to [0,6] -> Roman battle -> 2
-2/2: Retreat [1,5] to [1,6] -> Roman battle -> 2
-4/4: Close Combat from [1,5] to [1,4] -> Carthaginian retreat -> 2
Expand All @@ -21,18 +21,18 @@ exports[`2 on 2 1`] = `
-2/2: Close Combat from [1,5] to [1,4] -> Carthaginian retreat -> 2
2/2: Retreat [1,4] to [2,3] -> Roman advance after combat -> 2
0/0: Retreat [1,4] to [1,3] -> Roman advance after combat -> 0
2/7: Close Combat from [1,5] to [1,4] -> Roman retreat -> 2
2/7: Close Combat from [1,5] to [1,4] -> Roman attacker retreat -> 2
2/4: Retreat [1,5] to [0,6] -> Roman battle -> 2
0/3: Retreat [1,5] to [1,6] -> Roman battle -> 2
CHANCE/740: Close Combat from [0,5] to [0,4] -> Roman battle -> 2
-137/472: Close Combat from [0,5] to [0,4] -> Carthaginian retreat -> 2
0/0: Retreat [0,4] to [0,3] -> Roman advance after combat -> 0
137/472: Retreat [0,4] to [1,3] -> Roman advance after combat -> 2
84/267: Close Combat from [0,5] to [0,4] -> Roman retreat -> 2
84/267: Close Combat from [0,5] to [0,4] -> Roman attacker retreat -> 2
81/209: Retreat [0,5] to [-1,6] -> Roman battle -> 1
3/58: Retreat [0,5] to [0,6] -> Roman battle -> 1
CHANCE/1210: Close Combat from [0,5] to [1,4] -> Roman battle -> 5
126/347: Close Combat from [0,5] to [1,4] -> Roman retreat -> 2
126/347: Close Combat from [0,5] to [1,4] -> Roman attacker retreat -> 2
131/298: Retreat [0,5] to [-1,6] -> Roman battle -> 1
-5/49: Retreat [0,5] to [0,6] -> Roman battle -> 1
108/511: Close Combat from [0,5] to [1,4] -> Carthaginian retreat -> 2
Expand All @@ -41,7 +41,7 @@ exports[`2 on 2 1`] = `
-70/133: Close Combat from [0,5] to [1,4] -> Carthaginian retreat -> 2
70/133: Retreat [1,4] to [2,3] -> Roman advance after combat -> 2
0/0: Retreat [1,4] to [1,3] -> Roman advance after combat -> 0
-66/110: Close Combat from [0,5] to [1,4] -> Roman retreat -> 2
-66/110: Close Combat from [0,5] to [1,4] -> Roman attacker retreat -> 2
-32/52: Retreat [0,5] to [-1,6] -> Roman battle -> 1
-34/58: Retreat [0,5] to [0,6] -> Roman battle -> 1
-76/108: Close Combat from [0,5] to [1,4] -> Carthaginian retreat -> 2
Expand All @@ -53,22 +53,22 @@ exports[`2 on 2 1`] = `
exports[`close combat from light to heavy 1`] = `
"-24/30: undefined -> Roman play one card -> 1
-24/30: PlayCard(Order Light Troops) -> Roman order 1 light units -> 1
-23/29: End phase -> Roman movement -> 1
-24/29: End phase -> Roman movement -> 1
-23/28: MacroCommand(Move [2,3] to [3,2]) -> Roman battle -> 1
CHANCE/27: Close Combat from [3,2] to [2,2] -> Roman battle -> 5
-1/4: Close Combat from [3,2] to [2,2] -> Carthaginian retreat -> 2
1/4: Retreat [2,2] to [2,1] -> Roman advance after combat -> 2
0/1: Retreat [3,2] to [2,2] -> Roman battle -> 0
2/2: Retreat [3,2] to [3,2] -> Roman battle -> 1
0/1: Momentum advance [3,2] to [2,2] -> Roman battle -> 0
2/2: Skip Momentum Advance -> Roman battle -> 1
0/0: Retreat [2,2] to [3,1] -> Roman advance after combat -> 0
-8/8: Close Combat from [3,2] to [2,2] -> Roman retreat -> 3
-8/8: Close Combat from [3,2] to [2,2] -> Roman attacker retreat -> 3
-3/3: Retreat [3,2] to [2,4] -> Roman battle -> 1
2/2: End phase -> Carthaginian play one card -> 1
-2/2: Retreat [3,2] to [3,4] -> Roman battle -> 1
2/2: End phase -> Carthaginian play one card -> 1
-3/3: Retreat [3,2] to [1,4] -> Roman battle -> 1
3/3: End phase -> Carthaginian play one card -> 1
-4/4: Close Combat from [3,2] to [2,2] -> Roman retreat -> 3
-4/4: Close Combat from [3,2] to [2,2] -> Roman attacker retreat -> 3
-2/2: Retreat [3,2] to [1,4] -> Roman battle -> 1
1/1: End phase -> Carthaginian play one card -> 0
-1/1: Retreat [3,2] to [3,4] -> Roman battle -> 1
Expand All @@ -77,11 +77,108 @@ exports[`close combat from light to heavy 1`] = `
1/1: End phase -> Carthaginian play one card -> 0
3/3: Close Combat from [3,2] to [2,2] -> Carthaginian retreat -> 2
-3/3: Retreat [2,2] to [3,1] -> Roman advance after combat -> 2
-1/1: Retreat [3,2] to [2,2] -> Roman battle -> 0
-1/1: Retreat [3,2] to [3,2] -> Roman battle -> 1
-1/1: Momentum advance [3,2] to [2,2] -> Roman battle -> 0
-1/1: Skip Momentum Advance -> Roman battle -> 1
0/0: Retreat [2,2] to [2,1] -> Roman advance after combat -> 0
-7/7: Close Combat from [3,2] to [2,2] -> Roman battle -> 1
7/7: End phase -> Carthaginian play one card -> 1
6/6: PlayCard(Order Heavy Troops) -> Carthaginian order 1 heavy units -> 1
"
`;

exports[`melee 1`] = `
"600/2000: undefined -> Roman play one card -> 1
600/2000: PlayCard(Order Heavy Troops) -> Roman order 3 heavy units -> 4
216/666: OrderUnit([0,5],[1,5],[3,5]) -> Roman order 3 heavy units -> 1
216/666: End phase -> Roman movement -> 1
217/665: MacroCommand(Move [1,5] to [2,4],Move [0,5] to [1,4],Move [3,5] to [3,4]) -> Roman battle -> 5
CHANCE/334: Close Combat from [3,4] to [3,3] -> Roman battle -> 3
66/90: Close Combat from [3,4] to [3,3] -> Roman attacker retreat -> 2
-3/208: Close Combat from [3,4] to [3,3] -> Carthaginian retreat -> 3
31/35: Close Combat from [3,4] to [3,3] -> Roman attacker retreat -> 2
CHANCE/151: Close Combat from [2,4] to [3,3] -> Roman battle -> 2
12/56: Close Combat from [2,4] to [3,3] -> Roman attacker retreat -> 2
-1/94: Close Combat from [2,4] to [3,3] -> Carthaginian retreat -> 3
CHANCE/70: Close Combat from [1,4] to [2,3] -> Roman battle -> 2
-28/42: Close Combat from [1,4] to [2,3] -> Carthaginian retreat -> 2
19/27: Close Combat from [1,4] to [2,3] -> Roman attacker retreat -> 2
CHANCE/31: Close Combat from [3,4] to [4,3] -> Roman battle -> 6
-1/5: Close Combat from [3,4] to [4,3] -> Carthaginian retreat -> 2
-12/13: Close Combat from [3,4] to [4,3] -> Carthaginian retreat -> 2
-2/3: Close Combat from [3,4] to [4,3] -> Roman attacker retreat -> 2
1/5: Close Combat from [3,4] to [4,3] -> Roman attacker retreat -> 2
2/2: Close Combat from [3,4] to [4,3] -> Roman attacker retreat -> 2
-2/2: Close Combat from [3,4] to [4,3] -> Carthaginian retreat -> 2
CHANCE/82: Close Combat from [2,4] to [2,3] -> Roman battle -> 2
18/34: Close Combat from [2,4] to [2,3] -> Roman attacker retreat -> 2
-25/47: Close Combat from [2,4] to [2,3] -> Carthaginian retreat -> 2
116/422: OrderUnit([0,5],[1,5],[2,5]) -> Roman order 3 heavy units -> 1
116/422: End phase -> Roman movement -> 1
117/421: MacroCommand(Move [1,5] to [2,4],Move [2,5] to [3,4],Move [0,5] to [1,4]) -> Roman battle -> 5
CHANCE/22: Close Combat from [1,4] to [2,3] -> Roman battle -> 2
-9/13: Close Combat from [1,4] to [2,3] -> Carthaginian retreat -> 2
-1/8: Close Combat from [1,4] to [2,3] -> Roman attacker retreat -> 2
CHANCE/43: Close Combat from [2,4] to [2,3] -> Roman battle -> 2
10/18: Close Combat from [2,4] to [2,3] -> Roman attacker retreat -> 3
-17/24: Close Combat from [2,4] to [2,3] -> Carthaginian retreat -> 2
CHANCE/15: Close Combat from [3,4] to [4,3] -> Roman battle -> 5
1/1: Close Combat from [3,4] to [4,3] -> Roman attacker retreat -> 2
-2/2: Close Combat from [3,4] to [4,3] -> Carthaginian retreat -> 2
-6/7: Close Combat from [3,4] to [4,3] -> Carthaginian retreat -> 2
-1/2: Close Combat from [3,4] to [4,3] -> Roman attacker retreat -> 2
-2/2: Close Combat from [3,4] to [4,3] -> Carthaginian retreat -> 2
CHANCE/58: Close Combat from [2,4] to [3,3] -> Roman battle -> 2
1/16: Close Combat from [2,4] to [3,3] -> Roman attacker retreat -> 3
-4/41: Close Combat from [2,4] to [3,3] -> Carthaginian retreat -> 3
CHANCE/286: Close Combat from [3,4] to [3,3] -> Roman battle -> 2
14/169: Close Combat from [3,4] to [3,3] -> Carthaginian retreat -> 3
81/116: Close Combat from [3,4] to [3,3] -> Roman attacker retreat -> 2
257/756: OrderUnit([0,5],[2,5],[3,5]) -> Roman order 3 heavy units -> 1
256/755: End phase -> Roman movement -> 1
257/754: MacroCommand(Move [2,5] to [2,4],Move [0,5] to [1,4],Move [3,5] to [3,4]) -> Roman battle -> 5
CHANCE/32: Close Combat from [1,4] to [2,3] -> Roman battle -> 2
-15/18: Close Combat from [1,4] to [2,3] -> Carthaginian retreat -> 2
-3/13: Close Combat from [1,4] to [2,3] -> Roman attacker retreat -> 2
CHANCE/215: Close Combat from [2,4] to [3,3] -> Roman battle -> 2
9/93: Close Combat from [2,4] to [3,3] -> Roman attacker retreat -> 2
2/121: Close Combat from [2,4] to [3,3] -> Carthaginian retreat -> 3
CHANCE/75: Close Combat from [3,4] to [4,3] -> Roman battle -> 6
-4/8: Close Combat from [3,4] to [4,3] -> Carthaginian retreat -> 2
2/12: Close Combat from [3,4] to [4,3] -> Roman attacker retreat -> 2
-6/6: Close Combat from [3,4] to [4,3] -> Carthaginian retreat -> 2
-17/30: Close Combat from [3,4] to [4,3] -> Carthaginian retreat -> 2
5/12: Close Combat from [3,4] to [4,3] -> Roman attacker retreat -> 2
2/6: Close Combat from [3,4] to [4,3] -> Roman attacker retreat -> 2
CHANCE/150: Close Combat from [2,4] to [2,3] -> Roman battle -> 2
17/62: Close Combat from [2,4] to [2,3] -> Roman attacker retreat -> 2
-26/87: Close Combat from [2,4] to [2,3] -> Carthaginian retreat -> 2
CHANCE/285: Close Combat from [3,4] to [3,3] -> Roman battle -> 3
62/87: Close Combat from [3,4] to [3,3] -> Roman attacker retreat -> 2
-71/164: Close Combat from [3,4] to [3,3] -> Carthaginian retreat -> 3
28/33: Close Combat from [3,4] to [3,3] -> Roman attacker retreat -> 2
12/155: OrderUnit([1,5],[2,5],[3,5]) -> Roman order 3 heavy units -> 1
12/155: End phase -> Roman movement -> 1
11/154: MacroCommand(Move [1,5] to [2,4],Move [2,5] to [3,4],Move [3,5] to [4,4]) -> Roman battle -> 5
CHANCE/14: Close Combat from [2,4] to [2,3] -> Roman battle -> 2
3/3: Close Combat from [2,4] to [2,3] -> Roman attacker retreat -> 2
-8/10: Close Combat from [2,4] to [2,3] -> Carthaginian retreat -> 2
CHANCE/42: Close Combat from [2,4] to [3,3] -> Roman battle -> 2
4/14: Close Combat from [2,4] to [3,3] -> Roman attacker retreat -> 2
3/27: Close Combat from [2,4] to [3,3] -> Carthaginian retreat -> 3
CHANCE/40: Close Combat from [3,4] to [4,3] -> Roman battle -> 5
9/14: Close Combat from [3,4] to [4,3] -> Roman attacker retreat -> 3
0/16: Close Combat from [3,4] to [4,3] -> Carthaginian retreat -> 2
1/1: Close Combat from [3,4] to [4,3] -> Roman attacker retreat -> 3
0/4: Close Combat from [3,4] to [4,3] -> Carthaginian retreat -> 2
-4/4: Close Combat from [3,4] to [4,3] -> Carthaginian retreat -> 2
CHANCE/13: Close Combat from [4,4] to [4,3] -> Roman battle -> 5
-1/1: Close Combat from [4,4] to [4,3] -> Carthaginian retreat -> 2
-3/3: Close Combat from [4,4] to [4,3] -> Carthaginian retreat -> 2
-3/3: Close Combat from [4,4] to [4,3] -> Carthaginian retreat -> 2
2/4: Close Combat from [4,4] to [4,3] -> Roman attacker retreat -> 2
0/1: Close Combat from [4,4] to [4,3] -> Roman attacker retreat -> 2
CHANCE/48: Close Combat from [3,4] to [3,3] -> Roman battle -> 2
18/30: Close Combat from [3,4] to [3,3] -> Carthaginian retreat -> 3
-6/17: Close Combat from [3,4] to [3,3] -> Roman attacker retreat -> 3
"
`;
8 changes: 3 additions & 5 deletions src/ai/mcts_player.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const player = new MctsPlayer({
});

// fails bc I don't know
xtest('2 on 2', () => {
test('2 on 2', () => {
const game = makeGame(new TwoOnTwoMeleeScenario());

const root = player.search(game, 2000);
Expand All @@ -46,8 +46,7 @@ xtest('2 on 2', () => {
expect(rootAsString).toMatchSnapshot();
});

// disabled bc of bug in simulation of battle back after ignored flags
xtest('melee', () => {
test('melee', () => {
const game = makeGame(new MeleeScenario());

const root = player.search(game, 2000);
Expand All @@ -56,8 +55,7 @@ xtest('melee', () => {
expect(rootAsString).toMatchSnapshot();
});

// disabled bc of evasion phase is not yet implemented
xtest('close combat from light to heavy', () => {
test('close combat from light to heavy', () => {
const game = makeGame(new NullScenario());
game.placeUnit(hexOf(2, 2), new CarthaginianHeavyInfantry());
game.placeUnit(hexOf(2, 3), new RomanLightInfantry());
Expand Down
13 changes: 6 additions & 7 deletions src/model/commands/abstract_combat_command.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ export class AbstractCombatCommand extends Command {
return [totalDamage, flagResult.retreats, diceResults];
}


/**
* @param {Unit} attackingUnit
* @param {Hex} defendingHex
Expand All @@ -73,13 +72,13 @@ export class AbstractCombatCommand extends Command {
const attackingHex = game.hexOfUnit(attackingUnit);
if (game.isUnitDead(defendingUnit)) {
events.push(new UnitKilledEvent(defendingHex, defendingUnit));
if (!isBattleBack) {
game.unshiftPhase(new MomentumAdvancePhase(defendingHex, attackingHex));
}
// if (!isBattleBack) {
// game.unshiftPhase(new MomentumAdvancePhase(defendingHex, attackingHex));
// }
} else if (retreatHexes.length > 0) {
if (!isBattleBack) {
game.unshiftPhase(new MomentumAdvancePhase(defendingHex, attackingHex));
}
// if (!isBattleBack) {
// game.unshiftPhase(new MomentumAdvancePhase(defendingHex, attackingHex));
// }
const preventRecursiveBattleBack = isBattleBack ? null : attackingHex;
game.unshiftPhase(new FirstDefenderRetreatPhase(preventRecursiveBattleBack, defendingUnit.side, defendingHex, retreatHexes));
}
Expand Down
16 changes: 15 additions & 1 deletion src/model/commands/ranged_combat_command.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { DamageEvent, UnitKilledEvent } from "../events.js";
import { FirstDefenderRetreatPhase } from "../phases/FirstDefenderRetreatPhase.js";
import { RangedCombatRetreatPhase } from "../phases/RangedCombatRetreatPhase.js";
import { AbstractCombatCommand } from "./abstract_combat_command.js";

export class RangedCombatCommand extends AbstractCombatCommand {
Expand All @@ -22,7 +25,18 @@ export class RangedCombatCommand extends AbstractCombatCommand {
throw new Error(`Cannot Ranged Combat with unit at ${defendingHex} from ${attackingHex}`);
}
game.markUnitSpent(attackingUnit);
return this.attack(attackingUnit, defendingHex, defendingUnit, game);

let totalDamage, retreatHexes, diceResults;
[totalDamage, retreatHexes, diceResults] = this.simpleAttack(attackingUnit, defendingHex, defendingUnit, game);
let events = [];
game.damageUnit(defendingUnit, totalDamage);
events.push(new DamageEvent(attackingUnit, defendingUnit, defendingHex, totalDamage, diceResults));
if (game.isUnitDead(defendingUnit)) {
events.push(new UnitKilledEvent(defendingHex, defendingUnit));
} else if (retreatHexes.length > 0) {
game.unshiftPhase(new RangedCombatRetreatPhase(defendingHex, retreatHexes));
}
return events;
}

decideDiceCount(attackingUnit, game) {
Expand Down
6 changes: 3 additions & 3 deletions src/model/commands/skip_action_command.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import { Command } from "./commands.js";

export class SkipActionCommand extends Command {
/**
* @param {Hex} toHex
* @param {Hex} unitHex
*/
constructor(unitHex) {
super();
this.unitHex = unitHex;
this.toHex = unitHex;
}

play(game) {
Expand All @@ -15,6 +15,6 @@ export class SkipActionCommand extends Command {
}

toString() {
return `Skip action unit at ${this.unitHex}`;
return `Skip action unit at ${this.toHex}`;
}
}
36 changes: 36 additions & 0 deletions src/model/phases/RangedCombatRetreatPhase.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Hex } from "../../lib/hexlib.js";
import { RetreatCommand } from "../commands/retreatCommand.js";
import { Phase } from "./Phase.js";


export class RangedCombatRetreatPhase extends Phase {
/**
* @param {Hex} defendingHex
* @param {Hex[]} retreatHexes
*/
constructor(defendingHex, retreatHexes) {
super("retreat");
this.fromHex = defendingHex;
this.retreatHexes = retreatHexes;
}

validCommands(game) {
return this.retreatHexes.map(toHex => {
return new RetreatCommand(toHex, this.fromHex);
});
}

hilightedHexes(game) {
return new Set(this.retreatHexes);
}

/**
* @param {Hex} hex
* @param {InteractiveGame} interactiveGame
* @returns {Command|undefined}
*/
onClick(hex, interactiveGame) {
return this.validCommands(interactiveGame).
find(command => command["toHex"] === hex || command["battleBackHex"] === hex);
}
}

0 comments on commit 9af4d61

Please sign in to comment.