Compare commits

...

5 commits

Author SHA1 Message Date
fd03fe7ca5 piece display change and move constant to types.ts 2026-07-25 16:55:43 +07:00
d9683b43d3 remove random import? 2026-07-25 16:48:06 +07:00
07c90e9ef5 full fen parsing 2026-07-25 16:42:33 +07:00
9032a40b24 algebraic to index func 2026-07-25 16:41:01 +07:00
d1b8b777ac fen input and index label 2026-07-25 16:29:55 +07:00
15 changed files with 71 additions and 25 deletions

View file

@ -9,4 +9,36 @@ export enum Piece {
WHITE = 8, WHITE = 8,
BLACK = 16, BLACK = 16,
}
export const CHAR_TO_PIECE: Record<string, number> = {
"-": Piece.EMPTY,
"K": Piece.WHITE | Piece.KING,
"Q": Piece.WHITE | Piece.QUEEN,
"R": Piece.WHITE | Piece.ROOK,
"B": Piece.WHITE | Piece.BISHOP,
"N": Piece.WHITE | Piece.KNIGHT,
"P": Piece.WHITE | Piece.PAWN,
"k": Piece.BLACK | Piece.KING,
"q": Piece.BLACK | Piece.QUEEN,
"r": Piece.BLACK | Piece.ROOK,
"b": Piece.BLACK | Piece.BISHOP,
"n": Piece.BLACK | Piece.KNIGHT,
"p": Piece.BLACK | Piece.PAWN,
};
export const PIECE_TO_CHAR: Record<number, string> = {
[Piece.EMPTY]: "-",
[Piece.WHITE | Piece.KING]: "K",
[Piece.WHITE | Piece.QUEEN]: "Q",
[Piece.WHITE | Piece.ROOK]: "R",
[Piece.WHITE | Piece.BISHOP]: "B",
[Piece.WHITE | Piece.KNIGHT]: "N",
[Piece.WHITE | Piece.PAWN]: "P",
[Piece.BLACK | Piece.KING]: "k",
[Piece.BLACK | Piece.QUEEN]: "q",
[Piece.BLACK | Piece.ROOK]: "r",
[Piece.BLACK | Piece.BISHOP]: "b",
[Piece.BLACK | Piece.KNIGHT]: "n",
[Piece.BLACK | Piece.PAWN]: "p",
} }

View file

@ -1,29 +1,11 @@
import { Piece } from "./types"; import { CHAR_TO_PIECE, Piece } from "./types";
// export function fen2array(fen: string): Int8Array<ArrayBuffer> {
// }
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> = {
"-": Piece.EMPTY,
"K": Piece.WHITE | Piece.KING,
"Q": Piece.WHITE | Piece.QUEEN,
"R": Piece.WHITE | Piece.ROOK,
"B": Piece.WHITE | Piece.BISHOP,
"N": Piece.WHITE | Piece.KNIGHT,
"P": Piece.WHITE | Piece.PAWN,
"k": Piece.BLACK | Piece.KING,
"q": Piece.BLACK | Piece.QUEEN,
"r": Piece.BLACK | Piece.ROOK,
"b": Piece.BLACK | Piece.BISHOP,
"n": Piece.BLACK | Piece.KNIGHT,
"p": Piece.BLACK | Piece.PAWN,
};
export class Board { export class Board {
public board = new Int8Array(8 ** 2); public board = new Int8Array(8 ** 2);
public details = { public details = {
turn: "w", whiteTurn: true,
castling: { castling: {
white: { king: true, queen: true }, white: { king: true, queen: true },
black: { king: true, queen: true }, black: { king: true, queen: true },
@ -39,8 +21,8 @@ export class Board {
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);
this.board.fill(Piece.EMPTY);
position.split("/").forEach((row, rank) => { position.split("/").forEach((row, rank) => {
let file = 0; let file = 0;
row.split("").forEach((char) => { row.split("").forEach((char) => {
@ -49,5 +31,33 @@ export class Board {
file++; file++;
}); });
}); });
this.details.whiteTurn = turn === "w";
this.details.castling.white.king = castling.includes("K");
this.details.castling.white.queen = castling.includes("Q");
this.details.castling.black.king = castling.includes("k");
this.details.castling.black.queen = castling.includes("q");
this.details.enPassant = algebraicToIndex(enPassant);
this.details.halfMove = parseInt(halfMove);
this.details.fullMove = parseInt(fullMove);
}
}
function algebraicToIndex(algebraic: 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,
}
try {
if (algebraic.length !== 2) return -1;
const [file, rank] = algebraic.split("");
const rankIndex = parseInt(rank) - 1;
const fileIndex = FILE_TO_INDEX[file];
return rankIndex * 8 + fileIndex;
} catch {
return -1;
} }
} }

View file

@ -1,4 +1,5 @@
<script lang="ts"> <script lang="ts">
import { PIECE_TO_CHAR } from "$lib/chess/types";
import { Board, startFEN } from "$lib/chess/utils"; import { Board, startFEN } from "$lib/chess/utils";
const board = new Board(); const board = new Board();
@ -14,11 +15,11 @@
<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 boardView as square, index}
<div class="h-20 aspect-square 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'}
"> ">
{#if square}<img src="assets/{square}.svg" alt="p{square}" class="h-18 aspect-square"/>{/if} <span class="absolute top-0 left-0">{showIndex ? index : ''}</span>
{showIndex ? index : ''} {#if square}<img src="assets/{PIECE_TO_CHAR[square]}.svg" alt="{PIECE_TO_CHAR[square]}" class="h-18 aspect-square"/>{/if}
</div> </div>
{/each} {/each}
</div> </div>
@ -29,7 +30,10 @@
</label> </label>
<label class="block"> <label class="block">
fen (enter to set): 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)
updateView()
})()} 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(board)}>dump game to console</button>

View file

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 921 B

After

Width:  |  Height:  |  Size: 921 B

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 921 B

After

Width:  |  Height:  |  Size: 921 B

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Before After
Before After