fixed stockfish interpretation of smaller and larger boards
This commit is contained in:
parent
401d915a0b
commit
1cce2fe244
9 changed files with 148 additions and 25 deletions
|
|
@ -108,7 +108,15 @@ class ChessEngine extends EventEmitter {
|
||||||
this.engine.stdin.write(cmd + '\n');
|
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) {
|
async setBoardPosition(fen) {
|
||||||
if (!this.isReady) throw new Error('Engine not ready');
|
if (!this.isReady) throw new Error('Engine not ready');
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,7 @@ ffish.onRuntimeInitialized = async () => {
|
||||||
engine.sendCommand('setoption name Hash value 128');
|
engine.sendCommand('setoption name Hash value 128');
|
||||||
engine.sendCommand('setoption name MultiPV value 1');
|
engine.sendCommand('setoption name MultiPV value 1');
|
||||||
engine.sendCommand('setoption name UCI_LimitStrength value true');
|
engine.sendCommand('setoption name UCI_LimitStrength value true');
|
||||||
|
engine.sendCommand('uci');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log('Initialization error:', error);
|
console.log('Initialization error:', error);
|
||||||
|
|
@ -209,13 +210,10 @@ app.post('/new', async (req, res) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Set position endpoint
|
// Set position endpoint
|
||||||
app.post('/position', (req, res) => {
|
app.post('/position', async(req, res) => {
|
||||||
lastResponse = new Date().getTime()
|
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 {
|
try {
|
||||||
//we have a lot of funky rules lets not validate
|
//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);
|
board.setFen(fen);
|
||||||
|
await engine.setBoardPosition(fen)
|
||||||
|
}
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
status: 'ok',
|
status: 'ok',
|
||||||
|
|
@ -246,7 +250,7 @@ app.post('/position', (req, res) => {
|
||||||
moveStack: board.moveStack()
|
moveStack: board.moveStack()
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(500).json({ error: error.message });
|
res.status(500).json({ error: error.message, poserr: true });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ func connect_to_engine(_path: String, g: ChessGame) -> bool:
|
||||||
if ServerManager.is_server_running():
|
if ServerManager.is_server_running():
|
||||||
print("**************SERVER RUNNING ****************")
|
print("**************SERVER RUNNING ****************")
|
||||||
running = true
|
running = true
|
||||||
start_game(2100)
|
# start_game(2100)
|
||||||
return true
|
return true
|
||||||
|
|
||||||
await get_tree().create_timer(delay).timeout
|
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)
|
http_request.request(server_url + "/position", headers, HTTPClient.METHOD_POST, body)
|
||||||
await http_request.request_completed
|
await http_request.request_completed
|
||||||
func start_board(elo: int):
|
func start_board(elo: int, variant: String = "8x8"):
|
||||||
if not running:
|
if not running:
|
||||||
return
|
return
|
||||||
var headers = ["Content-Type: application/json"]
|
var headers = ["Content-Type: application/json"]
|
||||||
|
|
@ -85,7 +85,7 @@ func start_board(elo: int):
|
||||||
print(body)
|
print(body)
|
||||||
http_request.request(server_url + "/new", headers, HTTPClient.METHOD_POST, body)
|
http_request.request(server_url + "/new", headers, HTTPClient.METHOD_POST, body)
|
||||||
await http_request.request_completed
|
await http_request.request_completed
|
||||||
setElo(elo)
|
setElo(elo, variant)
|
||||||
|
|
||||||
func _exit_tree():
|
func _exit_tree():
|
||||||
ServerManager.stop_server()
|
ServerManager.stop_server()
|
||||||
|
|
@ -107,7 +107,40 @@ func get_globalDir() -> String:
|
||||||
return OS.get_environment("HOME").path_join("Library/ChessBuilder")
|
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:
|
if not running:
|
||||||
return
|
return
|
||||||
var headers = ["Content-Type: application/json"]
|
var headers = ["Content-Type: application/json"]
|
||||||
|
|
@ -127,7 +160,7 @@ func setElo(elo: int = 1350) -> void:
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "UCI_Variant",
|
"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,
|
HTTPClient.METHOD_POST,
|
||||||
body
|
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:
|
func generateMove(think_time_ms: int = 1000) -> void:
|
||||||
if not running:
|
if not running:
|
||||||
return
|
return
|
||||||
print("&&&&&&&&&&&&&&&GENERATING MOVE&&&&&&&&&&&&&&&&&&&&&&")
|
print("&&&&&&&&&&&&&&&GENERATING MOVE&&&&&&&&&&&&&&&&&&&&&&", str(game.getCurrentFen()))
|
||||||
|
|
||||||
move_time = think_time_ms
|
move_time = think_time_ms
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,8 @@ func _on_new_game_requested(options = {}):
|
||||||
cpuElo = options.elo
|
cpuElo = options.elo
|
||||||
if cameraController:
|
if cameraController:
|
||||||
cameraController.reset_view()
|
cameraController.reset_view()
|
||||||
|
print("ChessGame FEN ", currentFen)
|
||||||
|
print("ChessGame DIMENSIONS ", get_board_dimensions(currentFen))
|
||||||
if is_initialized:
|
if is_initialized:
|
||||||
resetBoard()
|
resetBoard()
|
||||||
initializeDeckSystem()
|
initializeDeckSystem()
|
||||||
|
|
@ -117,8 +119,10 @@ func _on_new_game_requested(options = {}):
|
||||||
stateMachine.transitionToNextState(Constants.WHITE_TURN)
|
stateMachine.transitionToNextState(Constants.WHITE_TURN)
|
||||||
else:
|
else:
|
||||||
initialize_game_system()
|
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():
|
func initialize_game_system():
|
||||||
print("Initializing game system")
|
print("Initializing game system")
|
||||||
# Set up basic styles first
|
# Set up basic styles first
|
||||||
|
|
@ -896,3 +900,20 @@ func updateHalfMoveClock(fromIdx: int, toIdx: int) -> void:
|
||||||
halfMoveClock = 0
|
halfMoveClock = 0
|
||||||
else:
|
else:
|
||||||
halfMoveClock += 1
|
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)
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ extends Control
|
||||||
class_name DeckManagerScreen
|
class_name DeckManagerScreen
|
||||||
|
|
||||||
signal back_pressed
|
signal back_pressed
|
||||||
|
signal deck_manager_visibility_changed(isvisible)
|
||||||
|
|
||||||
# Node references
|
# Node references
|
||||||
@onready var deckGrid = $MainContainer/GridScrollContainer/GridContainer
|
@onready var deckGrid = $MainContainer/GridScrollContainer/GridContainer
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,9 @@ var max_nodes_per_level = 4
|
||||||
var positions_per_level = 6
|
var positions_per_level = 6
|
||||||
var starting_elo = 1000
|
var starting_elo = 1000
|
||||||
var final_elo = 2100
|
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 _rng = RandomNumberGenerator.new()
|
||||||
var _next_id = 0
|
var _next_id = 0
|
||||||
|
|
@ -29,7 +32,7 @@ func generate_map():
|
||||||
_next_id = 0
|
_next_id = 0
|
||||||
|
|
||||||
var num_levels = _rng.randi_range(min_levels, max_levels)
|
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 elo_step = float(final_elo - starting_elo) / (num_levels - 1)
|
||||||
|
|
||||||
var start_node = {
|
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"
|
# "rnbqkbnr1/pppppppp1/9/9/9/9/9/PPPPPPPP1/RNBQKBNR1 w KQkq - 0 1"
|
||||||
func generate_chess_data(node):
|
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 {
|
return {
|
||||||
"is_escape": node.metadata.is_escape if node.metadata.has("is_escape") else false,
|
"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",
|
"game_type": "chess",
|
||||||
"win_condition": Utils.WinCondition.King,
|
"win_condition": Utils.WinCondition.King,
|
||||||
"elo": node.elo,
|
"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))
|
||||||
|
|
|
||||||
|
|
@ -38,5 +38,3 @@ func _on_state_delay_timeout() -> void:
|
||||||
finished.emit(Constants.HAND_SETUP)
|
finished.emit(Constants.HAND_SETUP)
|
||||||
func exit() -> void:
|
func exit() -> void:
|
||||||
moveTimer.stop()
|
moveTimer.stop()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,16 +48,19 @@ func enter(_previous: String, _data := {}) -> void:
|
||||||
print("GENERATED MOVE ", move)
|
print("GENERATED MOVE ", move)
|
||||||
if move:
|
if move:
|
||||||
var move_str = move.move # e.g., "e2e4"
|
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 source_square = move_str.substr(0, 2) # "e2"
|
||||||
var target_square = move_str.substr(2, 2) # "e4"
|
var target_square = move_str.substr(2, 2) # "e4"
|
||||||
|
|
||||||
# First select the piece
|
# 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
|
game.selectedNode = source_location
|
||||||
print("source_location ", source_location)
|
print("source_location ", source_location)
|
||||||
|
|
||||||
# Then make the move
|
# 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)
|
print("target_location ", target_location)
|
||||||
handleMovement(target_location, true)
|
handleMovement(target_location, true)
|
||||||
return
|
return
|
||||||
|
|
@ -94,8 +97,10 @@ func handleMovement(location: String, generated: bool = false) -> void:
|
||||||
var sourceContainer = game.get_node("Flow/" + game.selectedNode) as PieceContainer
|
var sourceContainer = game.get_node("Flow/" + game.selectedNode) as PieceContainer
|
||||||
var piece = sourceContainer.get_piece()
|
var piece = sourceContainer.get_piece()
|
||||||
if piece == null:
|
if piece == null:
|
||||||
# print("No Piece")
|
print("No Piece")
|
||||||
return
|
return
|
||||||
|
else:
|
||||||
|
print("Selected ", piece.name)
|
||||||
# print("SColor ", sourcePiece.Item_Color, " tColor ", piece.Item_Color)
|
# print("SColor ", sourcePiece.Item_Color, " tColor ", piece.Item_Color)
|
||||||
|
|
||||||
var piece_id = piece.get_instance_id()
|
var piece_id = piece.get_instance_id()
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ static func generate_guid() -> String:
|
||||||
return guid
|
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 file = square[0] # letter (a-h)
|
||||||
var rank = int(square[1]) # number (1-8)
|
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:
|
# 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
|
# 1. Flip rank: 8 - rank to mirror vertically
|
||||||
file_num = file_num
|
file_num = file_num
|
||||||
var rank_num = 8 - rank
|
var rank_num = maxRank - rank
|
||||||
|
|
||||||
return "%d-%d" % [file_num, rank_num]
|
return "%d-%d" % [file_num, rank_num]
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue