chess-board/src/boardState.ts
2022-01-07 22:25:01 -06:00

117 lines
2.4 KiB
TypeScript

import { COLOR, PIECE, FILE, RANK } from "./primitives";
import BoardWireFormat from "./boardWireFormat";
export type PieceState = {
kind: PIECE;
color: COLOR;
};
export type FileState = {
[key in RANK]?: PieceState;
};
export type BoardState = {
[key in FILE]?: FileState;
};
export type Coordinates = {
rank: RANK;
file: FILE;
};
const iconFor = ({ kind, color }: PieceState): string => {
switch (kind) {
case "pawn":
return color === "white" ? "♙" : "♟︎";
case "rook":
return color === "white" ? "♖" : "♜";
case "knight":
return color === "white" ? "♘" : "♞";
case "bishop":
return color === "white" ? "♗" : "♝";
case "queen":
return color === "white" ? "♕" : "♛";
case "king":
return color === "white" ? "♔" : "♚";
}
};
const assertFile = (maybeFile: string): FILE => {
switch (maybeFile) {
case "a":
case "b":
case "c":
case "d":
case "e":
case "f":
case "g":
case "h":
return maybeFile as FILE;
default:
throw new Error("Invalid file");
}
};
const opposite = (color: COLOR): COLOR => {
if (color === "white") {
return "black";
} else {
return "white";
}
};
const promoteCoordinates = (
state: BoardState,
color: COLOR
): Coordinates | undefined => {
const backRank: RANK = color === "white" ? 8 : 1;
const result = Object.entries(state).find((arr) => {
const elem = arr[1];
if (typeof elem === "undefined") {
return false;
}
const pieceState = elem[backRank];
if (typeof pieceState === "undefined") {
return false;
}
return pieceState.kind === "pawn" && pieceState.color === color;
});
if (typeof result === "undefined") {
return;
}
const fileId = result[0];
return {
file: assertFile(fileId),
rank: backRank,
};
};
const isPromoteAvailable = (state: BoardState, color: COLOR): boolean => {
return typeof promoteCoordinates(state, color) !== "undefined";
};
export const fromWireFormat = (boardWireFormat: BoardWireFormat): BoardState =>
boardWireFormat.reduce(
(currentState, [file, rank, kind, color]) => ({
...currentState,
[file]: {
...currentState[file],
[rank]: {
kind,
color,
},
},
}),
{} as BoardState
);
export default BoardState;
export { iconFor, isPromoteAvailable, opposite, promoteCoordinates };