Compare commits
3 commits
fd03fe7ca5
...
05debd41f1
| Author | SHA1 | Date | |
|---|---|---|---|
| 05debd41f1 | |||
| 7b396243ad | |||
| 43d1ed7932 |
4 changed files with 76 additions and 12 deletions
|
|
@ -1,3 +1,6 @@
|
||||||
|
import { Game } from "./utils";
|
||||||
|
export type GameListener = (board: Game) => void;
|
||||||
|
|
||||||
export enum Piece {
|
export enum Piece {
|
||||||
EMPTY = 0,
|
EMPTY = 0,
|
||||||
KING = 1,
|
KING = 1,
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { CHAR_TO_PIECE, Piece } from "./types";
|
import { CHAR_TO_PIECE, Piece, PIECE_TO_CHAR, type GameListener } from "./types";
|
||||||
|
|
||||||
export const startFEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0";
|
export const startFEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0";
|
||||||
|
|
||||||
export class Board {
|
export class Game {
|
||||||
public board = new Int8Array(8 ** 2);
|
public board = new Int8Array(8 ** 2);
|
||||||
public details = {
|
public details = {
|
||||||
whiteTurn: true,
|
whiteTurn: true,
|
||||||
|
|
@ -15,10 +15,21 @@ export class Board {
|
||||||
fullMove: 0,
|
fullMove: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private listeners = new Set<GameListener>();
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.loadFEN();
|
this.loadFEN();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private notify() {
|
||||||
|
for (const listener of this.listeners) listener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
subscribe(listener: GameListener): () => void {
|
||||||
|
this.listeners.add(listener);
|
||||||
|
return () => this.listeners.delete(listener);
|
||||||
|
}
|
||||||
|
|
||||||
loadFEN(fen = startFEN) {
|
loadFEN(fen = startFEN) {
|
||||||
const [position, turn, castling, enPassant, halfMove, fullMove] = fen.split(" ");
|
const [position, turn, castling, enPassant, halfMove, fullMove] = fen.split(" ");
|
||||||
|
|
||||||
|
|
@ -43,9 +54,20 @@ export class Board {
|
||||||
|
|
||||||
this.details.halfMove = parseInt(halfMove);
|
this.details.halfMove = parseInt(halfMove);
|
||||||
this.details.fullMove = parseInt(fullMove);
|
this.details.fullMove = parseInt(fullMove);
|
||||||
|
|
||||||
|
this.notify();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function boardToAscii(board: Int8Array): string {
|
||||||
|
let ascii = '';
|
||||||
|
board.forEach((piece, i) => {
|
||||||
|
if (i % 8 === 0 && i !== 0) ascii += '\n';
|
||||||
|
ascii += PIECE_TO_CHAR[piece];
|
||||||
|
});
|
||||||
|
return ascii;
|
||||||
|
}
|
||||||
|
|
||||||
function algebraicToIndex(algebraic: string): number {
|
function algebraicToIndex(algebraic: string): number {
|
||||||
const FILE_TO_INDEX: Record<string, number> = {
|
const FILE_TO_INDEX: Record<string, number> = {
|
||||||
a: 0, b: 1, c: 2, d: 3, e: 4, f: 5, g: 6, h: 7,
|
a: 0, b: 1, c: 2, d: 3, e: 4, f: 5, g: 6, h: 7,
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,25 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { PIECE_TO_CHAR } from "$lib/chess/types";
|
import { PIECE_TO_CHAR } from "$lib/chess/types";
|
||||||
import { Board, startFEN } from "$lib/chess/utils";
|
import { boardToAscii, Game, startFEN } from "$lib/chess/utils";
|
||||||
|
|
||||||
const board = new Board();
|
|
||||||
|
|
||||||
let boardView = $state(Array.from(board.board));
|
|
||||||
let showIndex = $state(false);
|
let showIndex = $state(false);
|
||||||
let fen = $state(startFEN);
|
let fen = $state(startFEN);
|
||||||
|
|
||||||
|
const game = new Game();
|
||||||
|
let board = $state(Array.from(game.board));
|
||||||
|
let ascii = $state(boardToAscii(game.board));
|
||||||
|
let details = $state(game.details)
|
||||||
|
|
||||||
|
game.subscribe(updateView);
|
||||||
function updateView() {
|
function updateView() {
|
||||||
boardView = Array.from(board.board);
|
board = Array.from(game.board);
|
||||||
|
ascii = boardToAscii(game.board);
|
||||||
|
details = game.details;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="grid grid-cols-8 gap-0 border-2">
|
<div class="grid grid-cols-8 gap-0 border-2">
|
||||||
{#each boardView as square, index}
|
{#each board as square, index}
|
||||||
<div class="h-20 aspect-square relative flex justify-center items-center
|
<div class="h-20 aspect-square relative flex justify-center items-center
|
||||||
{index % 2 === Math.floor(index / 8) % 2 ? 'bg-orange-200 text-stone-800' : 'bg-amber-800 text-stone-200'}
|
{index % 2 === Math.floor(index / 8) % 2 ? 'bg-orange-200 text-stone-800' : 'bg-amber-800 text-stone-200'}
|
||||||
">
|
">
|
||||||
|
|
@ -24,6 +29,37 @@
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
<pre>{ascii}</pre>
|
||||||
|
<ul>
|
||||||
|
{#each Object.entries(game.details).filter(([k]) => k !== "castling") as [key, val]}
|
||||||
|
<li>
|
||||||
|
<strong>{key}</strong>:
|
||||||
|
{val.toString()}
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Castling</th>
|
||||||
|
<th>King</th>
|
||||||
|
<th>Queen</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th>White</th>
|
||||||
|
<td>{game.details.castling.white.king}</td>
|
||||||
|
<td>{game.details.castling.white.queen}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Black</th>
|
||||||
|
<td>{game.details.castling.black.king}</td>
|
||||||
|
<td>{game.details.castling.black.queen}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</ul>
|
||||||
|
<hr class="border border-stone-200 my-4">
|
||||||
<label class="block">
|
<label class="block">
|
||||||
show index
|
show index
|
||||||
<input type="checkbox" bind:checked={showIndex} />
|
<input type="checkbox" bind:checked={showIndex} />
|
||||||
|
|
@ -31,10 +67,9 @@
|
||||||
<label class="block">
|
<label class="block">
|
||||||
fen (enter to set):
|
fen (enter to set):
|
||||||
<input type="text" onkeypress={(e) => e.key === 'Enter' && (() => {
|
<input type="text" onkeypress={(e) => e.key === 'Enter' && (() => {
|
||||||
board.loadFEN(fen)
|
game.loadFEN(fen);
|
||||||
updateView()
|
|
||||||
})()} bind:value={fen} />
|
})()} bind:value={fen} />
|
||||||
</label>
|
</label>
|
||||||
<button onclick={updateView}>update view</button>
|
<button onclick={updateView}>update view</button>
|
||||||
<button onclick={() => console.log(board)}>dump game to console</button>
|
<button onclick={() => console.log(game)}>dump game to console</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -4,3 +4,7 @@ html, body { @apply h-full; }
|
||||||
body { @apply bg-gray-900 text-gray-100; }
|
body { @apply bg-gray-900 text-gray-100; }
|
||||||
|
|
||||||
input, button { @apply bg-stone-200 text-stone-800 px-2 py-1 m-1 rounded; }
|
input, button { @apply bg-stone-200 text-stone-800 px-2 py-1 m-1 rounded; }
|
||||||
|
|
||||||
|
table { @apply w-full border-collapse; }
|
||||||
|
th, td { @apply border border-gray-700 px-2 py-1 text-center }
|
||||||
|
th { @apply font-bold; }
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue