Skip to content

Commit

Permalink
fucked up behavior
Browse files Browse the repository at this point in the history
  • Loading branch information
Oceankoh committed Jan 20, 2024
1 parent 2d57561 commit 00f3575
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 32 deletions.
58 changes: 42 additions & 16 deletions backend/src/chess/engine.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,45 @@
import { Chess, validateFen } from "chess.js";
import { Chess, Square, validateFen } from "chess.js";
import { llmInterpretPrompt } from "./llm.js";
import { assertUnreachable } from "../utils/assertions.js";

class NormalMove {
square1: string;
square2: string;
constructor(square1: string, square2: string) {
square1: Square;
square2: Square;
constructor(square1: Square, square2: Square) {
this.square1 = square1;
this.square2 = square2;
}

toString(): string {
format(): string {
return `(${this.square1}, ${this.square2})`;
}

toString(): string {
return `Move piece from ${this.square1} to ${this.square2}`;
}
}

class PromotionMove extends NormalMove {
piece: "q" | "r" | "b" | "n";
constructor(square1: string, square2: string, piece: "q" | "r" | "b" | "n") {
pieceMap = {
q: "queen",
r: "rook",
b: "bishop",
n: "knight",
}
constructor(square1: Square, square2: Square, piece: "q" | "r" | "b" | "n") {
super(square1, square2);
this.piece = piece;
}

toString(): string {
format(): string {
return `(${this.square1}, ${this.square2}, '${this.piece}')`;
}

toString(): string {
return `Move piece from ${this.square1} to ${this.square2} and promote to a ${this.pieceMap[this.piece]}`;
}

}

class InvalidMove {
Expand All @@ -33,7 +48,7 @@ class InvalidMove {
this.prompt = prompt;
}

toString() {
toString() : string {
return 'Invalid Move'
}
}
Expand All @@ -45,35 +60,46 @@ class FailedMove {
}
}

class SuccessfulMove {
fen: string;
move: NormalMove | PromotionMove;
constructor(fen: string, move: NormalMove | PromotionMove) {
this.fen = fen;
this.move = move;
}
}

type Move = InvalidMove | NormalMove | PromotionMove;

// const FEN = "rnbqkb1r/1p2ppp1/3p4/p2n3p/3P4/3B1N2/PPP2PPP/RNBQK2R w KQkq - 0 7";
const chess = new Chess();

function movePiece(square1, square2): string | FailedMove {
function movePiece(move: NormalMove): SuccessfulMove | FailedMove {
const { square1, square2 } = move;
const piece = chess.remove(square1);
if (!piece) {
return new FailedMove(`Tried to move piece at ${square1} to ${square2} but there was no piece found at ${square1}`);
}
chess.put(piece, square2);
const validate = validateFen(chess.fen());
if (validate.ok) {
return chess.fen();
return new SuccessfulMove(chess.fen(), move);
} else {
console.log(validateFen(chess.fen()));
return new FailedMove(validate.error);
}
}

function promotePiece(square1, square2, piece): string | FailedMove {
function promotePiece(move: PromotionMove): SuccessfulMove | FailedMove {
const { square1, square2, piece } = move;
const pawn = chess.remove(square1);
if (!pawn) {
return new FailedMove(`Tried to promote piece at ${square1}, but there was no piece found at ${square1}`);
}
chess.put({ type: piece, color: pawn.color }, square2);
const validate = validateFen(chess.fen());
if (validate.ok) {
return chess.fen();
return new SuccessfulMove(chess.fen(), move);
} else {
console.log(validateFen(chess.fen()));
return new FailedMove(validate.error);
Expand All @@ -83,14 +109,14 @@ function promotePiece(square1, square2, piece): string | FailedMove {
export async function interpretMove(
prompt: string,
fen: string
): Promise<string | FailedMove> {
): Promise<SuccessfulMove | FailedMove> {
const move = await llmInterpretPrompt(prompt, fen);
if (move instanceof NormalMove) {
console.log('return normal move')
return movePiece(move.square1, move.square2);
return movePiece(move);
} else if (move instanceof PromotionMove) {
console.log('return promotion move')
return promotePiece(move.square1, move.square2, move.piece);
return promotePiece(move);
} else if (move instanceof InvalidMove) {
console.log('return failed move')
return new FailedMove(move.prompt);
Expand All @@ -100,4 +126,4 @@ export async function interpretMove(
}
}

export { Move, NormalMove, PromotionMove, InvalidMove, FailedMove };
export { Move, NormalMove, PromotionMove, InvalidMove, FailedMove, SuccessfulMove };
23 changes: 12 additions & 11 deletions backend/src/chess/llm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
import { assertNever, assertUnreachable } from "../utils/assertions.js";
import dotenv from "dotenv";
import { InvalidMove, Move, NormalMove, PromotionMove } from "./engine.js";
import { Square } from "chess.js";
dotenv.config();

async function getTokenCount(
Expand Down Expand Up @@ -84,7 +85,7 @@ export async function llmInterpretPrompt(
if (safe) {
return parsed;
} else {
return new InvalidMove(`Illegal Move: ${text}`);
return new InvalidMove(`Illegal Move detected: ${parsed}`);
}
} else {
assertUnreachable(parsed);
Expand Down Expand Up @@ -120,7 +121,7 @@ async function llmCheckMoveValidity(
});

const result = await chat.sendMessage(
`The current game state is provided by the following FEN: ${fen}. The move to be made is ${prompt.toString()}`
`The current game state is provided by the following FEN: ${fen}. The move to be made is ${prompt.format()}`
);

const response = await result.response;
Expand All @@ -136,24 +137,24 @@ async function llmCheckMoveValidity(

function parseResponseMove(response: string): Move {
// check if response is in the format (square, square)
const moveRegex = /\(\'?([abcdefgh]\d)\'?,\s?\'?([abcdefgh]\d)\'?\)/;
const moveRegex = /.*([abcdefgh]\d).*([abcdefgh]\d).*/;
const moveMatch = response.match(moveRegex);
if (moveMatch) {
const [_, square1, square2] = moveMatch;
return new NormalMove(square1, square2);
return new NormalMove(square1 as Square, square2 as Square);
}

// check if response is in the format (square, square)
const promotionRegex =
/\('?([abcdefgh]\d)'?,\s?'?([abcdefgh]\d)'?,\s?'?([qrbn])'?\)/;
/.*([abcdefgh]\d).*([abcdefgh]\d).*([qrbn]).*/;
const promotionMatch = response.match(promotionRegex);
if (promotionMatch) {
const [_, square1, square2, piece] = promotionMatch;
if (piece === "q" || piece === "r" || piece === "b" || piece === "n") {
return new PromotionMove(square1, square2, piece);
} else {
assertNever();
}
return new PromotionMove(
square1 as Square,
square2 as Square,
piece as "q" | "r" | "b" | "n"
);
}
return new InvalidMove(`Invalid Response: ${response}`);
return new InvalidMove(`Prompt generated a response that could not be parsed: ${response}`);
}
10 changes: 5 additions & 5 deletions backend/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import dotenv from "dotenv";
import { Server } from "socket.io";
import { Chess } from "chess.js";
import "./utils/globals.js";
import { FailedMove, interpretMove } from "./chess/engine.js";
import { FailedMove, SuccessfulMove, interpretMove } from "./chess/engine.js";
import { assertUnreachable } from "./utils/assertions.js";
import stockfish from "stockfish";

Expand Down Expand Up @@ -146,10 +146,10 @@ io.on("connection", (socket) => {
const res = await interpretMove(move, globalThis.roomFen.get(roomId));
if (res instanceof FailedMove) {
callback(res.error);
} else if (typeof res === "string") {
io.to(roomId).emit("update", res, socket.id, move);
globalThis.roomFen.set(roomId, res);
callback(res);
} else if (res instanceof SuccessfulMove) {
io.to(roomId).emit("update", res.fen, socket.id, move);
globalThis.roomFen.set(roomId, res.fen);
callback(res.move.toString());

if (roomId === "ai") {
fetch("http://localhost:8080/stockfish", {
Expand Down

0 comments on commit 00f3575

Please sign in to comment.