mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 16:42:44 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			333 lines
		
	
	
	
		
			9.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			333 lines
		
	
	
	
		
			9.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * 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 <AK/StringBuilder.h>
 | |
| 
 | |
| 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<String> fen;
 | |
|     if (tokens[1] != "startpos")
 | |
|         fen = tokens[1];
 | |
| 
 | |
|     Vector<Move> 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.appendf(" wtime %i", wtime.value());
 | |
|     if (btime.has_value())
 | |
|         builder.appendf(" btime %i", btime.value());
 | |
|     if (winc.has_value())
 | |
|         builder.appendf(" winc %i", winc.value());
 | |
|     if (binc.has_value())
 | |
|         builder.appendf(" binc %i", binc.value());
 | |
|     if (movestogo.has_value())
 | |
|         builder.appendf(" movestogo %i", movestogo.value());
 | |
|     if (depth.has_value())
 | |
|         builder.appendf(" depth %i", depth.value());
 | |
|     if (nodes.has_value())
 | |
|         builder.appendf(" nodes %i", nodes.value());
 | |
|     if (mate.has_value())
 | |
|         builder.appendf(" mate %i", mate.value());
 | |
|     if (movetime.has_value())
 | |
|         builder.appendf(" movetime %i", 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(const StringView& command)
 | |
| {
 | |
|     (void)command;
 | |
|     // FIXME: Implement this.
 | |
|     ASSERT_NOT_REACHED();
 | |
| }
 | |
| 
 | |
| String InfoCommand::to_string() const
 | |
| {
 | |
|     // FIXME: Implement this.
 | |
|     ASSERT_NOT_REACHED();
 | |
|     return "info";
 | |
| }
 | |
| 
 | |
| }
 | 
