stub make move to game service

This commit is contained in:
Sorrel Bri 2020-01-30 22:50:34 -08:00 committed by sorrelbri
parent d83a58dcb4
commit b38637d3c8
3 changed files with 106 additions and 66 deletions

View file

@ -62,7 +62,8 @@ class Game {
this.winner = null; this.winner = null;
this.pass = null; this.pass = null;
this.turn = this.handicap ? -1 : 1; this.turn = this.handicap ? -1 : 1;
return this.initBoard(); this.initBoard();
return this.getBoardState();
} }
initBoard = () => { initBoard = () => {
@ -79,18 +80,57 @@ class Game {
if (this.handicap < 2) return; if (this.handicap < 2) return;
HANDI_PLACE[this.boardSize][this.handicap].forEach(pt => { HANDI_PLACE[this.boardSize][this.handicap].forEach(pt => {
if (!pt) return; if (!pt) return;
let handi = findPointFromIdx(pt); let handi = this.findPointFromIdx(pt);
handi.stone = 1; handi.stone = 1;
handi.joinGroup(); handi.joinGroup(this);
}) })
} }
getBoardState = () => { getBoardState = () => {
return this.boardState.reduce((boardState, point) => { return this.boardState.reduce((boardState, point) => {
boardState[point.pos[0]][point.pos[1]] = point.legal || point.stone boardState[`${point.pos[0]}-${point.pos[1]}`] = point.legal || point.stone;
return boardState;
}, {}) }, {})
} }
findPointFromIdx = (arr) => {
return this.boardState.find( point => point.pos[0] === arr[0] && point.pos[1] === arr[1] );
}
makeMove = (move) => {
const player = move.player === 'white' ? -1 : 1;
const point = this.findPointFromIdx([move.pos.X, move.pos.Y])
if ( !checkLegal(point, this) ) throw 'illegal move';
clearKo(this);
clearPass(this);
resolveCaptures(point, this);
point.stone = this.turn;
point.joinGroup(this);
clearCaptures(this);
this.gameRecord.push(`${STONES_DATA[this.turn]}: ${point.pos}`)
this.turn*= -1;
return this.getBoardState();
}
clickBoard = (evt) => {
evt.stopPropagation();
if (gameState.pass > 1 || gameState.winner) return editTerritory(evt);
// checks for placement and pushes to cell
let placement = [ parseInt(evt.target.closest('td').id.split('-')[0]), parseInt(evt.target.closest('td').id.split('-')[1]) ];
let point = findPointFromIdx(placement);
//checks that this placement was marked as legal
if ( !checkLegal(point) ) return;
clearKo();
clearPass();
resolveCaptures(point);
point.stone = gameState.turn;
point.joinGroup();
playSound(point);
clearCaptures();
gameState.gameRecord.push(`${STONES_DATA[gameState.turn]}: ${point.pos}`)
gameState.turn*= -1;
}
} }
// index represents handicap placement for different board-sizes, eg handiPlace['9][1] = { (3, 3), (7, 7) } // index represents handicap placement for different board-sizes, eg handiPlace['9][1] = { (3, 3), (7, 7) }
@ -146,28 +186,28 @@ class Point {
this.neighbors.lft = y > 1 ? [ x, y - 1 ] : null; this.neighbors.lft = y > 1 ? [ x, y - 1 ] : null;
} }
checkNeighbors = () => { checkNeighbors = (Game) => {
let neighborsArr = []; let neighborsArr = [];
for (let neighbor in this.neighbors) { for (let neighbor in this.neighbors) {
let nbr = this.neighbors[neighbor]; let nbr = this.neighbors[neighbor];
// neighbor exists it's point is stored as { rPos, cPos} // neighbor exists it's point is stored as { rPos, cPos}
if ( nbr !== null ) { if ( nbr !== null ) {
neighborsArr.push(boardState.find(pt => pt.pos[0] === nbr[0] && pt.pos[1] === nbr[1])) neighborsArr.push(Game.boardState.find(pt => pt.pos[0] === nbr[0] && pt.pos[1] === nbr[1]))
} }
}; };
// returns array of existing neighbors to calling function // returns array of existing neighbors to calling function
return neighborsArr; return neighborsArr;
} }
getLiberties = () => { getLiberties = (Game) => {
let neighborsArr = this.checkNeighbors().filter(pt => pt.stone === 0); let neighborsArr = this.checkNeighbors(Game).filter(pt => pt.stone === 0);
return neighborsArr; return neighborsArr;
} }
joinGroup = () => { joinGroup = (Game) => {
this.groupMembers = this.groupMembers.filter(grp => grp.stone === this.stone); this.groupMembers = this.groupMembers.filter(grp => grp.stone === this.stone);
this.groupMembers.push(this); this.groupMembers.push(this);
let frns = this.checkNeighbors().filter(nbr => nbr.stone === this.stone); let frns = this.checkNeighbors(Game).filter(nbr => nbr.stone === this.stone);
for (let frn of frns) { for (let frn of frns) {
this.groupMembers.push(frn); this.groupMembers.push(frn);
} }
@ -180,8 +220,8 @@ class Point {
} }
} }
checkCapture = () => { checkCapture = (Game) => {
let opps = this.checkNeighbors().filter(nbr => nbr.stone === gameState.turn * -1 let opps = this.checkNeighbors(Game).filter(nbr => nbr.stone === Game.turn * -1
&& nbr.getLiberties().every(liberty => liberty === this)); && nbr.getLiberties().every(liberty => liberty === this));
for (let opp of opps) { for (let opp of opps) {
if (opp.groupMembers.every(stone => stone.getLiberties().filter(liberty => liberty !== this).length === 0)) { if (opp.groupMembers.every(stone => stone.getLiberties().filter(liberty => liberty !== this).length === 0)) {
@ -221,63 +261,41 @@ class Point {
} }
} }
function findPointFromIdx(arr) {
return pointFromIdx = boardState.find( point => point.pos[0] === arr[0] && point.pos[1] === arr[1] );
}
function clickBoard(evt) { function clearKo(Game) {
evt.stopPropagation(); for (let point in Game.boardState) {
if (gameState.pass > 1 || gameState.winner) return editTerritory(evt); point = Game.boardState[point];
// checks for placement and pushes to cell
let placement = [ parseInt(evt.target.closest('td').id.split('-')[0]), parseInt(evt.target.closest('td').id.split('-')[1]) ];
let point = findPointFromIdx(placement);
//checks that this placement was marked as legal
if ( !checkLegal(point) ) return;
clearKo();
clearPass();
resolveCaptures(point);
point.stone = gameState.turn;
point.joinGroup();
playSound(point);
clearCaptures();
gameState.gameRecord.push(`${STONES_DATA[gameState.turn]}: ${point.pos}`)
gameState.turn*= -1;
}
function clearKo() {
for (let point in boardState) {
point = boardState[point];
point.stone = point.stone === 'k' ? 0 : point.stone; point.stone = point.stone === 'k' ? 0 : point.stone;
} }
} }
function clearPass() { function clearPass(Game) {
gameState.pass = 0; Game.pass = 0;
} }
function resolveCaptures(point) { function resolveCaptures(point, Game) {
if(!point.capturing.length) { if(!point.capturing.length) {
point.checkCapture(); point.checkCapture(Game);
} }
if(point.capturing.length) { if(point.capturing.length) {
point.capturing.forEach(cap => { point.capturing.forEach(cap => {
gameState.playerState[gameState.turn > 0 ? 'bCaptures' : 'wCaptures']++; Game.playerState[gameState.turn > 0 ? 'bCaptures' : 'wCaptures']++;
cap.stone = checkKo(point) ? 'k' : 0; cap.stone = checkKo(point) ? 'k' : 0;
cap.groupMembers = []; cap.groupMembers = [];
}) })
} }
} }
function checkLegal(point) { function checkLegal(point, Game) {
clearOverlay(); // clearOverlay();
// first step in logic: is point occupied, or in ko // first step in logic: is point occupied, or in ko
if (point.stone) return false; if (point.stone) return false;
// if point is not empty check if liberties // if point is not empty check if liberties
if (point.getLiberties().length < 1) { if (point.getLiberties(Game).length < 1) {
//if no liberties check if enemy group has liberties //if no liberties check if enemy group has liberties
if ( point.checkCapture().length ) return true; if ( point.checkCapture(Game).length ) return true;
//if neighboring point is not empty check if friendly group is alive //if neighboring point is not empty check if friendly group is alive
if (point.checkGroup()) return true; if (point.checkGroup(Game)) return true;
return false; return false;
} }
return true; return true;
@ -295,9 +313,9 @@ function checkKo(point) { // currently prevents snapback // capturing point has
} }
function clearCaptures() { function clearCaptures(Game) {
for (let point in boardState) { for (let point in Game.boardState) {
point = boardState[point]; point = Game.boardState[point];
point.capturing = []; point.capturing = [];
} }
} }

View file

@ -11,14 +11,9 @@ const initGame = (game) => {
return gamesInProgress[game.id].initGame(); return gamesInProgress[game.id].initGame();
} }
const placeMove = (game, move) => { const makeMove = (game, move) => {
if (!gamesInProgress[game]) {
gamesInProgress[game] = storeGame(game)
}
// gamesInProgress[]
let meta = {}; let meta = {};
// let newBoard = {...board}; const board = gamesInProgress[game.id].makeMove(move);
let board = [];
return {board, meta} return {board, meta}
} }
@ -31,7 +26,7 @@ const getAllGames = () => {
} }
module.exports = { module.exports = {
placeMove, makeMove,
getAllGames, getAllGames,
getBoard, getBoard,
initGame initGame

View file

@ -1,15 +1,42 @@
const assert = require('assert');
const gameServices = require('../services/gameServices'); const gameServices = require('../services/gameServices');
describe('game services', () => { describe('game services', () => {
it('games services persists game data', done => { it('init game returns game board', done => {
gameServices.placeMove({id: 1}, {player: 'black', move: '3,3'}) gameServices.initGame({id: 1, handicap: 4})
console.log(gameServices.getAllGames()) assert.deepEqual(gameServices.getBoard(1), fourHandicapBoard)
done(); done();
}); });
it('init game returns game board', done => { it('games services places move', done => {
gameServices.initGame({id: 1}) gameServices.initGame({id: 1, handicap: 4})
console.log(gameServices.getBoard(1)) const afterMoveOne = gameServices.makeMove({id: 1}, {player: 'white', pos: { X:6, Y:3 }});
const afterMoveOneShould = { board:{ ...fourHandicapBoard, '6-3': -1}, meta: {} };
assert.deepEqual(afterMoveOne, afterMoveOneShould);
done(); done();
});
}) })
})
const fourHandicapBoard = {
'1-1': 0,'1-2': 0,'1-3': 0,'1-4': 0,'1-5': 0,'1-6': 0,'1-7': 0,'1-8': 0,'1-9': 0,'1-10': 0,'1-11': 0,'1-12': 0,'1-13': 0,'1-14': 0,'1-15': 0,'1-16': 0,'1-17': 0,'1-18': 0,'1-19': 0,
'2-1': 0,'2-2': 0,'2-3': 0,'2-4': 0,'2-5': 0,'2-6': 0,'2-7': 0,'2-8': 0,'2-9': 0,'2-10': 0,'2-11': 0,'2-12': 0,'2-13': 0,'2-14': 0,'2-15': 0,'2-16': 0,'2-17': 0,'2-18': 0,'2-19': 0,
'3-1': 0,'3-2': 0,'3-3': 0,'3-4': 0,'3-5': 0,'3-6': 0,'3-7': 0,'3-8': 0,'3-9': 0,'3-10': 0,'3-11': 0,'3-12': 0,'3-13': 0,'3-14': 0,'3-15': 0,'3-16': 0,'3-17': 0,'3-18': 0,'3-19': 0,
'4-1': 0,'4-2': 0,'4-3': 0,'4-4': 1,'4-5': 0,'4-6': 0,'4-7': 0,'4-8': 0,'4-9': 0,'4-10': 0,'4-11': 0,'4-12': 0,'4-13': 0,'4-14': 0,'4-15': 0,'4-16': 1,'4-17': 0,'4-18': 0,'4-19': 0,
'5-1': 0,'5-2': 0,'5-3': 0,'5-4': 0,'5-5': 0,'5-6': 0,'5-7': 0,'5-8': 0,'5-9': 0,'5-10': 0,'5-11': 0,'5-12': 0,'5-13': 0,'5-14': 0,'5-15': 0,'5-16': 0,'5-17': 0,'5-18': 0,'5-19': 0,
'6-1': 0,'6-2': 0,'6-3': 0,'6-4': 0,'6-5': 0,'6-6': 0,'6-7': 0,'6-8': 0,'6-9': 0,'6-10': 0,'6-11': 0,'6-12': 0,'6-13': 0,'6-14': 0,'6-15': 0,'6-16': 0,'6-17': 0,'6-18': 0,'6-19': 0,
'7-1': 0,'7-2': 0,'7-3': 0,'7-4': 0,'7-5': 0,'7-6': 0,'7-7': 0,'7-8': 0,'7-9': 0,'7-10': 0,'7-11': 0,'7-12': 0,'7-13': 0,'7-14': 0,'7-15': 0,'7-16': 0,'7-17': 0,'7-18': 0,'7-19': 0,
'8-1': 0,'8-2': 0,'8-3': 0,'8-4': 0,'8-5': 0,'8-6': 0,'8-7': 0,'8-8': 0,'8-9': 0,'8-10': 0,'8-11': 0,'8-12': 0,'8-13': 0,'8-14': 0,'8-15': 0,'8-16': 0,'8-17': 0,'8-18': 0,'8-19': 0,
'9-1': 0,'9-2': 0,'9-3': 0,'9-4': 0,'9-5': 0,'9-6': 0,'9-7': 0,'9-8': 0,'9-9': 0,'9-10': 0,'9-11': 0,'9-12': 0,'9-13': 0,'9-14': 0,'9-15': 0,'9-16': 0,'9-17': 0,'9-18': 0,'9-19': 0,
'10-1': 0,'10-2': 0,'10-3': 0,'10-4': 0,'10-5': 0,'10-6': 0,'10-7': 0,'10-8': 0,'10-9': 0,'10-10': 0,'10-11': 0,'10-12': 0,'10-13': 0,'10-14': 0,'10-15': 0,'10-16': 0,'10-17': 0,'10-18': 0,'10-19': 0,
'11-1': 0,'11-2': 0,'11-3': 0,'11-4': 0,'11-5': 0,'11-6': 0,'11-7': 0,'11-8': 0,'11-9': 0,'11-10': 0,'11-11': 0,'11-12': 0,'11-13': 0,'11-14': 0,'11-15': 0,'11-16': 0,'11-17': 0,'11-18': 0,'11-19': 0,
'12-1': 0,'12-2': 0,'12-3': 0,'12-4': 0,'12-5': 0,'12-6': 0,'12-7': 0,'12-8': 0,'12-9': 0,'12-10': 0,'12-11': 0,'12-12': 0,'12-13': 0,'12-14': 0,'12-15': 0,'12-16': 0,'12-17': 0,'12-18': 0,'12-19': 0,
'13-1': 0,'13-2': 0,'13-3': 0,'13-4': 0,'13-5': 0,'13-6': 0,'13-7': 0,'13-8': 0,'13-9': 0,'13-10': 0,'13-11': 0,'13-12': 0,'13-13': 0,'13-14': 0,'13-15': 0,'13-16': 0,'13-17': 0,'13-18': 0,'13-19': 0,
'14-1': 0,'14-2': 0,'14-3': 0,'14-4': 0,'14-5': 0,'14-6': 0,'14-7': 0,'14-8': 0,'14-9': 0,'14-10': 0,'14-11': 0,'14-12': 0,'14-13': 0,'14-14': 0,'14-15': 0,'14-16': 0,'14-17': 0,'14-18': 0,'14-19': 0,
'15-1': 0,'15-2': 0,'15-3': 0,'15-4': 0,'15-5': 0,'15-6': 0,'15-7': 0,'15-8': 0,'15-9': 0,'15-10': 0,'15-11': 0,'15-12': 0,'15-13': 0,'15-14': 0,'15-15': 0,'15-16': 0,'15-17': 0,'15-18': 0,'15-19': 0,
'16-1': 0,'16-2': 0,'16-3': 0,'16-4': 1,'16-5': 0,'16-6': 0,'16-7': 0,'16-8': 0,'16-9': 0,'16-10': 0,'16-11': 0,'16-12': 0,'16-13': 0,'16-14': 0,'16-15': 0,'16-16': 1,'16-17': 0,'16-18': 0,'16-19': 0,
'17-1': 0,'17-2': 0,'17-3': 0,'17-4': 0,'17-5': 0,'17-6': 0,'17-7': 0,'17-8': 0,'17-9': 0,'17-10': 0,'17-11': 0,'17-12': 0,'17-13': 0,'17-14': 0,'17-15': 0,'17-16': 0,'17-17': 0,'17-18': 0,'17-19': 0,
'18-1': 0,'18-2': 0,'18-3': 0,'18-4': 0,'18-5': 0,'18-6': 0,'18-7': 0,'18-8': 0,'18-9': 0,'18-10': 0,'18-11': 0,'18-12': 0,'18-13': 0,'18-14': 0,'18-15': 0,'18-16': 0,'18-17': 0,'18-18': 0,'18-19': 0,
'19-1': 0,'19-2': 0,'19-3': 0,'19-4': 0,'19-5': 0,'19-6': 0,'19-7': 0,'19-8': 0,'19-9': 0,'19-10': 0,'19-11': 0,'19-12': 0,'19-13': 0,'19-14': 0,'19-15': 0,'19-16': 0,'19-17': 0,'19-18': 0,'19-19': 0
};