From 9164ee5987629c14ddfb4854f7f22d49e1c1fe59 Mon Sep 17 00:00:00 2001 From: Sorrel Bri Date: Sun, 26 Apr 2020 00:13:25 -0700 Subject: [PATCH] add support for group joining moves at points with no liberties --- packages/server/services/Game.v2.js | 18 +++++++--- packages/server/test/Game.v2.spec.js | 53 ++++++++++++++++++++++++---- 2 files changed, 60 insertions(+), 11 deletions(-) diff --git a/packages/server/services/Game.v2.js b/packages/server/services/Game.v2.js index 1b67d39..8d9b269 100644 --- a/packages/server/services/Game.v2.js +++ b/packages/server/services/Game.v2.js @@ -74,16 +74,26 @@ const checkLegal = ({ point, Game }) => { point.legal = legal; return point; } - const isEmptyAdjacent = Object.values(point.neighbors).filter(pt => pt.stone === 0)[0] - // .length; + + const isEmptyAdjacent = Object.values(point.neighbors).filter(pt => pt.stone === 0).length; // if empty point adjacent return true if (!isEmptyAdjacent) { + + // if group has liberties return true + const isTurnStone = neighbor => neighbor.stone === Game.turn; + const getGroupLiberties = point => Array.from(Game.groups[point.group].liberties); + const isInGroupWithLiberties = neighbor => getGroupLiberties(neighbor).filter(({ pos }) => pos.x !== point.pos.x && pos.y !== point.pos.y ); + const isInLiveGroup = () => Object.values(point.neighbors).filter(isTurnStone).filter(isInGroupWithLiberties).length; + + if (isInLiveGroup()) { + point.legal = true; + return point; + } + point.legal = legal; return { ...point, adj: isEmptyAdjacent }; - // TODO change to positive check with legal: true after remaining logic has been added } - // if group has liberties return true // if move would capture opposing group // set capturing object and return true point.legal = !point.stone ? true : false; diff --git a/packages/server/test/Game.v2.spec.js b/packages/server/test/Game.v2.spec.js index c7cd973..dcbb464 100644 --- a/packages/server/test/Game.v2.spec.js +++ b/packages/server/test/Game.v2.spec.js @@ -172,11 +172,11 @@ describe('Game.makeMove({ player: str, pos: { x: int, y: int } })', () => { }); it('makeMove next to adjacent stone of different color does not join stones as a group', done => { - const game = Game({ gameData: { handicap: 2 } }).initGame() // 3 4 - .makeMove({ player: 'white', pos: { x: 4, y: 15 } }) // 14 1 - .makeMove({ player: 'black', pos: { x: 4, y: 14 }}) // 15 1 -1 no groups - .makeMove({ player: 'white', pos: { x: 3, y: 16 } }) // 16 -1 1h - .makeMove({ player: 'black', pos: { x: 3, y: 15 }}) + const game = Game({ gameData: { handicap: 2 } }).initGame() // 3 4 + .makeMove({ player: 'white', pos: { x: 4, y: 15 } }) // 14 1 + .makeMove({ player: 'black', pos: { x: 4, y: 14 }}) // 15 1 -1 no groups + .makeMove({ player: 'white', pos: { x: 3, y: 16 } }) // 16 -1 1h + .makeMove({ player: 'black', pos: { x: 3, y: 15 }}) const hoshiGroupKey = game.boardState['4-16'].group; const hoshiGroup = game.groups[hoshiGroupKey].stones; @@ -194,11 +194,50 @@ describe('Game.makeMove({ player: str, pos: { x: int, y: int } })', () => { .makeMove({ player: 'white', pos: { x: 16, y: 10 }}).makeMove({ player: 'black', pos: { x: 5, y: 17 } }) // 6 1 .makeMove({ player: 'white', pos: { x: 5, y: 16 }}) .success.should.eql(false); - done(); - }) + }); }); +describe('makeMove group join and capture logic', () => { + const joinGame = Game().initGame() + .makeMove({ player: 'black', pos: { x: 4, y: 17 } }) // 3 4 5 + .makeMove({ player: 'white', pos: { x: 3, y: 16 } }) // 15 -1 + .makeMove({ player: 'black', pos: { x: 5, y: 16 } }) // 16 -1 1 1 + .makeMove({ player: 'white', pos: { x: 4, y: 15 } }) // 17 1 + .makeMove({ player: 'black', pos: { x: 4, y: 16 } }); + + it('gain liberties from group smoke test', done => { + joinGame.success.should.eql(true); // to work after + done(); + }); + + // test group with only remaining liberty at point to be played + + // const captureGame = Game({ gameData: { handicap: 2 } }).initGame() + // .makeMove({ player: 'white', pos: { x: 4, y: 15 } }) // 3 4 5 + // .makeMove({ player: 'black', pos: { x: 4, y: 4 } }) // 15 -1 + // .makeMove({ player: 'white', pos: { x: 3, y: 16 } }) // 16 -1 0 -1 + // .makeMove({ player: 'black', pos: { x: 4, y: 10 } }) // 17 -1 + // .makeMove({ player: 'white', pos: { x: 5, y: 16 } }) // 4,16 captured + // .makeMove({ player: 'black', pos: { x: 10, y: 4 } }) + // .makeMove({ player: 'white', pos: { x: 4, y: 17 } }) + + // it('makeMove capture smoke test', done => { + // captureGame.success.should.eql(true); + // done(); + // }); + + // it('makeMove capture removes captured stone', done => { + // captureGame.boardState['4-16'].stone.should.eql(0); + // done(); + // }); + + // it('makeMove capture increases capturing players captures', done => { + // captureGame.playerState.wCaptures.should.eql(1); + // }) +}) + + const initialMeta = { winner: null, turn: 0,