Compare commits

..

4 commits

Author SHA1 Message Date
ccd82c306e button styling 2026-07-25 16:09:50 +07:00
86acb6b350 view updater 2026-07-25 16:09:43 +07:00
3d7802fa6e FEN parser 2026-07-25 16:09:26 +07:00
fbadf1d436 add dump button 2026-07-25 15:21:30 +07:00
3 changed files with 24 additions and 4 deletions

View file

@ -5,6 +5,7 @@ import { Piece } 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";
const CHAR_TO_PIECE: Record<string, number> = { const CHAR_TO_PIECE: Record<string, number> = {
"-": Piece.EMPTY,
"K": Piece.WHITE | Piece.KING, "K": Piece.WHITE | Piece.KING,
"Q": Piece.WHITE | Piece.QUEEN, "Q": Piece.WHITE | Piece.QUEEN,
"R": Piece.WHITE | Piece.ROOK, "R": Piece.WHITE | Piece.ROOK,
@ -31,13 +32,22 @@ export class Board {
halfMove: 0, halfMove: 0,
fullMove: 0, fullMove: 0,
}; };
constructor() { constructor() {
this.loadFEN(); this.loadFEN();
} }
loadFEN(fen = startFEN) { loadFEN(fen = startFEN) {
const [position, turn, castling, enPassant, halfMove, fullMove] = fen.split(" "); const [position, turn, castling, enPassant, halfMove, fullMove] = fen.split(" ");
this.board.fill(Piece.EMPTY);
position.split("/").forEach((row, rank) => {
let file = 0;
row.split("").forEach((char) => {
if (!isNaN(parseInt(char))) return file += parseInt(char);
this.board[rank * 8 + file] = CHAR_TO_PIECE[char]
file++;
});
});
} }
} }

View file

@ -2,16 +2,22 @@
import { Board, startFEN } from "$lib/chess/utils"; import { Board, startFEN } from "$lib/chess/utils";
const board = new Board(); 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);
function updateView() {
boardView = Array.from(board.board);
}
</script> </script>
<div class="grid grid-cols-8 gap-0 border-2"> <div class="grid grid-cols-8 gap-0 border-2">
{#each board.board as square, index} {#each boardView as square, index}
<div class="h-20 aspect-square flex justify-center items-center <div class="h-20 aspect-square 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'}
"> ">
{#if square}<img src="assets/{square}.svg" alt="p{square}" class="h-16 aspect-square"/>{/if} {#if square}<img src="assets/{square}.svg" alt="p{square}" class="h-18 aspect-square"/>{/if}
{showIndex ? index : ''} {showIndex ? index : ''}
</div> </div>
{/each} {/each}
@ -22,7 +28,9 @@
<input type="checkbox" bind:checked={showIndex} /> <input type="checkbox" bind:checked={showIndex} />
</label> </label>
<label class="block"> <label class="block">
fen: fen (enter to set):
<input type="text" onkeypress={(e) => e.key === 'Enter' && board.loadFEN(fen)} bind:value={fen} /> <input type="text" onkeypress={(e) => e.key === 'Enter' && board.loadFEN(fen)} bind:value={fen} />
</label> </label>
<button onclick={updateView}>update view</button>
<button onclick={() => console.log(board)}>dump game to console</button>
</div> </div>

View file

@ -2,3 +2,5 @@
html, body { @apply h-full; } 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; }