diff --git a/packages/server/services/Game.v2.js b/packages/server/services/Game.v2.js index abffe41..10e851f 100644 --- a/packages/server/services/Game.v2.js +++ b/packages/server/services/Game.v2.js @@ -221,8 +221,8 @@ const Point = ({x, y, boardSize = 19}) => { legal: true, territory: 0, capturing: { - '1': [], - '-1': [] + '1': new Set(), + '-1': new Set() }, group: null, neighbors: { @@ -235,7 +235,7 @@ const Point = ({x, y, boardSize = 19}) => { makeMove: function(Game) { this.stone = Game.turn; this.legal = false; - if (this.capturing[this.stone].length) { + if (this.capturing[this.stone].size) { Game = this.makeCaptures(Game); } Game = this.joinGroup({ point: this, Game }); @@ -290,7 +290,7 @@ const Point = ({x, y, boardSize = 19}) => { const liberties = game.groups[this.group].liberties; if (liberties.size === 1) { const lastLiberty = getSingleItemFromSet(liberties); - lastLiberty.capturing[this.stone * -1].push(this.group); + lastLiberty.capturing[this.stone * -1].add(this.group); } // if neighbors have one liberty @@ -299,7 +299,7 @@ const Point = ({x, y, boardSize = 19}) => { const liberties = game.groups[neighbor.group] && game.groups[neighbor.group].liberties; if (liberties && liberties.size === 1) { const lastLiberty = getSingleItemFromSet(liberties); - lastLiberty.capturing[neighbor.stone * -1].push(neighbor.group); + lastLiberty.capturing[neighbor.stone * -1].add(neighbor.group); } }); return game; @@ -307,24 +307,28 @@ const Point = ({x, y, boardSize = 19}) => { makeCaptures: function(game) { // for each group - this.capturing[this.stone].forEach(captureGroup => { + for (let [captureGroup, _] of this.capturing[this.stone].entries()) { + const capturesSet = game.groups[captureGroup].stones; - for (let [capture] of capturesSet.entries()) { + for (let [capture, _] of capturesSet.entries()) { game = capture.removeStone(game); } - }); + } return game; }, removeStone: function(game) { + if (this.stone = 0) { + return game; + } // reset point this.stone = 0; this.group = null; - this.capturing[game.turn] = []; + this.capturing[game.turn] = new Set(); // add captures const player = game.turn > 0 ? 'b' : 'w'; game.playerState[`${player}Captures`] += 1; - return {...game, boardState: {...this.boardState, [this.key]: this}}; + return {...game, boardState: {...game.boardState, [this.key]: this}}; } } for (let [key, value] of Object.entries(point.neighbors)) { @@ -338,3 +342,21 @@ module.exports = { Game, Point } + + +Game().initGame() + .makeMove({ player: 'black', pos: { x: 4, y: 17 } }) + .makeMove({ player: 'white', pos: { x: 3, y: 16 } }) + .makeMove({ player: 'black', pos: { x: 5, y: 16 } }) + .makeMove({ player: 'white', pos: { x: 4, y: 15 } }) + .makeMove({ player: 'black', pos: { x: 4, y: 16 } }) + .makeMove({ player: 'black', pos: { x: 4, y: 10 } }) // 3 4 5 6 + .makeMove({ player: 'white', pos: { x: 3, y: 17 } }) // 15 -1 -1 + .makeMove({ player: 'black', pos: { x: 10, y: 4 } }) // 16 -1 1 1 -1 + .makeMove({ player: 'white', pos: { x: 5, y: 15 } }) // 17 -1 1 -1 + .makeMove({ player: 'black', pos: { x: 10, y: 8 } }) // 18 -1 + .makeMove({ player: 'white', pos: { x: 4, y: 18} }) + .makeMove({ player: 'black', pos: { x: 3, y: 6 } }) + .makeMove({ player: 'white', pos: { x: 5, y: 17} }) + .makeMove({ player: 'black', pos: { x: 6, y: 3 } }) + .makeMove({ player: 'white', pos: { x: 6, y: 16} }) \ No newline at end of file diff --git a/packages/server/test/Game.v2.spec.js b/packages/server/test/Game.v2.spec.js index a83fc8a..882f4d5 100644 --- a/packages/server/test/Game.v2.spec.js +++ b/packages/server/test/Game.v2.spec.js @@ -194,7 +194,7 @@ describe('Game.makeMove({ player: str, pos: { x: int, y: int } })', () => { }); }); -describe('makeMove group join and capture logic', () => { +describe('makeMove group join and basic 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 @@ -250,30 +250,30 @@ describe('makeMove group join and capture logic', () => { .makeMove({ player: 'white', pos: { x: 5, y: 16 } }) // 4,16 captured .makeMove({ player: 'black', pos: { x: 10, y: 4 } }) - it('makeMove capture smoke test', done => { - captureGame.makeMove({ player: 'white', pos: { x: 4, y: 17 } }) - .success.should.eql(true); - done(); - }); + it('makeMove capture smoke test', done => { + captureGame.makeMove({ player: 'white', pos: { x: 4, y: 17 } }) + .success.should.eql(true); + done(); + }); - it('makeMove assesses captures', done => { - captureGame.boardState['4-17'].capturing[-1].length.should.eql(1); - done(); - }) + it('makeMove assesses captures', done => { + captureGame.boardState['4-17'].capturing[-1].size.should.eql(1); + done(); + }) - it('makeMove capture removes captured stone', done => { - captureGame.makeMove({ player: 'white', pos: { x: 4, y: 17 } }) - .boardState['4-16'].stone.should.eql(0); - done(); - }); - - it('makeMove capture increases capturing players captures', done => { - captureGame.makeMove({ player: 'white', pos: { x: 4, y: 17 } }) - .playerState.wCaptures.should.eql(1); - done(); - }); + it('makeMove capture removes captured stone', done => { + captureGame.makeMove({ player: 'white', pos: { x: 4, y: 17 } }) + .boardState['4-16'].stone.should.eql(0); + done(); + }); + + it('makeMove capture increases capturing players captures', done => { + captureGame.makeMove({ player: 'white', pos: { x: 4, y: 17 } }) + .playerState.wCaptures.should.eql(1); + done(); + }); - const multiCaptureGame = () => Game().initGame() + const multiCaptureGame = () => Game().initGame() .makeMove({ player: 'black', pos: { x: 4, y: 17 } }) .makeMove({ player: 'white', pos: { x: 3, y: 16 } }) .makeMove({ player: 'black', pos: { x: 5, y: 16 } }) @@ -288,29 +288,38 @@ describe('makeMove group join and capture logic', () => { .makeMove({ player: 'black', pos: { x: 3, y: 6 } }) .makeMove({ player: 'white', pos: { x: 5, y: 17} }) .makeMove({ player: 'black', pos: { x: 6, y: 3 } }); - - it('smoke test multi stone group capture', done => { - multiCaptureGame().makeMove({ player: 'white', pos: { x: 6, y: 16} }) + + it('smoke test multi stone group capture', done => { + multiCaptureGame().makeMove({ player: 'white', pos: { x: 6, y: 16} }) .success.should.eql(true); - done(); - }) - - it('multi stone group full group is in capturing', done => { - const game = multiCaptureGame() - const group = game.boardState['4-16'].group; - game.boardState['6-16'].capturing[-1][0].should.eql(group); - done(); - }) - - it('multi stone group capture all points are 0', done => { - const game = multiCaptureGame(); - game.makeMove({ player: 'white', pos: { x: 6, y: 16} }); - game.boardState['5-16'].stone.should.eql(0) - game.boardState['4-16'].stone.should.eql(0) - game.boardState['4-17'].stone.should.eql(0) - done(); - }) -}) + done(); + }); + + it('multi stone group full group is in capturing', done => { + const game = multiCaptureGame() + const group = game.boardState['4-16'].group; + game.boardState['6-16'].capturing[-1].has(group).should.eql(true); + done(); + }); + + it('multi stone group capture all points are 0', done => { + const game = multiCaptureGame(); + game.makeMove({ player: 'white', pos: { x: 6, y: 16} }); + game.boardState['5-16'].stone.should.eql(0) + game.boardState['4-16'].stone.should.eql(0) + game.boardState['4-17'].stone.should.eql(0) + done(); + }); + + it('multi stone group capture scores points properly', done => { + const game = multiCaptureGame(); + game.makeMove({ player: 'white', pos: { x: 6, y: 16} }); + game.playerState.wCaptures.should.eql(3); + done(); + }) +}); + +// describe('capture logic: snapback') const initialMeta = {