00001
00002
00003
00004
00005 #include "SgSystem.h"
00006 #include "GoGtpCommandUtil.h"
00007
00008 #include <limits>
00009 #include "GoBoard.h"
00010 #include "GtpEngine.h"
00011 #include "SgDebug.h"
00012 #include "SgPointArray.h"
00013
00014 using namespace std;
00015 using SgPointUtil::Pt;
00016
00017
00018
00019 namespace {
00020
00021
00022
00023 bool LessAnalyzeLabel(const string& line1, const string& line2)
00024 {
00025
00026 size_t pos1 = line1.find("/");
00027 size_t pos2 = line2.find("/");
00028 if (pos1 == string::npos || pos2 == string::npos)
00029 {
00030
00031 SG_ASSERT(false);
00032 return true;
00033 }
00034 return (line1.substr(pos1) < line2.substr(pos2));
00035 }
00036
00037 }
00038
00039
00040
00041 SgEmptyBlackWhite GoGtpCommandUtil::EmptyBlackWhiteArg(const GtpCommand& cmd,
00042 std::size_t number)
00043 {
00044 string value = cmd.ArgToLower(number);
00045 if (value == "e" || value == "empty")
00046 return SG_EMPTY;
00047 if (value == "b" || value == "black")
00048 return SG_BLACK;
00049 if (value == "w" || value == "white")
00050 return SG_WHITE;
00051 throw GtpFailure() << "argument " << (number + 1)
00052 << " must be black, white or empty";
00053 }
00054
00055 SgBlackWhite GoGtpCommandUtil::BlackWhiteArg(const GtpCommand& cmd,
00056 std::size_t number)
00057 {
00058 string value = cmd.ArgToLower(number);
00059 if (value == "b" || value == "black")
00060 return SG_BLACK;
00061 if (value == "w" || value == "white")
00062 return SG_WHITE;
00063 throw GtpFailure() << "argument " << (number + 1)
00064 << " must be black or white";
00065 }
00066
00067 SgPoint GoGtpCommandUtil::EmptyPointArg(const GtpCommand& cmd,
00068 std::size_t number,
00069 const GoBoard& board)
00070 {
00071 SgPoint point = PointArg(cmd, number, board);
00072 if (board.GetColor(point) != SG_EMPTY)
00073 throw GtpFailure() << "point " << SgWritePoint(point)
00074 << " must be empty";
00075 return point;
00076 }
00077
00078 SgVector<SgPoint> GoGtpCommandUtil::GetHandicapStones(int size, int n)
00079 {
00080 SgVector<SgPoint> stones;
00081 if (n == 0)
00082 return stones;
00083
00084
00085 if (size > SG_MAX_SIZE || size > 25)
00086 throw GtpFailure("no standard handicap locations defined");
00087 int line1 = -1;
00088 int line2 = -1;
00089 int line3 = -1;
00090 if (size >= 13)
00091 {
00092 line1 = 4;
00093 line3 = size - 3;
00094 }
00095 else if (size >= 7)
00096 {
00097 line1 = 3;
00098 line3 = size - 2;
00099 }
00100 if (size >= 9 && size % 2 != 0)
00101 line2 = size / 2 + 1;
00102 if (line1 < 0 || n == 1 || n > 9 || (n > 4 && line2 < 0))
00103 throw GtpFailure("no standard handicap locations defined");
00104 if (n >= 1)
00105 stones.PushBack(Pt(line1, line1));
00106 if (n >= 2)
00107 stones.PushBack(Pt(line3, line3));
00108 if (n >= 3)
00109 stones.PushBack(Pt(line1, line3));
00110 if (n >= 4)
00111 stones.PushBack(Pt(line3, line1));
00112 if (n >= 5 && n % 2 != 0)
00113 {
00114 stones.PushBack(Pt(line2, line2));
00115 --n;
00116 }
00117 if (n >= 5)
00118 stones.PushBack(Pt(line1, line2));
00119 if (n >= 6)
00120 stones.PushBack(Pt(line3, line2));
00121 if (n >= 7)
00122 stones.PushBack(Pt(line2, line1));
00123 if (n >= 8)
00124 stones.PushBack(Pt(line2, line3));
00125 return stones;
00126 }
00127
00128 SgMove GoGtpCommandUtil::MoveArg(const GtpCommand& cmd, std::size_t number,
00129 const GoBoard& board)
00130 {
00131 if (cmd.ArgToLower(number) == "pass")
00132 return SG_PASS;
00133 return PointArg(cmd, number, board);
00134 }
00135
00136 void GoGtpCommandUtil::ParseMultiStoneArgument(GtpCommand& cmd,
00137 const GoBoard& board,
00138 SgBlackWhite& toPlay,
00139 SgBlackWhite& defender,
00140 SgVector<SgPoint>& crucial)
00141 {
00142 toPlay = GoGtpCommandUtil::BlackWhiteArg(cmd, 0);
00143 SgDebug() << "Set " << SgBW(toPlay) << " to play\n";
00144 SgPoint point = GoGtpCommandUtil::StoneArg(cmd, 1, board);
00145 defender = board.GetColor(point);
00146 SG_ASSERT(defender == SG_BLACK || defender == SG_WHITE);
00147 crucial.PushBack(point);
00148 for (size_t i = 2; i < cmd.NuArg(); ++i)
00149 {
00150 SgPoint p = GoGtpCommandUtil::StoneArg(cmd, i, board);
00151 if (board.GetColor(p) != defender)
00152 throw GtpFailure("Crucial stones must be same color");
00153 else
00154 crucial.PushBack(p);
00155 }
00156 }
00157
00158 SgPoint GoGtpCommandUtil::PointArg(const GtpCommand& cmd,
00159 const GoBoard& board)
00160 {
00161 cmd.CheckNuArg(1);
00162 return PointArg(cmd, 0, board);
00163 }
00164
00165 SgPoint GoGtpCommandUtil::PointArg(const GtpCommand& cmd, std::size_t number,
00166 const GoBoard& board)
00167 {
00168 string arg = cmd.Arg(number);
00169 istringstream in(arg);
00170 SgPoint p;
00171 in >> SgReadPoint(p);
00172 if (! in)
00173 throw GtpFailure() << "invalid point " << arg;
00174 if (p == SG_PASS)
00175 throw GtpFailure("expected point, not pass");
00176 if (SgMoveUtil::IsCouponMove(p))
00177 throw GtpFailure("expected point, not coupon move");
00178 if (! board.IsValidPoint(p))
00179 throw GtpFailure() << "point outside board " << arg;
00180 return p;
00181 }
00182
00183 SgVector<SgPoint> GoGtpCommandUtil::PointListArg(const GtpCommand& cmd,
00184 std::size_t number,
00185 const GoBoard& board)
00186 {
00187 SgVector<SgPoint> result;
00188 for (size_t i = number; i < cmd.NuArg(); ++i)
00189 result.PushBack(PointArg(cmd, i, board));
00190 return result;
00191 }
00192
00193 void GoGtpCommandUtil::RespondNumberArray(GtpCommand& cmd,
00194 const SgPointArray<int>& array,
00195 int scale, const GoBoard& board)
00196 {
00197 SgPointArray<string> result("\"\"");
00198 for (GoBoard::Iterator it(board); it; ++it)
00199 {
00200 SgPoint p(*it);
00201 if (array[p] != numeric_limits<int>::min())
00202 {
00203 ostringstream out;
00204 out << (array[p] / scale);
00205 result[p] = out.str();
00206 }
00207 }
00208 cmd << '\n' << SgWritePointArray<string>(result, board.Size());
00209 }
00210
00211 string GoGtpCommandUtil::SortResponseAnalyzeCommands(const string& response)
00212 {
00213 vector<string> allLines;
00214 istringstream in(response);
00215 string line;
00216 while (getline(in, line))
00217 allLines.push_back(line);
00218 sort(allLines.begin(), allLines.end(), LessAnalyzeLabel);
00219 ostringstream sortedResponse;
00220 for (vector<string>::const_iterator it = allLines.begin();
00221 it != allLines.end(); ++it)
00222 sortedResponse << *it << '\n';
00223 return sortedResponse.str();
00224 }
00225
00226 SgPoint GoGtpCommandUtil::StoneArg(const GtpCommand& cmd, std::size_t number,
00227 const GoBoard& board)
00228 {
00229 SgPoint point = PointArg(cmd, number, board);
00230 if (board.GetColor(point) == SG_EMPTY)
00231 throw GtpFailure() << "point " << SgWritePoint(point)
00232 << " must be occupied";
00233 return point;
00234 }
00235
00236
00237