diff --git a/README.md b/README.md index fda97c6..ef4f455 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,18 @@ I presented this work in progress at Codemotion Milano 2023; [here are the slide # The story of this repo so far + +## 2023-11-27 + +Implemented the deck. Now we randomize the players' hands. + +The MCTS AI has been set aside for the moment; AI is played by the Greedy player. + +BUG: it does not reshuffle the deck when the talon is empty!!! + + +## 2023-11-25 + When I presented at Codemotion, the MCTS-based AI was weak due to two factors: - choosing one unit at a time, ie simple moves were not grouped in macromoves diff --git a/src/ai/autoplay.js b/src/ai/autoplay.js index 3afd13c..3e639e3 100644 --- a/src/ai/autoplay.js +++ b/src/ai/autoplay.js @@ -44,8 +44,7 @@ export class Autoplay { const game = this.game.toGame(); const sideNorth = game.scenario.sideNorth; const northPlayer = new GreedyPlayer(); - const southPlayer = this.aiPlayer; - // const southPlayer = new MinimaxPlayer(8); + const southPlayer = new GreedyPlayer(); while (!this.game.isTerminal() && !paused()) { const player = this.game.currentSide === sideNorth ? northPlayer : southPlayer; const commands = player.decideMove(game); diff --git a/src/main.js b/src/main.js index 50e270b..b6085c9 100644 --- a/src/main.js +++ b/src/main.js @@ -1,6 +1,7 @@ +import { GreedyPlayer } from "./ai/greedy_player.js"; import { CARD_IMAGE_SIZE, MCTS_PLAYOUT_ITERATIONS, MCTS_SAMPLING_EXPLORATION_CHANCE } from "./config.js"; import { MCTS_EXPANSION_FACTOR, MCTS_ITERATIONS } from "./config.js"; -import { Autoplay, displayEvents } from "./ai/autoplay.js"; +import { Autoplay, displayEvents, RandomPlayer } from "./ai/autoplay.js"; import { MctsPlayer } from "./ai/mcts_player.js"; import { InteractiveGame } from "./interactive_game.js"; import { Point } from "./lib/hexlib.js"; @@ -23,12 +24,13 @@ const graphics = new GraphicalContext(canvas.getContext('2d')); // create game and AI const scenario = makeScenario(getQueryParameter("scenario")); -const aiPlayer = new MctsPlayer({ - iterations: MCTS_ITERATIONS, - expansionFactor: MCTS_EXPANSION_FACTOR, - playoutIterations: MCTS_PLAYOUT_ITERATIONS, - samplingExplorationChance: MCTS_SAMPLING_EXPLORATION_CHANCE, -}); +const aiPlayer = new GreedyPlayer(); +// const aiPlayer = new MctsPlayer({ +// iterations: MCTS_ITERATIONS, +// expansionFactor: MCTS_EXPANSION_FACTOR, +// playoutIterations: MCTS_PLAYOUT_ITERATIONS, +// samplingExplorationChance: MCTS_SAMPLING_EXPLORATION_CHANCE, +// }); let game; let autoplay; diff --git a/src/model/deck.js b/src/model/deck.js index 916478e..7bc39d2 100644 --- a/src/model/deck.js +++ b/src/model/deck.js @@ -86,6 +86,7 @@ export class Deck { this.#discards.push(card); } + /** @returns {Deck} */ clone() { return new Deck(this.#talon.slice(), this.#discards.slice()); } diff --git a/src/model/game.js b/src/model/game.js index 147d64d..d627c23 100644 --- a/src/model/game.js +++ b/src/model/game.js @@ -7,6 +7,7 @@ import { ORDER_LIGHT_TROOPS_CARD, ORDER_MEDIUM_TROOPS_CARD, } from "./cards.js"; +import { Deck, THE_DECK } from "./deck.js"; import { Dice, DiceResult } from "./dice.js"; import { SideSwitchedTo } from "./events.js"; import GameStatus from "./game_status.js"; @@ -41,6 +42,7 @@ export class Game { handSouth = DEFAULT_HAND.slice(); currentCard = null; turnCount = 0; + deck = THE_DECK.clone(); /** * @param {Scenario} scenario @@ -54,6 +56,9 @@ export class Game { initialize() { this.currentSideRaw = this.scenario.firstSide; this.scenario.placeUnitsOn(this); + this.deck.shuffle(); + this.handSouth = this.deck.deal(this.scenario.commandSouth); + this.handNorth = this.deck.deal(this.scenario.commandNorth); } toString() { @@ -202,6 +207,7 @@ export class Game { game.graveyard = this.graveyard.clone(); game.orderedUnits = this.orderedUnits.slice(); game.currentCard = this.currentCard; + game.deck = this.deck.clone(); return game; } @@ -474,6 +480,7 @@ export class Game { } else { this.handSouth = this.handSouth.filter(c => c !== card); } + this.deck.discard(card); } drawCard(side) { @@ -481,10 +488,12 @@ export class Game { side = this.currentSide; } if (side === this.scenario.sideNorth) { - this.handNorth = DEFAULT_HAND.slice(); + this.handNorth.push(this.deck.deal(1)[0]); } else { - this.handSouth = DEFAULT_HAND.slice(); + this.handSouth.push(this.deck.deal(1)[0]); } + console.log(`Hand N: ${this.handNorth.map(c => c.name)}`); + console.log(`Hand S: ${this.handSouth.map(c => c.name)}`); } neighbors(hex) {