export class Game { player1: string player2: string board: Board turn: "player1" | "player2" state: "playing" | "ended" constructor(player1: string, player2: string, board: Board, turn: "player1" | "player2", state: "playing" | "ended") { this.player1 = player1 this.player2 = player2 this.board = board this.turn = turn this.state = state } public moveByIndex(holeIndex: number, player: "player1" | "player2") { let hole = this.board.player1Holes[holeIndex] if (player == "player2") { hole = this.board.player2Holes[holeIndex] } return this.move(hole, player) } public move(hole: Hole, player: "player1" | "player2") { if (this.turn != player) return if (hole.ballCount == 0) return let holeIndex = -1 let circle: Array if (player == "player1") { holeIndex = this.board.player1Holes.indexOf(hole) circle = this.board.player1Circle() } else { holeIndex = this.board.player2Holes.indexOf(hole) circle = this.board.player2Circle() } // if can't find hole in own list if (holeIndex < 0) { return } const circleSize = circle.length const stepCount = hole.ballCount let startIndex = holeIndex let holeEndBallCount = 1 if (hole.ballCount == 1) { startIndex = holeIndex + 1 holeEndBallCount = 0 } let stopIndex = startIndex + stepCount - 1 stopIndex += (stopIndex / circleSize) | 0 // add the number of jump over opponent store const stopHole = circle[stopIndex % circle.length] iterateHoles(circle, startIndex, stopIndex, (eachHole: Hole, index: number) => { if (!checkIsOpponentStore(index, circleSize)) { eachHole.ballCount++ } }) hole.ballCount = holeEndBallCount console.log((stopIndex)); console.log(checkIsOwnHole(stopIndex, circleSize)); if (checkIsOwnHole(stopIndex, circleSize)) { //check if it was 0 before if (stopHole.ballCount == 1) { const ownStore = getOwnStore(circle) const opponentHole = getOpponentHoleByIndex(stopIndex%16, circle) if (opponentHole.ballCount > 0) { ownStore.ballCount++ stopHole.ballCount = 0; ownStore.ballCount += opponentHole.ballCount opponentHole.ballCount = 0 } } } if (!checkIsOwnStore(stopIndex, circleSize)) { this.changeTurn() } const ownHoles = circle.slice(0, circle.length / 2 - 1) let sumBallCount = 0; for (const hole of ownHoles) sumBallCount += hole.ballCount if (sumBallCount == 0) { const opppentHoles = circle.slice(circle.length / 2, circle.length - 1) let sumOppenentBallCount = 0; for (const hole of opppentHoles) { sumOppenentBallCount += hole.ballCount hole.ballCount = 0 } getOwnStore(circle).ballCount += sumOppenentBallCount this.state = "ended" } } public changeTurn() { if (this.turn == "player1") { this.turn = "player2" } else { this.turn = "player1" } } public clone() { return new Game(this.player1, this.player2, this.board, this.turn, this.state) } //todo throw expection public getPlayerNameByKey(key: string): "player1" | "player2" { if (this.player1 == key) { return "player1" } else { return "player2" } } //todo throw expection public getPlayerKeyByName(key: "player1" | "player2"): string { if (this.player1 == key) { return "player1" } else { return "player2" } } public checkGameTurn(user: string): boolean { return this.getPlayerNameByKey(user) == this.turn } public getWonPlayer() : string | undefined { const player1BallCount = this.board.player1Store.ballCount const player2BallCount = this.board.player2Store.ballCount if(player1BallCount < player2BallCount){ return this.getPlayerKeyByName("player1") }else if(player1BallCount > player2BallCount) { return this.getPlayerKeyByName("player2") }else{ return undefined } } } export function createGame(player1: string, player2: string) { // const board = new Board( // [new Hole(0), new Hole(1), new Hole(2), new Hole(3), new Hole(4), new Hole(5)], // [new Hole(0), new Hole(1), new Hole(2), new Hole(3), new Hole(4), new Hole(5)], // new Store(0), new Store(0)) const board = new Board( [new Hole(4), new Hole(4), new Hole(4), new Hole(4), new Hole(4), new Hole(4)], [new Hole(4), new Hole(4), new Hole(4), new Hole(4), new Hole(4), new Hole(4)], new Store(0), new Store(0)) // const board = new Board( // [new Hole(4), new Hole(4), new Hole(4), new Hole(4), new Hole(4), new Hole(1)], // [new Hole(1), new Hole(0), new Hole(0), new Hole(0), new Hole(1), new Hole(0)], // new Store(0), new Store(0)) return new Game(player1, player2, board, "player1", "playing") } export class Hole { public ballCount: number constructor(ballCount: number) { this.ballCount = ballCount } } export class Store extends Hole { constructor(ballCount: number) { super(ballCount) } } export class Board { public player1Holes: Array public player2Holes: Array public player1Store: Store public player2Store: Store constructor(player1Holes: Array, player2Holes: Array, player1Store: Store, player2Store: Store) { this.player1Holes = player1Holes this.player2Holes = player2Holes this.player1Store = player1Store this.player2Store = player2Store } // array.reverse didn't work public player1Circle(): Array { return [...this.player1Holes, this.player1Store, ...this.player2Holes, this.player2Store] } // array.reverse didn't work public player2Circle(): Array { return [...this.player2Holes, this.player2Store, ...this.player1Holes, this.player1Store] } public getBallCount(holes : Array ) : number { let ballCount = 0 for (let hole of holes) { ballCount += hole.ballCount; } return ballCount } } function iterateHoles(holes: Array, start: number, stop: number, callback: (hole: Hole, index: number) => void) { for (let index = start; index <= stop; index++) { callback(holes[index % holes.length], index) } } function reverse(holes: Array) { const array = new Array() for (let index = holes.length - 1; index > -1; index--) { array.push(holes[index]) } return array } function checkIsOpponentStore(index: number, size: number) { return (index % size) === size - 1 } function checkIsOpponentHole(index: number, size: number) { return (index % size) >= size / 2 } function checkIsOwnHole(index: number, size: number) { return (index % size) < size / 2 - 1 } function checkIsOwnStore(index: number, size: number) { return (index % size) == size / 2 - 1 } function getOwnStore(circle: Array) { return circle[circle.length / 2 - 1] } function getOpponentHoleByIndex(index: number, circle: Array) { return circle[circle.length - 2 - index] } export interface GameMove { index: number, }