Skip to content

Commit

Permalink
Start implementing monte carlo player
Browse files Browse the repository at this point in the history
  • Loading branch information
mhawryluk committed Dec 30, 2023
1 parent f20d73d commit 0959b61
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 6 deletions.
59 changes: 57 additions & 2 deletions computerOpponents.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
function copyArray(array) {
return JSON.parse(JSON.stringify(array));
}

class ComputerOpponent {
constructor(game, player, level = 'random') {
constructor(game, player) {
this.game = game;
this.player = player;
this.level = level;
}

makeMove() {
console.log('comp')
if (game.rollDice()) {
const possibleMoves = this.getPossibleMoves();
if (possibleMoves.length == 0) return;
Expand All @@ -30,3 +34,54 @@ class ComputerOpponent {
return possibleMoves;
}
}

class MonteCarloOpponent extends ComputerOpponent {
RANDOM_GAMES_PER_MOVE = 20;
MOVES_PER_GAME = 20;

constructor(game, player) {
super(game, player);

this.positions = copyArray(game.tokenPositons);
}

makeMove() {
if (game.rollDice()) {
const possibleMoves = this.getPossibleMoves();
if (possibleMoves.length == 0) return;
if (possibleMoves.length == 1) {
game.moveToken(this.player, possibleMoves[0]);
return;
}

const bestMove = this.monteCarlo(possibleMoves);
game.moveToken(this.player, bestMove);
}
}

monteCarlo(possibleMoves) {
const scores = [];

for (let move of possibleMoves) {

let scoreSum = 0;
for (let i = 0; i < this.RANDOM_GAMES_PER_MOVE; i++) {
scoreSum += this.randomGame(copyArray(this.positions), move);
}

scores.push([scoreSum, move]);
}

scores.sort((a, b) => a[0] - b[0]);
return scores[0][1];
}

randomGame(positions, firstMove) {
let score = 0;

// TODO: implement random game simulation and scoring

return score;
}
}

10 changes: 6 additions & 4 deletions game.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ let game;

class Game {

constructor(players, computerOpponentIndices = []) {
constructor(players, computerOpponentIndices = [], computerOpponentLevel = 'easy') {
this.players = players;
this.numberOfPlayers = players.length;
this.computerOpponentIndices = computerOpponentIndices; // which of the indices of players are robots
Expand Down Expand Up @@ -60,7 +60,7 @@ class Game {
// create computer components
this.computerOpponents = {};
for (let index of this.computerOpponentIndices) {
this.computerOpponents[index] = new ComputerOpponent(this, this.players[index]);
this.computerOpponents[index] = new (computerOpponentLevel === 'hard' ? MonteCarloOpponent : ComputerOpponent)(this, this.players[index]);
}
}

Expand Down Expand Up @@ -318,8 +318,9 @@ window.addEventListener('keypress', event => {
}
});

function setPlayers(players, computerOpponentIndices) {
game = new Game(players, computerOpponentIndices);
function setPlayers(players, computerOpponentIndices, computerOpponentLevel) {
game = new Game(players, computerOpponentIndices, computerOpponentLevel);

popup.style.display = 'none';
main.style.opacity = 1;

Expand All @@ -334,6 +335,7 @@ document.getElementById('3-players-button').addEventListener('click', () => setP
document.getElementById('4-players-button').addEventListener('click', () => setPlayers(allPossiblePlayers));

document.getElementById('easy-mode').addEventListener('click', () => setPlayers([allPossiblePlayers[0], allPossiblePlayers[2]], [1]));
document.getElementById('hard-mode').addEventListener('click', () => setPlayers([allPossiblePlayers[0], allPossiblePlayers[2]], [1], 'hard'));

h1.addEventListener('click', () => location.reload());

Expand Down
1 change: 1 addition & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ <h1>Ludo 3D</h1>

<div class="button-row">
<button id="easy-mode">Easy</button>
<button id="hard-mode">Hard</button>
</div>
</div>

Expand Down

0 comments on commit 0959b61

Please sign in to comment.