From bdfb6ebe8523510e2d56132967330b04f311451e Mon Sep 17 00:00:00 2001 From: Sorrel Bri Date: Mon, 20 Apr 2020 17:34:49 -0700 Subject: [PATCH] add getNeighbors to initBoard() allowing Points to directly reference neighbors --- packages/server/services/Game.v2.js | 16 +++++-- packages/server/test/Game.v2.spec.js | 68 ++++++++++++++++++++-------- 2 files changed, 63 insertions(+), 21 deletions(-) diff --git a/packages/server/services/Game.v2.js b/packages/server/services/Game.v2.js index d8bef4a..9d5ce90 100644 --- a/packages/server/services/Game.v2.js +++ b/packages/server/services/Game.v2.js @@ -67,8 +67,8 @@ const HANDI_PLACE = { const pipeMap = (...funcs) => obj => { - const arr = Object.entries(obj).reduce((acc, [key, value]) => { - funcs.forEach(func => value = func(value)); + const arr = Object.entries(obj).reduce((acc, [key, value], i, arr) => { + funcs.forEach(func => value = func(value, i, arr)); return [...acc, [key, value]]; },[]); return arr.reduce((acc, [key, value]) => { @@ -85,6 +85,15 @@ const getBoardState = (Game) => { return pipeMap(getLegal)(Game.boardState); } +const getNeighbors = (point, _, boardState) => { + const { top, btm, lft, rgt} = point.neighbors; + point.neighbors.top = top ? boardState.find(val => val[0] === top)[1] : top; + point.neighbors.btm = btm ? boardState.find(val => val[0] === btm)[1] : btm; + point.neighbors.lft = lft ? boardState.find(val => val[0] === lft)[1] : lft; + point.neighbors.rgt = rgt ? boardState.find(val => val[0] === rgt)[1] : rgt; + return point; +} + const initBoard = ({ boardSize, handicap }) => { const boardState = {}; for (let i = 0; i < Math.pow(boardSize, 2); i++) { @@ -100,7 +109,8 @@ const initBoard = ({ boardSize, handicap }) => { boardState[pt].stone = 1; }); } - return boardState; + const boardStateWithNeighbors = pipeMap(getNeighbors)(boardState) + return boardStateWithNeighbors; } // returns Game object diff --git a/packages/server/test/Game.v2.spec.js b/packages/server/test/Game.v2.spec.js index 5475167..28e4b13 100644 --- a/packages/server/test/Game.v2.spec.js +++ b/packages/server/test/Game.v2.spec.js @@ -3,19 +3,19 @@ const should = chai.should(); const { Game, Point } = require('../services/Game.v2'); describe('Game', () => { - it('smoke test Game', done => { + it('smoke test Game()', done => { (typeof Game()) .should.eql('object'); done(); }); - it('smoke test Point', done => { + it('smoke test Point()', done => { (typeof Point({x: 1, y: 1})) .should.eql('object'); done(); }); - it('smoke test init Game', done => { + it('smoke test initGame()', done => { (typeof Game().initGame()) .should.eql('object'); done(); @@ -27,23 +27,44 @@ describe('Game', () => { Game().initGame().getMeta() .should.eql({ ...initialMeta, turn: 1 }); done(); - }) + }); }); -describe('Game.initGame() returns boardState', () => { - it('init Game returns default 19x19', done => { +describe('Game().initGame() returns boardState', () => { + it('initGame() returns default 19x19', done => { Game().initGame().legalMoves .should.eql(emptyBoard); done(); }); - it('init Game with 2 handicap returns boardState with stones', done => { + it('initGame() with 2 handicap returns legalMoves with stones', done => { Game({gameData: { handicap: 2 }}).initGame().legalMoves .should.eql({...emptyBoard, '4-16': 1, '16-4': 1}); done(); }); - it('init 19x19 Game with all levels of handicap returns boardState with stones', done => { + it('initGame() returns Game with all Points having neighbors', done => { + const boardState = Game().initGame().boardState; + const oneOneNeighbors = boardState['1-1'].neighbors; + const fiveSevenNeighbors = boardState['5-7'].neighbors; + const nineteenTenNeighbors = boardState['19-10'].neighbors; + + oneOneNeighbors.rgt.pos.should.eql({x: 1, y: 2}); + oneOneNeighbors.btm.pos.should.eql({x: 2, y: 1}); + + fiveSevenNeighbors.top.pos.should.eql({x: 4, y: 7}); + fiveSevenNeighbors.btm.pos.should.eql({x: 6, y: 7}); + fiveSevenNeighbors.lft.pos.should.eql({x: 5, y: 6}); + fiveSevenNeighbors.rgt.pos.should.eql({x: 5, y: 8}); + + nineteenTenNeighbors.top.pos.should.eql({x: 18, y: 10}); + nineteenTenNeighbors.lft.pos.should.eql({x: 19, y: 9}); + nineteenTenNeighbors.rgt.pos.should.eql({x: 19, y: 11}); + + done(); + }); + + it('initGame( 19x19 ) with all levels of handicap returns legalMoves with stones', done => { Game({gameData: { boardSize: 19, handicap: 2 }}).initGame().legalMoves .should.eql({...emptyBoard, '4-16': 1, '16-4': 1 }); Game({gameData: { boardSize: 19, handicap: 3 }}).initGame().legalMoves @@ -63,13 +84,13 @@ describe('Game.initGame() returns boardState', () => { done(); }) - it('init 13x13 Game returns boardState', done => { + it('initGame( 13x13) returns legalMoves', done => { Game({gameData: { boardSize: 13 }}).initGame().legalMoves .should.eql(emptyBoard13); done(); }); - it('init 13x13 Game with all levels of handicap returns boardState with stones', done => { + it('initGame( 13x13 ) with all levels of handicap returns legalMoves with stones', done => { Game({gameData: { boardSize: 13, handicap: 2 }}).initGame().legalMoves .should.eql({...emptyBoard13, '4-10': 1, '10-4': 1 }); Game({gameData: { boardSize: 13, handicap: 3 }}).initGame().legalMoves @@ -89,13 +110,13 @@ describe('Game.initGame() returns boardState', () => { done(); }); - it('init 9x9 Game returns boardState', done => { + it('initGame( 9x9 ) returns legalMoves', done => { Game({gameData: { boardSize: 9 }}).initGame().legalMoves .should.eql(emptyBoard9); done(); }); - it('init 9x9 Game with all levels of handicap returns boardState with stones', done => { + it('initGame( 9x9 ) with all levels of handicap returns legalMoves with stones', done => { Game({gameData: { boardSize: 9, handicap: 2 }}).initGame().legalMoves .should.eql({...emptyBoard9, '3-7': 1, '7-3': 1 }); Game({gameData: { boardSize: 9, handicap: 3 }}).initGame().legalMoves @@ -108,12 +129,23 @@ describe('Game.initGame() returns boardState', () => { describe('Game.makeMove({ player: str, pos: { x: int, y: int } })', () => { it('place move returns game object with proper board', done => { - Game().initGame().makeMove({ player: 'black', pos: { x: 4, y: 4 } }).success - .should.eql(true) - // .should.eql({ ...emptyBoard, '4-4': 1 }); + Game().initGame().makeMove({ player: 'black', pos: { x: 4, y: 4 } }).legalMoves + .should.eql({ ...emptyBoard, '4-4': 1 }); + Game({ gameData: { handicap: 2 } }).initGame().makeMove({ player: 'white', pos: { x: 4, y: 4 } }).legalMoves + .should.eql({ ...emptyBoard, '4-16': 1, '16-4': 1, '4-4': -1 }); done(); - }) -}) + }); + + it('make move returns success: false with move out of turn', done => { + Game().initGame().makeMove({ player: 'white', pos: { x: 4, y: 4 } }).success + .should.eql(false); + Game({ gameData: { handicap: 2 } }).initGame().makeMove({ player: 'black', pos: { x: 4, y: 4 } }).success + .should.eql(false); + done(); + }); +}); + +// describe('Point.joinGroup() ') const initialMeta = { winner: null, @@ -176,4 +208,4 @@ const emptyBoard = { '17-1': 'l','17-2': 'l','17-3': 'l','17-4': 'l','17-5': 'l','17-6': 'l','17-7': 'l','17-8': 'l','17-9': 'l','17-10': 'l','17-11': 'l','17-12': 'l','17-13': 'l','17-14': 'l','17-15': 'l','17-16': 'l','17-17': 'l','17-18': 'l','17-19': 'l', '18-1': 'l','18-2': 'l','18-3': 'l','18-4': 'l','18-5': 'l','18-6': 'l','18-7': 'l','18-8': 'l','18-9': 'l','18-10': 'l','18-11': 'l','18-12': 'l','18-13': 'l','18-14': 'l','18-15': 'l','18-16': 'l','18-17': 'l','18-18': 'l','18-19': 'l', '19-1': 'l','19-2': 'l','19-3': 'l','19-4': 'l','19-5': 'l','19-6': 'l','19-7': 'l','19-8': 'l','19-9': 'l','19-10': 'l','19-11': 'l','19-12': 'l','19-13': 'l','19-14': 'l','19-15': 'l','19-16': 'l','19-17': 'l','19-18': 'l','19-19': 'l' -}; \ No newline at end of file +};