init Game.returnToMove(x) where x < 0 rewinds x number of moves
This commit is contained in:
parent
bdeb9c9d86
commit
d51e3f72f4
2 changed files with 96 additions and 79 deletions
|
@ -163,86 +163,92 @@ const initBoard = (game) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns Game object
|
// returns Game object
|
||||||
const Game = ({gameData = {}, gameRecord = []} = {}) => ({
|
const Game = ({gameData = {}, gameRecord = []} = {}) => {
|
||||||
winner: gameData.winner ||null,
|
if (gameRecord.length) {
|
||||||
turn: gameData.turn || 0, // turn logic depends on handicap stones
|
// play through all the moves
|
||||||
pass: gameData.pass || 0, // -1 represents state in which resignation has been submitted, not confirmed
|
return gameRecord.reduce((game, move) => game.makeMove(move), Game({gameData}).initGame())
|
||||||
komi: gameData.komi || 6.5, // komi depends on handicap stones + player rank
|
}
|
||||||
handicap: gameData.handicap || 0,
|
return {
|
||||||
boardSize: gameData.boardSize || 19,
|
winner: gameData.winner ||null,
|
||||||
groups: {},
|
turn: gameData.turn || 0, // turn logic depends on handicap stones
|
||||||
boardState: {},
|
pass: gameData.pass || 0, // -1 represents state in which resignation has been submitted, not confirmed
|
||||||
kos: [],
|
komi: gameData.komi || 6.5, // komi depends on handicap stones + player rank
|
||||||
gameRecord: gameRecord,
|
handicap: gameData.handicap || 0,
|
||||||
playerState: gameData.playerState || {
|
boardSize: gameData.boardSize || 19,
|
||||||
bCaptures: 0,
|
groups: {},
|
||||||
wCaptures: 0,
|
boardState: {},
|
||||||
bScore: 0,
|
kos: [],
|
||||||
wScore: 0
|
gameRecord: gameRecord,
|
||||||
},
|
playerState: gameData.playerState || {
|
||||||
|
bCaptures: 0,
|
||||||
|
wCaptures: 0,
|
||||||
|
bScore: 0,
|
||||||
|
wScore: 0
|
||||||
|
},
|
||||||
|
|
||||||
initGame: function() {
|
initGame: function() {
|
||||||
this.winner = null;
|
this.winner = null;
|
||||||
this.pass = 0;
|
this.pass = 0;
|
||||||
this.turn = 1;
|
this.turn = 1;
|
||||||
this.boardState = initBoard(this);
|
this.boardState = initBoard(this);
|
||||||
this.boardState = getBoardState(this);
|
this.boardState = getBoardState(this);
|
||||||
this.legalMoves = getLegalMoves(this)
|
this.legalMoves = getLegalMoves(this)
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
addToRecord: function(moveObject) {
|
addToRecord: function(moveObject) {
|
||||||
this.gameRecord.push(moveObject);
|
this.gameRecord.push(moveObject);
|
||||||
},
|
},
|
||||||
|
|
||||||
getMeta: function() {
|
getMeta: function() {
|
||||||
// cannot be chained
|
// cannot be chained
|
||||||
// does not affect game object
|
// does not affect game object
|
||||||
return { winner: this.winner, turn: this.turn, pass: this.pass, playerState: this.playerState, gameRecord: this.gameRecord }
|
return { winner: this.winner, turn: this.turn, pass: this.pass, playerState: this.playerState, gameRecord: this.gameRecord }
|
||||||
},
|
},
|
||||||
|
|
||||||
clearKo: function() {
|
clearKo: function() {
|
||||||
this.kos.forEach(ko => {
|
this.kos.forEach(ko => {
|
||||||
this.boardState[ko] = { ...this.boardState[ko], legal: true, ko: false };
|
this.boardState[ko] = { ...this.boardState[ko], legal: true, ko: false };
|
||||||
})
|
})
|
||||||
this.kos = [];
|
this.kos = [];
|
||||||
},
|
},
|
||||||
|
|
||||||
makeMove: function({ player, pos: {x, y}}) {
|
makeMove: function({ player, pos: {x, y}}) {
|
||||||
let game = this;
|
let game = this;
|
||||||
let success = false;
|
let success = false;
|
||||||
const point = game.boardState[`${x}-${y}`];
|
const point = game.boardState[`${x}-${y}`];
|
||||||
const isTurn = ( game.turn === 1 && player === 'black' )
|
const isTurn = ( game.turn === 1 && player === 'black' )
|
||||||
|| ( game.turn === -1 && player === 'white' );
|
|| ( game.turn === -1 && player === 'white' );
|
||||||
if (isTurn) {
|
if (isTurn) {
|
||||||
if (point.legal) {
|
if (point.legal) {
|
||||||
game.addToRecord({ player, pos: { x, y } });
|
game.addToRecord({ player, pos: { x, y } });
|
||||||
if (this.kos.length) this.clearKo();
|
if (this.kos.length) this.clearKo();
|
||||||
point.makeMove(game);
|
point.makeMove(game);
|
||||||
game.turn *= -1;
|
game.turn *= -1;
|
||||||
success = true;
|
success = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
game.boardState = getBoardState(game);
|
||||||
|
return {...game, legalMoves: getLegalMoves(game), success };
|
||||||
|
},
|
||||||
|
|
||||||
|
initGroup: function(point) {
|
||||||
|
const group = Symbol(`${point.pos.x}-${point.pos.y}`);
|
||||||
|
this.groups[group] = { stones: new Set(), liberties: new Set()};
|
||||||
|
return { game: this, group };
|
||||||
|
},
|
||||||
|
|
||||||
|
returnToMove: function(idx) {
|
||||||
|
if (idx < 0) {
|
||||||
|
const { komi, handicap, boardSize } = this;
|
||||||
|
return Game({
|
||||||
|
gameData: { komi, handicap, boardSize },
|
||||||
|
gameRecord: [...this.gameRecord.slice(0, this.gameRecord.length + idx)]
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
game.boardState = getBoardState(game);
|
|
||||||
return {...game, legalMoves: getLegalMoves(game), success };
|
|
||||||
},
|
|
||||||
|
|
||||||
initGroup: function(point) {
|
|
||||||
const group = Symbol(`${point.pos.x}-${point.pos.y}`);
|
|
||||||
this.groups[group] = { stones: new Set(), liberties: new Set()};
|
|
||||||
return { game: this, group };
|
|
||||||
},
|
|
||||||
|
|
||||||
returnToMove: function(idx) {
|
|
||||||
if (idx < 0) {
|
|
||||||
const { komi, handicap, boardSize } = this;
|
|
||||||
return Game({
|
|
||||||
gameData: { komi, handicap, boardSize },
|
|
||||||
gameRecord: [...this.gameRecord.slice(0, this.gameRecord.length + idx)]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
const Point = ({x, y, boardSize = 19}) => {
|
const Point = ({x, y, boardSize = 19}) => {
|
||||||
let point = {
|
let point = {
|
||||||
|
|
|
@ -422,16 +422,27 @@ describe('Game history functionality', () => {
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const rewoundGame = () => Game().initGame()
|
||||||
|
.makeMove(firstMove)
|
||||||
|
.makeMove(secondMove)
|
||||||
|
.makeMove({ player: 'black', pos: { x: 16, y: 4 } })
|
||||||
|
.returnToMove(-1);
|
||||||
|
|
||||||
it('Game.returnToMove returns new Game with gameRecord', done => {
|
it('Game.returnToMove returns new Game with gameRecord', done => {
|
||||||
Game().initGame()
|
rewoundGame()
|
||||||
.makeMove(firstMove)
|
|
||||||
.makeMove(secondMove)
|
|
||||||
.makeMove({ player: 'black', pos: { x: 16, y: 4 } })
|
|
||||||
.returnToMove(-1)
|
|
||||||
.gameRecord.should.eql([ firstMove, secondMove ])
|
.gameRecord.should.eql([ firstMove, secondMove ])
|
||||||
done();
|
done();
|
||||||
})
|
})
|
||||||
// .boardState['16-4'].stone.should.eql(0)
|
|
||||||
|
it('Game.returnToMove returns new Game with new board state', done => {
|
||||||
|
rewoundGame()
|
||||||
|
.boardState['16-4'].stone.should.eql(0);
|
||||||
|
rewoundGame()
|
||||||
|
.boardState['4-4'].stone.should.eql(1);
|
||||||
|
rewoundGame()
|
||||||
|
.boardState['16-16'].stone.should.eql(-1);
|
||||||
|
done();
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue