labyrinth-game-logic
Version:
A libary that implements the boardgame labyrinth and exposes the functionality to create and interact with games
161 lines (147 loc) • 4.94 kB
text/typescript
/**
* @author Timo Lehnertz
*/
import { BoardPosition } from "./BoardPosition";
import { Treasure } from "./Treasure";
/**
* Immutable Playerstate class containing all information about a player.
* Only publicly exposes the information that other players and the player itself can legaly know
*/
export class PlayerState {
private readonly foundTreasures: Treasure[];
private readonly remainingTreasures: Treasure[];
public readonly currentTreasure: Treasure | null;
public readonly position: BoardPosition;
public constructor(
foundTreasures: Treasure[],
remainingTreasures: Treasure[],
currentTreasure: Treasure | null,
position: BoardPosition
) {
this.foundTreasures = foundTreasures;
this.remainingTreasures = remainingTreasures;
this.currentTreasure = currentTreasure;
this.position = position;
}
/**
* Returns the number of remaining treasures to be found including the currently open treasure
*/
public get remainingTreasureCount(): number {
return (
this.remainingTreasures.length + (this.currentTreasure !== null ? 1 : 0)
);
}
public get lastFoundTreasure(): Treasure | null {
if (this.foundTreasures.length === 0) {
return null;
}
return this.foundTreasures[this.foundTreasures.length - 1];
}
public get foundTreasureCount(): number {
return this.foundTreasures.length;
}
public getFoundTreasure(index: number): Treasure {
return this.foundTreasures[index];
}
public setPosition(newPosition: BoardPosition): PlayerState {
return new PlayerState(
this.foundTreasures,
this.remainingTreasures,
this.currentTreasure,
newPosition
);
}
public collectTreasure(treasure: Treasure): PlayerState {
const newFoundTreasures = this.copyFoundTreasures();
const newRemainingTreasures = this.copyRemainingTreasures();
const newCurrentTreasure = newRemainingTreasures.pop() ?? null;
newFoundTreasures.push(treasure);
return new PlayerState(
newFoundTreasures,
newRemainingTreasures,
newCurrentTreasure,
this.position
);
}
public removeLastTreasure(): PlayerState {
const newFoundTreasures = this.copyFoundTreasures();
const newRemainingTreasures = this.copyRemainingTreasures();
if (this.currentTreasure !== null) {
newRemainingTreasures.push(this.currentTreasure);
}
const newCurrentTreasure = newFoundTreasures.pop() ?? null;
return new PlayerState(
newFoundTreasures,
newRemainingTreasures,
newCurrentTreasure,
this.position
);
}
/**
* Treasures are immutable so we dont need to make a deep copy here
*/
private copyFoundTreasures(): Treasure[] {
const newFoundTreasures: Treasure[] = [];
for (const foundTreasure of this.foundTreasures) {
newFoundTreasures.push(foundTreasure);
}
return newFoundTreasures;
}
/**
* Treasures are immutable so we dont need to make a deep copy here
*/
private copyRemainingTreasures(): Treasure[] {
const newRemainingTreasures: Treasure[] = [];
for (const remainingTreasure of this.remainingTreasures) {
newRemainingTreasures.push(remainingTreasure);
}
return newRemainingTreasures;
}
public equals(other: PlayerState): boolean {
if (!this.position.equals(other.position)) {
return false;
}
if (!Treasure.compare(this.currentTreasure, other.currentTreasure)) {
return false;
}
if (this.foundTreasures.length !== other.foundTreasures.length) {
return false;
}
for (let i = 0; i < this.foundTreasures.length; i++) {
const a = this.foundTreasures[i];
const b = other.foundTreasures[i];
if (!a.equals(b)) {
return false;
}
}
if (this.remainingTreasures.length !== other.remainingTreasures.length) {
return false;
}
for (let i = 0; i < this.remainingTreasures.length; i++) {
const a = this.remainingTreasures[i];
const b = other.remainingTreasures[i];
if (!a.equals(b)) {
return false;
}
}
return true;
}
public static create(instance: PlayerState): PlayerState {
const foundTreasures: Treasure[] = [];
for (const foundTreasure of instance.foundTreasures) {
foundTreasures.push(Treasure.create(foundTreasure));
}
const remainingTreasures: Treasure[] = [];
for (const remainingTreasure of instance.remainingTreasures) {
remainingTreasures.push(Treasure.create(remainingTreasure));
}
return new PlayerState(
foundTreasures,
remainingTreasures,
instance.currentTreasure !== null
? Treasure.create(instance.currentTreasure)
: null,
BoardPosition.create(instance.position)
);
}
}