00001
00002
00003
00004
00005
00006 #ifndef GO_BOARDUTIL_H
00007 #define GO_BOARDUTIL_H
00008
00009 #include "GoBoard.h"
00010 #include "SgBoardColor.h"
00011 #include "SgDebug.h"
00012 #include "SgPoint.h"
00013 #include "SgPointArray.h"
00014 #include "SgStack.h"
00015 #include "SgVector.h"
00016
00017
00018
00019
00020
00021
00022
00023 namespace GoBoardUtil
00024 {
00025
00026 void AddNeighborBlocksOfColor(const GoBoard& bd,
00027 SgPoint p,
00028 SgBlackWhite color,
00029 SgVector<SgPoint>& neighbors);
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 void AddWall(GoBoard& bd,
00044 SgBlackWhite color,
00045 SgPoint start,
00046 int length,
00047 int direction);
00048
00049
00050 GoPointList AdjacentStones(const GoBoard& bd, SgPoint point);
00051
00052
00053 void AdjacentBlocks(const GoBoard& bd, SgPoint p, int maxLib,
00054 SgVector<SgPoint>* blocks);
00055
00056
00057
00058 int Approx2Libs(const GoBoard& board, SgPoint block, SgPoint p,
00059 SgBlackWhite color);
00060
00061
00062
00063
00064 bool AtLeastTwoSharedLibs(const GoBoard& bd, SgPoint block1,
00065 SgPoint block2);
00066
00067 bool BlockIsAdjacentTo(const GoBoard& bd, SgPoint block,
00068 const SgPointSet& walls);
00069
00070 void BlocksAdjacentToPoints(const GoBoard& bd,
00071 const SgVector<SgPoint>& points,
00072 SgBlackWhite c,
00073 SgVector<SgPoint>* anchors);
00074
00075
00076
00077 void BlocksAdjacentToPoints(const GoBoard& bd, const SgPointSet& points,
00078 SgBlackWhite c, SgVector<SgPoint>* anchors);
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 SgPointArray<int> CfgDistance(const GoBoard& bd, SgPoint p,
00092 int maxDist = std::numeric_limits<int>::max());
00093
00094
00095
00096 bool ContainsAnchor(const SgPoint anchor[], const SgPoint p);
00097
00098
00099
00100
00101
00102
00103
00104 void DiagonalsOfColor(const GoBoard& bd, SgPoint p, int c,
00105 SgVector<SgPoint>* diagonals);
00106
00107
00108
00109
00110
00111 void DumpBoard(const GoBoard& bd, std::ostream& out = SgDebug());
00112
00113
00114
00115
00116 bool EndOfGame(const GoBoard& bd);
00117
00118
00119 void ExpandToBlocks(const GoBoard& board, SgPointSet& pointSet);
00120
00121
00122
00123 template<class BOARD>
00124 SgPoint FindNeighbor(const BOARD& bd, SgPoint p, SgEmptyBlackWhite c);
00125
00126
00127 bool GenerateIfLegal(const GoBoard& bd,
00128 SgPoint move,
00129 SgVector<SgPoint>* moves);
00130
00131
00132
00133 void GetCoordString(SgMove move, std::string* s, int boardSize);
00134
00135
00136
00137 void GetCoordString(const GoBoard& board, SgMove move, std::string* s);
00138
00139
00140
00141
00142 SgRect GetDirtyRegion(const GoBoard& bd, SgMove move, SgBlackWhite color,
00143 bool checklibs = false, bool premove = false);
00144
00145
00146
00147 bool HasAdjacentBlocks(const GoBoard& bd, SgPoint p, int maxLib);
00148
00149 bool HasStonesOfBothColors(const GoBoard& bd,
00150 const SgVector<SgPoint>& stones);
00151
00152 template<class BOARD>
00153 bool IsBoardEmpty(const BOARD& bd);
00154
00155
00156
00157
00158
00159
00160
00161 template<class BOARD>
00162 bool IsCompletelySurrounded(const BOARD& bd, SgPoint p);
00163
00164 bool IsHandicapPoint(SgGrid size, SgGrid col, SgGrid row);
00165
00166 template<class BOARD>
00167 bool IsNeighborOfSome(const BOARD& bd, SgPoint p, SgPoint anchors[],
00168 SgBlackWhite toPlay);
00169
00170
00171
00172
00173
00174 template<class BOARD>
00175 bool IsSimpleChain(const BOARD& bd, SgPoint block, SgPoint& other);
00176
00177
00178
00179
00180
00181 bool IsSimpleEyeOfBlock(const GoBoard& bd, SgPoint lib,
00182 SgPoint blockAnchor,
00183 const SgVector<SgPoint>& eyes);
00184
00185
00186
00187
00188
00189 bool IsSnapback(const GoBoard& bd, SgPoint p);
00190
00191
00192 SgPointSet Lines(const GoBoard& bd, SgGrid from, SgGrid to);
00193
00194 bool ManySecondaryLibs(const GoBoard& bd, SgPoint block);
00195
00196
00197
00198 bool MoveNotLegalOrAtari(const GoBoard& bd, SgPoint move);
00199
00200
00201
00202 bool MoveLegalAndNotAtari(const GoBoard& bd, SgPoint move);
00203
00204
00205
00206
00207
00208
00209 SgArrayList<SgPoint,4> NeighborsOfColor(const GoBoard& bd, SgPoint p,
00210 int c);
00211
00212
00213
00214
00215
00216
00217
00218 void NeighborsOfColor(const GoBoard& bd, SgPoint p, int c,
00219 SgVector<SgPoint>* neighbors);
00220
00221
00222 bool TrompTaylorPassWins(const GoBoard& bd, SgBlackWhite toPlay);
00223
00224
00225
00226
00227
00228
00229 bool PlayIfLegal(GoBoard& bd, SgPoint p, SgBlackWhite player);
00230
00231
00232
00233
00234
00235 bool PlayIfLegal(GoBoard& bd, SgPoint p);
00236
00237
00238
00239
00240
00241 void ReduceToAnchors(const GoBoard& bd, SgVector<SgPoint>* stones);
00242
00243
00244
00245
00246
00247 void ReduceToAnchors(const GoBoard& bd, const SgVector<SgPoint>& stones,
00248 SgArrayList<SgPoint,SG_MAXPOINT> &anchors);
00249
00250
00251 void RegionCode(const GoBoard& bd, const SgVector<SgPoint>& region,
00252 SgHashCode* c);
00253
00254
00255
00256 bool RemainingChineseHandicap(const GoBoard& bd);
00257
00258
00259
00260 template<class BOARD>
00261 bool SelfAtari(const BOARD& bd, SgPoint p);
00262
00263
00264
00265 template<class BOARD>
00266 bool SelfAtari(const BOARD& bd, SgPoint p, int& numStones);
00267
00268
00269
00270 template<class BOARD>
00271 bool SelfAtariForColor(const BOARD& bd, SgPoint p,
00272 SgBlackWhite toPlay);
00273
00274
00275
00276 void SharedLiberties(const GoBoard& bd, SgPoint block1, SgPoint block2,
00277 SgVector<SgPoint>* sharedLibs);
00278
00279 void SharedLibertyBlocks(const GoBoard& bd, SgPoint anchor, int maxLib,
00280 SgVector<SgPoint>* blocks);
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295 bool ScorePosition(const GoBoard& bd, const SgPointSet& deadStones,
00296 float& score);
00297
00298
00299 template<class BOARD>
00300 SgEmptyBlackWhite ScorePoint(const BOARD& bd, SgPoint p, bool noCheck);
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319 template<class BOARD>
00320 float ScoreSimpleEndPosition(const BOARD& bd, float komi,
00321 const SgBWSet& safe, bool noCheck,
00322 SgPointArray<SgEmptyBlackWhite>* scoreBoard);
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343 float ScoreSimpleEndPosition(const GoBoard& bd, float komi,
00344 bool noCheck = false);
00345
00346
00347
00348
00349
00350
00351
00352
00353 int Stones(const GoBoard& bd, SgPoint p, SgPoint stones[]);
00354
00355 void TestForChain(GoBoard& bd, SgPoint block, SgPoint block2, SgPoint lib,
00356 SgVector<SgPoint>* extended);
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366 template<class BOARD>
00367 float TrompTaylorScore(const BOARD& bd, float komi,
00368 SgPointArray<SgEmptyBlackWhite>* scoreBoard = 0);
00369
00370
00371
00372 bool TwoPasses(const GoBoard& bd);
00373
00374
00375 void UndoAll(GoBoard& bd);
00376
00377 }
00378
00379 inline bool GoBoardUtil::ContainsAnchor(const SgPoint anchor[],
00380 const SgPoint p)
00381 {
00382 for (int i=0; anchor[i] != SG_ENDPOINT; ++i)
00383 if (p == anchor[i])
00384 return true;
00385 return false;
00386 }
00387
00388 template<class BOARD>
00389 inline SgPoint GoBoardUtil::FindNeighbor(const BOARD& bd, SgPoint p,
00390 SgEmptyBlackWhite c)
00391 {
00392 if (bd.IsColor(p + SG_NS, c))
00393 return p + SG_NS;
00394 if (bd.IsColor(p - SG_NS, c))
00395 return p - SG_NS;
00396 if (bd.IsColor(p + SG_WE, c))
00397 return p + SG_WE;
00398 SG_ASSERT(bd.IsColor(p - SG_WE, c));
00399 return p - SG_WE;
00400 }
00401
00402 inline void GoBoardUtil::GetCoordString(const GoBoard& board, SgMove move,
00403 std::string* s)
00404 {
00405 GetCoordString(move, s, board.Size());
00406 }
00407
00408 template<class BOARD>
00409 bool GoBoardUtil::IsBoardEmpty(const BOARD& bd)
00410 {
00411 return bd.TotalNumStones(SG_BLACK) + bd.TotalNumStones(SG_WHITE) == 0;
00412 }
00413
00414 template<class BOARD>
00415 inline bool GoBoardUtil::IsCompletelySurrounded(const BOARD& bd, SgPoint p)
00416 {
00417 SG_ASSERT(bd.IsEmpty(p));
00418 if (bd.HasEmptyNeighbors(p))
00419 return false;
00420 if (bd.HasNeighbors(p, SG_BLACK) && bd.HasNeighbors(p, SG_WHITE))
00421 return false;
00422 if (! bd.IsBorder(p - SG_NS) && bd.NumLiberties(p - SG_NS) == 1)
00423 return false;
00424 if (! bd.IsBorder(p - SG_WE) && bd.NumLiberties(p - SG_WE) == 1)
00425 return false;
00426 if (! bd.IsBorder(p + SG_WE) && bd.NumLiberties(p + SG_WE) == 1)
00427 return false;
00428 if (! bd.IsBorder(p + SG_NS) && bd.NumLiberties(p + SG_NS) == 1)
00429 return false;
00430 return true;
00431 }
00432
00433 template<class BOARD>
00434 inline bool GoBoardUtil::IsNeighborOfSome(const BOARD& bd, SgPoint p,
00435 SgPoint anchors[],
00436 SgBlackWhite toPlay)
00437 {
00438 for (SgNb4Iterator it(p); it; ++it)
00439 {
00440 const SgPoint nb = *it;
00441 if (bd.IsColor(nb, toPlay))
00442 {
00443 SgPoint anchor = bd.Anchor(nb);
00444 for (int i = 0; anchors[i] != SG_ENDPOINT; ++i)
00445 if (anchor == anchors[i])
00446 return true;
00447 }
00448 }
00449 return false;
00450 }
00451
00452 template<class BOARD>
00453 bool GoBoardUtil::IsSimpleChain(const BOARD& bd,
00454 SgPoint block,
00455 SgPoint& other)
00456 {
00457 if (bd.NumLiberties(block) < 2)
00458 return false;
00459 block = bd.Anchor(block);
00460 const SgBlackWhite color = bd.GetStone(block);
00461 typename BOARD::LibertyIterator it(bd, block);
00462 const SgPoint lib1 = *it;
00463 ++it;
00464 const SgPoint lib2 = *it;
00465 SgPoint anchors1[4 + 1];
00466 SgPoint anchors2[4 + 1];
00467 bd.NeighborBlocks(lib1, color, anchors1);
00468 bd.NeighborBlocks(lib2, color, anchors2);
00469 for (int i=0; anchors1[i] != SG_ENDPOINT; ++i)
00470 {
00471 const SgPoint anchor = anchors1[i];
00472 if ( anchor != block
00473 && GoBoardUtil::ContainsAnchor(anchors2, anchor)
00474 )
00475 {
00476 other = anchor;
00477 return true;
00478 }
00479 }
00480 return false;
00481 }
00482
00483 inline bool GoBoardUtil::PlayIfLegal(GoBoard& bd, SgPoint p)
00484 {
00485 return PlayIfLegal(bd, p, bd.ToPlay());
00486 }
00487
00488 template<class BOARD>
00489 SgEmptyBlackWhite GoBoardUtil::ScorePoint(const BOARD& bd, SgPoint p,
00490 bool noCheck)
00491 {
00492 SG_DEBUG_ONLY(noCheck);
00493 SgEmptyBlackWhite c = bd.GetColor(p);
00494 if (c != SG_EMPTY)
00495 return c;
00496
00497 SG_ASSERT(noCheck || bd.NumEmptyNeighbors(p) == 0
00498 || GoBoardUtil::SelfAtari(bd, p));
00499 if (bd.NumNeighbors(p, SG_BLACK) > 0
00500 && bd.NumNeighbors(p, SG_WHITE) == 0)
00501 return SG_BLACK;
00502 else if (bd.NumNeighbors(p, SG_WHITE) > 0
00503 && bd.NumNeighbors(p, SG_BLACK) == 0)
00504 {
00505 SG_ASSERT(bd.NumNeighbors(p, SG_WHITE) > 0);
00506 return SG_WHITE;
00507 }
00508 else
00509 {
00510
00511 SG_ASSERT(noCheck || GoBoardUtil::SelfAtari(bd, p));
00512 return SG_EMPTY;
00513 }
00514 }
00515
00516 template<class BOARD>
00517 float GoBoardUtil::ScoreSimpleEndPosition(const BOARD& bd, float komi,
00518 const SgBWSet& safe, bool noCheck,
00519 SgPointArray<SgEmptyBlackWhite>* scoreBoard)
00520 {
00521 float score = -komi;
00522 for (typename BOARD::Iterator it(bd); it; ++it)
00523 {
00524 SgPoint p = *it;
00525 SgEmptyBlackWhite c;
00526 if (safe[SG_BLACK].Contains(p))
00527 c = SG_BLACK;
00528 else if (safe[SG_WHITE].Contains(p))
00529 c = SG_WHITE;
00530 else
00531 c = ScorePoint(bd, p, noCheck);
00532 switch (c)
00533 {
00534 case SG_BLACK:
00535 ++score;
00536 break;
00537 case SG_WHITE:
00538 --score;
00539 break;
00540 default:
00541 break;
00542 }
00543 if (scoreBoard != 0)
00544 (*scoreBoard)[p] = c;
00545 }
00546 return score;
00547 }
00548
00549 template<class BOARD>
00550 inline bool GoBoardUtil::SelfAtari(const BOARD& bd, SgPoint p)
00551 {
00552 return SelfAtariForColor(bd, p, bd.ToPlay());
00553 }
00554
00555 template<class BOARD>
00556 inline bool GoBoardUtil::SelfAtariForColor(const BOARD& bd, SgPoint p,
00557 SgBlackWhite toPlay)
00558 {
00559
00560
00561
00562
00563
00564
00565
00566 SG_ASSERT(bd.IsEmpty(p));
00567
00568 if (bd.NumEmptyNeighbors(p) >= 2)
00569 return false;
00570 const SgBlackWhite opp = SgOppBW(toPlay);
00571 SgPoint lib = SG_NULLPOINT;
00572 bool hasOwnNb = false;
00573 bool hasCapture = false;
00574 for (SgNb4Iterator it(p); it; ++it)
00575 {
00576 const SgPoint nb = *it;
00577 const SgBlackWhite nbColor = bd.GetColor(nb);
00578 if (nbColor == SG_EMPTY)
00579 {
00580 if (lib == SG_NULLPOINT)
00581 lib = nb;
00582 else if (lib != nb)
00583 return false;
00584 }
00585 else if (nbColor == toPlay)
00586 {
00587 if (bd.NumLiberties(nb) > 2)
00588 return false;
00589 else
00590 for (typename BOARD::LibertyIterator it(bd, nb); it; ++it)
00591 {
00592 if (*it != p)
00593 {
00594 if (lib == SG_NULLPOINT)
00595 lib = *it;
00596 else if (lib != *it)
00597 return false;
00598 }
00599 }
00600 hasOwnNb = true;
00601 }
00602 else if (nbColor == opp)
00603 {
00604 if (bd.InAtari(nb))
00605 {
00606 if (lib == SG_NULLPOINT)
00607 {
00608 lib = *it;
00609 hasCapture = true;
00610 }
00611 else if (lib != *it)
00612 return false;
00613 }
00614 }
00615 }
00616
00617 if (lib == SG_NULLPOINT)
00618 return false;
00619 if (! hasOwnNb && hasCapture)
00620 return false;
00621 if (hasOwnNb && hasCapture)
00622 {
00623
00624 SgPoint anchors[4 + 1];
00625 bd.NeighborBlocks(p, toPlay, 1, anchors);
00626 SG_ASSERT(bd.IsColor(lib, opp));
00627 for (typename BOARD::StoneIterator it(bd, lib); it; ++it)
00628 {
00629 if (*it != lib && IsNeighborOfSome(bd, *it, anchors, toPlay))
00630 return false;
00631 }
00632 }
00633 return true;
00634 }
00635
00636 template<class BOARD>
00637 bool GoBoardUtil::SelfAtari(const BOARD& bd, SgPoint p, int& numStones)
00638 {
00639 SG_ASSERT(bd.IsEmpty(p));
00640
00641 if (bd.NumEmptyNeighbors(p) >= 2)
00642 return false;
00643 const SgBlackWhite toPlay = bd.ToPlay();
00644 const SgBlackWhite opp = SgOppBW(toPlay);
00645 SgPoint lib = SG_NULLPOINT;
00646 bool hasOwnNb = false;
00647 bool hasCapture = false;
00648 for (SgNb4Iterator it(p); it; ++it)
00649 {
00650 const SgPoint nb = *it;
00651 const SgBlackWhite nbColor = bd.GetColor(nb);
00652 if (nbColor == SG_EMPTY)
00653 {
00654 if (lib == SG_NULLPOINT)
00655 lib = nb;
00656 else if (lib != nb)
00657 return false;
00658 }
00659 else if (nbColor == toPlay)
00660 {
00661 if (bd.NumLiberties(nb) > 2)
00662 return false;
00663 else
00664 for (typename BOARD::LibertyIterator it(bd, nb); it; ++it)
00665 {
00666 if (*it != p)
00667 {
00668 if (lib == SG_NULLPOINT)
00669 lib = *it;
00670 else if (lib != *it)
00671 return false;
00672 }
00673 }
00674 hasOwnNb = true;
00675 }
00676 else if (nbColor == opp)
00677 {
00678 if (bd.InAtari(nb))
00679 {
00680 if (lib == SG_NULLPOINT)
00681 {
00682 lib = *it;
00683 hasCapture = true;
00684 }
00685 else if (lib != *it)
00686 return false;
00687 }
00688 }
00689 }
00690
00691 if (lib == SG_NULLPOINT)
00692 return false;
00693 if (! hasOwnNb && hasCapture)
00694 return false;
00695 if (hasOwnNb && hasCapture)
00696 {
00697
00698 SgPoint anchors[4 + 1];
00699 bd.NeighborBlocks(p, toPlay, 1, anchors);
00700 SG_ASSERT(bd.IsColor(lib, opp));
00701 for (typename BOARD::StoneIterator it(bd, lib); it; ++it)
00702 {
00703 if (*it != lib && IsNeighborOfSome(bd, *it, anchors, toPlay))
00704 return false;
00705 }
00706 }
00707 numStones = 1;
00708 if (hasOwnNb)
00709 {
00710 SgPoint anchors[4 + 1];
00711 bd.NeighborBlocks(p, toPlay, 2, anchors);
00712 for (int i = 0; anchors[i] != SG_ENDPOINT; ++i)
00713 numStones += bd.NumStones(anchors[i]);
00714 }
00715 return true;
00716 }
00717
00718 template<class BOARD>
00719 float GoBoardUtil::TrompTaylorScore(const BOARD& bd, float komi,
00720 SgPointArray<SgEmptyBlackWhite>* scoreBoard)
00721 {
00722 float score = -komi;
00723
00724 SgMarker mark;
00725 for (typename BOARD::Iterator it(bd); it; ++it)
00726 {
00727 if (mark.Contains(*it))
00728 continue;
00729 SgEmptyBlackWhite c = bd.GetColor(*it);
00730 if (c == SG_BLACK)
00731 {
00732 ++score;
00733 if (scoreBoard != 0)
00734 (*scoreBoard)[*it] = SG_BLACK;
00735 continue;
00736 }
00737 if (c == SG_WHITE)
00738 {
00739 --score;
00740 if (scoreBoard != 0)
00741 (*scoreBoard)[*it] = SG_WHITE;
00742 continue;
00743 }
00744 SgStack<SgPoint,SG_MAXPOINT> stack;
00745 GoPointList list;
00746 SG_ASSERT(c == SG_EMPTY);
00747 stack.Push(*it);
00748 mark.Include(*it);
00749 list.PushBack(*it);
00750 SgBWArray<bool> adjacent(false);
00751 int size = 0;
00752 while (! stack.IsEmpty())
00753 {
00754 SgPoint p = stack.Pop();
00755 SG_ASSERT(bd.GetColor(p) == SG_EMPTY);
00756 ++size;
00757 if (bd.HasNeighbors(p, SG_BLACK))
00758 adjacent[SG_BLACK] = true;
00759 if (bd.HasNeighbors(p, SG_WHITE))
00760 adjacent[SG_WHITE] = true;
00761 for (SgNb4Iterator it2(p); it2; ++it2)
00762 if (! bd.IsBorder(*it2) && bd.GetColor(*it2) == SG_EMPTY
00763 && ! mark.Contains(*it2))
00764 {
00765 stack.Push(*it2);
00766 mark.Include(*it2);
00767 list.PushBack(*it2);
00768 }
00769 }
00770 if (adjacent[SG_BLACK] && ! adjacent[SG_WHITE])
00771 {
00772 score += float(size);
00773 c = SG_BLACK;
00774 }
00775 else if (! adjacent[SG_BLACK] && adjacent[SG_WHITE])
00776 {
00777 score -= float(size);
00778 c = SG_WHITE;
00779 }
00780 else
00781 c = SG_EMPTY;
00782 if (scoreBoard != 0)
00783 for (GoPointList::Iterator it2(list); it2; ++it2)
00784 (*scoreBoard)[*it2] = c;
00785 }
00786 return score;
00787 }
00788
00789
00790
00791 template<class BOARD>
00792 std::ostream& GoWriteBoard(std::ostream& out, const BOARD& bd)
00793 {
00794
00795
00796
00797 std::ostringstream buffer;
00798 SgGrid size = bd.Size();
00799 if (size > 9)
00800 buffer << " ";
00801 else
00802 buffer << " ";
00803 SgGrid col;
00804 char c;
00805 for (col = 1, c = 'A'; col <= size; ++col, ++c)
00806 {
00807 if (c == 'I')
00808 ++c;
00809 buffer << c << ' ';
00810 }
00811 buffer << '\n';
00812 for (SgGrid row = size; row >= 1; --row)
00813 {
00814 if (size > 9 && row < 10)
00815 buffer << ' ';
00816 buffer << row << ' ';
00817 for (SgGrid col = 1; col <= size; ++col)
00818 {
00819 SgPoint p = SgPointUtil::Pt(col, row);
00820 switch (bd.GetColor(p))
00821 {
00822 case SG_BLACK:
00823 buffer << 'X';
00824 break;
00825 case SG_WHITE:
00826 buffer << 'O';
00827 break;
00828 case SG_EMPTY:
00829 if (GoBoardUtil::IsHandicapPoint(size, col, row))
00830 buffer << '+';
00831 else
00832 buffer << '.';
00833 break;
00834 default:
00835 SG_ASSERT(false);
00836 }
00837 buffer << ' ';
00838 }
00839 buffer << row;
00840 if (row <= 2)
00841 {
00842 if (size < 10)
00843 buffer << " ";
00844 else
00845 buffer << " ";
00846
00847
00848 if (row == 1)
00849 buffer << SgBW(bd.ToPlay()) << " to play";
00850 }
00851 buffer << '\n';
00852 }
00853 if (size > 9)
00854 buffer << " ";
00855 else
00856 buffer << " ";
00857 for (col = 1, c = 'A'; col <= size; ++col, ++c)
00858 {
00859 if (c == 'I')
00860 ++c;
00861 buffer << c << ' ';
00862 }
00863 buffer << '\n';
00864 out << buffer.str();
00865 return out;
00866 }
00867
00868 inline std::ostream& operator<<(std::ostream& out, const GoBoard& bd)
00869 {
00870 return GoWriteBoard(out, bd);
00871 }
00872
00873
00874
00875
00876
00877
00878 class GoRestoreKoRule
00879 {
00880 public:
00881 GoRestoreKoRule(GoBoard& board);
00882
00883 ~GoRestoreKoRule();
00884
00885 private:
00886 GoBoard& m_board;
00887
00888 GoRules::KoRule m_koRule;
00889
00890
00891 GoRestoreKoRule(const GoRestoreKoRule&);
00892
00893
00894 GoRestoreKoRule& operator=(const GoRestoreKoRule&);
00895 };
00896
00897 inline GoRestoreKoRule::GoRestoreKoRule(GoBoard& board)
00898 : m_board(board),
00899 m_koRule(board.Rules().GetKoRule())
00900 {
00901 }
00902
00903 inline GoRestoreKoRule::~GoRestoreKoRule()
00904 {
00905 m_board.Rules().SetKoRule(m_koRule);
00906 }
00907
00908
00909
00910
00911
00912
00913 class GoRestoreToPlay
00914 {
00915 public:
00916 GoRestoreToPlay(GoBoard& board)
00917 : m_board(board),
00918 m_oldToPlay(board.ToPlay())
00919 { }
00920
00921 ~GoRestoreToPlay()
00922 {
00923 m_board.SetToPlay(m_oldToPlay);
00924 }
00925
00926 private:
00927 GoBoard& m_board;
00928
00929 SgBlackWhite m_oldToPlay;
00930
00931
00932 GoRestoreToPlay(const GoRestoreToPlay&);
00933
00934
00935 GoRestoreToPlay& operator=(const GoRestoreToPlay&);
00936 };
00937
00938
00939
00940
00941 class GoBlockIterator
00942 {
00943 public:
00944 GoBlockIterator(const GoBoard& board)
00945 : m_board(board),
00946 m_p(board)
00947 {
00948 if (! *this)
00949 ++(*this);
00950 }
00951
00952 void operator++()
00953 {
00954 do
00955 {
00956 ++m_p;
00957 }
00958 while (m_p && ! *this);
00959 }
00960
00961 SgPoint operator*() const
00962 {
00963 SG_ASSERT(*this);
00964 return *m_p;
00965 }
00966
00967 operator bool() const
00968 {
00969 SgPoint p = *m_p;
00970 return (m_board.Occupied(p) && p == m_board.Anchor(p));
00971 }
00972
00973 private:
00974 const GoBoard& m_board;
00975
00976 GoBoard::Iterator m_p;
00977
00978
00979 GoBlockIterator(const GoBlockIterator&);
00980
00981
00982 GoBlockIterator& operator=(const GoBlockIterator&);
00983 };
00984
00985
00986
00987
00988
00989
00990
00991 class GoRestoreSuicide
00992 {
00993 public:
00994 GoRestoreSuicide(GoBoard& board, bool allow)
00995 : m_board(board),
00996 m_oldState(board.Rules().AllowSuicide())
00997 {
00998 m_board.Rules().SetAllowSuicide(allow);
00999 }
01000
01001 ~GoRestoreSuicide()
01002 {
01003 m_board.Rules().SetAllowSuicide(m_oldState);
01004 }
01005
01006 private:
01007 GoBoard& m_board;
01008
01009 bool m_oldState;
01010
01011
01012 GoRestoreSuicide(const GoRestoreSuicide&);
01013
01014
01015 GoRestoreSuicide& operator=(const GoRestoreSuicide&);
01016 };
01017
01018
01019
01020
01021
01022
01023
01024
01025 class GoRestoreRepetitionAndSuicide
01026 {
01027 public:
01028 GoRestoreRepetitionAndSuicide(GoBoard& board, bool allowAnyRepetition,
01029 bool allowKoRepetition, bool allowSuicide)
01030 : m_board(board),
01031 m_oldAnyRepetition(board.AnyRepetitionAllowed()),
01032 m_oldKoRepetition(board.KoRepetitionAllowed()),
01033 m_oldSuicide(board.Rules().AllowSuicide())
01034 {
01035 m_board.AllowAnyRepetition(allowAnyRepetition);
01036 m_board.AllowKoRepetition(allowKoRepetition);
01037 m_board.Rules().SetAllowSuicide(allowSuicide);
01038 }
01039
01040 ~GoRestoreRepetitionAndSuicide()
01041 {
01042 m_board.AllowAnyRepetition(m_oldAnyRepetition);
01043 m_board.AllowKoRepetition(m_oldKoRepetition);
01044 m_board.Rules().SetAllowSuicide(m_oldSuicide);
01045 }
01046
01047 private:
01048 GoBoard& m_board;
01049
01050
01051 bool m_oldAnyRepetition;
01052
01053 bool m_oldKoRepetition;
01054
01055
01056 bool m_oldSuicide;
01057
01058
01059 GoRestoreRepetitionAndSuicide(const GoRestoreRepetitionAndSuicide&);
01060
01061
01062 GoRestoreRepetitionAndSuicide&
01063 operator=(const GoRestoreRepetitionAndSuicide&);
01064 };
01065
01066
01067
01068
01069
01070 class GoNeighborBlockIterator
01071 : public SgPointIterator
01072 {
01073 public:
01074 GoNeighborBlockIterator(const GoBoard& board, SgPoint p, SgBlackWhite c)
01075 : SgPointIterator(m_points)
01076 {
01077 board.NeighborBlocks(p, c, m_points);
01078 }
01079
01080 GoNeighborBlockIterator(const GoBoard& board, SgPoint p, SgBlackWhite c,
01081 int maxLib)
01082 : SgPointIterator(m_points)
01083 {
01084 board.NeighborBlocks(p, c, maxLib, m_points);
01085 }
01086
01087
01088 private:
01089
01090 SgPoint m_points[5];
01091 };
01092
01093
01094
01095 static const int MAX_ADJACENT = (SG_MAX_SIZE + 1) * (SG_MAX_SIZE + 1) / 4;
01096
01097
01098
01099 template<class BOARD>
01100 class GoAdjBlockIterator
01101 : public SgPointIterator
01102 {
01103 public:
01104 GoAdjBlockIterator(const BOARD& board, SgPoint p, int maxLib);
01105
01106 private:
01107
01108
01109
01110
01111
01112 SgPoint m_points[MAX_ADJACENT];
01113 };
01114
01115 template<class BOARD>
01116 GoAdjBlockIterator<BOARD>::GoAdjBlockIterator(const BOARD& board,
01117 SgPoint p, int maxLib)
01118 : SgPointIterator(m_points)
01119 {
01120 board.AdjacentBlocks(p, maxLib, m_points, MAX_ADJACENT);
01121 }
01122
01123
01124
01125 class GoNbIterator
01126 : public SgNbIterator
01127 {
01128 public:
01129 GoNbIterator(const GoBoard& bd, SgPoint p);
01130 };
01131
01132 inline GoNbIterator::GoNbIterator(const GoBoard& bd, SgPoint p)
01133 : SgNbIterator(bd.BoardConst(), p)
01134 {
01135 }
01136
01137
01138
01139
01140 namespace GoBoardWrite
01141 {
01142
01143
01144 class WriteMap
01145 {
01146 public:
01147 WriteMap(const GoBoard& bd, const SgPointSet& points)
01148 : m_bd(bd),
01149 m_points(points)
01150 {
01151 }
01152
01153 const GoBoard& Board() const {return m_bd;}
01154
01155 const SgPointSet& Points() const { return m_points; }
01156
01157 private:
01158 const GoBoard& m_bd;
01159
01160 const SgPointSet& m_points;
01161 };
01162
01163 }
01164
01165 std::ostream& operator<<(std::ostream& out, const GoBoardWrite::WriteMap& w);
01166
01167
01168
01169 #endif // GO_BOARDUTIL_H