/* * Copyright (c) 2020, the SerenityOS developers. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "UCICommand.h" #include namespace Chess::UCI { UCICommand UCICommand::from_string(const StringView& command) { auto tokens = command.split_view(' '); ASSERT(tokens[0] == "uci"); ASSERT(tokens.size() == 1); return UCICommand(); } String UCICommand::to_string() const { return "uci\n"; } DebugCommand DebugCommand::from_string(const StringView& command) { auto tokens = command.split_view(' '); ASSERT(tokens[0] == "debug"); ASSERT(tokens.size() == 2); if (tokens[1] == "on") return DebugCommand(Flag::On); if (tokens[1] == "off") return DebugCommand(Flag::On); ASSERT_NOT_REACHED(); } String DebugCommand::to_string() const { if (flag() == Flag::On) { return "debug on\n"; } else { return "debug off\n"; } } IsReadyCommand IsReadyCommand::from_string(const StringView& command) { auto tokens = command.split_view(' '); ASSERT(tokens[0] == "isready"); ASSERT(tokens.size() == 1); return IsReadyCommand(); } String IsReadyCommand::to_string() const { return "isready\n"; } SetOptionCommand SetOptionCommand::from_string(const StringView& command) { auto tokens = command.split_view(' '); ASSERT(tokens[0] == "setoption"); ASSERT(tokens[1] == "name"); if (tokens.size() == 3) { return SetOptionCommand(tokens[1]); } else if (tokens.size() == 4) { ASSERT(tokens[2] == "value"); return SetOptionCommand(tokens[1], tokens[3]); } ASSERT_NOT_REACHED(); } String SetOptionCommand::to_string() const { StringBuilder builder; builder.append("setoption name "); builder.append(name()); if (value().has_value()) { builder.append(" value "); builder.append(value().value()); } builder.append('\n'); return builder.build(); } PositionCommand PositionCommand::from_string(const StringView& command) { auto tokens = command.split_view(' '); ASSERT(tokens.size() >= 3); ASSERT(tokens[0] == "position"); ASSERT(tokens[2] == "moves"); Optional fen; if (tokens[1] != "startpos") fen = tokens[1]; Vector moves; for (size_t i = 3; i < tokens.size(); ++i) { moves.append(Move(tokens[i])); } return PositionCommand(fen, moves); } String PositionCommand::to_string() const { StringBuilder builder; builder.append("position "); if (fen().has_value()) { builder.append(fen().value()); } else { builder.append("startpos "); } builder.append("moves"); for (auto& move : moves()) { builder.append(' '); builder.append(move.to_long_algebraic()); } builder.append('\n'); return builder.build(); } GoCommand GoCommand::from_string(const StringView& command) { auto tokens = command.split_view(' '); ASSERT(tokens[0] == "go"); GoCommand go_command; for (size_t i = 1; i < tokens.size(); ++i) { if (tokens[i] == "searchmoves") { ASSERT_NOT_REACHED(); } else if (tokens[i] == "ponder") { go_command.ponder = true; } else if (tokens[i] == "wtime") { ASSERT(i++ < tokens.size()); go_command.wtime = tokens[i].to_int().value(); } else if (tokens[i] == "btime") { ASSERT(i++ < tokens.size()); go_command.btime = tokens[i].to_int().value(); } else if (tokens[i] == "winc") { ASSERT(i++ < tokens.size()); go_command.winc = tokens[i].to_int().value(); } else if (tokens[i] == "binc") { ASSERT(i++ < tokens.size()); go_command.binc = tokens[i].to_int().value(); } else if (tokens[i] == "movestogo") { ASSERT(i++ < tokens.size()); go_command.movestogo = tokens[i].to_int().value(); } else if (tokens[i] == "depth") { ASSERT(i++ < tokens.size()); go_command.depth = tokens[i].to_int().value(); } else if (tokens[i] == "nodes") { ASSERT(i++ < tokens.size()); go_command.nodes = tokens[i].to_int().value(); } else if (tokens[i] == "mate") { ASSERT(i++ < tokens.size()); go_command.mate = tokens[i].to_int().value(); } else if (tokens[i] == "movetime") { ASSERT(i++ < tokens.size()); go_command.movetime = tokens[i].to_int().value(); } else if (tokens[i] == "infinite") { go_command.infinite = true; } } return go_command; } String GoCommand::to_string() const { StringBuilder builder; builder.append("go"); if (searchmoves.has_value()) { builder.append(" searchmoves"); for (auto& move : searchmoves.value()) { builder.append(' '); builder.append(move.to_long_algebraic()); } } if (ponder) builder.append(" ponder"); if (wtime.has_value()) builder.appendff(" wtime {}", wtime.value()); if (btime.has_value()) builder.appendff(" btime {}", btime.value()); if (winc.has_value()) builder.appendff(" winc {}", winc.value()); if (binc.has_value()) builder.appendff(" binc {}", binc.value()); if (movestogo.has_value()) builder.appendff(" movestogo {}", movestogo.value()); if (depth.has_value()) builder.appendff(" depth {}", depth.value()); if (nodes.has_value()) builder.appendff(" nodes {}", nodes.value()); if (mate.has_value()) builder.appendff(" mate {}", mate.value()); if (movetime.has_value()) builder.appendff(" movetime {}", movetime.value()); if (infinite) builder.append(" infinite"); builder.append('\n'); return builder.build(); } StopCommand StopCommand::from_string(const StringView& command) { auto tokens = command.split_view(' '); ASSERT(tokens[0] == "stop"); ASSERT(tokens.size() == 1); return StopCommand(); } String StopCommand::to_string() const { return "stop\n"; } IdCommand IdCommand::from_string(const StringView& command) { auto tokens = command.split_view(' '); ASSERT(tokens[0] == "id"); StringBuilder value; for (size_t i = 2; i < tokens.size(); ++i) { if (i != 2) value.append(' '); value.append(tokens[i]); } if (tokens[1] == "name") { return IdCommand(Type::Name, value.build()); } else if (tokens[1] == "author") { return IdCommand(Type::Author, value.build()); } ASSERT_NOT_REACHED(); } String IdCommand::to_string() const { StringBuilder builder; builder.append("id "); if (field_type() == Type::Name) { builder.append("name "); } else { builder.append("author "); } builder.append(value()); builder.append('\n'); return builder.build(); } UCIOkCommand UCIOkCommand::from_string(const StringView& command) { auto tokens = command.split_view(' '); ASSERT(tokens[0] == "uciok"); ASSERT(tokens.size() == 1); return UCIOkCommand(); } String UCIOkCommand::to_string() const { return "uciok\n"; } ReadyOkCommand ReadyOkCommand::from_string(const StringView& command) { auto tokens = command.split_view(' '); ASSERT(tokens[0] == "readyok"); ASSERT(tokens.size() == 1); return ReadyOkCommand(); } String ReadyOkCommand::to_string() const { return "readyok\n"; } BestMoveCommand BestMoveCommand::from_string(const StringView& command) { auto tokens = command.split_view(' '); ASSERT(tokens[0] == "bestmove"); ASSERT(tokens.size() == 2); return BestMoveCommand(Move(tokens[1])); } String BestMoveCommand::to_string() const { StringBuilder builder; builder.append("bestmove "); builder.append(move().to_long_algebraic()); builder.append('\n'); return builder.build(); } InfoCommand InfoCommand::from_string([[maybe_unused]] const StringView& command) { // FIXME: Implement this. ASSERT_NOT_REACHED(); } String InfoCommand::to_string() const { // FIXME: Implement this. ASSERT_NOT_REACHED(); return "info"; } }