Skip to content

Commit

Permalink
Open Loop: now we can compute bestCommands
Browse files Browse the repository at this point in the history
  • Loading branch information
xpmatteo committed Nov 14, 2023
1 parent dce6933 commit c938c44
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 15 deletions.
40 changes: 37 additions & 3 deletions src/ai/OpenLoopNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,45 @@ export default class OpenLoopNode {
}

/**
This decides which is the best command for the real game
@returns {[Command, OpenLoopNode]}
*/
bestAbsoluteChild() {
if (this.childrenSize === 0) {
throw new Error("No children???");
}
let best = undefined;
let bestValue = -Infinity;
for (let [__, [command, child]] of this.#children) {
if (child.value() > bestValue) {
best = [command, child];
bestValue = child.value();
}
}
return best;
}

/**
* Returns the best commands sequence for the real game, stopping after the first non-deterministic command,
* and before the game changes side
* @param {Side?} side
* @returns {Command[]}
*/
bestCommands() {
return undefined;
bestCommands(side= undefined) {
if (side && this.side !== side) {
// stop because *after* this command, the side will change
return [];
}
if (this.childrenSize === 0) {
return [];
}
const [bestCommand, bestChild] = this.bestAbsoluteChild();
if (!bestCommand.isDeterministic()) {
// stop because *after* this command, we don't know what the actual situation will be
return [bestCommand];
} else {
return [bestCommand].concat(bestChild.bestCommands(side));
}
}

/**
Expand All @@ -100,5 +135,4 @@ export default class OpenLoopNode {
}
return this.#children.get(command.toString())[1];
}

}
16 changes: 4 additions & 12 deletions src/ai/OpenLoopNode.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,6 @@ describe('Open Loop nodes', () => {
});

describe('bestCommands', () => {
function gameWithSide(side) {
return {
currentSide: side,
};
}

function aDeterministicCommand(name) {
return {
isDeterministic: () => true,
Expand All @@ -125,9 +119,7 @@ describe('Open Loop nodes', () => {
return commands.map(c => c.toString());
}

let game = gameWithSide('A');

xit('should return the best commands sequence from root to leaf', () => {
it('should return the best commands sequence from root to leaf', () => {
const rootNode = new OpenLoopNode(Side.ROMAN, null, 1, 1);
const child1 = new OpenLoopNode(Side.ROMAN, rootNode, 3, 1);
const child2 = new OpenLoopNode(Side.ROMAN, rootNode, 4, 1);
Expand All @@ -144,7 +136,7 @@ describe('Open Loop nodes', () => {
expect(names(result)).toEqual(['child2Command', 'grandChildCommand']);
});

xit('should stop at the command that will switch side', () => {
it('should stop at the command that will switch side', () => {
const rootNode = new OpenLoopNode(Side.ROMAN);

const child1 = new OpenLoopNode(Side.CARTHAGINIAN, rootNode, 3, 1);
Expand All @@ -160,7 +152,7 @@ describe('Open Loop nodes', () => {
expect(names(result)).toEqual(['child1Command']);
});

xit('should stop after the first command that is not deterministic', () => {
it('should stop after the first command that is not deterministic', () => {
const rootNode = new OpenLoopNode(Side.ROMAN);

const child1 = new OpenLoopNode(Side.ROMAN, rootNode, 3, 1);
Expand All @@ -173,7 +165,7 @@ describe('Open Loop nodes', () => {
child1.addChild(grandChildCommand, grandChild);

const result = rootNode.bestCommands(Side.ROMAN);
expect(names(result)).toEqual(['rootCommand', 'child1Command']);
expect(names(result)).toEqual(['child1Command']);
});
});

Expand Down

0 comments on commit c938c44

Please sign in to comment.