From 41e6e662e90a2e08c7961f8942f3f77c489a963f Mon Sep 17 00:00:00 2001 From: Sorrel Bri Date: Sun, 19 Apr 2020 15:02:09 -0700 Subject: [PATCH] initialize board for all board sizes and handicap amounts --- packages/server/services/Game.v2.js | 75 ++++++++++-------- packages/server/test/Game.v2.spec.js | 113 +++++++++++++++++++++++++-- 2 files changed, 148 insertions(+), 40 deletions(-) diff --git a/packages/server/services/Game.v2.js b/packages/server/services/Game.v2.js index bd99b85..53977aa 100644 --- a/packages/server/services/Game.v2.js +++ b/packages/server/services/Game.v2.js @@ -35,36 +35,37 @@ const HANDI_REC = { // index represents handicap placement for different board-sizes, eg handiPlace['9][1] = { (3, 3), (7, 7) } // last array in each property also used for hoshi rendering const HANDI_PLACE = { - '9' : [ + 9 : [ 0, 0, - [[ 7, 3 ], [ 3, 7 ] ], - [ [ 7, 7 ], [ 7, 3 ], [ 3, 7 ] ], - [ [ 3, 3 ], [ 7, 7 ], [ 3, 7 ], [ 7, 3 ] ] + [ '7-3', '3-7' ], // 2 + [ '7-7', '7-3', '3-7' ], + [ '3-3', '7-7', '3-7', '7-3' ] ], - '13' : [ + 13 : [ 0, 0, - [ [ 4, 10 ], [ 10, 4 ] ], - [ [ 10, 10 ], [ 4, 10 ], [ 10, 4] ], - [ [ 4, 4 ], [ 10, 10 ], [ 4, 10 ], [ 10, 4] ], - [ [ 7, 7 ], [ 4, 4 ], [ 10, 10 ], [ 4, 10 ], [ 10, 4] ], - [ [ 7, 4 ], [ 4, 7 ], [ 4, 4 ], [ 10, 10 ], [ 4, 10 ], [ 10, 4] ], - [ [ 7, 7 ], [ 7, 4 ], [ 4, 7 ], [ 4, 4 ], [ 10, 10 ], [ 4, 10 ], [ 10, 4] ], - [ [ 10, 7 ], [ 7, 4 ], [ 7, 10 ], [ 4, 7 ], [ 4, 4 ], [ 10, 10 ], [ 4, 10 ], [ 10, 4] ], - [ [ 7, 7 ], [ 10, 7 ], [ 7, 4 ], [ 7, 10 ], [ 4, 7 ], [ 4, 4 ], [ 10, 10 ], [ 4, 10 ], [ 10, 4] ], + [ '4-10', '10-4' ], // 2 + [ '10-10', '4-10', '10-4' ], + [ '4-4', '10-10', '4-10', '10-4' ], + [ '7-7', '4-4', '10-10', '4-10', '10-4' ], + [ '7-4', '4-7', '4-4', '10-10', '4-10', '10-4' ], + [ '7-7', '7-4', '4-7', '4-4', '10-10', '4-10', '10-4' ], + [ '10-7', '7-4', '7-10', '4-7', '4-4', '10-10', '4-10', '10-4' ], + [ '7-7', '10-7', '7-4', '7-10', '4-7', '4-4', '10-10', '4-10', '10-4' ], ], - '19' : [ + 19 : [ 0, 0, - [ [ 4, 16 ], [ 16, 4 ] ], - [ [ 16, 16 ], [ 4, 16 ], [ 16, 4] ], - [ [ 4, 4 ], [ 16, 16 ], [ 4, 16 ], [ 16, 4] ], - [ [ 10, 10 ], [ 4, 4 ], [ 16, 16 ], [ 4, 16 ], [ 16, 4] ], - [ [ 10, 4 ], [ 4, 10 ], [ 4, 4 ], [ 16, 16 ], [ 4, 16 ], [ 16, 4] ], - [ [ 10, 10 ], [ 10, 4 ], [ 4, 10 ], [ 4, 4 ], [ 16, 16 ], [ 4, 16 ], [ 16, 4] ], - [ [ 16, 10 ], [ 10, 4 ], [ 10, 16 ], [ 4, 10 ], [ 4, 4 ], [ 16, 16 ], [ 4, 16 ], [ 16, 4] ], - [ [ 10, 10 ], [ 16, 10 ], [ 10, 4 ], [ 10, 16 ], [ 4, 10 ], [ 4, 4 ], [ 16, 16 ], [ 4, 16 ], [ 16, 4] ], + [ '4-16', '16-4' ], // 2 + [ '16-16', '4-16', '16-4' ], + [ '4-4', '16-16', '4-16', '16-4' ], + [ '10-10', '4-4', '16-16', '4-16', '16-4' ], + [ '10-4', '4-10', '4-4', '16-16', '4-16', '16-4' ], + [ '10-10', '10-4', '4-10', '4-4', '16-16', '4-16', '16-4' ], + [ '16-10', '10-4', '10-16', '4-10', '4-4', '16-16', '4-16', '16-4' ], + [ '10-10', '16-10', '10-4', '10-16', '4-10', '4-4', '16-16', '4-16', '16-4' ], ] }; + const pipeMap = (...funcs) => obj => { const arr = Object.entries(obj).reduce((acc, [key, value]) => { funcs.forEach(func => value = func(value)); @@ -76,7 +77,7 @@ const pipeMap = (...funcs) => obj => { } const checkLegal = ({ point, Game }) => { - return 'l'; + return point.stone || 'l'; } const getBoardState = (Game) => { @@ -84,7 +85,7 @@ const getBoardState = (Game) => { return pipeMap(getLegal)(Game.boardState); } -const initBoard = boardSize => { +const initBoard = ({ boardSize, handicap }) => { const boardState = {}; for (let i = 0; i < Math.pow(boardSize, 2); i++) { const point = Point({ @@ -94,21 +95,26 @@ const initBoard = boardSize => { }); boardState[`${point.pos.x}-${point.pos.y}`] = point; } + if (handicap) { + HANDI_PLACE[boardSize][handicap].forEach(pt => { + boardState[pt].stone = 1; + }); + } return boardState; } // returns Game object -const Game = ({gameData, gameRecord} = {}) => ({ - winner: gameData ? gameData.winner : null, - turn: gameData ? gameData.turn : 1, // turn logic depends on handicap stones - pass: gameData ? gameData.pass : 0, // -1 represents state in which resignation has been submitted, not confirmed - komi: gameData ? gameData.komi : 6.5, // komi depends on handicap stones + player rank - handicap: gameData ? gameData.handicap : 0, - boardSize: gameData ? gameData.boardSize : 19, +const Game = ({gameData = {}, gameRecord = []} = {}) => ({ + winner: gameData.winner ||null, + turn: gameData.turn || 1, // turn logic depends on handicap stones + pass: gameData.pass || 0, // -1 represents state in which resignation has been submitted, not confirmed + komi: gameData.komi || 6.5, // komi depends on handicap stones + player rank + handicap: gameData.handicap || 0, + boardSize: gameData.boardSize || 19, groups: {}, boardState: {}, - gameRecord: gameRecord || [], - playerState: gameData ? gameData.playerState : { + gameRecord: gameRecord, + playerState: gameData.playerState || { bCaptures: 0, wCaptures: 0, bScore: 0, @@ -119,7 +125,8 @@ const Game = ({gameData, gameRecord} = {}) => ({ this.winner = null; this.pass = 0; this.turn = this.handicap ? -1 : 1; - this.boardState = initBoard(this.boardSize) + this.boardState = initBoard({ boardSize: this.boardSize, handicap: this.handicap}) + // return this.boardState return getBoardState(this); } }); diff --git a/packages/server/test/Game.v2.spec.js b/packages/server/test/Game.v2.spec.js index 43122c2..38632b8 100644 --- a/packages/server/test/Game.v2.spec.js +++ b/packages/server/test/Game.v2.spec.js @@ -4,28 +4,129 @@ const { Game, Point } = require('../services/Game.v2'); describe('Game v2', () => { it('smoke test Game', done => { - (typeof Game()).should.eql('object'); + (typeof Game()) + .should.eql('object'); done(); }); it('smoke test Point', done => { - (typeof Point({x: 1, y: 1})).should.eql('object'); + (typeof Point({x: 1, y: 1})) + .should.eql('object'); done(); }); it('smoke test init Game', done => { - (typeof Game().initGame()).should.eql('object'); + (typeof Game().initGame()) + .should.eql('object'); done(); }) }); -describe('Game.initGame()', () => { - it('init Game returns boardState', done => { - Game().initGame().should.eql(emptyBoard); +describe('Game.initGame() returns boardState', () => { + it('init Game returns default 19x19', done => { + Game().initGame() + .should.eql(emptyBoard); + done(); + }); + + it('init Game with 2 handicap returns boardState with stones', done => { + Game({gameData: { handicap: 2 }}).initGame() + .should.eql({...emptyBoard, '4-16': 1, '16-4': 1}); + done(); + }); + + it('init 19x19 Game with all levels of handicap returns boardState with stones', done => { + Game({gameData: { boardSize: 19, handicap: 2 }}).initGame() + .should.eql({...emptyBoard, '4-16': 1, '16-4': 1 }); + Game({gameData: { boardSize: 19, handicap: 3 }}).initGame() + .should.eql({...emptyBoard, '16-16': 1, '4-16': 1, '16-4': 1 }); + Game({gameData: { boardSize: 19, handicap: 4 }}).initGame() + .should.eql({...emptyBoard, '4-4': 1, '16-16': 1, '4-16': 1, '16-4': 1 }); + Game({gameData: { boardSize: 19, handicap: 5 }}).initGame() + .should.eql({...emptyBoard, '10-10': 1, '4-4': 1, '16-16': 1, '4-16': 1, '16-4': 1 }); + Game({gameData: { boardSize: 19, handicap: 6 }}).initGame() + .should.eql({...emptyBoard, '10-4': 1, '4-10': 1, '4-4': 1, '16-16': 1, '4-16': 1, '16-4': 1 }); + Game({gameData: { boardSize: 19, handicap: 7 }}).initGame() + .should.eql({...emptyBoard, '10-10': 1, '10-4': 1, '4-10': 1, '4-4': 1, '16-16': 1, '4-16': 1, '16-4': 1 }); + Game({gameData: { boardSize: 19, handicap: 8 }}).initGame() + .should.eql({...emptyBoard, '16-10': 1, '10-4': 1, '10-16': 1, '4-10': 1, '4-4': 1, '16-16': 1, '4-16': 1, '16-4': 1 }); + Game({gameData: { boardSize: 19, handicap: 9 }}).initGame() + .should.eql({...emptyBoard, '10-10': 1, '16-10': 1, '10-4': 1, '10-16': 1, '4-10': 1, '4-4': 1, '16-16': 1, '4-16': 1, '16-4': 1 }); done(); }) + + it('init 13x13 Game returns boardState', done => { + Game({gameData: { boardSize: 13 }}).initGame() + .should.eql(emptyBoard13); + done(); + }); + + it('init 13x13 Game with all levels of handicap returns boardState with stones', done => { + Game({gameData: { boardSize: 13, handicap: 2 }}).initGame() + .should.eql({...emptyBoard13, '4-10': 1, '10-4': 1 }); + Game({gameData: { boardSize: 13, handicap: 3 }}).initGame() + .should.eql({...emptyBoard13, '10-10': 1, '4-10': 1, '10-4': 1 }); + Game({gameData: { boardSize: 13, handicap: 4 }}).initGame() + .should.eql({...emptyBoard13, '4-4': 1, '10-10': 1, '4-10': 1, '10-4': 1 }); + Game({gameData: { boardSize: 13, handicap: 5 }}).initGame() + .should.eql({...emptyBoard13, '7-7': 1, '4-4': 1, '10-10': 1, '4-10': 1, '10-4': 1 }); + Game({gameData: { boardSize: 13, handicap: 6 }}).initGame() + .should.eql({...emptyBoard13, '7-4': 1, '4-7': 1, '4-4': 1, '10-10': 1, '4-10': 1, '10-4': 1 }); + Game({gameData: { boardSize: 13, handicap: 7 }}).initGame() + .should.eql({...emptyBoard13, '7-7': 1, '7-4': 1, '4-7': 1, '4-4': 1, '10-10': 1, '4-10': 1, '10-4': 1 }); + Game({gameData: { boardSize: 13, handicap: 8 }}).initGame() + .should.eql({...emptyBoard13, '10-7': 1, '7-4': 1, '7-10': 1, '4-7': 1, '4-4': 1, '10-10': 1, '4-10': 1, '10-4': 1 }); + Game({gameData: { boardSize: 13, handicap: 9 }}).initGame() + .should.eql({...emptyBoard13, '7-7': 1, '10-7': 1, '7-4': 1, '7-10': 1, '4-7': 1, '4-4': 1, '10-10': 1, '4-10': 1, '10-4': 1 }); + done(); + }); + + it('init 9x9 Game returns boardState', done => { + Game({gameData: { boardSize: 9 }}).initGame() + .should.eql(emptyBoard9); + done(); + }); + + it('init 9x9 Game with all levels of handicap returns boardState with stones', done => { + Game({gameData: { boardSize: 9, handicap: 2 }}).initGame() + .should.eql({...emptyBoard9, '3-7': 1, '7-3': 1 }); + Game({gameData: { boardSize: 9, handicap: 3 }}).initGame() + .should.eql({...emptyBoard9, '7-7': 1, '3-7': 1, '7-3': 1 }); + Game({gameData: { boardSize: 9, handicap: 4 }}).initGame() + .should.eql({...emptyBoard9, '3-3': 1, '7-7': 1, '3-7': 1, '7-3': 1 }); + done(); + }); + }) +const emptyBoard9 = { + '1-1': 'l','1-2': 'l','1-3': 'l','1-4': 'l','1-5': 'l','1-6': 'l','1-7': 'l','1-8': 'l','1-9': 'l', + '2-1': 'l','2-2': 'l','2-3': 'l','2-4': 'l','2-5': 'l','2-6': 'l','2-7': 'l','2-8': 'l','2-9': 'l', + '3-1': 'l','3-2': 'l','3-3': 'l','3-4': 'l','3-5': 'l','3-6': 'l','3-7': 'l','3-8': 'l','3-9': 'l', + '4-1': 'l','4-2': 'l','4-3': 'l','4-4': 'l','4-5': 'l','4-6': 'l','4-7': 'l','4-8': 'l','4-9': 'l', + '5-1': 'l','5-2': 'l','5-3': 'l','5-4': 'l','5-5': 'l','5-6': 'l','5-7': 'l','5-8': 'l','5-9': 'l', + '6-1': 'l','6-2': 'l','6-3': 'l','6-4': 'l','6-5': 'l','6-6': 'l','6-7': 'l','6-8': 'l','6-9': 'l', + '7-1': 'l','7-2': 'l','7-3': 'l','7-4': 'l','7-5': 'l','7-6': 'l','7-7': 'l','7-8': 'l','7-9': 'l', + '8-1': 'l','8-2': 'l','8-3': 'l','8-4': 'l','8-5': 'l','8-6': 'l','8-7': 'l','8-8': 'l','8-9': 'l', + '9-1': 'l','9-2': 'l','9-3': 'l','9-4': 'l','9-5': 'l','9-6': 'l','9-7': 'l','9-8': 'l','9-9': 'l' +} + +const emptyBoard13 = { + '1-1': 'l','1-2': 'l','1-3': 'l','1-4': 'l','1-5': 'l','1-6': 'l','1-7': 'l','1-8': 'l','1-9': 'l','1-10': 'l','1-11': 'l','1-12': 'l','1-13': 'l', + '2-1': 'l','2-2': 'l','2-3': 'l','2-4': 'l','2-5': 'l','2-6': 'l','2-7': 'l','2-8': 'l','2-9': 'l','2-10': 'l','2-11': 'l','2-12': 'l','2-13': 'l', + '3-1': 'l','3-2': 'l','3-3': 'l','3-4': 'l','3-5': 'l','3-6': 'l','3-7': 'l','3-8': 'l','3-9': 'l','3-10': 'l','3-11': 'l','3-12': 'l','3-13': 'l', + '4-1': 'l','4-2': 'l','4-3': 'l','4-4': 'l','4-5': 'l','4-6': 'l','4-7': 'l','4-8': 'l','4-9': 'l','4-10': 'l','4-11': 'l','4-12': 'l','4-13': 'l', + '5-1': 'l','5-2': 'l','5-3': 'l','5-4': 'l','5-5': 'l','5-6': 'l','5-7': 'l','5-8': 'l','5-9': 'l','5-10': 'l','5-11': 'l','5-12': 'l','5-13': 'l', + '6-1': 'l','6-2': 'l','6-3': 'l','6-4': 'l','6-5': 'l','6-6': 'l','6-7': 'l','6-8': 'l','6-9': 'l','6-10': 'l','6-11': 'l','6-12': 'l','6-13': 'l', + '7-1': 'l','7-2': 'l','7-3': 'l','7-4': 'l','7-5': 'l','7-6': 'l','7-7': 'l','7-8': 'l','7-9': 'l','7-10': 'l','7-11': 'l','7-12': 'l','7-13': 'l', + '8-1': 'l','8-2': 'l','8-3': 'l','8-4': 'l','8-5': 'l','8-6': 'l','8-7': 'l','8-8': 'l','8-9': 'l','8-10': 'l','8-11': 'l','8-12': 'l','8-13': 'l', + '9-1': 'l','9-2': 'l','9-3': 'l','9-4': 'l','9-5': 'l','9-6': 'l','9-7': 'l','9-8': 'l','9-9': 'l','9-10': 'l','9-11': 'l','9-12': 'l','9-13': 'l', + '10-1': 'l','10-2': 'l','10-3': 'l','10-4': 'l','10-5': 'l','10-6': 'l','10-7': 'l','10-8': 'l','10-9': 'l','10-10': 'l','10-11': 'l','10-12': 'l','10-13': 'l', + '11-1': 'l','11-2': 'l','11-3': 'l','11-4': 'l','11-5': 'l','11-6': 'l','11-7': 'l','11-8': 'l','11-9': 'l','11-10': 'l','11-11': 'l','11-12': 'l','11-13': 'l', + '12-1': 'l','12-2': 'l','12-3': 'l','12-4': 'l','12-5': 'l','12-6': 'l','12-7': 'l','12-8': 'l','12-9': 'l','12-10': 'l','12-11': 'l','12-12': 'l','12-13': 'l', + '13-1': 'l','13-2': 'l','13-3': 'l','13-4': 'l','13-5': 'l','13-6': 'l','13-7': 'l','13-8': 'l','13-9': 'l','13-10': 'l','13-11': 'l','13-12': 'l','13-13': 'l' +} + const emptyBoard = { '1-1': 'l','1-2': 'l','1-3': 'l','1-4': 'l','1-5': 'l','1-6': 'l','1-7': 'l','1-8': 'l','1-9': 'l','1-10': 'l','1-11': 'l','1-12': 'l','1-13': 'l','1-14': 'l','1-15': 'l','1-16': 'l','1-17': 'l','1-18': 'l','1-19': 'l', '2-1': 'l','2-2': 'l','2-3': 'l','2-4': 'l','2-5': 'l','2-6': 'l','2-7': 'l','2-8': 'l','2-9': 'l','2-10': 'l','2-11': 'l','2-12': 'l','2-13': 'l','2-14': 'l','2-15': 'l','2-16': 'l','2-17': 'l','2-18': 'l','2-19': 'l',