diff --git a/package.json b/package.json index 42295bd..20b29fa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mancala.js", - "version": "0.0.2-beta.1", + "version": "0.0.2-beta.2", "description": "Mancala game library", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/src/common/CommonMancalaGame.ts b/src/common/CommonMancalaGame.ts index 0c0e850..22499c8 100644 --- a/src/common/CommonMancalaGame.ts +++ b/src/common/CommonMancalaGame.ts @@ -1,6 +1,7 @@ import { MancalaGame } from '../core/MancalaGame'; import { CommonBoard } from './CommonBoard'; import { GRClearBoardAtEnd } from './game_rules/GRClearBoardAtEnd'; +import { GRDoubleStoneInPit } from './game_rules/GRDoubleStoneInPit'; import { GRLastStoneInBank } from './game_rules/GRLastStoneInBank'; import { GRLastStoneInEmptyPit } from './game_rules/GRLastStoneInEmptyPit'; @@ -14,6 +15,7 @@ export class CommonMancalaGame extends MancalaGame { player1Id, [ new GRLastStoneInEmptyPit(), + new GRDoubleStoneInPit(), new GRLastStoneInBank(), new GRClearBoardAtEnd() ], diff --git a/src/common/game_rules/GRDoubleStoneInPit.ts b/src/common/game_rules/GRDoubleStoneInPit.ts new file mode 100644 index 0000000..a605eb3 --- /dev/null +++ b/src/common/game_rules/GRDoubleStoneInPit.ts @@ -0,0 +1,44 @@ +import { GameRule } from '../../core/GameRule'; +import { GameStep } from '../../core/HistoryItem'; +import { MancalaGame } from '../../core/MancalaGame'; + +export const GAME_STEP_DOUBLE_STONE_IN_PIT = 'GAME_STEP_DOUBLE_STONE_IN_PIT'; + +export type DoubleStoneInPitData = { pitIndex: number; bankIndex: number }; + +export class GRDoubleStoneInPit implements GameRule { + onGameMoveStart(game: MancalaGame, index: number): void {} + onGameMove(game: MancalaGame, index: number): void {} + onGameMoveEnd(game: MancalaGame, index: number): void { + index = game.board.getPitIndexCircularly(index); + const pit = game.board.pits[index]; + const pitType = game.board.getPitTypeByIndex(index); + if (pit.stoneCount % 2 === 0) { + if (pitType === 'player1Pit' && game.isTurnPlayer2()) { + const pitIndex = index; + const bankIndex = game.board.player2BankIndex(); + game.board.player2Bank.stoneCount += + game.board.getPitCircularly(pitIndex).stoneCount; + game.board.getPitCircularly(pitIndex).stoneCount = 0; + this.addGameStep(game, index, { pitIndex, bankIndex }); + } else if (pitType === 'player2Pit' && game.isTurnPlayer1()) { + const pitIndex = index; + const bankIndex = game.board.player1BankIndex(); + game.board.player1Bank.stoneCount += + game.board.getPitCircularly(pitIndex).stoneCount; + game.board.getPitCircularly(pitIndex).stoneCount = 0; + this.addGameStep(game, index, { pitIndex, bankIndex }); + } + } + } + + private addGameStep( + game: MancalaGame, + index: number, + doubleStoneInPitData: DoubleStoneInPitData + ) { + game.addGameStep( + new GameStep(index, GAME_STEP_DOUBLE_STONE_IN_PIT, doubleStoneInPitData) + ); + } +} diff --git a/src/index.ts b/src/index.ts index 0d4b07c..5968890 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,8 +2,10 @@ export * from './core/MancalaGame'; export * from './core/Board'; export * from './core/Pit'; export * from './core/GameRule'; +export * from './core/HistoryItem'; export * from './common/CommonBoard'; export * from './common/CommonMancalaGame'; export * from './common/game_rules/GRLastStoneInBank'; export * from './common/game_rules/GRLastStoneInEmptyPit'; +export * from './common/game_rules/GRDoubleStoneInPit'; export * from './common/game_rules/GRClearBoardAtEnd'; diff --git a/tests/TestUtil.ts b/tests/TestUtil.ts index dc338ce..951fc26 100644 --- a/tests/TestUtil.ts +++ b/tests/TestUtil.ts @@ -1,6 +1,7 @@ import { GRClearBoardAtEnd } from '../src/common/game_rules/GRClearBoardAtEnd'; import { GRLastStoneInBank } from '../src/common/game_rules/GRLastStoneInBank'; import { GRLastStoneInEmptyPit } from '../src/common/game_rules/GRLastStoneInEmptyPit'; +import { GRDoubleStoneInPit } from '../src/common/game_rules/GRDoubleStoneInPit'; import { Board } from '../src/core/Board'; import { MancalaGame } from '../src/core/MancalaGame'; @@ -16,6 +17,7 @@ export function createGame(): MancalaGame { player1Id, [ new GRLastStoneInEmptyPit(), + new GRDoubleStoneInPit(), new GRLastStoneInBank(), new GRClearBoardAtEnd() ], diff --git a/tests/game_rules/GRDoubleStoneInPit.test.ts b/tests/game_rules/GRDoubleStoneInPit.test.ts new file mode 100644 index 0000000..0d07a12 --- /dev/null +++ b/tests/game_rules/GRDoubleStoneInPit.test.ts @@ -0,0 +1,43 @@ +import { GameStep } from '../../src/core/HistoryItem'; +import { GAME_STEP_GAME_MOVE } from '../../src/core/MancalaGame'; +import { createGame } from '../TestUtil'; +import { GAME_STEP_DOUBLE_STONE_IN_PIT } from '../../src/common/game_rules/GRDoubleStoneInPit'; + +describe('GRDoubleStoneInPit Test', () => { + test('test GRDoubleStoneInPit 1', () => { + const game = createGame(); + const board = game.board; + const initialBoard = [3, 4, 4, 4, 4, 3, 0, 3, 4, 4, 4, 4, 3, 0]; + game.board.pits[5].stoneCount = 3; + game.board.pits[7].stoneCount = 3; + game.board.pits[12].stoneCount = 3; + game.board.pits[0].stoneCount = 3; + expect(board.getStoneArray()).toStrictEqual(initialBoard); + game.moveByPlayerPit('0', 5); + expect(board.getStoneArray()).toStrictEqual([ + 3, 4, 4, 4, 4, 1, 5, 0, 4, 4, 4, 4, 3, 0 + ]); + expect(game.history[0].gameSteps).toStrictEqual([ + new GameStep(5, GAME_STEP_GAME_MOVE), + new GameStep(6, GAME_STEP_GAME_MOVE), + new GameStep(7, GAME_STEP_GAME_MOVE), + new GameStep(7, GAME_STEP_DOUBLE_STONE_IN_PIT, { + pitIndex: 7, + bankIndex: 6 + }) + ]); + game.moveByPlayerPit('1', 5); + expect(board.getStoneArray()).toStrictEqual([ + 0, 4, 4, 4, 4, 1, 5, 0, 4, 4, 4, 4, 1, 5 + ]); + expect(game.history[game.history.length - 1].gameSteps).toStrictEqual([ + new GameStep(12, GAME_STEP_GAME_MOVE), + new GameStep(13, GAME_STEP_GAME_MOVE), + new GameStep(14, GAME_STEP_GAME_MOVE), + new GameStep(0, GAME_STEP_DOUBLE_STONE_IN_PIT, { + pitIndex: 0, + bankIndex: 13 + }) + ]); + }); +});