SafetyVantage Coding Challenge
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

110 lines
2.8 KiB

import { Board } from "./board.js";
import { Player } from "./player.js";
import { DuplicatePlayerError } from "./errors/duplicate_player_error.js";
import { NotParticipatingError } from "./errors/not_participating_error.js";
import { OutOfTurnError } from "./errors/out_of_turn_error.js";
import { GameCompleteError } from "./errors/game_complete_error.js";
class PlayerData {
pos: number = 0;
snakeCount: number = 0;
ladderCount: number = 0;
}
export class Game {
public players: Map<Player, PlayerData> = new Map();
private winningPlayer: Player | undefined;
private nextPlayer: Player | undefined;
constructor(public gameId: number, public board: Board) {}
get playerCount() {
return this.players.size;
}
get winner() {
return this.winningPlayer;
}
get isComplete() {
return this.winningPlayer !== undefined;
}
addPlayer(player: Player) {
if (this.hasPlayer(player)) {
new DuplicatePlayerError(this.gameId, player.playerId);
}
this.players.set(player, new PlayerData());
}
hasPlayer(player: Player) {
return this.players.has(player);
}
rollDice(player: Player, roll: number) {
const playerData = this.players.get(player);
if (!playerData) {
throw new NotParticipatingError(
this.gameId,
player.playerId,
"roll dice"
);
}
if (this.nextPlayer && this.nextPlayer !== player) {
throw new OutOfTurnError(this.gameId, player.playerId);
}
if (this.winningPlayer) {
throw new GameCompleteError(this.gameId, player.playerId);
}
const rollPos = playerData.pos + roll;
if (this.board.tileHasLadder(rollPos)) {
playerData.ladderCount++;
} else if (this.board.tileHasSnake(rollPos)) {
playerData.snakeCount++;
}
playerData.pos = this.board.calculateLandingPosition(rollPos);
if (playerData.pos >= this.board.size) {
this.winningPlayer = player;
}
this.nextTurn(player);
}
ladderCountForPlayer(player: Player) {
const playerData = this.players.get(player);
if (!playerData) {
throw new NotParticipatingError(
this.gameId,
player.playerId,
"get ladder count"
);
}
return playerData.ladderCount;
}
snakeCountForPlayer(player: Player) {
const playerData = this.players.get(player);
if (!playerData) {
throw new NotParticipatingError(
this.gameId,
player.playerId,
"get snake count"
);
}
return playerData.snakeCount;
}
private nextTurn(currentPlayer: Player) {
const players = Array.from(this.players.keys());
const playerIndex = players.indexOf(currentPlayer);
const nextIndex = playerIndex === players.length - 1 ? 0 : playerIndex + 1;
this.nextPlayer = players[nextIndex];
}
}