00001 //---------------------------------------------------------------------------- 00002 /** @file SgProp.cpp 00003 See SgProp.h. 00004 00005 Implementation details: 00006 00007 A property list is simply kept as a list. 00008 Any special characteristics of the 00009 property list are enforced when adding new items to the list. 00010 */ 00011 //---------------------------------------------------------------------------- 00012 00013 #include "SgSystem.h" 00014 #include "SgProp.h" 00015 00016 #include <iomanip> 00017 #include <sstream> 00018 #include "SgRect.h" 00019 #include "SgUtil.h" 00020 #include "SgVector.h" 00021 00022 using namespace std; 00023 using SgPointUtil::InBoardRange; 00024 using SgPropUtil::PointToSgfString; 00025 using SgPropUtil::SgfStringToPoint; 00026 using SgPropUtil::EscapeSpecialCharacters; 00027 using SgUtil::InRange; 00028 00029 //---------------------------------------------------------------------------- 00030 00031 SgPropPointFmt SgPropUtil::GetPointFmt(int gameNumber) 00032 { 00033 switch (gameNumber) 00034 { 00035 case 2: // Othello 00036 case 11: // Hex 00037 return SG_PROPPOINTFMT_HEX; 00038 default: 00039 return SG_PROPPOINTFMT_GO; 00040 } 00041 } 00042 00043 string SgPropUtil::PointToSgfString(SgMove p, int boardSize, 00044 SgPropPointFmt fmt, int fileFormat) 00045 { 00046 SG_ASSERT(boardSize >= SG_MIN_SIZE && boardSize <= SG_MAX_SIZE); 00047 SG_ASSERT(p != SG_NULLMOVE); 00048 ostringstream out; 00049 switch (fmt) 00050 { 00051 case SG_PROPPOINTFMT_GO: 00052 { 00053 if (p == SG_PASS) 00054 { 00055 if (fileFormat < 4) 00056 out << "tt"; 00057 // Pass is empty string in FF[4] 00058 } 00059 else 00060 { 00061 int col = SgPointUtil::Col(p); 00062 int row = boardSize - SgPointUtil::Row(p) + 1; 00063 SG_ASSERT(row > 0); 00064 out << static_cast<char>('a' + col - 1) 00065 << static_cast<char>('a' + row - 1); 00066 } 00067 } 00068 break; 00069 case SG_PROPPOINTFMT_HEX: 00070 { 00071 SG_ASSERT(p != SG_PASS); 00072 int col = SgPointUtil::Col(p); 00073 int row = boardSize - SgPointUtil::Row(p) + 1; 00074 out << static_cast<char>('a' + col - 1) << row; 00075 } 00076 break; 00077 default: 00078 SG_ASSERT(false); 00079 } 00080 return out.str(); 00081 } 00082 00083 string SgPropUtil::EscapeSpecialCharacters(const string& s, bool escapeColon) 00084 { 00085 ostringstream buffer; 00086 for (size_t i = 0; i < s.size(); ++i) 00087 { 00088 char c = s[i]; 00089 if (c == ']' || c =='\\' || (c == ':' && escapeColon)) 00090 buffer << '\\' << c; 00091 else if (c == '\r' || c == '\t') 00092 buffer << ' '; 00093 else 00094 buffer << c; 00095 } 00096 return buffer.str(); 00097 } 00098 00099 SgMove SgPropUtil::SgfStringToPoint(const string& s, int boardSize, 00100 SgPropPointFmt fmt) 00101 { 00102 SG_ASSERT(boardSize >= SG_MIN_SIZE && boardSize <= SG_MAX_SIZE); 00103 SgPoint p = SG_NULLMOVE; 00104 switch (fmt) 00105 { 00106 case SG_PROPPOINTFMT_GO: 00107 { 00108 if (s.size() == 2 00109 && 'a' <= s[0] && s[0] <= 's' 00110 && 'a' <= s[1] && s[1] <= 's') 00111 { 00112 int col = s[0] - 'a' + 1; 00113 int row = s[1] - 'a' + 1; 00114 p = SgPointUtil::Pt(col, boardSize - row + 1); 00115 } 00116 else if (s.empty() // new FF[4] definition 00117 || (s.size() == 2 && s[0] == 't' && s[1] == 't')) 00118 p = SG_PASS; 00119 } 00120 break; 00121 case SG_PROPPOINTFMT_HEX: 00122 { 00123 if (s.size() >= 2 && s.size() <= 3) 00124 { 00125 int col = s[0] - 'a' + 1; 00126 int row = s[1] - '1' + 1; 00127 if (s.size() == 3) 00128 row = row * 10 + (s[2] - '1' + 1); 00129 if (InRange(col, 1, boardSize) && InRange(row, 1, boardSize)) 00130 p = SgPointUtil::Pt(col, boardSize - row + 1); 00131 } 00132 } 00133 break; 00134 default: 00135 SG_ASSERT(false); 00136 } 00137 return p; 00138 } 00139 00140 //---------------------------------------------------------------------------- 00141 00142 SgPropList::SgPropList() 00143 : m_list() 00144 { } 00145 00146 SgPropList::~SgPropList() 00147 { 00148 Clear(); 00149 } 00150 00151 void SgPropList::Clear() 00152 { 00153 for (SgVectorIteratorOf<SgProp> iter(m_list); iter; ++iter) 00154 delete *iter; 00155 m_list.Clear(); 00156 } 00157 00158 SgProp* SgPropList::Get(SgPropID id) const 00159 { 00160 for (SgVectorIteratorOf<SgProp> iter(m_list); iter; ++iter) 00161 { 00162 SgProp* prop = *iter; 00163 if (prop->MatchesID(id)) 00164 return prop; 00165 } 00166 return 0; 00167 } 00168 00169 void SgPropList::Add(const SgProp* prop) 00170 { 00171 SG_ASSERT(prop); 00172 00173 // First remove any property of that type, then add new property. 00174 // Enforce constraint that there can be only one move annotation per node. 00175 // Can have multiple unknown properties per node. 00176 if (prop->ID() != SG_PROP_UNKNOWN) 00177 { 00178 if (prop->Flag(SG_PROPCLASS_ANNO_MOVE)) 00179 Remove(SG_PROP_MOVE_ANNO, prop); 00180 else if (prop->Flag(SG_PROPCLASS_ANNO_POS)) 00181 Remove(SG_PROP_POS_ANNO, prop); 00182 else if (prop->Flag(SG_PROPCLASS_MOVE)) 00183 Remove(SG_PROP_MOVE, prop); 00184 else 00185 Remove(prop->ID(), prop); 00186 } 00187 m_list.Include(prop); 00188 } 00189 00190 void SgPropList::MoveToFront(SgPropID id) 00191 { 00192 SgProp* prop = Get(id); 00193 if (prop && m_list.Exclude(prop)) 00194 m_list.PushFront(prop); 00195 } 00196 00197 bool SgPropList::Remove(const SgProp* prop) 00198 { 00199 if (prop) 00200 delete prop; 00201 return m_list.Exclude(const_cast<SgProp*>(prop)); 00202 } 00203 00204 void SgPropList::Remove(SgPropID id, const SgProp* protectProp) 00205 { 00206 SgVectorOf<SgProp> toBeDeleted; 00207 for (SgVectorIteratorOf<SgProp> iter(m_list); iter; ++iter) 00208 { 00209 SgProp* prop = *iter; 00210 if (prop != protectProp && prop->MatchesID(id)) 00211 { 00212 // Can't exclude while iterating over same list. 00213 toBeDeleted.PushBack(prop); 00214 delete prop; 00215 } 00216 } 00217 m_list.Exclude(toBeDeleted); 00218 } 00219 00220 bool SgPropList::AppendMoveAnnotation(string* s) const 00221 { 00222 SgProp* moveAnnoProp = Get(SG_PROP_MOVE_ANNO); 00223 if (! moveAnnoProp) 00224 return false; 00225 SgPropInt* intProp = dynamic_cast<SgPropInt*>(moveAnnoProp); 00226 int value = intProp ? intProp->Value() : 1; 00227 SgPropID id = moveAnnoProp->ID(); 00228 if (id == SG_PROP_GOOD_MOVE) 00229 *s += (value == 2) ? "!!" : "!"; 00230 else if (id == SG_PROP_BAD_MOVE) 00231 *s += (value == 2) ? "??" : "?"; 00232 else if (id == SG_PROP_INTERESTING) 00233 *s += "!?"; 00234 else if (id == SG_PROP_DOUBTFUL) 00235 *s += "?!"; 00236 return true; 00237 } 00238 00239 SgProp* SgPropList::GetPropContainingText(const string& findText) const 00240 { 00241 for (SgVectorIteratorOf<SgProp> iter(m_list); iter; ++iter) 00242 { 00243 SgProp* prop = *iter; 00244 if (prop->ContainsText(findText)) 00245 return prop; 00246 } 00247 return 0; 00248 } 00249 00250 //---------------------------------------------------------------------------- 00251 00252 //--- general 00253 SgPropID SG_PROP_NONE = 0; 00254 SgPropID SG_PROP_UNKNOWN = 0; 00255 00256 //--- moves 00257 SgPropID SG_PROP_MOVE = 0; 00258 SgPropID SG_PROP_MOVE_BLACK = 0; 00259 SgPropID SG_PROP_MOVE_WHITE = 0; 00260 00261 //--- board edits 00262 SgPropID SG_PROP_ADD_BLACK = 0; 00263 SgPropID SG_PROP_ADD_WHITE = 0; 00264 SgPropID SG_PROP_ADD_EMPTY = 0; 00265 SgPropID SG_PROP_PLAYER = 0; 00266 00267 //--- value and territory 00268 SgPropID SG_PROP_VALUE = 0; 00269 SgPropID SG_PROP_TERR_BLACK = 0; 00270 SgPropID SG_PROP_TERR_WHITE = 0; 00271 00272 //--- marks drawn on the board 00273 SgPropID SG_PROP_MARKS = 0; 00274 SgPropID SG_PROP_SELECT = 0; 00275 SgPropID SG_PROP_MARKED = 0; 00276 SgPropID SG_PROP_TRIANGLE = 0; 00277 SgPropID SG_PROP_SQUARE = 0; 00278 SgPropID SG_PROP_DIAMOND = 0; 00279 SgPropID SG_PROP_CIRCLE = 0; 00280 SgPropID SG_PROP_DIMMED = 0; 00281 SgPropID SG_PROP_LABEL = 0; 00282 00283 //--- time control 00284 SgPropID SG_PROP_TIMES = 0; 00285 SgPropID SG_PROP_TIME_BLACK = 0; 00286 SgPropID SG_PROP_TIME_WHITE = 0; 00287 SgPropID SG_PROP_OT_NU_MOVES = 0; 00288 SgPropID SG_PROP_OT_PERIOD = 0; 00289 SgPropID SG_PROP_OT_BLACK = 0; 00290 SgPropID SG_PROP_OT_WHITE = 0; 00291 SgPropID SG_PROP_LOSE_TIME = 0; 00292 SgPropID SG_PROP_OVERHEAD = 0; 00293 00294 //--- statistics 00295 SgPropID SG_PROP_COUNT = 0; 00296 SgPropID SG_PROP_TIME_USED = 0; 00297 SgPropID SG_PROP_NUM_NODES = 0; 00298 SgPropID SG_PROP_NUM_LEAFS = 0; 00299 SgPropID SG_PROP_MAX_DEPTH = 0; 00300 SgPropID SG_PROP_DEPTH = 0; 00301 SgPropID SG_PROP_PART_DEPTH = 0; 00302 SgPropID SG_PROP_EVAL = 0; 00303 SgPropID SG_PROP_EXPECTED = 0; 00304 00305 //--- root props 00306 SgPropID SG_PROP_FORMAT = 0; 00307 SgPropID SG_PROP_SIZE = 0; 00308 SgPropID SG_PROP_GAME = 0; 00309 SgPropID SG_PROP_SPEC_BLACK = 0; 00310 SgPropID SG_PROP_SPEC_WHITE = 0; 00311 SgPropID SG_PROP_CHINESE = 0; 00312 SgPropID SG_PROP_APPLIC = 0; 00313 00314 //--- annotations 00315 SgPropID SG_PROP_ANNOTATE = 0; 00316 SgPropID SG_PROP_COMMENT = 0; 00317 SgPropID SG_PROP_NAME = 0; 00318 SgPropID SG_PROP_CHECK = 0; 00319 SgPropID SG_PROP_SIGMA = 0; 00320 SgPropID SG_PROP_HOTSPOT = 0; 00321 SgPropID SG_PROP_FIGURE = 0; 00322 00323 //--- position annotations 00324 SgPropID SG_PROP_POS_ANNO = 0; 00325 SgPropID SG_PROP_GOOD_BLACK = 0; 00326 SgPropID SG_PROP_GOOD_WHITE = 0; 00327 SgPropID SG_PROP_EVEN_POS = 0; 00328 SgPropID SG_PROP_UNCLEAR = 0; 00329 00330 //--- move annotations 00331 SgPropID SG_PROP_MOVE_ANNO = 0; 00332 SgPropID SG_PROP_GOOD_MOVE = 0; 00333 SgPropID SG_PROP_BAD_MOVE = 0; 00334 SgPropID SG_PROP_INTERESTING = 0; 00335 SgPropID SG_PROP_DOUBTFUL = 0; 00336 00337 //--- game info 00338 SgPropID SG_PROP_INFO = 0; 00339 SgPropID SG_PROP_GAME_NAME = 0; 00340 SgPropID SG_PROP_GAME_COMMENT = 0; 00341 SgPropID SG_PROP_EVENT = 0; 00342 SgPropID SG_PROP_ROUND = 0; 00343 SgPropID SG_PROP_DATE = 0; 00344 SgPropID SG_PROP_PLACE = 0; 00345 SgPropID SG_PROP_PLAYER_BLACK = 0; 00346 SgPropID SG_PROP_PLAYER_WHITE = 0; 00347 SgPropID SG_PROP_RESULT = 0; 00348 SgPropID SG_PROP_USER = 0; 00349 SgPropID SG_PROP_TIME = 0; 00350 SgPropID SG_PROP_SOURCE = 0; 00351 SgPropID SG_PROP_COPYRIGHT = 0; 00352 SgPropID SG_PROP_ANALYSIS = 0; 00353 SgPropID SG_PROP_RANK_BLACK = 0; 00354 SgPropID SG_PROP_RANK_WHITE = 0; 00355 SgPropID SG_PROP_TEAM_BLACK = 0; 00356 SgPropID SG_PROP_TEAM_WHITE = 0; 00357 SgPropID SG_PROP_OPENING = 0; 00358 SgPropID SG_PROP_RULES = 0; 00359 SgPropID SG_PROP_HANDICAP = 0; 00360 SgPropID SG_PROP_KOMI = 0; 00361 00362 //--- abstract properties 00363 SgPropID SG_PROP_FIND_MOVE = 0; 00364 SgPropID SG_PROP_FIND_TEXT = 0; 00365 SgPropID SG_PROP_BRANCH = 0; 00366 SgPropID SG_PROP_TERMINAL = 0; 00367 00368 //--- Smart Go specific properties 00369 SgPropID SG_PROP_MOTIVE = 0; 00370 SgPropID SG_PROP_SEQUENCE = 0; 00371 SgPropID SG_PROP_NOT_EMPTY = 0; 00372 SgPropID SG_PROP_NOT_BLACK = 0; 00373 SgPropID SG_PROP_NOT_WHITE = 0; 00374 00375 //---------------------------------------------------------------------------- 00376 00377 bool SgProp::s_initialized = false; 00378 00379 int SgProp::s_numPropClasses = 0; 00380 00381 SgPropFlags SgProp::s_flags[SG_MAX_PROPCLASS]; 00382 00383 string SgProp::s_label[SG_MAX_PROPCLASS]; 00384 00385 SgProp* SgProp::s_prop[SG_MAX_PROPCLASS]; 00386 00387 SgProp::~SgProp() 00388 { 00389 } 00390 00391 void SgProp::ChangeToOpponent() 00392 { 00393 m_id = OpponentProp(m_id); 00394 } 00395 00396 bool SgProp::ContainsText(const std::string& findText) 00397 { 00398 SG_UNUSED(findText); 00399 return false; 00400 } 00401 00402 SgPropFlags SgProp::Flags() const 00403 { 00404 return s_flags[m_id]; 00405 } 00406 00407 bool SgProp::Initialized() 00408 { 00409 return s_initialized; 00410 } 00411 00412 string SgProp::Label() const 00413 { 00414 return s_label[m_id]; 00415 } 00416 00417 SgPropID SgProp::Register(SgProp* prop, const char* label, SgPropFlags flags) 00418 { 00419 ++s_numPropClasses; 00420 SG_ASSERT(s_numPropClasses < SG_MAX_PROPCLASS); 00421 if (s_numPropClasses < SG_MAX_PROPCLASS) 00422 { 00423 s_flags[s_numPropClasses] = flags; 00424 s_label[s_numPropClasses] = label; 00425 s_prop[s_numPropClasses] = prop; 00426 if (prop) 00427 { 00428 SG_ASSERT(prop->m_id == 0); // can't know the ID yet 00429 } 00430 // Black and white properties must be created in pairs, black first. 00431 if (flags & SG_PROPCLASS_WHITE) 00432 SG_ASSERT(s_flags[s_numPropClasses-1] & SG_PROPCLASS_BLACK); 00433 00434 return s_numPropClasses; 00435 } 00436 else 00437 return 0; 00438 } 00439 00440 SgProp* SgProp::CreateProperty(SgPropID id) 00441 { 00442 SG_ASSERT(id <= s_numPropClasses); 00443 SG_ASSERT(s_prop[id]); 00444 00445 // Create a property of the right class, and set its ID (because 00446 // prototype that's duplicated contains a zero ID). 00447 SgProp* prop = s_prop[id]->Duplicate(); 00448 prop->m_id = id; 00449 return prop; 00450 } 00451 00452 SgPropID SgProp::GetIDOfLabel(const string& label) 00453 { 00454 for (int i = 1; i <= s_numPropClasses; ++i) 00455 if (s_label[i] == label) 00456 return i; 00457 return SG_PROP_NONE; 00458 } 00459 00460 SgPropID SgProp::OpponentProp(SgPropID id) 00461 { 00462 // Relies on the fact that these properties are always created in pairs, 00463 // with black created before white. 00464 // AR: ---> Flags cannot really be overridden 00465 SgPropFlags flags = s_flags[id]; 00466 00467 if (flags & SG_PROPCLASS_BLACK) 00468 { 00469 ++id; 00470 SG_ASSERT(s_flags[id] & SG_PROPCLASS_WHITE); 00471 } 00472 else if (flags & SG_PROPCLASS_WHITE) 00473 { 00474 --id; 00475 SG_ASSERT(s_flags[id] & SG_PROPCLASS_BLACK); 00476 } 00477 return id; 00478 } 00479 00480 SgPropID SgProp::PlayerProp(SgPropID id, SgBlackWhite player) 00481 { 00482 // AR: ---> Flags cannot really be overridden 00483 SgPropFlags flags = s_flags[id]; 00484 SG_ASSERT(flags & (SG_PROPCLASS_BLACK | SG_PROPCLASS_WHITE)); 00485 int mask = (player == SG_WHITE ? SG_PROPCLASS_WHITE : SG_PROPCLASS_BLACK); 00486 if (flags & mask) 00487 return id; 00488 else 00489 return OpponentProp(id); 00490 } 00491 00492 SgBlackWhite SgProp::Player() const 00493 { 00494 SG_ASSERT(Flag(SG_PROPCLASS_BLACK | SG_PROPCLASS_WHITE)); 00495 if (Flags() & SG_PROPCLASS_BLACK) 00496 return SG_BLACK; 00497 else if (Flags() & SG_PROPCLASS_WHITE) 00498 return SG_WHITE; 00499 SG_ASSERT(false); 00500 return -1; 00501 } 00502 00503 bool SgProp::IsPlayer(SgBlackWhite player) const 00504 { 00505 SG_ASSERT_BW(player); 00506 return (Player() == player); 00507 } 00508 00509 bool SgProp::MatchesID(SgPropID id) const 00510 { 00511 // Matches if ID matches exactly. 00512 if (id == ID()) 00513 return true; 00514 00515 // Matches if looking for abstract property and matches that category. 00516 if (s_flags[id] & SG_PROPCLASS_ABSTRACT) 00517 { 00518 SgPropFlags fCategories = s_flags[id] & (~SG_PROPCLASS_ABSTRACT); 00519 if ((Flags() & fCategories) == fCategories) 00520 return true; 00521 } 00522 00523 return false; 00524 } 00525 00526 SgPropID SgProp::ConvertFindTextToPropID(const string& findText) 00527 { 00528 size_t length = findText.size(); 00529 if ( (3 <= length && findText[1] == ' ' && findText[2] == '<') 00530 || (2 <= length && findText[1] == '<') 00531 || 1 == length 00532 ) 00533 { 00534 switch (findText[0]) 00535 { 00536 case 'A': return SG_PROP_ANNOTATE; 00537 case 'B': return SG_PROP_MOVE_BLACK; 00538 case 'C': return SG_PROP_COMMENT; 00539 case 'H': return SG_PROP_HOTSPOT; 00540 case 'I': return SG_PROP_INFO; 00541 case 'K': return SG_PROP_CHECK; 00542 case 'M': return SG_PROP_MARKS; 00543 case 'N': return SG_PROP_NAME; 00544 case 'S': return SG_PROP_SIGMA; 00545 case 'T': return SG_PROP_TRIANGLE; 00546 case 'W': return SG_PROP_MOVE_WHITE; 00547 case '!': return SG_PROP_GOOD_MOVE; 00548 case '?': return SG_PROP_BAD_MOVE; 00549 case '.': return SG_PROP_TERMINAL; 00550 case ':': return SG_PROP_BRANCH; 00551 default: break; 00552 } 00553 } 00554 return SG_PROP_NONE; 00555 } 00556 00557 void SgProp::Init() 00558 { 00559 // Attributes of SG_PROP_NONE. 00560 s_flags[0] = 0; 00561 s_label[0] = ""; 00562 s_prop[0] = 0; 00563 00564 // Create prototype properties, one for each property class. 00565 SgProp* unknownProp = new SgPropUnknown(0); 00566 SgProp* simpleProp = new SgPropSimple(0); 00567 SgProp* intProp = new SgPropInt(0); 00568 SgProp* realProp = new SgPropReal(0); 00569 SgProp* multipleProp = new SgPropMultiple(0); 00570 SgProp* valueProp = new SgPropValue(0); 00571 SgProp* timeProp = new SgPropTime(0); 00572 SgProp* mSecProp = new SgPropMSec(0); 00573 SgProp* moveProp = new SgPropMove(0); 00574 SgProp* listProp = new SgPropPointList(0); 00575 SgProp* textProp = new SgPropText(0); 00576 SgProp* textListProp = new SgPropTextList(0); 00577 SgProp* playerProp = new SgPropPlayer(0); 00578 SgProp* addStoneProp = new SgPropAddStone(0); 00579 00580 // Register abstract property classes so they get cleaned up on fini. 00581 SG_PROP_NONE = 0; 00582 SG_PROP_UNKNOWN = Register(unknownProp, ""); 00583 Register(simpleProp, ""); 00584 Register(intProp, ""); 00585 Register(realProp, ""); 00586 Register(multipleProp, ""); 00587 Register(valueProp, ""); 00588 Register(timeProp, ""); 00589 Register(mSecProp, ""); 00590 Register(moveProp, ""); 00591 Register(listProp, ""); 00592 Register(textProp, ""); 00593 Register(textListProp, ""); 00594 Register(playerProp, ""); 00595 Register(addStoneProp, ""); 00596 00597 // Create the standard properties. 00598 00599 //--- moves and board edits 00600 SG_PROP_MOVE = Register(0, "", SG_PROPCLASS_MOVE + SG_PROPCLASS_ABSTRACT); 00601 SG_PROP_PLAYER = Register(playerProp, "PL"); 00602 SG_PROP_ADD_BLACK = Register(addStoneProp, "AB", 00603 SG_PROPCLASS_BLACK + SG_PROPCLASS_NEWLINE); 00604 SG_PROP_ADD_WHITE = Register(addStoneProp, "AW", 00605 SG_PROPCLASS_WHITE + SG_PROPCLASS_NEWLINE); 00606 SG_PROP_ADD_EMPTY = Register(addStoneProp, "AE", SG_PROPCLASS_NEWLINE); 00607 00608 //--- value and territory 00609 SG_PROP_VALUE = Register(valueProp, "V"); 00610 SG_PROP_TERR_BLACK = Register(listProp, "TB", 00611 SG_PROPCLASS_BLACK + SG_PROPCLASS_NEWLINE); 00612 SG_PROP_TERR_WHITE = Register(listProp, "TW", 00613 SG_PROPCLASS_WHITE + SG_PROPCLASS_NEWLINE); 00614 00615 //--- marks drawn on the board 00616 SG_PROP_MARKS = Register(0, "", SG_PROPCLASS_MARK + SG_PROPCLASS_ABSTRACT); 00617 SG_PROP_SELECT = Register(listProp, "SL", SG_PROPCLASS_MARK); 00618 SG_PROP_MARKED = Register(listProp, "MA", SG_PROPCLASS_MARK); 00619 SG_PROP_TRIANGLE = Register(listProp, "TR", SG_PROPCLASS_MARK); 00620 SG_PROP_SQUARE = Register(listProp, "SQ", SG_PROPCLASS_MARK); 00621 SG_PROP_DIAMOND = Register(listProp, "RG", SG_PROPCLASS_MARK); 00622 SG_PROP_CIRCLE = Register(listProp, "CR", SG_PROPCLASS_MARK); 00623 SG_PROP_DIMMED = Register(listProp, "DD", SG_PROPCLASS_MARK); 00624 SG_PROP_LABEL = Register(textListProp, "LB", SG_PROPCLASS_MARK); 00625 00626 //--- time control 00627 SG_PROP_TIMES = Register(0, "", SG_PROPCLASS_TIME + SG_PROPCLASS_ABSTRACT); 00628 SG_PROP_TIME_BLACK = Register(timeProp, "BL", 00629 SG_PROPCLASS_TIME + SG_PROPCLASS_BLACK); 00630 SG_PROP_TIME_WHITE = Register(timeProp, "WL", 00631 SG_PROPCLASS_TIME + SG_PROPCLASS_WHITE); 00632 SG_PROP_OT_BLACK = Register(intProp, "OB", 00633 SG_PROPCLASS_TIME + SG_PROPCLASS_BLACK 00634 + SG_PROPCLASS_NOTCLEAN); 00635 SG_PROP_OT_WHITE = Register(intProp, "OW", 00636 SG_PROPCLASS_TIME + SG_PROPCLASS_WHITE 00637 + SG_PROPCLASS_NOTCLEAN); 00638 SG_PROP_OT_NU_MOVES = Register(intProp, "OM", 00639 SG_PROPCLASS_TIME + SG_PROPCLASS_ROOT 00640 + SG_PROPCLASS_CUSTOM 00641 + SG_PROPCLASS_NOTCLEAN); 00642 SG_PROP_OT_PERIOD = Register(timeProp, "OP", 00643 SG_PROPCLASS_TIME + SG_PROPCLASS_ROOT 00644 + SG_PROPCLASS_CUSTOM + SG_PROPCLASS_NOTCLEAN); 00645 SG_PROP_OVERHEAD = Register(timeProp, "OV", 00646 SG_PROPCLASS_TIME + SG_PROPCLASS_ROOT 00647 + SG_PROPCLASS_CUSTOM + SG_PROPCLASS_NOTCLEAN); 00648 SG_PROP_LOSE_TIME = Register(simpleProp, "LT", 00649 SG_PROPCLASS_TIME + SG_PROPCLASS_ROOT 00650 + SG_PROPCLASS_CUSTOM + SG_PROPCLASS_NOTCLEAN); 00651 00652 //--- statistics 00653 // AR: is official property? 00654 SG_PROP_COUNT = Register(0, "CN", 00655 SG_PROPCLASS_STAT + SG_PROPCLASS_ABSTRACT); 00656 SG_PROP_TIME_USED = Register(mSecProp, "TU", 00657 SG_PROPCLASS_STAT + SG_PROPCLASS_CUSTOM 00658 + SG_PROPCLASS_NOTCLEAN); 00659 SG_PROP_NUM_NODES = Register(intProp, "NN", 00660 SG_PROPCLASS_STAT + SG_PROPCLASS_CUSTOM 00661 + SG_PROPCLASS_NOTCLEAN); 00662 SG_PROP_NUM_LEAFS = Register(intProp, "NL", 00663 SG_PROPCLASS_STAT + SG_PROPCLASS_CUSTOM 00664 + SG_PROPCLASS_NOTCLEAN); 00665 SG_PROP_MAX_DEPTH = Register(intProp, "MD", 00666 SG_PROPCLASS_STAT + SG_PROPCLASS_CUSTOM 00667 + SG_PROPCLASS_NOTCLEAN); 00668 SG_PROP_DEPTH = Register(intProp, "DE", 00669 SG_PROPCLASS_STAT + SG_PROPCLASS_CUSTOM 00670 + SG_PROPCLASS_NOTCLEAN); 00671 SG_PROP_PART_DEPTH = Register(intProp, "PD", 00672 SG_PROPCLASS_STAT + SG_PROPCLASS_CUSTOM 00673 + SG_PROPCLASS_NOTCLEAN); 00674 SG_PROP_EVAL = Register(valueProp, "EL", 00675 SG_PROPCLASS_STAT + SG_PROPCLASS_CUSTOM 00676 + SG_PROPCLASS_NOTCLEAN); 00677 SG_PROP_EXPECTED = Register(moveProp, "EX", 00678 SG_PROPCLASS_STAT + SG_PROPCLASS_CUSTOM 00679 + SG_PROPCLASS_NOTCLEAN); 00680 00681 //--- root props 00682 SG_PROP_FORMAT = Register(intProp, "FF", SG_PROPCLASS_ROOT); 00683 SG_PROP_SIZE = Register(intProp, "SZ", SG_PROPCLASS_ROOT); 00684 SG_PROP_GAME = Register(intProp, "GM", SG_PROPCLASS_ROOT); 00685 // AR: not root props? 00686 SG_PROP_SPEC_BLACK = Register(intProp, "BS", SG_PROPCLASS_CUSTOM); 00687 SG_PROP_SPEC_WHITE = Register(intProp, "WS", SG_PROPCLASS_CUSTOM); 00688 SG_PROP_CHINESE = Register(intProp, "CI", 00689 SG_PROPCLASS_ROOT + SG_PROPCLASS_CUSTOM); 00690 SG_PROP_APPLIC = Register(textProp, "AP", 00691 SG_PROPCLASS_ROOT + SG_PROPCLASS_NOT_FF3); 00692 00693 //--- annotations 00694 SG_PROP_ANNOTATE = Register(0, "", 00695 SG_PROPCLASS_ANNO + SG_PROPCLASS_ABSTRACT); 00696 SG_PROP_COMMENT = Register(textProp, "C", 00697 SG_PROPCLASS_ANNO + SG_PROPCLASS_NEWLINE); 00698 SG_PROP_NAME = Register(textProp, "N", 00699 SG_PROPCLASS_ANNO + SG_PROPCLASS_NEWLINE); 00700 SG_PROP_CHECK = Register(multipleProp, "CH", 00701 SG_PROPCLASS_ANNO + SG_PROPCLASS_CUSTOM); 00702 SG_PROP_SIGMA = Register(multipleProp, "SI", 00703 SG_PROPCLASS_ANNO + SG_PROPCLASS_CUSTOM); 00704 SG_PROP_HOTSPOT = Register(multipleProp, "HO", 00705 SG_PROPCLASS_ANNO + SG_PROPCLASS_CUSTOM); 00706 SG_PROP_FIGURE = Register(simpleProp, "FG", 00707 SG_PROPCLASS_ANNO + SG_PROPCLASS_NEWLINE); 00708 00709 //--- position annotations 00710 SG_PROP_POS_ANNO = Register(0, "", 00711 SG_PROPCLASS_ANNO + SG_PROPCLASS_ANNO_POS 00712 + SG_PROPCLASS_ABSTRACT); 00713 SG_PROP_GOOD_BLACK = Register(multipleProp, "GB", 00714 SG_PROPCLASS_ANNO + SG_PROPCLASS_ANNO_POS 00715 + SG_PROPCLASS_BLACK); 00716 SG_PROP_GOOD_WHITE = Register(multipleProp, "GW", 00717 SG_PROPCLASS_ANNO + SG_PROPCLASS_ANNO_POS 00718 + SG_PROPCLASS_WHITE); 00719 SG_PROP_EVEN_POS = Register(multipleProp, "DM", 00720 SG_PROPCLASS_ANNO + SG_PROPCLASS_ANNO_POS); 00721 SG_PROP_UNCLEAR = Register(multipleProp, "UC", 00722 SG_PROPCLASS_ANNO + SG_PROPCLASS_ANNO_POS); 00723 00724 //--- move annotations 00725 SG_PROP_MOVE_ANNO = Register(0, "", 00726 SG_PROPCLASS_ANNO + SG_PROPCLASS_ANNO_MOVE 00727 + SG_PROPCLASS_ABSTRACT); 00728 SG_PROP_GOOD_MOVE = Register(multipleProp, "TE", 00729 SG_PROPCLASS_ANNO + SG_PROPCLASS_ANNO_MOVE); 00730 SG_PROP_BAD_MOVE = Register(multipleProp, "BM", 00731 SG_PROPCLASS_ANNO + SG_PROPCLASS_ANNO_MOVE); 00732 SG_PROP_INTERESTING = Register(simpleProp, "IT", 00733 SG_PROPCLASS_ANNO + SG_PROPCLASS_ANNO_MOVE); 00734 SG_PROP_DOUBTFUL = Register(simpleProp, "DO", 00735 SG_PROPCLASS_ANNO + SG_PROPCLASS_ANNO_MOVE); 00736 00737 //--- game info 00738 SG_PROP_INFO = Register(0, "", SG_PROPCLASS_INFO + SG_PROPCLASS_ABSTRACT); 00739 SG_PROP_GAME_NAME = Register(textProp, "GN", 00740 SG_PROPCLASS_INFO + SG_PROPCLASS_NEWLINE); 00741 SG_PROP_GAME_COMMENT = Register(textProp, "GC", 00742 SG_PROPCLASS_INFO + SG_PROPCLASS_NEWLINE); 00743 SG_PROP_EVENT = Register(textProp, "EV", 00744 SG_PROPCLASS_INFO + SG_PROPCLASS_NEWLINE); 00745 SG_PROP_ROUND = Register(textProp, "RO", SG_PROPCLASS_INFO); 00746 SG_PROP_DATE = Register(textProp, "DT", 00747 SG_PROPCLASS_INFO + SG_PROPCLASS_NEWLINE); 00748 SG_PROP_PLACE = Register(textProp, "PC", 00749 SG_PROPCLASS_INFO + SG_PROPCLASS_NEWLINE); 00750 SG_PROP_PLAYER_BLACK = Register(textProp, "PB", 00751 SG_PROPCLASS_INFO + SG_PROPCLASS_BLACK 00752 + SG_PROPCLASS_NEWLINE); 00753 SG_PROP_PLAYER_WHITE = Register(textProp, "PW", 00754 SG_PROPCLASS_INFO + SG_PROPCLASS_WHITE 00755 + SG_PROPCLASS_NEWLINE); 00756 SG_PROP_RESULT = Register(textProp, "RE", 00757 SG_PROPCLASS_INFO + SG_PROPCLASS_NEWLINE); 00758 SG_PROP_USER = Register(textProp, "US", 00759 SG_PROPCLASS_INFO + SG_PROPCLASS_NEWLINE); 00760 SG_PROP_TIME = Register(textProp, "TM", SG_PROPCLASS_INFO); 00761 SG_PROP_SOURCE = Register(textProp, "SO", 00762 SG_PROPCLASS_INFO + SG_PROPCLASS_NEWLINE); 00763 SG_PROP_COPYRIGHT = Register(textProp, "CP", SG_PROPCLASS_INFO); 00764 SG_PROP_ANALYSIS = Register(textProp, "AN", SG_PROPCLASS_INFO); 00765 SG_PROP_RANK_BLACK = Register(textProp, "BR", 00766 SG_PROPCLASS_INFO + SG_PROPCLASS_BLACK); 00767 SG_PROP_RANK_WHITE = Register(textProp, "WR", 00768 SG_PROPCLASS_INFO + SG_PROPCLASS_WHITE); 00769 SG_PROP_TEAM_BLACK = Register(textProp, "BT", 00770 SG_PROPCLASS_INFO + SG_PROPCLASS_BLACK); 00771 SG_PROP_TEAM_WHITE = Register(textProp, "WT" 00772 , SG_PROPCLASS_INFO + SG_PROPCLASS_WHITE); 00773 SG_PROP_OPENING = Register(textProp, "ON", 00774 SG_PROPCLASS_INFO + SG_PROPCLASS_NEWLINE); 00775 SG_PROP_RULES = Register(textProp, "RU", 00776 SG_PROPCLASS_INFO + SG_PROPCLASS_NEWLINE); 00777 SG_PROP_HANDICAP = Register(intProp, "HA", SG_PROPCLASS_INFO); 00778 SG_PROP_KOMI = Register(realProp, "KM", SG_PROPCLASS_INFO); 00779 00780 //--- abstract properties 00781 SG_PROP_FIND_MOVE = Register(0, "", SG_PROPCLASS_ABSTRACT); 00782 SG_PROP_FIND_TEXT = Register(0, "", SG_PROPCLASS_ABSTRACT); 00783 SG_PROP_BRANCH = Register(0, "", SG_PROPCLASS_ABSTRACT); 00784 SG_PROP_TERMINAL = Register(0, "", SG_PROPCLASS_ABSTRACT); 00785 00786 //--- Smart Go specific properties 00787 SG_PROP_MOTIVE = Register(textListProp, "MM", 00788 SG_PROPCLASS_STAT + SG_PROPCLASS_CUSTOM 00789 + SG_PROPCLASS_NOTCLEAN); 00790 SG_PROP_SEQUENCE = Register(listProp, "MS", 00791 SG_PROPCLASS_STAT + SG_PROPCLASS_CUSTOM 00792 + SG_PROPCLASS_NOTCLEAN); 00793 SG_PROP_NOT_EMPTY = Register(listProp, "NE", 00794 SG_PROPCLASS_MARK + SG_PROPCLASS_CUSTOM 00795 + SG_PROPCLASS_NOTCLEAN); 00796 SG_PROP_NOT_BLACK = Register(listProp, "NB", 00797 SG_PROPCLASS_MARK + SG_PROPCLASS_CUSTOM 00798 + SG_PROPCLASS_NOTCLEAN); 00799 SG_PROP_NOT_WHITE = Register(listProp, "NW", 00800 SG_PROPCLASS_MARK + SG_PROPCLASS_CUSTOM 00801 + SG_PROPCLASS_NOTCLEAN); 00802 00803 s_initialized = true; 00804 } 00805 00806 void SgProp::Fini() 00807 { 00808 s_initialized = false; 00809 } 00810 00811 //---------------------------------------------------------------------------- 00812 00813 SgProp* SgPropUnknown::Duplicate() const 00814 { 00815 return new SgPropUnknown(m_id, m_label, m_values); 00816 } 00817 00818 bool SgPropUnknown::ToString(std::vector<std::string>& values, int boardSize, 00819 SgPropPointFmt fmt, int fileFormat) const 00820 { 00821 SG_UNUSED(boardSize); 00822 SG_UNUSED(fmt); 00823 SG_UNUSED(fileFormat); 00824 values.clear(); 00825 for (vector<string>::const_iterator it = m_values.begin(); 00826 it != m_values.end(); ++it) 00827 values.push_back(EscapeSpecialCharacters(*it, false)); 00828 return true; 00829 } 00830 00831 bool SgPropUnknown::FromString(const std::vector<std::string>& values, 00832 int boardSize, SgPropPointFmt fmt) 00833 { 00834 SG_UNUSED(boardSize); 00835 SG_UNUSED(fmt); 00836 m_values = values; 00837 return true; 00838 } 00839 00840 //---------------------------------------------------------------------------- 00841 00842 SgProp* SgPropSimple::Duplicate() const 00843 { 00844 return new SgPropSimple(m_id); 00845 } 00846 00847 bool SgPropSimple::ToString(std::vector<std::string>& values, int boardSize, 00848 SgPropPointFmt fmt, int fileFormat) const 00849 { 00850 SG_UNUSED(boardSize); 00851 SG_UNUSED(fmt); 00852 SG_UNUSED(fileFormat); 00853 values.assign(1, ""); 00854 return true; 00855 } 00856 00857 bool SgPropSimple::FromString(const std::vector<std::string>& values, 00858 int boardSize, SgPropPointFmt fmt) 00859 { 00860 SG_UNUSED(values); 00861 SG_UNUSED(boardSize); 00862 SG_UNUSED(fmt); 00863 return true; 00864 } 00865 00866 //---------------------------------------------------------------------------- 00867 00868 SgProp* SgPropMultiple::Duplicate() const 00869 { 00870 return new SgPropMultiple(m_id, m_value); 00871 } 00872 00873 //---------------------------------------------------------------------------- 00874 00875 SgProp* SgPropInt::Duplicate() const 00876 { 00877 return new SgPropInt(m_id, m_value); 00878 } 00879 00880 bool SgPropInt::ToString(std::vector<std::string>& values, int boardSize, 00881 SgPropPointFmt fmt, int fileFormat) const 00882 { 00883 SG_UNUSED(fileFormat); 00884 SG_UNUSED(boardSize); 00885 SG_UNUSED(fmt); 00886 ostringstream buffer; 00887 buffer << m_value; 00888 values.assign(1, buffer.str()); 00889 return true; 00890 } 00891 00892 bool SgPropInt::FromString(const std::vector<std::string>& values, 00893 int boardSize, SgPropPointFmt fmt) 00894 { 00895 SG_UNUSED(boardSize); 00896 SG_UNUSED(fmt); 00897 if (values.empty()) 00898 { 00899 m_value = 0; 00900 return true; 00901 } 00902 istringstream in(values[0]); 00903 in >> m_value; 00904 return (! in.fail()); 00905 } 00906 00907 //---------------------------------------------------------------------------- 00908 00909 SgProp* SgPropReal::Duplicate() const 00910 { 00911 return new SgPropReal(m_id, m_value, m_precision); 00912 } 00913 00914 bool SgPropReal::ToString(std::vector<std::string>& values, int boardSize, 00915 SgPropPointFmt fmt, int fileFormat) const 00916 { 00917 SG_UNUSED(boardSize); 00918 SG_UNUSED(fmt); 00919 SG_UNUSED(fileFormat); 00920 ostringstream buffer; 00921 if (m_precision > 0) 00922 buffer.precision(m_precision); 00923 buffer << fixed << m_value; 00924 values.assign(1, buffer.str()); 00925 return true; 00926 } 00927 00928 bool SgPropReal::FromString(const std::vector<std::string>& values, 00929 int boardSize, SgPropPointFmt fmt) 00930 { 00931 SG_UNUSED(boardSize); 00932 SG_UNUSED(fmt); 00933 if (values.empty()) 00934 { 00935 m_value = 0; 00936 return true; 00937 } 00938 istringstream in(values[0]); 00939 in >> m_value; 00940 return (! in.fail()); 00941 } 00942 00943 //---------------------------------------------------------------------------- 00944 00945 void SgPropValue::ChangeToOpponent() 00946 { 00947 m_value = -m_value; 00948 } 00949 00950 SgProp* SgPropValue::Duplicate() const 00951 { 00952 return new SgPropValue(m_id, m_value); 00953 } 00954 00955 //---------------------------------------------------------------------------- 00956 00957 SgPropTime::~SgPropTime() 00958 { 00959 } 00960 00961 SgProp* SgPropTime::Duplicate() const 00962 { 00963 return new SgPropTime(m_id, m_value, m_precision); 00964 } 00965 00966 //---------------------------------------------------------------------------- 00967 00968 SgPropMSec::~SgPropMSec() 00969 { 00970 } 00971 00972 SgProp* SgPropMSec::Duplicate() const 00973 { 00974 return new SgPropMSec(m_id, m_value); 00975 } 00976 00977 //---------------------------------------------------------------------------- 00978 00979 SgPropPointList::SgPropPointList(SgPropID id, 00980 const SgVector<SgPoint>& vector) 00981 : SgProp(id), 00982 m_list(vector) 00983 { 00984 } 00985 00986 SgPropPointList::~SgPropPointList() 00987 { 00988 } 00989 00990 SgProp* SgPropPointList::Duplicate() const 00991 { 00992 return new SgPropPointList(ID(), Value()); 00993 } 00994 00995 bool SgPropPointList::ToString(std::vector<std::string>& values, 00996 int boardSize, SgPropPointFmt fmt, 00997 int fileFormat) const 00998 { 00999 // Don't write out empty list properties. 01000 if (Value().IsEmpty()) 01001 return false; 01002 values.clear(); 01003 for (SgVectorIterator<SgPoint> it(Value()); it; ++it) 01004 { 01005 if (! SgIsSpecialMove(*it)) 01006 values.push_back(PointToSgfString(*it, boardSize, fmt, 01007 fileFormat)); 01008 } 01009 return true; 01010 } 01011 01012 bool SgPropPointList::FromString(const std::vector<std::string>& values, 01013 int boardSize, SgPropPointFmt fmt) 01014 { 01015 for (vector<string>::const_iterator it = values.begin(); 01016 it != values.end(); ++it) 01017 { 01018 string s = *it; 01019 if (s.size() == 5 && s[2] == ':') 01020 { 01021 // Compressed point list. 01022 string s1 = s.substr(0, 2); 01023 string s2 = s.substr(3, 2); 01024 SgPoint p1 = SgfStringToPoint(s1, boardSize, fmt); 01025 SgPoint p2 = SgfStringToPoint(s2, boardSize, fmt); 01026 if (InBoardRange(p1) && InBoardRange(p2)) 01027 { 01028 SgRect rect(p1, p2); 01029 for (SgRectIterator iter(rect); iter; ++iter) 01030 Value().PushBack(*iter); 01031 } 01032 else 01033 { 01034 return false; 01035 } 01036 } 01037 else 01038 { 01039 // Single point. 01040 SgPoint p = SgfStringToPoint(s, boardSize, fmt); 01041 if (InBoardRange(p) || p == SG_PASS) 01042 // Pass needed for move sequence 01043 Value().PushBack(p); 01044 else 01045 return false; 01046 } 01047 } 01048 return true; 01049 } 01050 01051 //---------------------------------------------------------------------------- 01052 01053 SgProp* SgPropText::Duplicate() const 01054 { 01055 return new SgPropText(m_id, m_text); 01056 } 01057 01058 bool SgPropText::ToString(std::vector<std::string>& values, int boardSize, 01059 SgPropPointFmt fmt, int fileFormat) const 01060 { 01061 SG_UNUSED(fileFormat); 01062 SG_UNUSED(boardSize); 01063 SG_UNUSED(fmt); 01064 values.assign(1, EscapeSpecialCharacters(m_text, false)); 01065 return true; 01066 } 01067 01068 bool SgPropText::FromString(const std::vector<std::string>& values, 01069 int boardSize, SgPropPointFmt fmt) 01070 { 01071 SG_UNUSED(boardSize); 01072 SG_UNUSED(fmt); 01073 if (values.size() == 0) 01074 m_text = ""; 01075 else 01076 m_text = values[0]; 01077 return true; 01078 } 01079 01080 bool SgPropText::ContainsText(const string& findText) 01081 { 01082 return (m_text.find(findText) != string::npos); 01083 } 01084 01085 //---------------------------------------------------------------------------- 01086 01087 SgPropTextList::SgPropTextList(SgPropID id, const SgVector<SgPoint>& points, 01088 SgVectorOf<std::string> strings) 01089 : SgProp(id), 01090 m_points(points), 01091 m_strings() 01092 { 01093 for (SgVectorIteratorOf<string> it(strings); it; ++it) 01094 { 01095 m_strings.PushBack(new string(*(*it))); 01096 } 01097 } 01098 01099 SgPropTextList::~SgPropTextList() 01100 { 01101 for (SgVectorIteratorOf<string> it(m_strings); it; ++it) 01102 { 01103 delete *it; 01104 } 01105 } 01106 01107 SgProp* SgPropTextList::Duplicate() const 01108 { 01109 return new SgPropTextList(m_id, m_points, m_strings); 01110 } 01111 01112 bool SgPropTextList::GetStringAtPoint(SgPoint p, string* s) const 01113 { 01114 int index = m_points.Index(p); 01115 if (index >= 0) 01116 { 01117 *s = *m_strings[index]; 01118 return true; 01119 } 01120 return false; 01121 } 01122 01123 void SgPropTextList::AddStringAtPoint(SgPoint p, const string& s) 01124 { 01125 ClearStringAtPoint(p); 01126 m_points.PushBack(p); 01127 m_strings.PushBack(new string(s)); 01128 } 01129 01130 void SgPropTextList::AppendToStringAtPoint(SgPoint p, const string& s) 01131 { 01132 string value; 01133 GetStringAtPoint(p, &value); // may be empty. 01134 value += s; 01135 AddStringAtPoint(p, value); // this clears out old string, if any. 01136 } 01137 01138 void SgPropTextList::ClearStringAtPoint(SgPoint p) 01139 { 01140 int index = m_points.Index(p); 01141 if (index >= 0) 01142 { 01143 m_points.DeleteAt(index); 01144 delete m_strings[index]; 01145 m_strings.DeleteAt(index); 01146 } 01147 } 01148 01149 bool SgPropTextList::ToString(std::vector<std::string>& values, 01150 int boardSize, SgPropPointFmt fmt, 01151 int fileFormat) const 01152 { 01153 // Don't write out empty text list properties. 01154 if (m_points.IsEmpty()) 01155 return false; 01156 values.clear(); 01157 int index = 0; 01158 for (SgVectorIterator<SgPoint> it(m_points); it; ++it) 01159 { 01160 ostringstream buffer; 01161 buffer << PointToSgfString(*it, boardSize, fmt, fileFormat) << ':' 01162 << EscapeSpecialCharacters(*m_strings[index], true) 01163 ; 01164 values.push_back(buffer.str()); 01165 ++index; 01166 } 01167 return true; 01168 } 01169 01170 bool SgPropTextList::FromString(const std::vector<std::string>& values, 01171 int boardSize, SgPropPointFmt fmt) 01172 { 01173 for (vector<string>::const_iterator it = values.begin(); 01174 it != values.end(); ++it) 01175 { 01176 string s = *it; 01177 if (s.size() >= 2) 01178 { 01179 string pointString = s.substr(0, 2); 01180 SgPoint p = SgfStringToPoint(pointString, boardSize, fmt); 01181 if (InBoardRange(p) && s.size() >= 3 && s[2] == ':') 01182 { 01183 string text = s.substr(3); 01184 AddStringAtPoint(p, text); 01185 return true; 01186 } 01187 } 01188 } 01189 return false; 01190 } 01191 01192 bool SgPropTextList::ContainsText(const string& findText) 01193 { 01194 for (SgVectorIteratorOf<string> it(m_strings); it; ++it) 01195 { 01196 if ((*it)->find(findText) != string::npos) 01197 return true; 01198 } 01199 return false; 01200 } 01201 01202 //---------------------------------------------------------------------------- 01203 01204 SgProp* SgPropPlayer::Duplicate() const 01205 { 01206 return new SgPropPlayer(m_id, m_player); 01207 } 01208 01209 bool SgPropPlayer::ToString(std::vector<std::string>& values, int boardSize, 01210 SgPropPointFmt fmt, int fileFormat) const 01211 { 01212 SG_UNUSED(fileFormat); 01213 SG_UNUSED(boardSize); 01214 SG_UNUSED(fmt); 01215 values.assign(1, m_player == SG_WHITE ? "W" : "B"); 01216 return true; 01217 } 01218 01219 bool SgPropPlayer::FromString(const std::vector<std::string>& values, 01220 int boardSize, SgPropPointFmt fmt) 01221 { 01222 SG_UNUSED(boardSize); 01223 SG_UNUSED(fmt); 01224 if (values.size() == 0) 01225 return false; 01226 m_player = (values[0] == "W" || values[0] == "w") ? SG_WHITE : SG_BLACK; 01227 return true; 01228 } 01229 01230 void SgPropPlayer::ChangeToOpponent() 01231 { 01232 m_player = SgOppBW(m_player); 01233 } 01234 01235 //---------------------------------------------------------------------------- 01236 01237 SgPropAddStone::~SgPropAddStone() 01238 { 01239 } 01240 01241 SgProp* SgPropAddStone::Duplicate() const 01242 { 01243 return new SgPropAddStone(m_id, Value()); 01244 } 01245 01246 //---------------------------------------------------------------------------- 01247 01248 SgProp* SgPropMove::Duplicate() const 01249 { 01250 return new SgPropMove(m_id, m_move); 01251 } 01252 01253 bool SgPropMove::ToString(std::vector<std::string>& values, int boardSize, 01254 SgPropPointFmt fmt, int fileFormat) const 01255 { 01256 values.assign(1, PointToSgfString(m_move, boardSize, fmt, fileFormat)); 01257 return true; 01258 } 01259 01260 bool SgPropMove::FromString(const std::vector<std::string>& values, 01261 int boardSize, SgPropPointFmt fmt) 01262 { 01263 if (values.size() == 0) 01264 return false; 01265 m_move = SgfStringToPoint(values[0], boardSize, fmt); 01266 return m_move != SG_NULLMOVE; 01267 } 01268 01269 //---------------------------------------------------------------------------- 01270