Create board object builder and supporting classes and types
parent
9f5ec017b7
commit
37a84be3c3
|
|
@ -0,0 +1,110 @@
|
|||
import { CellType } from "./constants/CellType";
|
||||
import { Direction } from "./constants/Direction";
|
||||
import { ExitType } from "./constants/ExitType";
|
||||
import { Cell } from "./types/Cell";
|
||||
import { Exit } from "./types/Exit";
|
||||
|
||||
const boardSize = 7;
|
||||
const universityLocations = [
|
||||
[2, 0],
|
||||
[4, 1],
|
||||
[3, 3],
|
||||
];
|
||||
const factoryLocations = [
|
||||
[0, 0],
|
||||
[5, 2],
|
||||
[4, 6],
|
||||
];
|
||||
const houseLocations = [
|
||||
[0, 2],
|
||||
[1, 5],
|
||||
[2, 4],
|
||||
[5, 4],
|
||||
];
|
||||
const mapPosition = (position: number[], type: CellType) => {
|
||||
return {
|
||||
row: position[0],
|
||||
col: position[1],
|
||||
type: type,
|
||||
};
|
||||
};
|
||||
const specialUniversityCells = universityLocations.map((position) =>
|
||||
mapPosition(position, CellType.UNIVERSITY),
|
||||
);
|
||||
const specialFactoryCells = factoryLocations.map((position) =>
|
||||
mapPosition(position, CellType.FACTORY),
|
||||
);
|
||||
const specialHouseCells = houseLocations.map((position) =>
|
||||
mapPosition(position, CellType.HOUSE),
|
||||
);
|
||||
const specialCells = specialUniversityCells
|
||||
.concat(specialFactoryCells)
|
||||
.concat(specialHouseCells);
|
||||
|
||||
const specialExitIndexes1 = [1, 5];
|
||||
const specialExitIndexes2 = [3];
|
||||
|
||||
function createBoard(): Cell[][] {
|
||||
const indexes = Array.from(Array(boardSize).keys());
|
||||
return indexes.map((rowIndex) =>
|
||||
indexes.map((colIndex) => {
|
||||
const specialCell = specialCells.find(
|
||||
(specialCell) =>
|
||||
specialCell.row === rowIndex && specialCell.col === colIndex,
|
||||
);
|
||||
return new Cell(specialCell ? specialCell.type : CellType.NORMAL);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
function connectAdjacentCells(board: Cell[][]) {
|
||||
const indexes = Array.from(Array(boardSize).keys());
|
||||
for (const rowIndex of indexes.slice(0, -1)) {
|
||||
for (const colIndex of indexes.slice(0, -1)) {
|
||||
const cell = board[rowIndex][colIndex];
|
||||
const rightCell = board[rowIndex][colIndex + 1];
|
||||
const bottomCell = board[rowIndex + 1][colIndex];
|
||||
|
||||
cell
|
||||
.getNodeAt(Direction.SOUTH)
|
||||
.linkToNode(bottomCell.getNodeAt(Direction.NORTH));
|
||||
cell
|
||||
.getNodeAt(Direction.EAST)
|
||||
.linkToNode(rightCell.getNodeAt(Direction.WEST));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addExits(board: Cell[][]) {
|
||||
// Add exits to top row
|
||||
board[0].forEach((cell, colIndex) => {
|
||||
let exitType = ExitType.AMBIVALENT;
|
||||
if (specialExitIndexes1.includes(colIndex)) exitType = ExitType.ROAD;
|
||||
if (specialExitIndexes2.includes(colIndex)) exitType = ExitType.RAIL;
|
||||
cell.getNodeAt(Direction.NORTH).linkToNode(new Exit(exitType));
|
||||
});
|
||||
|
||||
// Add exits to bottom row
|
||||
board[boardSize - 1].forEach((cell, colIndex) => {
|
||||
let exitType = ExitType.AMBIVALENT;
|
||||
if (specialExitIndexes1.includes(colIndex)) exitType = ExitType.ROAD;
|
||||
if (specialExitIndexes2.includes(colIndex)) exitType = ExitType.RAIL;
|
||||
cell.getNodeAt(Direction.SOUTH).linkToNode(new Exit(exitType));
|
||||
});
|
||||
|
||||
// Add exits to left and right columns
|
||||
board.forEach((row, rowIndex) => {
|
||||
let exitType = ExitType.AMBIVALENT;
|
||||
if (specialExitIndexes1.includes(rowIndex)) exitType = ExitType.RAIL;
|
||||
if (specialExitIndexes2.includes(rowIndex)) exitType = ExitType.ROAD;
|
||||
row[0].getNodeAt(Direction.WEST).linkToNode(new Exit(exitType));
|
||||
row[boardSize - 1].getNodeAt(Direction.EAST).linkToNode(new Exit(exitType));
|
||||
});
|
||||
}
|
||||
|
||||
export function buildBoard(): Cell[][] {
|
||||
const board: Cell[][] = createBoard();
|
||||
connectAdjacentCells(board);
|
||||
addExits(board);
|
||||
return board;
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
export enum CellType {
|
||||
NORMAL = "NORMAL",
|
||||
HOUSE = "HOUSE",
|
||||
FACTORY = "FACTORY",
|
||||
UNIVERSITY = "UNIVERSITY",
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
export enum Direction {
|
||||
NORTH = "NORTH",
|
||||
SOUTH = "SOUTH",
|
||||
EAST = "EAST",
|
||||
WEST = "WEST",
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
export enum ExitType {
|
||||
RAIL = "RAIL",
|
||||
ROAD = "ROAD",
|
||||
AMBIVALENT = "AMBIVALENT",
|
||||
}
|
||||
|
|
@ -1,3 +1,6 @@
|
|||
export * from "./constants/CellType";
|
||||
export * from "./constants/Direction";
|
||||
export * from "./constants/ExitType";
|
||||
export * from "./constants/TrackType";
|
||||
export * from "./server-events/CreateLobbyError";
|
||||
export * from "./server-events/ServerError";
|
||||
|
|
@ -6,3 +9,9 @@ export * from "./server-events/UpdateLobbyEvent";
|
|||
export * from "./client-events/ClientEvent";
|
||||
export * from "./client-events/CreateLobbyEvent";
|
||||
export * from "./client-events/JoinLobbyEvent";
|
||||
export * from "./types/Border";
|
||||
export * from "./types/Cell";
|
||||
export * from "./types/Exit";
|
||||
export * from "./types/ExternalNode";
|
||||
export * from "./types/Node";
|
||||
export * from "./BoardBuilder";
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
import { Exit } from "./Exit";
|
||||
import { ExternalNode } from "./ExternalNode";
|
||||
|
||||
export class Border {
|
||||
private readonly firstNode: ExternalNode;
|
||||
private readonly secondNode: ExternalNode | Exit;
|
||||
|
||||
constructor(firstNode: ExternalNode, secondNode: ExternalNode | Exit) {
|
||||
this.firstNode = firstNode;
|
||||
this.secondNode = secondNode;
|
||||
}
|
||||
|
||||
public traverseFrom(node: ExternalNode): ExternalNode | Exit {
|
||||
if (node === this.firstNode) {
|
||||
return this.secondNode;
|
||||
}
|
||||
if (node === this.secondNode) {
|
||||
return this.firstNode;
|
||||
}
|
||||
throw Error("Unable to traverse border");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
import { CellType } from "../constants/CellType";
|
||||
import { Direction } from "../constants/Direction";
|
||||
import { ExternalNode } from "./ExternalNode";
|
||||
|
||||
export class Cell {
|
||||
public readonly externalNodes: Map<Direction, ExternalNode>;
|
||||
public readonly cellType: CellType;
|
||||
|
||||
constructor(cellType: CellType) {
|
||||
this.externalNodes = new Map([
|
||||
[Direction.NORTH, new ExternalNode(this, Direction.NORTH)],
|
||||
[Direction.SOUTH, new ExternalNode(this, Direction.SOUTH)],
|
||||
[Direction.EAST, new ExternalNode(this, Direction.EAST)],
|
||||
[Direction.WEST, new ExternalNode(this, Direction.WEST)],
|
||||
]);
|
||||
this.cellType = cellType;
|
||||
}
|
||||
|
||||
public getNodeAt(direction: Direction): ExternalNode {
|
||||
const node = this.externalNodes.get(direction);
|
||||
if (!node) throw Error(`Could not find node at ${direction}`);
|
||||
return this.externalNodes.get(direction) as ExternalNode;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import { ExitType } from "../constants/ExitType";
|
||||
|
||||
export class Exit {
|
||||
public readonly type: ExitType;
|
||||
|
||||
constructor(type: ExitType) {
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
import { Direction } from "../constants/Direction";
|
||||
import { Border } from "./Border";
|
||||
import { Cell } from "./Cell";
|
||||
import { Exit } from "./Exit";
|
||||
import { Node } from "./Node";
|
||||
|
||||
export class ExternalNode extends Node {
|
||||
public readonly direction: Direction;
|
||||
private border?: Border;
|
||||
|
||||
constructor(cell: Cell, direction: Direction) {
|
||||
super(cell);
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
public linkToNode(other: ExternalNode | Exit) {
|
||||
this.border = new Border(this, other);
|
||||
}
|
||||
|
||||
public traverseBorder(): ExternalNode | Exit {
|
||||
if (!this.border) throw Error(`Missing border for node`);
|
||||
return (this.border as Border).traverseFrom(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import { Cell } from "./Cell";
|
||||
|
||||
export abstract class Node {
|
||||
public readonly cell: Cell;
|
||||
|
||||
constructor(cell: Cell) {
|
||||
this.cell = cell;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue