-
-
Save slior/604501df6fde21baffea7899dfed071e to your computer and use it in GitHub Desktop.
Mancala - Adding AI facility to game
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const PLAYER = { | |
one : { | |
toString : () => "ONE" | |
, theOtherOne : () => PLAYER.two | |
, number : 1 | |
, ai : () => PLAYER.one._aiPlayer | |
, _aiPlayer : None | |
} | |
, two : { | |
toString : () => "TWO" | |
, theOtherOne : () => PLAYER.one | |
, number : 2 | |
, ai : () => PLAYER.two._aiPlayer | |
, _aiPlayer : None | |
} | |
} | |
class MancalaGame | |
{ | |
constructor(gameSize,cnvsELID,_updatePlayerCallback,_showMsgCallback,requestedAIPlayers) | |
{ | |
... | |
this._setupAIPlayersIfRequested(requestedAIPlayers); | |
... | |
} | |
_setupAIPlayersIfRequested(requestedAIPlayers) | |
{ | |
dbg("Setting AI Players..."); | |
PLAYER.one._aiPlayer = maybe(determineAIPlayer(requestedAIPlayers.p1)) | |
PLAYER.two._aiPlayer = maybe(determineAIPlayer(requestedAIPlayers.p2)) | |
dbg("AI Players: P1: " + PLAYER.one._aiPlayer + ", P2: " + PLAYER.two._aiPlayer); | |
function determineAIPlayer(requestedAI) | |
{ | |
return requestedAI ? new SimpleAIPlayer() : null; | |
} | |
} | |
start() | |
{ | |
this._makeNextMoveIfCurrentPlayerIsAI(); | |
} | |
handleCellClick(boardCell) | |
{ | |
... | |
this._makeNextMoveIfCurrentPlayerIsAI() | |
} | |
_makeNextMoveIfCurrentPlayerIsAI() | |
{ | |
if (!this.gameDone) | |
{ | |
this.player.ai().ifPresent(aiPlayer => { | |
let aiMove = aiPlayer.nextMove(this.board,this.player.number) | |
setTimeout(() => { this._makeMove(aiMove)}, 200) //artifical wait, so we can "see" the ai playing | |
}) | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const P2_PARAM_NAME = "p2"; | |
const P1_PARAM_NAME = "p1"; | |
function setup() | |
{ | |
game = new main.MancalaGame(resolveGameSize(),'cnvsMain',updateCurrentPlayer,showMsg, resolveRequestedAI()); | |
game.start(); | |
} | |
function resolveRequestedAI() | |
{ | |
let params = new URLSearchParams(window.location.search); | |
let p2 = params.has(P2_PARAM_NAME) ? params.get(P2_PARAM_NAME) : ""; | |
let p1 = params.has(P1_PARAM_NAME) ? params.get(P1_PARAM_NAME) : ""; | |
return { p1 : p1, p2 : p2} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class SimpleAIPlayer | |
{ | |
constructor() | |
{ | |
} | |
/** | |
* Given a board and side to play, return the cell to play | |
* @param {Board} board The current board to play | |
* @param {number} side The side to player, either 1 or 2 | |
* | |
* @returns The board cell to play | |
*/ | |
nextMove(board,side) | |
{ | |
requires(board != null, "Board can't be null for calculating next move") | |
requires(side == 1 || side == 2,"Side must be either 1 or 2") | |
//Simple heuristic: choose the cell with the largest number of stones. | |
var maxStoneCell = side == 1 ? 1 : board.totalCellCount()-1; | |
switch (side) | |
{ | |
case 1 : board.forAllPlayer1Cells(c => { if (board.stonesIn(c) > board.stonesIn(maxStoneCell)) maxStoneCell = c }) | |
case 2 : board.forAllPlayer2Cells(c => { if (board.stonesIn(c) > board.stonesIn(maxStoneCell)) maxStoneCell = c }) | |
} | |
dbg("Playing cell: " + maxStoneCell + " with " + board.stonesIn(maxStoneCell) + " for player " + side); | |
return maxStoneCell; | |
} | |
} | |
module.exports = { | |
SimpleAIPlayer | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment