Code source de crocrodile.uci

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Crocrodile UCI.

Created by @Virinas-code.
"""
from __future__ import annotations

import copy
import os
import sys
import time
from typing import Optional

import chess
import crocrodile.engine
from crocrodile.engine import evaluate

# ====== IDLE ======
# import os
# os.chdir("../")
# ==== END IDLE ====

print(os.getcwd())
print(sys.path)

NoneType = type(None)


[docs]class UCI: """Base class for Crocrodile UCI.""" def __init__(self): """Initialize UCI.""" self.name = "Crocrodile" self.author = "Created by Virinas-code / Co-developed by ZeBox / " self.author += "Tested by PerleShetland" # default true when NN complete self.options: dict[str, str] = {"Hash": "16", "NeuralNetwork": "true", "OwnBook": "false", "SyzygyOnline": "false", "SyzygyPath": "", "HashPath": ""} self.debug_mode = False self.board = chess.Board() self.positionned = False self.engine = crocrodile.engine.EngineBase(self.name, self.author) print(self.name, self.author.lower())
[docs] def run(self): """Run UCI input.""" inner = "" while inner != "quit": inner = input() self.uci_parse(inner)
[docs] def uci_parse(self, string: str) -> NoneType: """ Parse UCI command. :param string: UCI command :type string: str :return: Nothing :rtype: NoneType """ self.info("Received " + string) args = [value for value in string.split(" ") if value != ""] if string != "": command = args[0] else: command = "" if command == "uci": self.uci() elif command == "isready": print("readyok") elif command == "debug" and len(args) > 1: self.debug(args[1]) elif command == "quit": pass elif command == "register": print("No support for register") elif command == "ucinewgame": self.new_game() elif command == "go" and len(args) > 1: self.go(args[1:]) elif command == "position" and len(args) > 1: self.position(args[1:]) elif command == "setoption" and len(args) > 1: self.set_option(args[1:]) elif command == "crocrodile.display" and self.debug_mode is True: print(self.board) elif command == "crocrodile.bruh" and self.debug_mode is True: print("Yes BRUH.") print("https://lichess.org/83hsKBy2/black#2") elif len(args) == 0: pass elif len(args) == 1: print("Unknown command: {0} with no arguments".format(string)) else: print("Unknown command: {0}".format(string))
[docs] def info(self, msg: str) -> NoneType: """ Print debug information. :param msg: Message to display. :type msg: str :return: Nothing :rtype: NoneType """ if self.debug_mode: print("info string", msg)
[docs] def uci(self) -> NoneType: """ Uci UCI command. :return: Nothing :rtype: NoneType """ print("id name {0}".format(self.name)) print("id author {0}".format(self.author)) print() print("option name Hash type spin default 16 min 0 max 65536") print("option name NeuralNetwork type check default true") print("option name OwnBook type check default false") print("option name SyzygyOnline type check default false") print("option name SyzygyPath type string default <empty>") print("option name HashPath type string default <empty>") print("uciok")
[docs] def debug(self, boolean: str) -> NoneType: """ Enable or disable debug mode. :param boolean: 'on' or 'off' :type boolean: str :return: Nothing :rtype: NoneType """ if boolean == "on": self.debug_mode = True elif boolean == "off": self.debug_mode = False else: print("Unknown debug mode: {0}".format(boolean))
[docs] def set_option(self, args) -> None: """ Setoption UCI command. Configure Crocrodile. """ if len(args) > 3 and args[0] == "name" and args[2] == "value": if args[1] in self.options: self.options[args[1]] = " ".join(args[3:]) self.engine.hashlimit = int(self.options["Hash"]) if self.options["NeuralNetwork"] == "true": self.engine.use_nn = True else: self.engine.use_nn = False if self.options["OwnBook"] == "true": self.engine.own_book = True else: self.engine.own_book = False if self.options["SyzygyOnline"] == "true": self.engine.syzygy_online = True else: self.engine.syzygy_online = False if self.options["SyzygyPath"] != "": self.engine.syzygy_tb: chess.syzygy.Table = chess.syzygy.open_tablebase(self.options["SyzygyPath"]) if self.options["HashPath"] != "": self.engine.hashpath = self.options["HashPath"] if args[1] == "HashPath": self.engine.tb_update() else: print("Unknow option:", args[1]) else: print("Unknow syntax: setoption", " ".join(args))
[docs] def go(self, args: list) -> None: """ Go UCI command. Start calculating. """ depth: Optional[int] = 256 wtime: Optional[int] = None btime: Optional[int] = None movetime: bool | int = False for indice, element in enumerate(args): if element == "depth": try: depth = int(args[indice + 1]) except ValueError: print("Invalid depth.", file=sys.stderr) if element == "wtime": try: wtime = int(args[indice + 1]) except ValueError: print("Invalid wtime.", file=sys.stderr) if element == "btime": try: btime = int(args[indice + 1]) except ValueError: print("Invalid btime.", file=sys.stderr) if element == "movetime": try: movetime = int(args[indice + 1]) except ValueError: print("Invalid movetime.", file=sys.stderr) if depth != 256: if self.board.turn and wtime: limit = ((wtime / 1000) / 40) + time.time() elif (not self.board.turn) and btime: limit = ((btime / 1000) / 40) + time.time() elif movetime: limit = movetime / 1000 else: limit = float("inf") else: limit = float("inf") print(limit) evaluation, best_move = self.engine.search(self.board, 1, self.board.turn, float('inf')) last_best_move = copy.copy(best_move.uci()) for search_depth in range(2, depth + 1): evaluation, best_move = self.engine.search( self.board, search_depth, self.board.turn, limit ) if evaluation == float("inf"): break else: last_best_move = copy.copy(best_move.uci()) print(f"bestmove {last_best_move}")
[docs] def position(self, args: list) -> None: """ Position UCI command. Change current position. """ next_arg = 0 if args[0] == "startpos": self.board = chess.Board() self.positionned = True next_arg = 1 elif args[0] == "fen" and len(args) > 6: self.board = chess.Board(" ".join(args[1:7])) self.positionned = True next_arg = 7 else: print("Unknow syntax: position", " ".join(args)) if next_arg and len(args) > next_arg + 1: self.info(args[next_arg]) self.info(args[next_arg + 1 :]) for uci_move in args[next_arg + 1 :]: try: self.board.push(chess.Move.from_uci(uci_move)) except ValueError: print("Unknow UCI move:", uci_move)
def new_game(self): self.board = chess.Board() self.positionned = False
if __name__ == "__main__": uci = UCI() uci.run()