stub make move to game service
This commit is contained in:
parent
63afa73570
commit
4a06a6939f
3 changed files with 106 additions and 66 deletions
|
@ -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 = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
};
|
Loading…
Reference in a new issue