Skip to content

Commit

Permalink
Now adding samples when explore is chosen
Browse files Browse the repository at this point in the history
  • Loading branch information
xpmatteo committed Oct 27, 2023
1 parent 3e5fb84 commit 80c22ef
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 9 deletions.
16 changes: 16 additions & 0 deletions src/ai/macro_command_sampling.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,19 @@ function groupByFromHex(availableCommands) {
return groups;
}

/**
* @param {MoveCommand[]} availableCommands
* @param {MacroCommand} existingSample
* @returns {MacroCommand}
*/
export function perturbSample(availableCommands, existingSample) {
// find an available command that has a fromHex in the sample and a toHex not in the sample
const commandToReplace = availableCommands.find((command) =>
command.fromHex && existingSample.hasFromHex(command.fromHex) && !existingSample.hasToHex(command.toHex));

// replace it in the new sample
const newCommands = existingSample.commands.slice();
newCommands[existingSample.indexOfFromHex(commandToReplace.fromHex)] = commandToReplace;
return new MacroCommand(newCommands);
}

10 changes: 9 additions & 1 deletion src/ai/mcts_player.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { sample } from "./macro_command_sampling.js";
import { MacroCommand } from "model/commands/macro_command.js";
import { perturbSample, sample } from "./macro_command_sampling.js";
import { MoveCommand } from "../model/commands/move_command.js";
import { randomElement, randomShuffleArray } from "../lib/random.js";
import { attackProximityScoreForHex, scoreGreedy, scoreMcts } from "./score.js";
Expand Down Expand Up @@ -178,6 +179,13 @@ export class DecisionNode extends TreeNode {
bestScore = currentScore;
}
}
if (best.command instanceof MacroCommand && bestScore < expansionFactor * Math.sqrt(logOfThisVisits / 1)) {
const macroCommand = perturbSample(this.game.validCommands(), best.command);
const clone = executeCommand(this.game, macroCommand);
const childNode = new DecisionNode(clone, this, 0, 0, [], macroCommand);
this.children.push(childNode);
return childNode;
}
return best;
}

Expand Down
11 changes: 11 additions & 0 deletions src/model/commands/macro_command.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,16 @@ export class MacroCommand extends Command {
return events;
}

hasFromHex(hex) {
return this.commands.some((command) => command.fromHex === hex);
}

hasToHex(hex) {
return this.commands.some((command) => command.toHex === hex);
}

indexOfFromHex(hex) {
return this.commands.findIndex((command) => command.fromHex === hex);
}
}

61 changes: 53 additions & 8 deletions test/ai/macro_command_sampling_test.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import { sample } from "ai/macro_command_sampling.js";
import { perturbSample, sample } from "ai/macro_command_sampling.js";
import { EndPhaseCommand } from "model/commands/end_phase_command.js";
import { MacroCommand } from "model/commands/macro_command.js";
import { MoveCommand } from "model/commands/move_command.js";
import { hexOf } from "xlib/hexlib.js";
import { fixedRandom, resetFixedRandom } from "xlib/random.js";


/**
* @param {Hex} hex
*/
function scoreFunction(hex) {
return hex.q + 10 * hex.r;
}

describe('construct the best move for each unit individually', () => {
/**
* @param {Hex} hex
*/
function scoreFunction(hex) {
return hex.q + 10 * hex.r;
}

test('just one command', () => {
const availableMoves = [
new MoveCommand(hexOf(1, 4), hexOf(1, 5)),
Expand Down Expand Up @@ -110,3 +111,47 @@ describe('construct the best move for each unit individually', () => {
]).toString());
});
});

describe('deriving a sample from another sample', () => {
const originalRandom = Math.random;
beforeEach(() => {
resetFixedRandom();
Math.random = fixedRandom;
});

afterEach(() => {
Math.random = originalRandom;
});

const availableCommands = [
new MoveCommand(hexOf(1, 1), hexOf(0, 0)),
new MoveCommand(hexOf(3, 3), hexOf(0, 0)),
new EndPhaseCommand(),
]
const existingSample = new MacroCommand([
new MoveCommand(hexOf(1, 1), hexOf(0, 0)),
new MoveCommand(hexOf(4, 4), hexOf(10, 10)),
]);
const existingSampleAsString = existingSample.toString();

const newSample = perturbSample(availableCommands, existingSample);

test('changes one unit movement', () => {
expect(newSample.toString()).toEqual(new MacroCommand([
new MoveCommand(hexOf(3, 3), hexOf(0, 0)),
new MoveCommand(hexOf(4, 4), hexOf(10, 10)),
]).toString());
});

test('does not change the existing sample', () => {
expect(existingSample.toString()).toEqual(existingSampleAsString);
});

test('chooses unit at random', () => {
});

test('chooses move at random', () => {
});


});

0 comments on commit 80c22ef

Please sign in to comment.