+
Player: {player.username}
Colour: {player.colour}
- {player.state === State.inGame || player.state === State.disconnected ?
+ {player.state === State.inGame || player.state === State.disconnected ? (
<>
Pellets: {player.box.pellets}
PowerPellets: {player.box.powerPellets}
>
- :
-
{player.state === State.waitingForPlayers ? "Waiting" : "Ready"}
}
+ ) : (
+
{player.state === State.waitingForPlayers ? "Waiting" : "Ready"}
+ )}
- );
-};
+ )
+}
-export default PlayerStats;
+export default PlayerStats
diff --git a/pac-man-board-game/ClientApp/src/game/box.ts b/pac-man-board-game/ClientApp/src/game/box.ts
index 0504976..81ba555 100644
--- a/pac-man-board-game/ClientApp/src/game/box.ts
+++ b/pac-man-board-game/ClientApp/src/game/box.ts
@@ -1,32 +1,31 @@
export default class Box implements BoxProps {
- public readonly colour;
- public pellets;
- public powerPellets;
+ public readonly colour
+ public pellets
+ public powerPellets
- public constructor({colour, pellets = 0, powerPellets = 0}: BoxProps) {
- this.colour = colour;
- this.pellets = pellets;
- this.powerPellets = powerPellets;
+ public constructor({ colour, pellets = 0, powerPellets = 0 }: BoxProps) {
+ this.colour = colour
+ this.pellets = pellets
+ this.powerPellets = powerPellets
}
public addPellet(): void {
- this.pellets++;
+ this.pellets++
}
public removePellet(): boolean {
- if (this.pellets <= 0) return false;
- this.pellets--;
- return true;
+ if (this.pellets <= 0) return false
+ this.pellets--
+ return true
}
public addPowerPellet(): void {
- this.powerPellets++;
+ this.powerPellets++
}
public removePowerPellet(): boolean {
- if (this.powerPellets <= 0) return false;
- this.powerPellets--;
- return true;
+ if (this.powerPellets <= 0) return false
+ this.powerPellets--
+ return true
}
-
}
diff --git a/pac-man-board-game/ClientApp/src/game/character.ts b/pac-man-board-game/ClientApp/src/game/character.ts
index 61ec36b..f2bdd93 100644
--- a/pac-man-board-game/ClientApp/src/game/character.ts
+++ b/pac-man-board-game/ClientApp/src/game/character.ts
@@ -1,5 +1,5 @@
-import {Direction} from "./direction";
-import {Colour} from "./colour";
+import { Direction } from "./direction"
+import { Colour } from "./colour"
export enum CharacterType {
pacMan,
@@ -8,89 +8,106 @@ export enum CharacterType {
}
export class Character implements CharacterProps {
- public readonly colour;
- public position;
- public isEatable;
- public readonly spawnPosition;
- public readonly type;
+ public readonly colour
+ public position
+ public isEatable
+ public readonly spawnPosition
+ public readonly type
- public constructor(
- {
- colour,
- position = null,
- type = CharacterType.dummy,
- isEatable = type === CharacterType.pacMan,
- spawnPosition = null
- }: CharacterProps) {
- this.colour = colour;
- this.isEatable = isEatable;
- this.spawnPosition = spawnPosition;
+ public constructor({
+ colour,
+ position = null,
+ type = CharacterType.dummy,
+ isEatable = type === CharacterType.pacMan,
+ spawnPosition = null,
+ }: CharacterProps) {
+ this.colour = colour
+ this.isEatable = isEatable
+ this.spawnPosition = spawnPosition
if (position) {
- this.position = position;
+ this.position = position
} else {
- this.position = spawnPosition ? {
- end: spawnPosition!.at,
- direction: spawnPosition!.direction
- } : null;
+ this.position = spawnPosition
+ ? {
+ end: spawnPosition!.at,
+ direction: spawnPosition!.direction,
+ }
+ : null
}
- this.type = type;
+ this.type = type
}
public follow(path: Path): void {
if (!this.position) {
- this.position = path;
+ this.position = path
} else {
- this.position.end = path.end;
- this.position.direction = path.direction;
- this.position.path = undefined;
+ this.position.end = path.end
+ this.position.direction = path.direction
+ this.position.path = undefined
}
}
public isPacMan(): boolean {
- return this.type === CharacterType.pacMan;
+ return this.type === CharacterType.pacMan
}
public isGhost(): boolean {
- return this.type === CharacterType.ghost;
+ return this.type === CharacterType.ghost
}
public moveToSpawn(): void {
- if (!this.spawnPosition) return;
- this.follow({end: this.spawnPosition.at, direction: this.spawnPosition.direction});
+ if (!this.spawnPosition) return
+ this.follow({
+ end: this.spawnPosition.at,
+ direction: this.spawnPosition.direction,
+ })
}
public isAt(position: Position): boolean {
- return this.position !== null && this.position.end.x === position.x && this.position.end.y === position.y;
+ return this.position !== null && this.position.end.x === position.x && this.position.end.y === position.y
}
}
export class PacMan extends Character implements CharacterProps {
-
- public constructor({colour, position, isEatable = true, spawnPosition, type = CharacterType.pacMan}: CharacterProps) {
- super({colour: colour, position: position, isEatable: isEatable, spawnPosition: spawnPosition, type: type});
+ public constructor({
+ colour,
+ position,
+ isEatable = true,
+ spawnPosition,
+ type = CharacterType.pacMan,
+ }: CharacterProps) {
+ super({
+ colour: colour,
+ position: position,
+ isEatable: isEatable,
+ spawnPosition: spawnPosition,
+ type: type,
+ })
}
-
}
export class Ghost extends Character implements CharacterProps {
-
- public constructor({colour, position, isEatable, spawnPosition, type = CharacterType.ghost}: CharacterProps) {
- super({colour: colour, position: position, isEatable: isEatable, spawnPosition: spawnPosition, type: type});
+ public constructor({ colour, position, isEatable, spawnPosition, type = CharacterType.ghost }: CharacterProps) {
+ super({
+ colour: colour,
+ position: position,
+ isEatable: isEatable,
+ spawnPosition: spawnPosition,
+ type: type,
+ })
}
}
export class Dummy extends Character implements CharacterProps {
-
public constructor(position: Path) {
super({
colour: Colour.grey,
position: position,
isEatable: false,
- spawnPosition: {at: {x: 0, y: 0}, direction: Direction.up},
+ spawnPosition: { at: { x: 0, y: 0 }, direction: Direction.up },
type: CharacterType.dummy,
- });
+ })
}
-
}
diff --git a/pac-man-board-game/ClientApp/src/game/colour.ts b/pac-man-board-game/ClientApp/src/game/colour.ts
index fa6fa22..1b35109 100644
--- a/pac-man-board-game/ClientApp/src/game/colour.ts
+++ b/pac-man-board-game/ClientApp/src/game/colour.ts
@@ -8,4 +8,4 @@ export enum Colour {
grey = "grey",
}
-export const getColours = (): Colour[] => Object.values(Colour);
+export const getColours = (): Colour[] => Object.values(Colour)
diff --git a/pac-man-board-game/ClientApp/src/game/direction.ts b/pac-man-board-game/ClientApp/src/game/direction.ts
index a8580bd..f6f5ef2 100644
--- a/pac-man-board-game/ClientApp/src/game/direction.ts
+++ b/pac-man-board-game/ClientApp/src/game/direction.ts
@@ -2,8 +2,7 @@ export enum Direction {
left,
up,
right,
- down
+ down,
}
-export const getDirections = () => Object.values(Direction)
- .filter(d => !isNaN(Number(d))) as Direction[];
+export const getDirections = () => Object.values(Direction).filter(d => !isNaN(Number(d))) as Direction[]
diff --git a/pac-man-board-game/ClientApp/src/game/map.ts b/pac-man-board-game/ClientApp/src/game/map.ts
index a264d43..12879fb 100644
--- a/pac-man-board-game/ClientApp/src/game/map.ts
+++ b/pac-man-board-game/ClientApp/src/game/map.ts
@@ -1,5 +1,5 @@
-import {CharacterType} from "./character";
-import {Direction} from "./direction";
+import { CharacterType } from "./character"
+import { Direction } from "./direction"
/**
* 0 = empty
@@ -25,29 +25,32 @@ export const customMap: GameMap = [
[1, 2, 1, 0, 1, 2, 1, 0, 1, 2, 1, 0, 1, 2, 1],
[1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1],
[1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1],
-];
+]
-export function getCharacterSpawns(map: GameMap): { type: CharacterType, position: DirectionalPosition }[] {
-
- const result: { type: CharacterType, position: DirectionalPosition }[] = [];
+export function getCharacterSpawns(map: GameMap): { type: CharacterType; position: DirectionalPosition }[] {
+ const result: { type: CharacterType; position: DirectionalPosition }[] = []
for (let row = 0; row < map.length; row++) {
for (let col = 0; col < map.length; col++) {
// TODO find direction
if (map[row][col] === 4) {
- result.push({type: CharacterType.ghost, position: {at: {x: col, y: row}, direction: Direction.up}});
+ result.push({
+ type: CharacterType.ghost,
+ position: { at: { x: col, y: row }, direction: Direction.up },
+ })
} else if (map[row][col] === 5) {
result.push({
- type: CharacterType.pacMan, position: {at: {x: col, y: row}, direction: Direction.up}
- });
+ type: CharacterType.pacMan,
+ position: { at: { x: col, y: row }, direction: Direction.up },
+ })
}
}
}
- return result;
+ return result
}
export function getPacManSpawns(map: GameMap): DirectionalPosition[] {
return getCharacterSpawns(map)
.filter(s => s.type === CharacterType.pacMan)
.map(s => s.position)
-}
\ No newline at end of file
+}
diff --git a/pac-man-board-game/ClientApp/src/game/player.ts b/pac-man-board-game/ClientApp/src/game/player.ts
index ecec3b2..0c37c09 100644
--- a/pac-man-board-game/ClientApp/src/game/player.ts
+++ b/pac-man-board-game/ClientApp/src/game/player.ts
@@ -1,54 +1,57 @@
-import {Character, CharacterType} from "./character";
-import Box from "./box";
-import {getDefaultStore} from "jotai";
-import {currentPlayerNameAtom, playersAtom} from "../utils/state";
-import rules from "./rules";
+import { Character, CharacterType } from "./character"
+import Box from "./box"
+import { getDefaultStore } from "jotai"
+import { currentPlayerNameAtom, playersAtom } from "../utils/state"
+import rules from "./rules"
export enum State {
waitingForPlayers,
ready,
inGame,
- disconnected
+ disconnected,
}
export default class Player implements PlayerProps {
- private static store = getDefaultStore();
- public readonly username;
- public readonly pacMan;
- public readonly colour;
- public readonly box;
- public state;
+ private static store = getDefaultStore()
+ public readonly username
+ public readonly pacMan
+ public readonly colour
+ public readonly box
+ public state
constructor(props: PlayerProps) {
- this.username = props.username;
- this.colour = props.colour;
- this.box = new Box(props.box ?? {colour: props.colour});
- this.pacMan = new Character(props.pacMan ?? {
- colour: props.colour,
- type: CharacterType.pacMan
- });
- this.state = props.state ?? State.waitingForPlayers;
+ this.username = props.username
+ this.colour = props.colour
+ this.box = new Box(props.box ?? { colour: props.colour })
+ this.pacMan = new Character(
+ props.pacMan ?? {
+ colour: props.colour,
+ type: CharacterType.pacMan,
+ },
+ )
+ this.state = props.state ?? State.waitingForPlayers
}
public isTurn(): boolean {
- return Player.store.get(currentPlayerNameAtom) === this.username;
+ return Player.store.get(currentPlayerNameAtom) === this.username
}
public addPellet(): void {
- this.box.addPellet();
+ this.box.addPellet()
}
public addPowerPellet(): void {
- this.box.addPowerPellet();
+ this.box.addPowerPellet()
}
public stealFrom(other: Player): void {
for (let i = 0; i < rules.maxStealPellets; i++) {
- const removed = other.box.removePellet();
- if (removed)
- this.box.addPellet();
+ const removed = other.box.removePellet()
+ if (removed) this.box.addPellet()
}
- Player.store.set(playersAtom, Player.store.get(playersAtom).map(player => player));
+ Player.store.set(
+ playersAtom,
+ Player.store.get(playersAtom).map(player => player),
+ )
}
-
}
diff --git a/pac-man-board-game/ClientApp/src/game/possibleMovesAlgorithm.ts b/pac-man-board-game/ClientApp/src/game/possibleMovesAlgorithm.ts
index 61238f5..fb597bb 100644
--- a/pac-man-board-game/ClientApp/src/game/possibleMovesAlgorithm.ts
+++ b/pac-man-board-game/ClientApp/src/game/possibleMovesAlgorithm.ts
@@ -1,6 +1,6 @@
-import {TileType} from "./tileType";
-import {Character} from "./character";
-import {Direction, getDirections} from "./direction";
+import { TileType } from "./tileType"
+import { Character } from "./character"
+import { Direction, getDirections } from "./direction"
/**
* Finds all the possible positions for the character to move to
@@ -10,10 +10,15 @@ import {Direction, getDirections} from "./direction";
* @param characters All the characters on the map
* @returns An array of paths the character can move to
*/
-export default function findPossiblePositions(board: GameMap, character: Character, steps: number, characters: Character[]): Path[] {
- if (!character.position || !character.spawnPosition) throw new Error("Character has no position or spawn position");
- return findPossibleRecursive(board, character.position, steps, character, characters);
-};
+export default function findPossiblePositions(
+ board: GameMap,
+ character: Character,
+ steps: number,
+ characters: Character[],
+): Path[] {
+ if (!character.position || !character.spawnPosition) throw new Error("Character has no position or spawn position")
+ return findPossibleRecursive(board, character.position, steps, character, characters)
+}
/**
* Uses recursion to move through the map and find all the possible positions
@@ -24,38 +29,40 @@ export default function findPossiblePositions(board: GameMap, character: Charact
* @param characters All the characters on the map
* @returns {Path[]} An array of paths the character can move to
*/
-function findPossibleRecursive(map: GameMap, currentPath: Path, steps: number, character: Character, characters: Character[]): Path[] {
-
- const paths: Path[] = [];
+function findPossibleRecursive(
+ map: GameMap,
+ currentPath: Path,
+ steps: number,
+ character: Character,
+ characters: Character[],
+): Path[] {
+ const paths: Path[] = []
if (isOutsideBoard(currentPath, map.length)) {
if (character.isPacMan()) {
- return addTeleportationTiles(map, currentPath, steps, character, characters);
+ return addTeleportationTiles(map, currentPath, steps, character, characters)
}
} else if (!isWall(map, currentPath)) {
-
if (!characterHitsAnotherCharacter(character, currentPath, characters)) {
if (steps <= 0) {
if (!(isSpawn(map, currentPath) && !isOwnSpawn(currentPath, character))) {
- paths.push(currentPath);
+ paths.push(currentPath)
}
-
} else {
+ tryAddToPath(currentPath)
- tryAddToPath(currentPath);
-
- steps--;
+ steps--
for (const direction of getDirections()) {
- paths.push(...tryMove(map, currentPath, direction, steps, character, characters));
+ paths.push(...tryMove(map, currentPath, direction, steps, character, characters))
}
}
} else {
- const pacMan = ghostHitsPacMan(character, currentPath, characters);
+ const pacMan = ghostHitsPacMan(character, currentPath, characters)
if (pacMan instanceof Character && !isCharactersSpawn(currentPath, pacMan)) {
- paths.push(currentPath);
+ paths.push(currentPath)
}
}
}
- return paths;
+ return paths
}
/**
@@ -65,7 +72,7 @@ function findPossibleRecursive(map: GameMap, currentPath: Path, steps: number, c
* @returns {boolean} True if the character is on its spawn, otherwise false
*/
function isCharactersSpawn(currentPath: Path, character: Character): boolean {
- return character.spawnPosition?.at.x === currentPath.end.x && character.spawnPosition.at.y === currentPath.end.y;
+ return character.spawnPosition?.at.x === currentPath.end.x && character.spawnPosition.at.y === currentPath.end.y
}
/**
@@ -75,8 +82,12 @@ function isCharactersSpawn(currentPath: Path, character: Character): boolean {
* @param characters All the characters on the board
* @returns {boolean} True if the character is a ghost and hits Pac-Man, otherwise false
*/
-function ghostHitsPacMan(character: Character, currentPath: Path, characters: Character[]): Character | undefined | false {
- return character.isGhost() && characters.find(c => c.isPacMan() && c.isAt(currentPath.end));
+function ghostHitsPacMan(
+ character: Character,
+ currentPath: Path,
+ characters: Character[],
+): Character | undefined | false {
+ return character.isGhost() && characters.find(c => c.isPacMan() && c.isAt(currentPath.end))
}
/**
@@ -87,7 +98,7 @@ function ghostHitsPacMan(character: Character, currentPath: Path, characters: Ch
* @returns {boolean} True if the character hits another character, otherwise false
*/
function characterHitsAnotherCharacter(character: Character, currentPath: Path, characters: Character[]): boolean {
- return characters.find(c => c !== character && c.isAt(currentPath.end)) !== undefined;
+ return characters.find(c => c !== character && c.isAt(currentPath.end)) !== undefined
}
/**
@@ -96,9 +107,9 @@ function characterHitsAnotherCharacter(character: Character, currentPath: Path,
*/
function tryAddToPath(currentPos: Path): void {
if (!currentPos.path) {
- currentPos.path = [];
+ currentPos.path = []
} else if (!currentPos.path.includes(currentPos.end)) {
- currentPos.path = [...currentPos.path, currentPos.end];
+ currentPos.path = [...currentPos.path, currentPos.end]
}
}
@@ -113,39 +124,53 @@ function tryAddToPath(currentPos: Path): void {
* @param characters All the characters on the board
* @returns An array of paths the character can move to
*/
-function tryMove(board: GameMap, path: Path, direction: Direction, steps: number, character: Character, characters: Character[]): Path[] {
-
+function tryMove(
+ board: GameMap,
+ path: Path,
+ direction: Direction,
+ steps: number,
+ character: Character,
+ characters: Character[],
+): Path[] {
function getNewPosition(): Position {
switch (direction) {
case Direction.left:
return {
x: path.end.x - 1,
- y: path.end.y
- };
+ y: path.end.y,
+ }
case Direction.up:
return {
x: path.end.x,
- y: path.end.y - 1
- };
+ y: path.end.y - 1,
+ }
case Direction.right:
return {
x: path.end.x + 1,
- y: path.end.y
- };
+ y: path.end.y,
+ }
case Direction.down:
return {
x: path.end.x,
- y: path.end.y + 1
- };
+ y: path.end.y + 1,
+ }
}
}
if (path.direction !== (direction + 2) % 4) {
- return findPossibleRecursive(board, {
- end: getNewPosition(), direction: direction, path: path.path
- }, steps, character, characters);
+ return findPossibleRecursive(
+ board,
+ {
+ end: getNewPosition(),
+ direction: direction,
+ path: path.path,
+ },
+ steps,
+ character,
+ characters,
+ )
}
- return [];
+ return []
}
/**
@@ -157,22 +182,26 @@ function tryMove(board: GameMap, path: Path, direction: Direction, steps: number
* @param characters All the characters on the map
* @returns {Path[]} An array of paths the character can move to
*/
-function addTeleportationTiles(board: GameMap, currentPath: Path, steps: number, character: Character, characters: Character[]): Path[] {
- const possiblePositions = findTeleportationTiles(board);
- const paths: Path[] = [];
+function addTeleportationTiles(
+ board: GameMap,
+ currentPath: Path,
+ steps: number,
+ character: Character,
+ characters: Character[],
+): Path[] {
+ const possiblePositions = findTeleportationTiles(board)
+ const paths: Path[] = []
for (const pos of possiblePositions) {
-
function inInterval(coordinate: "x" | "y"): boolean {
return pos.end[coordinate] !== interval(0, board.length - 1, currentPath.end[coordinate])
}
if (inInterval("x") || inInterval("y")) {
-
- pos.path = currentPath.path;
- paths.push(...findPossibleRecursive(board, pos, steps, character, characters));
+ pos.path = currentPath.path
+ paths.push(...findPossibleRecursive(board, pos, steps, character, characters))
}
}
- return paths;
+ return paths
}
/**
@@ -183,7 +212,7 @@ function addTeleportationTiles(board: GameMap, currentPath: Path, steps: number,
* @returns {number} The value if it's between the lower and upper bounds, otherwise it returns the lower or upper bound
*/
function interval(lower: number, upper: number, value: number): number {
- return Math.max(Math.min(value, upper), lower);
+ return Math.max(Math.min(value, upper), lower)
}
/**
@@ -192,18 +221,17 @@ function interval(lower: number, upper: number, value: number): number {
* @returns An array of paths containing the teleportation tiles
*/
function findTeleportationTiles(map: GameMap): Path[] {
- const possiblePositions: Path[] = [];
- const edge = [0, map.length - 1];
+ const possiblePositions: Path[] = []
+ const edge = [0, map.length - 1]
for (const e of edge) {
for (let i = 0; i < map[e].length; i++) {
-
- pushPath(map, possiblePositions, i, e);
- pushPath(map, possiblePositions, e, i);
+ pushPath(map, possiblePositions, i, e)
+ pushPath(map, possiblePositions, e, i)
}
}
- return possiblePositions;
+ return possiblePositions
}
/**
@@ -215,7 +243,10 @@ function findTeleportationTiles(map: GameMap): Path[] {
*/
function pushPath(board: GameMap, possiblePositions: Path[], x: number, y: number): void {
if (board[y] && board[y][x] !== TileType.wall) {
- possiblePositions.push({end: {x: x, y: y}, direction: findDirection(x, y, board.length)});
+ possiblePositions.push({
+ end: { x: x, y: y },
+ direction: findDirection(x, y, board.length),
+ })
}
}
@@ -226,17 +257,17 @@ function pushPath(board: GameMap, possiblePositions: Path[], x: number, y: numbe
* @param boardSize The length of the board
*/
function findDirection(x: number, y: number, boardSize: number): Direction {
- let direction: Direction;
+ let direction: Direction
if (x === 0) {
- direction = Direction.right;
+ direction = Direction.right
} else if (y === 0) {
- direction = Direction.down;
+ direction = Direction.down
} else if (x === boardSize - 1) {
- direction = Direction.left;
+ direction = Direction.left
} else {
- direction = Direction.up;
+ direction = Direction.up
}
- return direction;
+ return direction
}
/**
@@ -245,8 +276,8 @@ function findDirection(x: number, y: number, boardSize: number): Direction {
* @param boardSize The size of the board
*/
function isOutsideBoard(currentPos: Path, boardSize: number): boolean {
- const pos = currentPos.end;
- return pos.x < 0 || pos.x >= boardSize || pos.y < 0 || pos.y >= boardSize;
+ const pos = currentPos.end
+ return pos.x < 0 || pos.x >= boardSize || pos.y < 0 || pos.y >= boardSize
}
/**
@@ -255,8 +286,8 @@ function isOutsideBoard(currentPos: Path, boardSize: number): boolean {
* @param currentPos The current position of the character
*/
function isWall(board: GameMap, currentPos: Path): boolean {
- const pos = currentPos.end;
- return board[pos.y][pos.x] === TileType.wall; // Shouldn't work, but it does
+ const pos = currentPos.end
+ return board[pos.y][pos.x] === TileType.wall // Shouldn't work, but it does
}
/**
@@ -265,8 +296,8 @@ function isWall(board: GameMap, currentPos: Path): boolean {
* @param currentPos The current position of the character
*/
function isSpawn(board: GameMap, currentPos: Path) {
- const pos = currentPos.end;
- return board[pos.y][pos.x] === TileType.pacmanSpawn || board[pos.y][pos.x] === TileType.ghostSpawn;
+ const pos = currentPos.end
+ return board[pos.y][pos.x] === TileType.pacmanSpawn || board[pos.y][pos.x] === TileType.ghostSpawn
}
/**
@@ -275,8 +306,7 @@ function isSpawn(board: GameMap, currentPos: Path) {
* @param character The current character
*/
function isOwnSpawn(currentPos: Path, character: Character): boolean {
- const pos = currentPos.end;
- const charPos = character.spawnPosition!.at;
- return charPos.x === pos.x && charPos.y === pos.y;
+ const pos = currentPos.end
+ const charPos = character.spawnPosition!.at
+ return charPos.x === pos.x && charPos.y === pos.y
}
-
diff --git a/pac-man-board-game/ClientApp/src/game/rules.ts b/pac-man-board-game/ClientApp/src/game/rules.ts
index c692819..b1668b7 100644
--- a/pac-man-board-game/ClientApp/src/game/rules.ts
+++ b/pac-man-board-game/ClientApp/src/game/rules.ts
@@ -4,4 +4,4 @@ const rules = {
maxStealPellets: 2,
}
-export default rules;
+export default rules
diff --git a/pac-man-board-game/ClientApp/src/game/tileType.ts b/pac-man-board-game/ClientApp/src/game/tileType.ts
index 2ea8ed0..e2fcefb 100644
--- a/pac-man-board-game/ClientApp/src/game/tileType.ts
+++ b/pac-man-board-game/ClientApp/src/game/tileType.ts
@@ -5,4 +5,4 @@ export enum TileType {
powerPellet,
ghostSpawn,
pacmanSpawn,
-}
\ No newline at end of file
+}
diff --git a/pac-man-board-game/ClientApp/src/hooks/useToggle.ts b/pac-man-board-game/ClientApp/src/hooks/useToggle.ts
index ef437ab..5e1cb91 100644
--- a/pac-man-board-game/ClientApp/src/hooks/useToggle.ts
+++ b/pac-man-board-game/ClientApp/src/hooks/useToggle.ts
@@ -1,4 +1,4 @@
-import {useState} from "react";
+import { useState } from "react"
/**
* A hook that returns a boolean value and a function to toggle it. The function can optionally be passed a boolean
@@ -6,7 +6,7 @@ import {useState} from "react";
* @returns A tuple containing the boolean value and a function to toggle it.
*/
export default function useToggle(defaultValue = false): [boolean, (value?: boolean) => void] {
- const [value, setValue] = useState(defaultValue);
- const toggleValue = (newValue?: boolean) => newValue ? setValue(newValue) : setValue(!value);
- return [value, toggleValue];
-}
\ No newline at end of file
+ const [value, setValue] = useState(defaultValue)
+ const toggleValue = (newValue?: boolean) => (newValue ? setValue(newValue) : setValue(!value))
+ return [value, toggleValue]
+}
diff --git a/pac-man-board-game/ClientApp/src/index.css b/pac-man-board-game/ClientApp/src/index.css
index 7d18b5f..8a6cc40 100644
--- a/pac-man-board-game/ClientApp/src/index.css
+++ b/pac-man-board-game/ClientApp/src/index.css
@@ -3,35 +3,37 @@
@tailwind utilities;
.debug {
- @apply border border-red-500;
- @apply after:content-['debug'] after:absolute;
+ @apply border border-red-500;
+ @apply after:content-['debug'] after:absolute;
}
.flex-center {
- @apply flex justify-center items-center;
+ @apply flex justify-center items-center;
}
.inline-flex-center {
- @apply inline-flex justify-center items-center;
+ @apply inline-flex justify-center items-center;
}
.wh-full {
- @apply w-full h-full;
+ @apply w-full h-full;
}
h1 {
- @apply text-4xl;
+ @apply text-4xl;
}
h2 {
- @apply text-3xl;
+ @apply text-3xl;
}
br {
- @apply my-2;
+ @apply my-2;
}
-.button-default, button[type=submit], input[type=submit] {
- @apply bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded;
- @apply disabled:bg-gray-500;
+.button-default,
+button[type="submit"],
+input[type="submit"] {
+ @apply bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded;
+ @apply disabled:bg-gray-500;
}
diff --git a/pac-man-board-game/ClientApp/src/index.tsx b/pac-man-board-game/ClientApp/src/index.tsx
index 215e774..e25335f 100644
--- a/pac-man-board-game/ClientApp/src/index.tsx
+++ b/pac-man-board-game/ClientApp/src/index.tsx
@@ -1,25 +1,26 @@
-import React from 'react';
-import {createRoot} from 'react-dom/client';
-import {BrowserRouter} from 'react-router-dom';
-import {App} from './App';
+import React from "react"
+import { createRoot } from "react-dom/client"
+import { BrowserRouter } from "react-router-dom"
+import { App } from "./App"
// @ts-ignore
-import reportWebVitals from './reportWebVitals';
-import {DevTools} from "jotai-devtools";
-import DebugMenu from "./components/debugMenu";
+import reportWebVitals from "./reportWebVitals"
+import { DevTools } from "jotai-devtools"
+import DebugMenu from "./components/debugMenu"
-const baseUrl = document.getElementsByTagName('base')[0].getAttribute('href');
-const rootElement = document.getElementById('root');
-if (rootElement === null) throw new Error("Root element is null");
-const root = createRoot(rootElement);
+const baseUrl = document.getElementsByTagName("base")[0].getAttribute("href")
+const rootElement = document.getElementById("root")
+if (rootElement === null) throw new Error("Root element is null")
+const root = createRoot(rootElement)
root.render(
-
-
-
- );
+
+
+
+ ,
+)
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
-reportWebVitals();
+reportWebVitals()
diff --git a/pac-man-board-game/ClientApp/src/pages/counter.tsx b/pac-man-board-game/ClientApp/src/pages/counter.tsx
index 91f5603..373176b 100644
--- a/pac-man-board-game/ClientApp/src/pages/counter.tsx
+++ b/pac-man-board-game/ClientApp/src/pages/counter.tsx
@@ -1,29 +1,27 @@
-import React, {FC} from "react";
-import WebSocketService from "../websockets/WebSocketService";
+import React, { FC } from "react"
+import WebSocketService from "../websockets/WebSocketService"
-const ws = new WebSocketService("wss://localhost:3000/api/ws");
+const ws = new WebSocketService("wss://localhost:3000/api/ws")
export const Counter: FC = () => {
+ const [currentCount, setCurrentCount] = React.useState(0)
- const [currentCount, setCurrentCount] = React.useState(0);
-
- async function incrementCounterAndSend() {
+ function incrementCounterAndSend() {
if (ws.isOpen()) {
- await ws.send((currentCount + 1).toString());
+ ws.send((currentCount + 1).toString())
}
}
function receiveMessage(data: MessageEvent
) {
- const count = parseInt(data.data);
- if (!isNaN(count))
- setCurrentCount(count);
+ const count = parseInt(data.data)
+ if (!isNaN(count)) setCurrentCount(count)
}
React.useEffect(() => {
- ws.onReceive = receiveMessage;
- ws.open();
- return () => ws.close();
- }, []);
+ ws.onReceive = receiveMessage
+ ws.open()
+ return () => ws.close()
+ }, [])
return (
@@ -31,9 +29,13 @@ export const Counter: FC = () => {
This is a simple example of a React component.
-
Current count: {currentCount}
+
+ Current count: {currentCount}
+
-
+
- );
-};
+ )
+}
diff --git a/pac-man-board-game/ClientApp/src/pages/game.tsx b/pac-man-board-game/ClientApp/src/pages/game.tsx
index 752d4a6..5ea664f 100644
--- a/pac-man-board-game/ClientApp/src/pages/game.tsx
+++ b/pac-man-board-game/ClientApp/src/pages/game.tsx
@@ -1,17 +1,16 @@
-import React, {FC} from "react";
-import {GameComponent} from "../components/gameComponent";
-import {useAtomValue} from "jotai";
-import {selectedMapAtom, thisPlayerAtom} from "../utils/state";
+import React, { FC } from "react"
+import { GameComponent } from "../components/gameComponent"
+import { useAtomValue } from "jotai"
+import { selectedMapAtom, thisPlayerAtom } from "../utils/state"
const GamePage: FC = () => {
- const player = useAtomValue(thisPlayerAtom);
- const map = useAtomValue(selectedMapAtom);
+ const player = useAtomValue(thisPlayerAtom)
+ const map = useAtomValue(selectedMapAtom)
if (player && map) {
- return ;
- } else {
- return null;
+ return
}
-};
+ return null
+}
-export default GamePage;
+export default GamePage
diff --git a/pac-man-board-game/ClientApp/src/pages/home.tsx b/pac-man-board-game/ClientApp/src/pages/home.tsx
index 0916e8d..0d4a3c6 100644
--- a/pac-man-board-game/ClientApp/src/pages/home.tsx
+++ b/pac-man-board-game/ClientApp/src/pages/home.tsx
@@ -1,27 +1,35 @@
-import React, {FC} from "react";
-import {Link} from "react-router-dom";
-import {useAtomValue} from "jotai";
-import {thisPlayerAtom} from "../utils/state";
+import React, { FC } from "react"
+import { Link } from "react-router-dom"
+import { useAtomValue } from "jotai"
+import { thisPlayerAtom } from "../utils/state"
const HomePage: FC = () => {
- const player = useAtomValue(thisPlayerAtom);
+ const player = useAtomValue(thisPlayerAtom)
return (
Hello {player?.username ?? "Player"}. Do you want to play a game?
- {!player ?
- <>Start by {" "}
- logging in.
+ {!player ? (
+ <>
+ Start by{" "}
+
+ logging in
+
+ .
>
- :
- <>Go to the {" "}
- lobby to select a game.
+ ) : (
+ <>
+ Go to the{" "}
+
+ lobby
+ {" "}
+ to select a game.
>
- }
+ )}
- );
-};
+ )
+}
-export default HomePage;
\ No newline at end of file
+export default HomePage
diff --git a/pac-man-board-game/ClientApp/src/pages/lobby.tsx b/pac-man-board-game/ClientApp/src/pages/lobby.tsx
index 22bbd9a..a6084d5 100644
--- a/pac-man-board-game/ClientApp/src/pages/lobby.tsx
+++ b/pac-man-board-game/ClientApp/src/pages/lobby.tsx
@@ -1,66 +1,65 @@
-import React, {FC, Suspense} from "react";
-import {atom, useAtomValue} from "jotai";
-import {Button} from "../components/button";
-import {selectedMapAtom, thisPlayerAtom} from "../utils/state";
-import {getData, postData} from "../utils/api";
-import {getPacManSpawns} from "../game/map";
-import {useNavigate} from "react-router-dom";
+import React, { FC, Suspense } from "react"
+import { atom, useAtomValue } from "jotai"
+import { Button } from "../components/button"
+import { selectedMapAtom, thisPlayerAtom } from "../utils/state"
+import { getData, postData } from "../utils/api"
+import { getPacManSpawns } from "../game/map"
+import { useNavigate } from "react-router-dom"
const fetchAtom = atom(async () => {
- const response = await getData("/game/all");
- return await response.json() as Game[];
-});
+ const response = await getData("/game/all")
+ return (await response.json()) as Game[]
+})
const LobbyPage: FC = () => {
-
- const thisPlayer = useAtomValue(thisPlayerAtom);
- const navigate = useNavigate();
- const map = useAtomValue(selectedMapAtom);
+ const thisPlayer = useAtomValue(thisPlayerAtom)
+ const navigate = useNavigate()
+ const map = useAtomValue(selectedMapAtom)
async function createGame(): Promise {
-
const response = await postData("/game/create", {
- body: {player: thisPlayer, spawns: getPacManSpawns(map)} as CreateGameData
- });
+ body: {
+ player: thisPlayer,
+ spawns: getPacManSpawns(map),
+ } as CreateGameData,
+ })
if (response.ok) {
- const data = await response.json();
+ const data = await response.json()
navigate("/game/" + data.id)
} else {
- const data = await response.text();
- console.error("Error: ", data);
+ const data = await response.text()
+ console.error("Error: ", data)
// TODO display error
}
-
}
return (
<>
-
+
>
- );
+ )
}
-export default LobbyPage;
+export default LobbyPage
-const GameTable: FC = ({className}) => {
-
- const data = useAtomValue(fetchAtom);
- const thisPlayer = useAtomValue(thisPlayerAtom);
- const navigate = useNavigate();
+const GameTable: FC = ({ className }) => {
+ const data = useAtomValue(fetchAtom)
+ const thisPlayer = useAtomValue(thisPlayerAtom)
+ const navigate = useNavigate()
async function joinGame(gameId: string): Promise {
- if (thisPlayer === undefined) throw new Error("Player is undefined");
+ if (thisPlayer === undefined) throw new Error("Player is undefined")
- const result = await postData("/game/join/" + gameId, {body: thisPlayer});
+ const result = await postData("/game/join/" + gameId, { body: thisPlayer })
if (result.ok) {
- navigate("/game/" + gameId);
+ navigate("/game/" + gameId)
} else {
- console.error("Failed to join game " + gameId, await result.text());
+ console.error("Failed to join game " + gameId, await result.text())
// TODO show error message
}
}
@@ -68,33 +67,34 @@ const GameTable: FC = ({className}) => {
return (
-
- Id |
- Count |
- State |
- Join |
-
+
+ Id |
+ Count |
+ State |
+ Join |
+
- {data?.map(game =>
-
- {game.id} |
- {game.count} |
- {game.isGameStarted ? "Closed" : "Open"} |
-
-
- |
-
- )}
- {
- data?.length === 0 &&
-
- No games found |
+ {data?.map(game => (
+
+ {game.id} |
+ {game.count} |
+ {game.isGameStarted ? "Closed" : "Open"} |
+
+
+ |
- }
+ ))}
+ {data?.length === 0 && (
+
+
+ No games found
+ |
+
+ )}
- );
+ )
}
diff --git a/pac-man-board-game/ClientApp/src/pages/login.tsx b/pac-man-board-game/ClientApp/src/pages/login.tsx
index 2e799aa..707980c 100644
--- a/pac-man-board-game/ClientApp/src/pages/login.tsx
+++ b/pac-man-board-game/ClientApp/src/pages/login.tsx
@@ -1,23 +1,22 @@
-import React, {FC, FormEvent, useState} from "react";
-import {Button} from "../components/button";
-import Input from "../components/input";
-import {useSetAtom} from "jotai";
-import {thisPlayerAtom} from "../utils/state";
-import Player from "../game/player";
-import {useNavigate} from "react-router-dom";
-import {postData} from "../utils/api";
+import React, { FC, FormEvent, useState } from "react"
+import { Button } from "../components/button"
+import Input from "../components/input"
+import { useSetAtom } from "jotai"
+import { thisPlayerAtom } from "../utils/state"
+import Player from "../game/player"
+import { useNavigate } from "react-router-dom"
+import { postData } from "../utils/api"
const LoginPage: FC = () => {
-
- const setThisPlayer = useSetAtom(thisPlayerAtom);
- const navigate = useNavigate();
- const [error, setError] = useState();
+ const setThisPlayer = useSetAtom(thisPlayerAtom)
+ const navigate = useNavigate()
+ const [error, setError] = useState()
async function handleLogin(e: FormEvent): Promise {
- e.preventDefault();
- const fields = e.currentTarget.querySelectorAll("input");
+ e.preventDefault()
+ const fields = e.currentTarget.querySelectorAll("input")
- let user: User = {username: "", password: ""};
+ let user: User = { username: "", password: "" }
for (const field of fields) {
user = {
...user,
@@ -26,36 +25,41 @@ const LoginPage: FC = () => {
}
const response = await postData("/player/login", {
- body: {username: user.username, password: user.password} as User
+ body: { username: user.username, password: user.password } as User,
})
-
if (response.ok) {
- const data = await response.json() as PlayerProps;
- setThisPlayer(new Player(data));
- navigate("/lobby");
+ const data = (await response.json()) as PlayerProps
+ setThisPlayer(new Player(data))
+ navigate("/lobby")
} else {
- const data = await response.text();
- console.error(data);
- setError(data);
+ const data = await response.text()
+ console.error(data)
+ setError(data)
}
-
}
- const username = "username", password = "password";
+ const username = "username",
+ password = "password"
return (
- );
+ )
}
-export default LoginPage;
+export default LoginPage
diff --git a/pac-man-board-game/ClientApp/src/reportWebVitals.js b/pac-man-board-game/ClientApp/src/reportWebVitals.js
index 532f29b..eee308d 100644
--- a/pac-man-board-game/ClientApp/src/reportWebVitals.js
+++ b/pac-man-board-game/ClientApp/src/reportWebVitals.js
@@ -1,13 +1,13 @@
-const reportWebVitals = (onPerfEntry) => {
+const reportWebVitals = onPerfEntry => {
if (onPerfEntry && onPerfEntry instanceof Function) {
- import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
- getCLS(onPerfEntry);
- getFID(onPerfEntry);
- getFCP(onPerfEntry);
- getLCP(onPerfEntry);
- getTTFB(onPerfEntry);
- });
+ import("web-vitals").then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
+ getCLS(onPerfEntry)
+ getFID(onPerfEntry)
+ getFCP(onPerfEntry)
+ getLCP(onPerfEntry)
+ getTTFB(onPerfEntry)
+ })
}
-};
+}
-export default reportWebVitals;
+export default reportWebVitals
diff --git a/pac-man-board-game/ClientApp/src/types/props.d.ts b/pac-man-board-game/ClientApp/src/types/props.d.ts
index a903022..0f5d7da 100644
--- a/pac-man-board-game/ClientApp/src/types/props.d.ts
+++ b/pac-man-board-game/ClientApp/src/types/props.d.ts
@@ -1,25 +1,27 @@
-type FRComponent = React.ForwardRefExoticComponent & React.RefAttributes>;
+type FRComponent = React.ForwardRefExoticComponent<
+ React.PropsWithoutRef & React.RefAttributes
+>
interface ComponentProps {
- className?: string,
- style?: React.CSSProperties,
- id?: string,
- title?: string,
+ className?: string
+ style?: React.CSSProperties
+ id?: string
+ title?: string
}
interface ChildProps extends ComponentProps {
- children?: React.JSX.Element | string,
+ children?: React.JSX.Element | string
}
interface LinkProps extends ChildProps {
- to: string,
- newTab?: boolean,
+ to: string
+ newTab?: boolean
}
interface ButtonProps extends ChildProps {
- onClick?: (event: React.MouseEvent) => void,
- disabled?: boolean,
- type?: "button" | "submit" | "reset",
+ onClick?: (event: React.MouseEvent) => void
+ disabled?: boolean
+ type?: "button" | "submit" | "reset"
}
interface InputProps extends ComponentProps {
@@ -31,23 +33,23 @@ interface InputProps extends ComponentProps {
}
interface CharacterProps {
- colour: import("../game/colour").Colour,
- position?: Path | null,
- isEatable?: boolean,
- spawnPosition?: DirectionalPosition | null,
- type?: import("../game/character").CharacterType,
+ colour: import("../game/colour").Colour
+ position?: Path | null
+ isEatable?: boolean
+ spawnPosition?: DirectionalPosition | null
+ type?: import("../game/character").CharacterType
}
interface BoxProps {
- pellets?: number,
- powerPellets?: number,
- readonly colour: import("../game/colour").Colour,
+ pellets?: number
+ powerPellets?: number
+ readonly colour: import("../game/colour").Colour
}
interface PlayerProps {
- readonly username: string,
- readonly pacMan?: CharacterProps,
- readonly colour: import("../game/colour").Colour,
- readonly box?: BoxProps,
- state?: import("../game/player").State,
+ readonly username: string
+ readonly pacMan?: CharacterProps
+ readonly colour: import("../game/colour").Colour
+ readonly box?: BoxProps
+ state?: import("../game/player").State
}
diff --git a/pac-man-board-game/ClientApp/src/types/types.d.ts b/pac-man-board-game/ClientApp/src/types/types.d.ts
index 00ea66d..1c961bb 100644
--- a/pac-man-board-game/ClientApp/src/types/types.d.ts
+++ b/pac-man-board-game/ClientApp/src/types/types.d.ts
@@ -1,68 +1,68 @@
-type MessageEventFunction = (data: MessageEvent) => void;
+type MessageEventFunction = (data: MessageEvent) => void
-type Setter = React.Dispatch>;
+type Setter = React.Dispatch>
-type GUID = `${string}-${string}-${string}-${string}-${string}`;
+type GUID = `${string}-${string}-${string}-${string}-${string}`
-type WebSocketData = string | ArrayBufferLike | Blob | ArrayBufferView;
+type WebSocketData = string | ArrayBufferLike | Blob | ArrayBufferView
type ActionMessage = {
- readonly action: import("../utils/actions").GameAction,
+ readonly action: import("../utils/actions").GameAction
readonly data?: T
}
-type Action = (obj: T) => void;
+type Action = (obj: T) => void
-type BiAction = (obj1: T1, obj2: T2) => void;
+type BiAction = (obj1: T1, obj2: T2) => void
-type Predicate = (obj: T) => boolean;
+type Predicate = (obj: T) => boolean
type SelectedDice = {
- value: number,
+ value: number
index: number
-};
+}
-type Position = { x: number, y: number };
+type Position = { x: number; y: number }
-type GameMap = number[][];
+type GameMap = number[][]
type DirectionalPosition = {
- at: Position,
+ at: Position
direction: import("../game/direction").Direction
}
type Path = {
- path?: Position[] | null,
+ path?: Position[] | null
// TODO replace with DirectionalPosition
- end: Position,
+ end: Position
direction: import("../game/direction").Direction
}
type Game = {
- readonly id: string,
- readonly count: number,
- readonly isGameStarted: boolean,
+ readonly id: string
+ readonly count: number
+ readonly isGameStarted: boolean
}
type User = {
- readonly username: string,
- readonly password: string,
+ readonly username: string
+ readonly password: string
readonly colour?: import("../game/colour").Colour
}
-type Api = (path: string, data?: ApiRequest & T) => Promise;
+type Api = (path: string, data?: ApiRequest & T) => Promise
type ApiRequest = {
- headers?: HeadersInit,
+ headers?: HeadersInit
body?: any
}
type JoinGameData = {
- readonly username: string,
- readonly gameId: GUID,
+ readonly username: string
+ readonly gameId: GUID
}
type CreateGameData = {
- readonly player: PlayerProps,
- readonly spawns: DirectionalPosition[],
+ readonly player: PlayerProps
+ readonly spawns: DirectionalPosition[]
}
diff --git a/pac-man-board-game/ClientApp/src/utils/actions.ts b/pac-man-board-game/ClientApp/src/utils/actions.ts
index 7e2f610..9792c70 100644
--- a/pac-man-board-game/ClientApp/src/utils/actions.ts
+++ b/pac-man-board-game/ClientApp/src/utils/actions.ts
@@ -1,10 +1,10 @@
-import Player from "../game/player";
-import {CharacterType, Ghost} from "../game/character";
-import {getCharacterSpawns} from "../game/map";
-import {TileType} from "../game/tileType";
-import {getDefaultStore} from "jotai";
-import {currentPlayerNameAtom, diceAtom, ghostsAtom, playersAtom, rollDiceButtonAtom, selectedMapAtom} from "./state";
-import {Colour} from "../game/colour";
+import Player from "../game/player"
+import { CharacterType, Ghost } from "../game/character"
+import { getCharacterSpawns } from "../game/map"
+import { TileType } from "../game/tileType"
+import { getDefaultStore } from "jotai"
+import { currentPlayerNameAtom, diceAtom, ghostsAtom, playersAtom, rollDiceButtonAtom, selectedMapAtom } from "./state"
+import { Colour } from "../game/colour"
export enum GameAction {
error,
@@ -17,107 +17,112 @@ export enum GameAction {
// TODO add updatePellets
}
-const store = getDefaultStore();
-const map = store.get(selectedMapAtom);
+const store = getDefaultStore()
+const map = store.get(selectedMapAtom)
-const ghostsProps: CharacterProps[] = [
- {colour: Colour.purple},
- {colour: Colour.purple},
-];
-let spawns = getCharacterSpawns(map).filter(spawn => spawn.type === CharacterType.ghost);
+const ghostsProps: CharacterProps[] = [{ colour: Colour.purple }, { colour: Colour.purple }]
+let spawns = getCharacterSpawns(map).filter(spawn => spawn.type === CharacterType.ghost)
ghostsProps.forEach(ghost => {
- ghost.spawnPosition = spawns.pop()?.position;
+ ghost.spawnPosition = spawns.pop()?.position
+})
+const ghosts = ghostsProps.map(props => new Ghost(props))
-});
-const ghosts = ghostsProps.map(props => new Ghost(props));
-
-store.set(ghostsAtom, ghosts);
+store.set(ghostsAtom, ghosts)
export const doAction: MessageEventFunction = (event): void => {
- const message: ActionMessage = JSON.parse(event.data);
- console.debug("Received message:", message);
+ const message: ActionMessage = JSON.parse(event.data)
+ console.debug("Received message:", message)
switch (message.action as GameAction) {
case GameAction.error:
- console.error("Error:", message.data);
- break;
+ console.error("Error:", message.data)
+ break
case GameAction.rollDice:
- setDice(message.data);
- break;
+ setDice(message.data)
+ break
case GameAction.moveCharacter:
- moveCharacter(message.data);
- break;
+ moveCharacter(message.data)
+ break
case GameAction.joinGame:
- joinGame(message.data);
- break;
+ joinGame(message.data)
+ break
case GameAction.ready:
- ready(message.data);
- break;
+ ready(message.data)
+ break
case GameAction.nextPlayer:
- nextPlayer(message.data);
- break;
+ nextPlayer(message.data)
+ break
case GameAction.disconnect:
- updatePlayers(message.data);
- break;
+ updatePlayers(message.data)
+ break
}
-};
-
-function setDice(data?: number[]): void {
- store.set(diceAtom, data);
}
-type MoveCharacterData = { dice: number[], players: PlayerProps[], ghosts: CharacterProps[], eatenPellets: Position[] };
+function setDice(data?: number[]): void {
+ store.set(diceAtom, data)
+}
+
+type MoveCharacterData = {
+ dice: number[]
+ players: PlayerProps[]
+ ghosts: CharacterProps[]
+ eatenPellets: Position[]
+}
function moveCharacter(data?: MoveCharacterData): void {
- store.set(diceAtom, data?.dice);
- updatePlayers(data?.players);
- updateGhosts(data);
- removeEatenPellets(data);
+ store.set(diceAtom, data?.dice)
+ updatePlayers(data?.players)
+ updateGhosts(data)
+ removeEatenPellets(data)
}
function updatePlayers(updatedPlayers?: PlayerProps[]): void {
if (updatedPlayers) {
- const newList: Player[] = updatedPlayers.map(p => new Player(p));
- store.set(playersAtom, newList);
+ const newList: Player[] = updatedPlayers.map(p => new Player(p))
+ store.set(playersAtom, newList)
}
}
function updateGhosts(data?: MoveCharacterData): void {
- const updatedGhosts = data?.ghosts;
+ const updatedGhosts = data?.ghosts
if (updatedGhosts) {
- const newList: Ghost[] = updatedGhosts.map(g => new Ghost(g));
- store.set(ghostsAtom, newList);
+ const newList: Ghost[] = updatedGhosts.map(g => new Ghost(g))
+ store.set(ghostsAtom, newList)
}
}
function removeEatenPellets(data?: MoveCharacterData): void {
- const pellets = data?.eatenPellets;
+ const pellets = data?.eatenPellets
for (const pellet of pellets ?? []) {
- map[pellet.y][pellet.x] = TileType.empty;
+ map[pellet.y][pellet.x] = TileType.empty
}
}
-function joinGame(data?: PlayerProps[]): void { // TODO missing data when refreshing page
- const playerProps = data ?? [];
- spawns = getCharacterSpawns(map).filter(spawn => spawn.type === CharacterType.pacMan);
- store.set(playersAtom, playerProps.map(p => new Player(p)));
+function joinGame(data?: PlayerProps[]): void {
+ // TODO missing data when refreshing page
+ const playerProps = data ?? []
+ spawns = getCharacterSpawns(map).filter(spawn => spawn.type === CharacterType.pacMan)
+ store.set(
+ playersAtom,
+ playerProps.map(p => new Player(p)),
+ )
}
-type ReadyData = { allReady: boolean, players: PlayerProps[] };
+type ReadyData = { allReady: boolean; players: PlayerProps[] }
function ready(data?: ReadyData): void {
if (data) {
- const players = data.players.map(p => new Player(p));
- store.set(playersAtom, players);
+ const players = data.players.map(p => new Player(p))
+ store.set(playersAtom, players)
if (data.allReady) {
- store.set(currentPlayerNameAtom, data.players[0].username);
+ store.set(currentPlayerNameAtom, data.players[0].username)
}
}
}
function nextPlayer(currentPlayerName?: string): void {
- store.set(currentPlayerNameAtom, currentPlayerName);
- store.set(rollDiceButtonAtom, true);
+ store.set(currentPlayerNameAtom, currentPlayerName)
+ store.set(rollDiceButtonAtom, true)
}
diff --git a/pac-man-board-game/ClientApp/src/utils/api.ts b/pac-man-board-game/ClientApp/src/utils/api.ts
index b9ab872..25eaa4d 100644
--- a/pac-man-board-game/ClientApp/src/utils/api.ts
+++ b/pac-man-board-game/ClientApp/src/utils/api.ts
@@ -1,12 +1,12 @@
-export const getData: Api = async (path, {headers} = {}) => {
- if (import.meta.env.MODE === "test") return Promise.resolve(new Response(JSON.stringify([])));
+export const getData: Api = async (path, { headers } = {}) => {
+ if (import.meta.env.MODE === "test") return Promise.resolve(new Response(JSON.stringify([])))
return await fetch(import.meta.env.VITE_API_HTTP + path, {
method: "GET",
- headers: headers
- });
+ headers: headers,
+ })
}
-export const postData: Api = async (path, {body, headers} = {}) => {
+export const postData: Api = async (path, { body, headers } = {}) => {
return await fetch(import.meta.env.VITE_API_HTTP + path, {
method: "POST",
headers: {
diff --git a/pac-man-board-game/ClientApp/src/utils/state.ts b/pac-man-board-game/ClientApp/src/utils/state.ts
index e1134b3..5715b46 100644
--- a/pac-man-board-game/ClientApp/src/utils/state.ts
+++ b/pac-man-board-game/ClientApp/src/utils/state.ts
@@ -1,74 +1,75 @@
-import Player from "../game/player";
-import {atom} from "jotai";
-import {Ghost} from "../game/character";
-import {customMap} from "../game/map";
+import Player from "../game/player"
+import { atom } from "jotai"
+import { Ghost } from "../game/character"
+import { customMap } from "../game/map"
-const playerStorage = "player";
+const playerStorage = "player"
/**
* All players in the game.
*/
-export const playersAtom = atom([]);
+export const playersAtom = atom([])
/**
* All player characters (Pac-Man) in the game.
*/
-export const playerCharactersAtom = atom(get => get(playersAtom).map(player => player.pacMan));
+export const playerCharactersAtom = atom(get => get(playersAtom).map(player => player.pacMan))
/**
* All ghosts in the game.
*/
-export const ghostsAtom = atom([]);
+export const ghostsAtom = atom([])
/**
* All characters in the game.
*/
-export const allCharactersAtom = atom(get => [...get(playerCharactersAtom), ...get(ghostsAtom)]);
+export const allCharactersAtom = atom(get => [...get(playerCharactersAtom), ...get(ghostsAtom)])
/**
* The player that is currently logged in.
*/
-const playerAtom = atom(undefined);
+const playerAtom = atom(undefined)
/**
* Gets a getter and setter to get or set the player that is currently logged in.
* Returns A tuple containing a getter and setter to get or set the player that is currently logged in.
*/
-export const thisPlayerAtom = atom(get => {
- const atomValue = get(playerAtom);
- if (!atomValue) {
- const item = sessionStorage.getItem(playerStorage);
- if (item) {
- const playerProps = JSON.parse(item) as PlayerProps;
- return new Player(playerProps);
+export const thisPlayerAtom = atom(
+ get => {
+ const atomValue = get(playerAtom)
+ if (!atomValue) {
+ const item = sessionStorage.getItem(playerStorage)
+ if (item) {
+ const playerProps = JSON.parse(item) as PlayerProps
+ return new Player(playerProps)
+ }
}
- }
- return atomValue;
-}, (_get, set, player: Player | undefined) => {
- if (player)
- sessionStorage.setItem(playerStorage, JSON.stringify(player));
- else
- sessionStorage.removeItem(playerStorage);
- set(playerAtom, player);
-});
+ return atomValue
+ },
+ (_get, set, player: Player | undefined) => {
+ if (player) sessionStorage.setItem(playerStorage, JSON.stringify(player))
+ else sessionStorage.removeItem(playerStorage)
+ set(playerAtom, player)
+ },
+)
/**
* All dice that have been rolled.
*/
-export const diceAtom = atom(undefined);
+export const diceAtom = atom(undefined)
/**
* The dice that have been selected by the player.
*/
-export const selectedDiceAtom = atom(undefined);
+export const selectedDiceAtom = atom(undefined)
/**
* The name of the player whose turn it is.
*/
-export const currentPlayerNameAtom = atom(undefined);
+export const currentPlayerNameAtom = atom(undefined)
/**
* The player whose turn it is.
*/
export const currentPlayerAtom = atom(get => {
- const currentPlayerName = get(currentPlayerNameAtom);
- return get(playersAtom).find(player => player.username === currentPlayerName);
-});
+ const currentPlayerName = get(currentPlayerNameAtom)
+ return get(playersAtom).find(player => player.username === currentPlayerName)
+})
/**
* Whether the roll dice button should be enabled.
*/
-export const rollDiceButtonAtom = atom(true);
+export const rollDiceButtonAtom = atom(true)
/**
* The map that is currently selected.
*/
-export const selectedMapAtom = atom(customMap);
+export const selectedMapAtom = atom(customMap)
diff --git a/pac-man-board-game/ClientApp/src/utils/utils.ts b/pac-man-board-game/ClientApp/src/utils/utils.ts
index 0c03df9..35ffaef 100644
--- a/pac-man-board-game/ClientApp/src/utils/utils.ts
+++ b/pac-man-board-game/ClientApp/src/utils/utils.ts
@@ -5,14 +5,14 @@
* @returns A promise that resolves when the predicate is true.
*/
export function wait(predicate: Predicate, timeout: number = 50): Promise {
- return new Promise((resolve) => {
+ return new Promise(resolve => {
const f = () => {
if (predicate()) {
- return resolve();
+ return resolve()
}
- setTimeout(f, timeout);
- };
+ setTimeout(f, timeout)
+ }
- f();
- });
+ f()
+ })
}
diff --git a/pac-man-board-game/ClientApp/src/vite-env.d.ts b/pac-man-board-game/ClientApp/src/vite-env.d.ts
index 68c1e06..5bfcd16 100644
--- a/pac-man-board-game/ClientApp/src/vite-env.d.ts
+++ b/pac-man-board-game/ClientApp/src/vite-env.d.ts
@@ -1,11 +1,11 @@
///
interface ImportMetaEnv {
- readonly VITE_API_URI: string,
- readonly VITE_API_HTTP: string,
- readonly VITE_API_WS: string,
+ readonly VITE_API_URI: string
+ readonly VITE_API_HTTP: string
+ readonly VITE_API_WS: string
}
interface ImportMeta {
- readonly env: ImportMetaEnv;
-}
\ No newline at end of file
+ readonly env: ImportMetaEnv
+}
diff --git a/pac-man-board-game/ClientApp/src/websockets/WebSocketService.ts b/pac-man-board-game/ClientApp/src/websockets/WebSocketService.ts
index 42cd93e..b78226d 100644
--- a/pac-man-board-game/ClientApp/src/websockets/WebSocketService.ts
+++ b/pac-man-board-game/ClientApp/src/websockets/WebSocketService.ts
@@ -1,9 +1,9 @@
-import {wait} from "../utils/utils";
+import { wait } from "../utils/utils"
interface IWebSocket {
- onOpen?: VoidFunction,
- onReceive?: MessageEventFunction,
- onClose?: VoidFunction,
+ onOpen?: VoidFunction
+ onReceive?: MessageEventFunction
+ onClose?: VoidFunction
onError?: VoidFunction
}
@@ -11,59 +11,59 @@ interface IWebSocket {
* WebSocketService class provides a WebSocket client interface for easy communication with a WebSocket server.
*/
export default class WebSocketService {
- private ws?: WebSocket;
- private readonly _url: string;
+ private ws?: WebSocket
+ private readonly _url: string
- constructor(url: string, {onOpen, onReceive, onClose, onError}: IWebSocket = {}) {
- this._url = url;
- this._onOpen = onOpen;
- this._onReceive = onReceive;
- this._onClose = onClose;
- this._onError = onError;
+ constructor(url: string, { onOpen, onReceive, onClose, onError }: IWebSocket = {}) {
+ this._url = url
+ this._onOpen = onOpen
+ this._onReceive = onReceive
+ this._onClose = onClose
+ this._onError = onError
}
- private _onOpen?: VoidFunction;
+ private _onOpen?: VoidFunction
set onOpen(onOpen: VoidFunction) {
- this._onOpen = onOpen;
- if (!this.ws) return;
- this.ws.onopen = onOpen;
+ this._onOpen = onOpen
+ if (!this.ws) return
+ this.ws.onopen = onOpen
}
- private _onReceive?: MessageEventFunction;
+ private _onReceive?: MessageEventFunction
set onReceive(onReceive: MessageEventFunction) {
- this._onReceive = onReceive;
- if (!this.ws) return;
- this.ws.onmessage = onReceive;
+ this._onReceive = onReceive
+ if (!this.ws) return
+ this.ws.onmessage = onReceive
}
- private _onClose?: VoidFunction;
+ private _onClose?: VoidFunction
set onClose(onClose: VoidFunction) {
- this._onClose = onClose;
- if (!this.ws) return;
- this.ws.onclose = onClose;
+ this._onClose = onClose
+ if (!this.ws) return
+ this.ws.onclose = onClose
}
- private _onError?: VoidFunction;
+ private _onError?: VoidFunction
set onError(onError: VoidFunction) {
- this._onError = onError;
- if (!this.ws) return;
- this.ws.onerror = onError;
+ this._onError = onError
+ if (!this.ws) return
+ this.ws.onerror = onError
}
/**
* Opens a WebSocket connection with the specified URL and sets the event callbacks.
*/
public open(): void {
- if (typeof WebSocket === "undefined" || this.isConnecting()) return;
- this.ws = new WebSocket(this._url);
- if (this._onOpen) this.ws.onopen = this._onOpen;
- if (this._onReceive) this.ws.onmessage = this._onReceive;
- if (this._onClose) this.ws.onclose = this._onClose;
- if (this._onError) this.ws.onerror = this._onError;
+ if (typeof WebSocket === "undefined" || this.isConnecting()) return
+ this.ws = new WebSocket(this._url)
+ if (this._onOpen) this.ws.onopen = this._onOpen
+ if (this._onReceive) this.ws.onmessage = this._onReceive
+ if (this._onClose) this.ws.onclose = this._onClose
+ if (this._onError) this.ws.onerror = this._onError
}
/**
@@ -72,8 +72,8 @@ export default class WebSocketService {
* @returns {Promise} - A promise that resolves when the "isOpen" condition is met.
*/
public async waitForOpen(): Promise {
- await wait(() => this.isOpen());
- if (this._onOpen) this.onOpen = this._onOpen;
+ await wait(() => this.isOpen())
+ if (this._onOpen) this.onOpen = this._onOpen
}
/**
@@ -83,16 +83,16 @@ export default class WebSocketService {
*/
public send(data: ActionMessage | string): void {
if (typeof data !== "string") {
- data = JSON.stringify(data);
+ data = JSON.stringify(data)
}
- this.ws?.send(data);
+ this.ws?.send(data)
}
/**
* Closes the WebSocket connection.
*/
public close(): void {
- this.ws?.close();
+ this.ws?.close()
}
/**
@@ -100,7 +100,7 @@ export default class WebSocketService {
* @returns {boolean} Returns true if the WebSocket is open, otherwise false.
*/
public isOpen(): boolean {
- return this.ws?.readyState === WebSocket?.OPEN;
+ return this.ws?.readyState === WebSocket?.OPEN
}
/**
@@ -109,7 +109,7 @@ export default class WebSocketService {
* @returns {boolean} - Returns 'true' if the WebSocket is connecting, otherwise 'false'.
*/
public isConnecting(): boolean {
- return this.ws?.readyState === WebSocket?.CONNECTING;
+ return this.ws?.readyState === WebSocket?.CONNECTING
}
/**
@@ -118,6 +118,6 @@ export default class WebSocketService {
* @returns {boolean} Returns true if the WebSocket connection is closed, false otherwise.
*/
public isClosed(): boolean {
- return this.ws?.readyState === WebSocket?.CLOSED;
+ return this.ws?.readyState === WebSocket?.CLOSED
}
}
diff --git a/pac-man-board-game/Controllers/GameController.cs b/pac-man-board-game/Controllers/GameController.cs
index c905ce4..4a289db 100644
--- a/pac-man-board-game/Controllers/GameController.cs
+++ b/pac-man-board-game/Controllers/GameController.cs
@@ -69,7 +69,7 @@ public class GameController : GenericController
}
catch (Exception e)
{
- return BadRequest(e.Message); // TODO not necessary?
+ return BadRequest(e.Message);
}
}