Skip to content

Commit

Permalink
Merge pull request #126 from dcSpark/feature/add-chess-move-tool
Browse files Browse the repository at this point in the history
feat: add chess-move tool
  • Loading branch information
guillevalin authored Feb 4, 2025
2 parents 2ec2b44 + 5a7f94d commit 4ad0e81
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 0 deletions.
Binary file added tools/chess-move/banner.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tools/chess-move/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
35 changes: 35 additions & 0 deletions tools/chess-move/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { expect } from '@jest/globals';
import { getToolTestClient } from '../../src/test/utils';
import * as path from 'path';

describe('Chess Move Tool', () => {
const toolPath = path.join(__dirname, 'tool.py');
const client = getToolTestClient();

it('makes a legal move from the start position', async () => {
const startFen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
const response = await client.executeToolFromFile(toolPath, {
fen: startFen,
move_uci: "e2e4"
});

console.log(response);

expect(response).toHaveProperty('new_fen');
expect(response).toHaveProperty('is_legal', true);
// newFen should be different from startFen
expect(typeof response.new_fen).toBe('string');
expect(response.new_fen).not.toBe(startFen);
});

it('rejects an illegal move', async () => {
const startFen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
const response = await client.executeToolFromFile(toolPath, {
fen: startFen,
move_uci: "e2e5" // Pawn can't jump three squares
});
expect(response.is_legal).toBe(false);
// The fen should remain unchanged
expect(response.new_fen).toBe(startFen);
});
});
46 changes: 46 additions & 0 deletions tools/chess-move/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"id": "chess-move",
"name": "Chess Move",
"version": "1.0.0",
"description": "Apply a move in UCI format to a given FEN and return the resulting position",
"author": "Example",
"keywords": [
"chess",
"move",
"uci",
"fen",
"position",
"game"
],
"configurations": {
"type": "object",
"properties": {},
"required": []
},
"parameters": {
"type": "object",
"properties": {
"fen": {
"type": "string",
"description": "FEN describing the current position"
},
"move_uci": {
"type": "string",
"description": "Move in UCI format (e.g. 'e2e4')"
}
},
"required": ["fen", "move_uci"]
},
"result": {
"type": "object",
"properties": {
"new_fen": {
"type": "string"
},
"is_legal": {
"type": "boolean"
}
},
"required": ["new_fen", "is_legal"]
}
}
3 changes: 3 additions & 0 deletions tools/chess-move/store.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"categoryId": "f4906ba5-16bb-445d-9241-85422cf5a055"
}
51 changes: 51 additions & 0 deletions tools/chess-move/tool.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# /// script
# dependencies = [
# "python-chess>=1.999"
# ]
# ///
import chess
from typing import Dict, Any, Optional, List

class CONFIG:
pass

class INPUTS:
fen: str
move_uci: str

class OUTPUT:
new_fen: str
is_legal: bool

async def run(c: CONFIG, p: INPUTS) -> OUTPUT:
if not p.fen:
raise ValueError("No FEN provided")
if not p.move_uci:
raise ValueError("No UCI move provided")

board = chess.Board()
try:
board.set_fen(p.fen)
except ValueError:
raise ValueError("Invalid FEN")

# Validate the move format, e.g. "e2e4", "e7e8q"
if len(p.move_uci) < 4 or len(p.move_uci) > 5:
raise ValueError(f"Move '{p.move_uci}' not in typical UCI format")

move = None
try:
move = board.parse_uci(p.move_uci)
except:
pass

result = OUTPUT()
if move and move in board.legal_moves:
board.push(move)
result.is_legal = True
result.new_fen = board.fen()
else:
result.is_legal = False
result.new_fen = board.fen() # unchanged

return result

0 comments on commit 4ad0e81

Please sign in to comment.