fixed stockfish interpretation of smaller and larger boards

This commit is contained in:
2ManyProjects 2025-03-07 14:04:40 -06:00
parent 401d915a0b
commit 1cce2fe244
9 changed files with 148 additions and 25 deletions

View file

@ -108,7 +108,15 @@ class ChessEngine extends EventEmitter {
this.engine.stdin.write(cmd + '\n');
}
}
async startPos() {
if (!this.isReady) throw new Error('Engine not ready');
this.sendCommand(`position startpos`);
// Ensure engine is ready after position set
this.sendCommand('isready');
await new Promise(resolve => this.once('ready', resolve));
}
async setBoardPosition(fen) {
if (!this.isReady) throw new Error('Engine not ready');

View file

@ -94,6 +94,7 @@ ffish.onRuntimeInitialized = async () => {
engine.sendCommand('setoption name Hash value 128');
engine.sendCommand('setoption name MultiPV value 1');
engine.sendCommand('setoption name UCI_LimitStrength value true');
engine.sendCommand('uci');
}
} catch (error) {
console.log('Initialization error:', error);
@ -209,13 +210,10 @@ app.post('/new', async (req, res) => {
});
// Set position endpoint
app.post('/position', (req, res) => {
app.post('/position', async(req, res) => {
lastResponse = new Date().getTime()
const { fen, variant = 'chess' } = req.body;
const { fen, variant = 'chess', start } = req.body;
if (!fen) {
return res.status(400).json({ error: 'FEN string required' });
}
try {
//we have a lot of funky rules lets not validate
@ -232,7 +230,13 @@ app.post('/position', (req, res) => {
// // }
// board.setFen(fen);
// }
board.setFen(fen);
if(start){
await engine.startPos()
engine.sendCommand('d');
}else if(fen){
board.setFen(fen);
await engine.setBoardPosition(fen)
}
res.json({
status: 'ok',
@ -246,7 +250,7 @@ app.post('/position', (req, res) => {
moveStack: board.moveStack()
});
} catch (error) {
res.status(500).json({ error: error.message });
res.status(500).json({ error: error.message, poserr: true });
}
});

View file

@ -34,7 +34,7 @@ func connect_to_engine(_path: String, g: ChessGame) -> bool:
if ServerManager.is_server_running():
print("**************SERVER RUNNING ****************")
running = true
start_game(2100)
# start_game(2100)
return true
await get_tree().create_timer(delay).timeout
@ -74,7 +74,7 @@ func load_fen(fen: String):
http_request.request(server_url + "/position", headers, HTTPClient.METHOD_POST, body)
await http_request.request_completed
func start_board(elo: int):
func start_board(elo: int, variant: String = "8x8"):
if not running:
return
var headers = ["Content-Type: application/json"]
@ -85,7 +85,7 @@ func start_board(elo: int):
print(body)
http_request.request(server_url + "/new", headers, HTTPClient.METHOD_POST, body)
await http_request.request_completed
setElo(elo)
setElo(elo, variant)
func _exit_tree():
ServerManager.stop_server()
@ -107,7 +107,40 @@ func get_globalDir() -> String:
return OS.get_environment("HOME").path_join("Library/ChessBuilder")
func setElo(elo: int = 1350) -> void:
func setVariant(variant: String = "8x8"):
if not running:
return
print("####################################")
print("####################################")
print("chessbuilder" + variant)
print("####################################")
print("####################################")
print("####################################")
var headers = ["Content-Type: application/json"]
var data = {
"options": [
{
"name": "VariantPath",
"value": get_globalDir() + "/Assets" + "/ChessEngines/Fairy-Stockfish/src/variants.ini"
},
{
"name": "UCI_Variant",
"value": "chessbuilder" + variant
},
]
}
var body = JSON.new().stringify(data)
# Request engine move
http_request.request(
server_url + "/setoptions",
headers,
HTTPClient.METHOD_POST,
body
)
func setElo(elo: int = 1350, variant: String = "8x8") -> void:
if not running:
return
var headers = ["Content-Type: application/json"]
@ -127,7 +160,7 @@ func setElo(elo: int = 1350) -> void:
},
{
"name": "UCI_Variant",
"value": "chessbuilder" # Convert int to string
"value": "chessbuilder" + variant
},
]
}
@ -144,11 +177,18 @@ func setElo(elo: int = 1350) -> void:
HTTPClient.METHOD_POST,
body
)
await elo_req.request_completed
http_request.request(
server_url + "/position",
headers,
HTTPClient.METHOD_POST,
JSON.new().stringify({"start": true})
)
func generateMove(think_time_ms: int = 1000) -> void:
if not running:
return
print("&&&&&&&&&&&&&&&GENERATING MOVE&&&&&&&&&&&&&&&&&&&&&&")
print("&&&&&&&&&&&&&&&GENERATING MOVE&&&&&&&&&&&&&&&&&&&&&&", str(game.getCurrentFen()))
move_time = think_time_ms

View file

@ -107,6 +107,8 @@ func _on_new_game_requested(options = {}):
cpuElo = options.elo
if cameraController:
cameraController.reset_view()
print("ChessGame FEN ", currentFen)
print("ChessGame DIMENSIONS ", get_board_dimensions(currentFen))
if is_initialized:
resetBoard()
initializeDeckSystem()
@ -117,8 +119,10 @@ func _on_new_game_requested(options = {}):
stateMachine.transitionToNextState(Constants.WHITE_TURN)
else:
initialize_game_system()
stockfishController.start_board(cpuElo)
if currentFen:
stockfishController.start_board(cpuElo, get_board_dimensions(currentFen))
else:
stockfishController.start_board(cpuElo, "8x8")
func initialize_game_system():
print("Initializing game system")
# Set up basic styles first
@ -896,3 +900,20 @@ func updateHalfMoveClock(fromIdx: int, toIdx: int) -> void:
halfMoveClock = 0
else:
halfMoveClock += 1
func get_board_dimensions(fen_string: String) -> String:
var board_part: String = fen_string.split(" ")[0]
var ranks: Array = board_part.split("/")
var height: int = ranks.size()
var width: int = 0
var first_rank: String = ranks[0]
for character in first_rank:
if character.is_valid_int():
width += int(character)
else:
width += 1
return str(width) + "x" + str(height)

View file

@ -2,6 +2,7 @@ extends Control
class_name DeckManagerScreen
signal back_pressed
signal deck_manager_visibility_changed(isvisible)
# Node references
@onready var deckGrid = $MainContainer/GridScrollContainer/GridContainer

View file

@ -12,6 +12,9 @@ var max_nodes_per_level = 4
var positions_per_level = 6
var starting_elo = 1000
var final_elo = 2100
var current_max_level = 0;
# var level_unit_distribution = ["", "", "", "nkr", "rnkr", "rnkbr", "rnqkbr", "rnqkbnr", "rnbqkbnr", "rbnqknbnr", "rnbnqknbnr", "rnbnqknbnbr", "rbnbnqknbnbr"]
var level_unit_distribution = ["", "", "nkr", "rnkr", "rnkr", "rnkbr", "rnqkbr", "rnqkbnr", "rnbqkbnr", "rbnqknbnr", "rnbnqknbnr", "rnbnqknbnbr", "rbnbnqknbnbr"]
var _rng = RandomNumberGenerator.new()
var _next_id = 0
@ -29,7 +32,7 @@ func generate_map():
_next_id = 0
var num_levels = _rng.randi_range(min_levels, max_levels)
current_max_level = num_levels;
var elo_step = float(final_elo - starting_elo) / (num_levels - 1)
var start_node = {
@ -307,10 +310,53 @@ func generate_event_data(node):
}
# "rnbqkbnr1/pppppppp1/9/9/9/9/9/PPPPPPPP1/RNBQKBNR1 w KQkq - 0 1"
func generate_chess_data(node):
# level_unit_distribution
# current_max_level
var rng = float(node.level) / int(current_max_level)
var index = map_to_array_index(node.level, 2, current_max_level - 2, 3, level_unit_distribution.size() - 1);
var unit_string = level_unit_distribution[index]
var pawn_string = ""
for x in unit_string.length():
pawn_string += "p"
var height = 6;
# "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR"
var fen = "";
if node.level > 7 and node.level <= 10:
height = node.level
elif node.level > 10:
height = 10
for x in height - 2:
if x == 0:
fen += unit_string + "/"
elif x == 1:
fen += pawn_string + "/"
else:
fen += str(unit_string.length()) + "/"
fen += pawn_string.to_upper() + "/" + unit_string.to_upper()
var fen_ending = " w KQkq - 0 1"
# print("generate_chess_data ", fen + fen_ending)
return {
"is_escape": node.metadata.is_escape if node.metadata.has("is_escape") else false,
"fen": "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
"fen": fen + fen_ending,
"game_type": "chess",
"win_condition": Utils.WinCondition.King,
"elo": node.elo,
}
func map_to_array_index(current_value, min_value, max_value, min_index, max_index):
# Ensure the current value is within bounds
var clamped_value = clamp(current_value, min_value, max_value)
# Calculate how far along the input range we are (0.0 to 1.0)
var normalized_position = float(clamped_value - min_value) / float(max_value - min_value)
# Map this to our target index range
var index_range = max_index - min_index
var mapped_index = min_index + round(normalized_position * index_range)
# Ensure we're returning an integer within the valid array index range
return int(clamp(mapped_index, min_index, max_index))

View file

@ -38,5 +38,3 @@ func _on_state_delay_timeout() -> void:
finished.emit(Constants.HAND_SETUP)
func exit() -> void:
moveTimer.stop()

View file

@ -48,16 +48,19 @@ func enter(_previous: String, _data := {}) -> void:
print("GENERATED MOVE ", move)
if move:
var move_str = move.move # e.g., "e2e4"
if "," in move_str:
move_str = move.move.split(",")[0]
var source_square = move_str.substr(0, 2) # "e2"
var target_square = move_str.substr(2, 2) # "e4"
# First select the piece
var source_location = Utils.convert_algebraic_to_location(source_square)
var source_location = Utils.convert_algebraic_to_location(source_square, game.boardYSize)
game.selectedNode = source_location
print("source_location ", source_location)
# Then make the move
var target_location = Utils.convert_algebraic_to_location(target_square)
var target_location = Utils.convert_algebraic_to_location(target_square, game.boardYSize)
print("target_location ", target_location)
handleMovement(target_location, true)
return
@ -94,8 +97,10 @@ func handleMovement(location: String, generated: bool = false) -> void:
var sourceContainer = game.get_node("Flow/" + game.selectedNode) as PieceContainer
var piece = sourceContainer.get_piece()
if piece == null:
# print("No Piece")
print("No Piece")
return
else:
print("Selected ", piece.name)
# print("SColor ", sourcePiece.Item_Color, " tColor ", piece.Item_Color)
var piece_id = piece.get_instance_id()

View file

@ -23,7 +23,7 @@ static func generate_guid() -> String:
return guid
static func convert_algebraic_to_location(square: String) -> String:
static func convert_algebraic_to_location(square: String, maxRank: int) -> String:
var file = square[0] # letter (a-h)
var rank = int(square[1]) # number (1-8)
@ -33,7 +33,7 @@ static func convert_algebraic_to_location(square: String) -> String:
# Since we're working with black's moves and our board is oriented with white at bottom:
# 1. Flip rank: 8 - rank to mirror vertically
file_num = file_num
var rank_num = 8 - rank
var rank_num = maxRank - rank
return "%d-%d" % [file_num, rank_num]