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