Compare commits
5 commits
ccd82c306e
...
fd03fe7ca5
| Author | SHA1 | Date | |
|---|---|---|---|
| fd03fe7ca5 | |||
| d9683b43d3 | |||
| 07c90e9ef5 | |||
| 9032a40b24 | |||
| d1b8b777ac |
|
|
@ -10,3 +10,35 @@ 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",
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 921 B After Width: | Height: | Size: 921 B |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 921 B After Width: | Height: | Size: 921 B |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |