import "dart:async"; import "dart:collection"; import "dart:convert"; import "dart:io"; import "package:omnichess/classes/best_move_searcher.dart"; import "package:omnichess/classes/position.dart"; import "package:omnichess/constants/piece.dart"; class Omnichess { BestMoveSearcher bestMoveSearcher = BestMoveSearcher(); String positionCommand = "startpos"; String? bestMove; bool debug = false; Omnichess(); void _positionCommand(Queue inputComponents) { positionCommand = inputComponents.join(" "); } Future _goCommand(Queue inputComponents) async { int? moveTime; while (inputComponents.isNotEmpty) { final String inputComponent = inputComponents.removeFirst(); if ("movetime" == inputComponent) { moveTime = int.tryParse(inputComponents.firstOrNull ?? ""); } } final Position position = Position.fromPositionCommand(positionCommand); final String? bestMove = await bestMoveSearcher.search(position, moveTime); print("bestmove ${bestMove ?? "(none)"}"); } Future _stopCommand() async { await bestMoveSearcher.stop(); } Future elaborate(String line) async { final Queue inputComponents = Queue.from(line.split(" ")); final String command = inputComponents.removeFirst(); if (command == "uci") { print("id name Omnichess"); print("id author Dany Thach"); print("uciok"); return true; } if (command == "debug") { debug = "on" == inputComponents.first; return true; } if (command == "isready") { print("readyok"); return true; } if (command == "ucinewgame") { positionCommand = "startpos"; return true; } if (command == "position") { _positionCommand(inputComponents); return true; } if (command == "go") { await _goCommand(inputComponents); return true; } if (command == "stop") { await _stopCommand(); return true; } if (command == "quit") { return false; } return true; } void debugPrintPosition() { final Position position = Position.fromPositionCommand(positionCommand); for (int i = 0; i < position.board.length; i++) { if (i % 8 == 0) { stdout.write("info string "); } stdout.write(Piece.fenCharacterByPiece[position.board[i]]); if (i % 8 == 7) { stdout.writeln(); } } print(position.isWhiteTurn ? "info string white to move" : "info string black to move"); if (position.canWhiteCastleKingside) { print("info string white can castle kingside"); } if (position.canWhiteCastleQueenside) { print("info string white can castle queenside"); } if (position.canBlackCastleKingside) { print("info string black can castle kingside"); } if (position.canBlackCastleQueenside) { print("info string black can castle queenside"); } if (null != position.enPassantTargetSquare) { print("info string en passant possible on ${position.enPassantTargetSquareAlgebraic}"); } print("info string halfmove clock ${position.halfmoveClock}"); print("info string fullmove number ${position.fullmoveNumber}"); print("info string position fen ${position.fen}"); } void loop() async { // final DateTime now = DateTime.now(); // final String logName = "${now.year}" // "${now.month.toString().padLeft(2, "0")}" // "${now.day.toString().padLeft(2, "0")}" // "-" // "${now.hour.toString().padLeft(2, "0")}" // "${now.minute.toString().padLeft(2, "0")}" // "${now.second.toString().padLeft(2, "0")}" // "${now.millisecond.toString().padLeft(3, "0")}" // ".log"; // final File log = File("logs/$logName"); // if (!log.existsSync()) { // log.createSync(); // } late StreamSubscription inputSubscription; inputSubscription = stdin .transform(utf8.decoder) .transform(LineSplitter()) .listen((String line) async { // log.writeAsStringSync("$line\n", mode: FileMode.append); final String input = line.trim(); final bool keepGoing = await elaborate(input); if (!keepGoing) { await inputSubscription.cancel(); } if (debug) { debugPrintPosition(); } }); await inputSubscription.asFuture(); } }