diff --git a/src/mancala.ts b/src/mancala.ts index 3a9cd7d..7e96b5d 100644 --- a/src/mancala.ts +++ b/src/mancala.ts @@ -1,8 +1,195 @@ -type User = { - id : Number, +export class Game { + player1: string + player2: string + board: Board + turn: "player1" | "player2" + + constructor(player1: string, player2: string, board: Board, turn: "player1" | "player2") { + this.player1 = player1 + this.player2 = player2 + this.board = board + this.turn = turn + } + + 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, circle) + + ownStore.ballCount++ + stopHole.ballCount = 0; + + ownStore.ballCount += opponentHole.ballCount + opponentHole.ballCount = 0 + } + } + + if (!checkIsOwnStore(stopIndex, circleSize)) { + this.changeTurn() + } + } + + 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) } + + //todo throw expection + public getPlayerNameByKey(key : string) : "player1" | "player2" { + if(this.player1 == key){ + return "player1" + }else{ + return "player2" + } + } + + public checkGameTurn(user : string) : boolean{ + return this.getPlayerNameByKey(user) == this.turn + } } -type Game = { - user1 : User, - user2 : User, +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)) + return new Game(player1, player2, board, "player1") +} + +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] + } +} + +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, } \ No newline at end of file