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