# StockfishClient.gd extends Node var server_url = "http://localhost:27531" var http_request: HTTPRequest var running := false var generated_move: Dictionary = {} var move_time: int = 1000 var game: ChessGame var symbol_from_piece_type := { "PAWN": "p", "KNIGHT": "n", "BISHOP": "b", "ROOK": "r", "QUEEN": "q", "KING": "k" } var piece_type_from_symbol := { "p": "PAWN", "n": "KNIGHT", "b": "BISHOP", "r": "ROOK", "q": "QUEEN", "k": "KING" } func _init(): print("STARTING SERVER CLIENT") http_request = HTTPRequest.new() add_child(http_request) http_request.request_completed.connect(self._on_request_completed) func connect_to_engine(_path: String, g: ChessGame) -> bool: game = g # Wait for server to be ready var retries = 5 var delay = 1.0 # seconds while retries > 0: if ServerManager.is_server_running(): print("**************SERVER RUNNING ****************") running = true # start_game(2100) return true await get_tree().create_timer(delay).timeout retries -= 1 print("**************ATTEMPTING SERVER CONNECTION****************") return false func start_game(elo: int) -> void: start_board(elo) load_fen(game.getCurrentFen()) func disconnect_engine(): running = false func stop_calculating(): if not running: return # Send stop command to server http_request.request(server_url + "/stop", [], HTTPClient.METHOD_POST) func load_fen(fen: String): if not running: return # var http_request = HTTPRequest.new() # add_child(http_request) # http_request.request_completed.connect(self._on_request_completed) var headers = ["Content-Type: application/json"] var body = JSON.new().stringify({ "fen": fen }) print(server_url + "/position") print(body) http_request.request(server_url + "/position", headers, HTTPClient.METHOD_POST, body) await http_request.request_completed func start_board(elo: int, variant: String = "8x8"): if not running: return var headers = ["Content-Type: application/json"] var body = JSON.new().stringify({ "variant": 'chess' }) print(server_url + "/new") print(body) http_request.request(server_url + "/new", headers, HTTPClient.METHOD_POST, body) await http_request.request_completed setElo(elo, variant) func clear_game( ): if not running: return var headers = ["Content-Type: application/json"] var body = JSON.new().stringify({ "variant": 'chess' }) print(server_url + "/new") print(body) http_request.request(server_url + "/new", headers, HTTPClient.METHOD_POST, body) await http_request.request_completed func _exit_tree(): ServerManager.stop_server() disconnect_engine(); func get_globalDir() -> String: if OS.get_name() == "Linux": return OS.get_environment("HOME").path_join(".local/share/ChessBuilder") elif OS.get_name() == "Windows": return OS.get_environment("APPDATA").path_join("Roaming/ChessBuilder") else: # macOS return OS.get_environment("HOME").path_join("Library/ChessBuilder") 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() + "/variant" + "/custom_variant.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"] var data = { "options": [ { "name": "VariantPath", "value": get_globalDir() + "/variant" + "/custom_variant.ini" }, { "name": "UCI_LimitStrength", "value": "true" }, { "name": "UCI_Elo", "value": str(elo) # Convert int to string }, { "name": "UCI_Variant", "value": "chessbuilder" + variant }, ] } var body = JSON.new().stringify(data) # Request engine move var elo_req = HTTPRequest.new() add_child(elo_req) elo_req.request_completed.connect(self._on_request_completed) elo_req.request( server_url + "/setoptions", headers, 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&&&&&&&&&&&&&&&&&&&&&&", str(game.generate_variant_aware_fen())) move_time = think_time_ms var headers = ["Content-Type: application/json"] var body = JSON.stringify({ "movetime": think_time_ms, "depth": 15, "fen": str(game.generate_variant_aware_fen()) }) # Request engine move var move_request = HTTPRequest.new() add_child(move_request) move_request.request_completed.connect(self._on_bestmove_completed) var error = move_request.request( server_url + "/enginemove", headers, HTTPClient.METHOD_POST, body ) func getGeneratedMove() -> Dictionary: var move = generated_move.duplicate() generated_move.clear() return move func send_move(move_data: Dictionary): if not running: return var headers = ["Content-Type: application/json"] var move_str = from_move_to_string(move_data) var body = JSON.stringify({ "move": move_str }) http_request.request(server_url + "/move", headers, HTTPClient.METHOD_POST, body) # Helper functions func from_move_to_string(move_data: Dictionary) -> String: # Same implementation as original var board_size = 8 # Standard chess board var source_i = move_data.source % board_size var source_j = move_data.source / board_size var target_i = move_data.target % board_size var target_j = move_data.target / board_size var letters = "abcdefgh" var str_move = "%s%d%s%d" % [ letters[source_i], board_size - source_j, letters[target_i], board_size - target_j ] if move_data.get("flags", "") == "PROMOTION": str_move += symbol_from_piece_type[move_data.promotion_piece].to_lower() return str_move func _on_bestmove_completed(result: int, response_code: int, headers: PackedStringArray, body: PackedByteArray): print("^^^^^^^^^^^^^^^_on_bestmove_completed^^^^^^^^^^^^^^^^^") var json = JSON.new() json.parse(body.get_string_from_utf8()) var response = json.get_data() # Will print the user agent string used by the HTTPRequest node (as recognized by httpbin.org). print(response) if response == null or result != HTTPRequest.RESULT_SUCCESS: print("HTTP Request failed") return if response.status != "ok": print("Server error:", response_code, response,) return generated_move = { "move": response.move, "ponder": "" } func _on_request_completed(result: int, response_code: int, headers: PackedStringArray, body: PackedByteArray): print("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^") var json = JSON.new() json.parse(body.get_string_from_utf8()) var response = json.get_data() # Will print the user agent string used by the HTTPRequest node (as recognized by httpbin.org). print(response) if result != HTTPRequest.RESULT_SUCCESS: print("HTTP Request failed") return if response.status != "ok": print("Server error:", response_code, json.parse(body.get_string_from_utf8()),) return