stub make move to game service
This commit is contained in:
parent
d83a58dcb4
commit
b38637d3c8
3 changed files with 106 additions and 66 deletions
|
@ -62,7 +62,8 @@ class Game {
|
|||
this.winner = null;
|
||||
this.pass = null;
|
||||
this.turn = this.handicap ? -1 : 1;
|
||||
return this.initBoard();
|
||||
this.initBoard();
|
||||
return this.getBoardState();
|
||||
}
|
||||
|
||||
initBoard = () => {
|
||||
|
@ -79,18 +80,57 @@ class Game {
|
|||
if (this.handicap < 2) return;
|
||||
HANDI_PLACE[this.boardSize][this.handicap].forEach(pt => {
|
||||
if (!pt) return;
|
||||
let handi = findPointFromIdx(pt);
|
||||
let handi = this.findPointFromIdx(pt);
|
||||
handi.stone = 1;
|
||||
handi.joinGroup();
|
||||
handi.joinGroup(this);
|
||||
})
|
||||
}
|
||||
|
||||
getBoardState = () => {
|
||||
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) }
|
||||
|
@ -146,28 +186,28 @@ class Point {
|
|||
this.neighbors.lft = y > 1 ? [ x, y - 1 ] : null;
|
||||
}
|
||||
|
||||
checkNeighbors = () => {
|
||||
checkNeighbors = (Game) => {
|
||||
let neighborsArr = [];
|
||||
for (let neighbor in this.neighbors) {
|
||||
let nbr = this.neighbors[neighbor];
|
||||
// neighbor exists it's point is stored as { rPos, cPos}
|
||||
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
|
||||
return neighborsArr;
|
||||
}
|
||||
|
||||
getLiberties = () => {
|
||||
let neighborsArr = this.checkNeighbors().filter(pt => pt.stone === 0);
|
||||
getLiberties = (Game) => {
|
||||
let neighborsArr = this.checkNeighbors(Game).filter(pt => pt.stone === 0);
|
||||
return neighborsArr;
|
||||
}
|
||||
|
||||
joinGroup = () => {
|
||||
joinGroup = (Game) => {
|
||||
this.groupMembers = this.groupMembers.filter(grp => grp.stone === this.stone);
|
||||
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) {
|
||||
this.groupMembers.push(frn);
|
||||
}
|
||||
|
@ -180,8 +220,8 @@ class Point {
|
|||
}
|
||||
}
|
||||
|
||||
checkCapture = () => {
|
||||
let opps = this.checkNeighbors().filter(nbr => nbr.stone === gameState.turn * -1
|
||||
checkCapture = (Game) => {
|
||||
let opps = this.checkNeighbors(Game).filter(nbr => nbr.stone === Game.turn * -1
|
||||
&& nbr.getLiberties().every(liberty => liberty === this));
|
||||
for (let opp of opps) {
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
function clearKo() {
|
||||
for (let point in boardState) {
|
||||
point = boardState[point];
|
||||
function clearKo(Game) {
|
||||
for (let point in Game.boardState) {
|
||||
point = Game.boardState[point];
|
||||
point.stone = point.stone === 'k' ? 0 : point.stone;
|
||||
}
|
||||
}
|
||||
|
||||
function clearPass() {
|
||||
gameState.pass = 0;
|
||||
function clearPass(Game) {
|
||||
Game.pass = 0;
|
||||
}
|
||||
|
||||
function resolveCaptures(point) {
|
||||
function resolveCaptures(point, Game) {
|
||||
if(!point.capturing.length) {
|
||||
point.checkCapture();
|
||||
point.checkCapture(Game);
|
||||
}
|
||||
if(point.capturing.length) {
|
||||
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.groupMembers = [];
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function checkLegal(point) {
|
||||
clearOverlay();
|
||||
function checkLegal(point, Game) {
|
||||
// clearOverlay();
|
||||
// first step in logic: is point occupied, or in ko
|
||||
if (point.stone) return false;
|
||||
// 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 ( 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 (point.checkGroup()) return true;
|
||||
if (point.checkGroup(Game)) return true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -295,9 +313,9 @@ function checkKo(point) { // currently prevents snapback // capturing point has
|
|||
}
|
||||
|
||||
|
||||
function clearCaptures() {
|
||||
for (let point in boardState) {
|
||||
point = boardState[point];
|
||||
function clearCaptures(Game) {
|
||||
for (let point in Game.boardState) {
|
||||
point = Game.boardState[point];
|
||||
point.capturing = [];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,14 +11,9 @@ const initGame = (game) => {
|
|||
return gamesInProgress[game.id].initGame();
|
||||
}
|
||||
|
||||
const placeMove = (game, move) => {
|
||||
if (!gamesInProgress[game]) {
|
||||
gamesInProgress[game] = storeGame(game)
|
||||
}
|
||||
// gamesInProgress[]
|
||||
const makeMove = (game, move) => {
|
||||
let meta = {};
|
||||
// let newBoard = {...board};
|
||||
let board = [];
|
||||
const board = gamesInProgress[game.id].makeMove(move);
|
||||
return {board, meta}
|
||||
}
|
||||
|
||||
|
@ -31,7 +26,7 @@ const getAllGames = () => {
|
|||
}
|
||||
|
||||
module.exports = {
|
||||
placeMove,
|
||||
makeMove,
|
||||
getAllGames,
|
||||
getBoard,
|
||||
initGame
|
||||
|
|
|
@ -1,15 +1,42 @@
|
|||
const assert = require('assert');
|
||||
const gameServices = require('../services/gameServices');
|
||||
|
||||
describe('game services', () => {
|
||||
it('games services persists game data', done => {
|
||||
gameServices.placeMove({id: 1}, {player: 'black', move: '3,3'})
|
||||
console.log(gameServices.getAllGames())
|
||||
it('init game returns game board', done => {
|
||||
gameServices.initGame({id: 1, handicap: 4})
|
||||
assert.deepEqual(gameServices.getBoard(1), fourHandicapBoard)
|
||||
done();
|
||||
});
|
||||
|
||||
it('init game returns game board', done => {
|
||||
gameServices.initGame({id: 1})
|
||||
console.log(gameServices.getBoard(1))
|
||||
it('games services places move', done => {
|
||||
gameServices.initGame({id: 1, handicap: 4})
|
||||
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();
|
||||
})
|
||||
});
|
||||
|
||||
})
|
||||
|
||||
|
||||
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
|
||||
};
|
Loading…
Reference in a new issue