stockfish for godot
add info parsing
bendn 2022-10-04
parent f90c619 · commit 39156c5
-rw-r--r--addons/stockfish.gd/package.json2
-rw-r--r--addons/stockfish.gd/stockfish_wrapper.gd62
2 files changed, 59 insertions, 5 deletions
diff --git a/addons/stockfish.gd/package.json b/addons/stockfish.gd/package.json
index 44bc690..75d12a8 100644
--- a/addons/stockfish.gd/package.json
+++ b/addons/stockfish.gd/package.json
@@ -1,6 +1,6 @@
{
"name": "@bendn/stockfish.gd",
- "version": "2.0.0",
+ "version": "2.1.2",
"description": "godot stockfish",
"main": "stockfish_loader.gd",
"scripts": {
diff --git a/addons/stockfish.gd/stockfish_wrapper.gd b/addons/stockfish.gd/stockfish_wrapper.gd
index 0c94096..5591495 100644
--- a/addons/stockfish.gd/stockfish_wrapper.gd
+++ b/addons/stockfish.gd/stockfish_wrapper.gd
@@ -1,4 +1,3 @@
-
class_name Stockfish
extends Reference
@@ -12,6 +11,7 @@ signal engine_ready
signal line_recieved
signal load_failed
signal bestmove
+signal info
func send_line(cmd: String) -> void:
if not engine_ready:
@@ -28,7 +28,8 @@ func _init() -> void:
connect("line_recieved", self, "_line_recieved")
connect("engine_ready", self, "_engine_ready")
-func dbg_prints(a1 := "", a2 := "") -> void:
+
+func dbg_prints(a1 = "", a2 = "") -> void:
if OS.is_debug_build():
prints(a1, a2)
@@ -54,12 +55,16 @@ func _position():
func _line_recieved(line: String) -> void:
if line.begins_with("info "):
- dbg_prints("(stockfish)", line)
+ emit_signal("info", parse_info(line.split(" ", true, 1)[1]))
elif searching_bestmove and line.begins_with("bestmove "):
searching_bestmove = false
parse_bestmove(line.split(" ", true, 1)[1])
- elif (sent_isready) && (line == "readyok" || line.begins_with("Stockfish [commit: ")):
+ elif (
+ (sent_isready)
+ && (line == "readyok" || (OS.has_feature("JavaScript") && line.begins_with("Stockfish [commit: ")))
+ ):
sent_isready = false
+ print("ENGINE READY")
emit_signal("engine_ready")
else:
push_error("unexpected output: %s" % line)
@@ -73,6 +78,55 @@ func parse_bestmove(args: String) -> void:
return
emit_signal("bestmove", null)
+
+# given a string like
+# depth 18 seldepth 21 multipv 1 score cp 74 nodes 351592 nps 267167 hashfull 147 tbhits 0 time 1316 pv e2e4 c7c5 g1f3 d7d6 d2d4 c5d4 f3d4 g8f6 b1c3 e7e5 d4b3 c8e6 c1g5 f8e7 f1b5 b8c6 g5f6 e7f6
+# it will produce a dictionary:
+# ```json
+# {
+# "depth": 18,
+# "seldepth": 21,
+# "multipv": 1,
+# "score": { "cp": 74 },
+# "nodes": 351592,
+# "nps": 267167,
+# "hashfull": 147,
+# "tbhits": 0,
+# "time":1.316,
+# "pv": ["e2e4", "c7c5", "g1f3", "d7d6", "d2d4", "c5d4", "f3d4", "g8f6", "b1c3", "e7e5", "d4b3", "c8e6", "c1g5", "f8e7", "f1b5", "b8c6", "g5f6", "e7f6"]
+# }
+# ```
+func parse_info(args: String) -> Dictionary:
+ var tokens := Array(args.split(" "))
+ var info := {}
+
+ while !tokens.empty():
+ var parameter: String = tokens.pop_front()
+
+ if parameter == "string":
+ info["string"] = " ".join(tokens)
+ break
+ elif parameter in ["depth", "seldepth", "nodes", "multipv", "currmovenumber", "hashfull", "nps", "tbhits"]:
+ info[parameter] = int(tokens.pop_front()) # type: ignore
+ elif parameter == "time":
+ info["time"] = int(tokens.pop_front()) / 1000.0
+ elif parameter == "score":
+ # cp 74 ->
+ # kind: cp
+ # value: 74
+ var kind: String = tokens.pop_front()
+ var value := int(tokens.pop_front())
+ if kind == "cp":
+ info["score"] = {cp = value}
+ elif kind == "mate":
+ info["score"] = {mate = value}
+ elif parameter == "currmove":
+ info["currmove"] = game.__move_to_san(game.__move_from_uci(tokens.pop_front()))
+ elif parameter == "pv":
+ var pv: PoolStringArray = tokens.slice(0, len(tokens))
+ info["pv"] = pv
+ return info
+
func go(depth: int = 15) -> void:
if searching_bestmove:
push_error("already searching. did you mean `stop()`?")