Index   Main   Namespaces   Classes   Hierarchy   Annotated   Files   Compound   Global   Pages  

GoUctBoard.h

Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 /** @file GoUctBoard.h
00003     Go board optimized for Monte-Carlo. */
00004 //----------------------------------------------------------------------------
00005 
00006 #ifndef GOUCT_BOARD_H
00007 #define GOUCT_BOARD_H
00008 
00009 #include <bitset>
00010 #include <cstring>
00011 #include <stdint.h>
00012 #include <boost/static_assert.hpp>
00013 #include "GoBoard.h"
00014 #include "GoBoardUtil.h"
00015 #include "GoPlayerMove.h"
00016 #include "SgArray.h"
00017 #include "SgArrayList.h"
00018 #include "SgBoardConst.h"
00019 #include "SgBoardColor.h"
00020 #include "SgMarker.h"
00021 #include "SgBWArray.h"
00022 #include "SgNbIterator.h"
00023 #include "SgPoint.h"
00024 #include "SgPointArray.h"
00025 #include "SgPointIterator.h"
00026 
00027 //----------------------------------------------------------------------------
00028 
00029 /** Go board optimized for Monte-Carlo.
00030     In contrast to class GoBoard, this board makes certain assumptions
00031     that are usually true for Monte-Carlo simulations for better efficiency:
00032     - No undo
00033     - Alternating play
00034     - Simple-Ko rule
00035     - Suicide not allowed
00036 
00037     Otherwise, the member functions are named like in class GoBoard to allow
00038     writing utility functions that use the board class as a template parameter
00039     (as long as they use only the functionality shared by both board classes) */
00040 class GoUctBoard
00041 {
00042 public:
00043     /** Marker that can be used in client code.
00044         This marker is never used by this class, it is intended for external
00045         functions that operate on the board and can profit from the fast clear
00046         operation of SgMarker (if reused), but cannot store its own
00047         marker (or don't want to use a global variable for thread-safety).
00048         Since only one function can use this marker at a time, you should
00049         assert with SgReserveMarker that the marker is not used in a
00050         conflicting way. */
00051     mutable SgMarker m_userMarker;
00052 
00053     explicit GoUctBoard(const GoBoard& bd);
00054 
00055     ~GoUctBoard();
00056 
00057     const SgBoardConst& BoardConst() const;
00058 
00059     /** Re-initializes the board from GoBoard position. */
00060     void Init(const GoBoard& bd);
00061 
00062     /** Return the size of this board. */
00063     SgGrid Size() const;
00064 
00065     /** Check if point is occupied by a stone.
00066         Can be called with border points. */
00067     bool Occupied(SgPoint p) const;
00068 
00069     bool IsEmpty(SgPoint p) const;
00070 
00071     bool IsBorder(SgPoint p) const;
00072 
00073     bool IsColor(SgPoint p, int c) const;
00074 
00075     SgBoardColor GetColor(SgPoint p) const;
00076 
00077     SgBlackWhite GetStone(SgPoint p) const;
00078 
00079     /** %Player whose turn it is to play. */
00080     SgBlackWhite ToPlay() const;
00081 
00082     /** Opponent of player whose turn it is to play. */
00083     SgBlackWhite Opponent() const;
00084 
00085     /** See SgBoardConst::Line */
00086     SgGrid Line(SgPoint p) const;
00087 
00088     /** See SgBoardConst::Pos */
00089     SgGrid Pos(SgPoint p) const;
00090 
00091     /** Returns the offset to the point on the line above this point.
00092         Returns zero for points outside the board, and for the center
00093         point(s). */
00094     int Up(SgPoint p) const;
00095 
00096     /** Returns the offset along left side of the board.
00097         Left and right are as seen from the edge toward the center of the
00098         board.
00099         Returns zero for the same points as Up does. */
00100     int Left(SgPoint p) const;
00101 
00102     /** Returns the offset along right side of the board.
00103         @see Left for more info. */
00104     int Right(SgPoint p) const;
00105 
00106     /** Same as Left/Right, but the side is passed in as an index (0 or 1). */
00107     int Side(SgPoint p, int index) const;
00108 
00109     bool IsSuicide(SgPoint p, SgBlackWhite toPlay) const;
00110 
00111     bool IsValidPoint(SgPoint p) const;
00112 
00113     bool HasEmptyNeighbors(SgPoint p) const;
00114 
00115     int NumEmptyNeighbors(SgPoint p) const;
00116 
00117     /** Includes diagonals. */
00118     int Num8EmptyNeighbors(SgPoint p) const;
00119 
00120     bool HasNeighbors(SgPoint p, SgBlackWhite c) const;
00121 
00122     int NumNeighbors(SgPoint p, SgBlackWhite c) const;
00123 
00124     /** Includes diagonals. */
00125     int Num8Neighbors(SgPoint p, SgBlackWhite c) const;
00126 
00127     bool HasDiagonals(SgPoint p, SgBoardColor c) const;
00128 
00129     int NumDiagonals(SgPoint p, SgBoardColor c) const;
00130 
00131     int NumEmptyDiagonals(SgPoint p) const;
00132 
00133     bool HasNeighborsOrDiags(SgPoint p, SgBlackWhite c) const;
00134 
00135     bool InCorner(SgPoint p) const;
00136 
00137     bool OnEdge(SgPoint p) const;
00138 
00139     bool InCenter(SgPoint p) const;
00140 
00141     /** See SgBoardConst::FirstBoardPoint */
00142     int FirstBoardPoint() const;
00143 
00144     /** See SgBoardConst::FirstBoardPoint */
00145     int LastBoardPoint() const;
00146 
00147     /** Play a move for the current player.
00148         @see Play(SgPoint,SgBlackWhite); */
00149     void Play(SgPoint p);
00150 
00151     /** Check whether the move at 'p' is legal.
00152         Since it's not clear how 'p' was arrived at, any value of 'p' is
00153         admissible, even out of point range and on border points; just return
00154         false on such input. */
00155     bool IsLegal(int p, SgBlackWhite player) const;
00156 
00157     /** Check whether the move at 'p' is legal for color to play.
00158         @see IsLegal(int, SgBlackWhite). */
00159     bool IsLegal(int p) const;
00160 
00161     bool IsSuicide(SgPoint p) const;
00162 
00163     /** Whether the most recent move captured any stones. */
00164     bool CapturingMove() const;
00165 
00166     /** The stones removed from the board by the most recent move.
00167         Can be used for incremental update of other data structures.
00168         Only valid directly after a GoUctBoard::Play, otherwise undefined. */
00169     const GoPointList& CapturedStones() const;
00170 
00171     /** The stones captured by the most recent move.
00172         @see CapturedStones */
00173     int NuCapturedStones() const;
00174 
00175     /** The total number of stones of 'color' that have been
00176         captured by the opponent throughout the game. */
00177     int NumPrisoners(SgBlackWhite color) const;
00178 
00179     /** Return last move played.
00180         @return The last move played or SG_NULLMOVE, if
00181         - No move was played yet
00182         - The last move was not by the opposite color of the current player */
00183     SgPoint GetLastMove() const;
00184 
00185     /** 2nd Last move = last move by ToPlay().
00186         Conditions similar to GetLastMove(). */
00187     SgPoint Get2ndLastMove() const;
00188 
00189     /** Return the number of stones in the block at 'p'.
00190         Not defined for empty or border points. */
00191     int NumStones(SgPoint p) const;
00192 
00193     /** Return NumStones(p) == 1. */
00194     bool IsSingleStone(SgPoint p) const;
00195 
00196     /** Return whether the two stones are located in the same block.
00197         Return false if one of the stones is an empty or border point. */
00198     bool AreInSameBlock(SgPoint stone1, SgPoint stone2) const;
00199 
00200     /** Return a reference point in the block at a point.
00201         @note In contrast to GoBoard, the anchor point is not guaranteed
00202         to be the smallest point (this functionality is not needed in
00203         Monte-Carlo)
00204         Requires: Occupied(p). */
00205     SgPoint Anchor(SgPoint p) const;
00206 
00207     /** See GoBoard::IsInBlock */
00208     bool IsInBlock(SgPoint p, SgPoint anchor) const;
00209 
00210     /** See GoBoard::IsLibertyOfBlock */
00211     bool IsLibertyOfBlock(SgPoint p, SgPoint anchor) const;
00212 
00213     /** Get adjacent opponent blocks with a maximum number of liberties for a
00214         given block.
00215         Not defined for empty points.
00216         @param p The block to check.
00217         @param maxLib The maximum number of liberties of the neighbors.
00218         @param anchors Resulting neighbor anchors and an additional END_POINT.
00219         @param maxAnchors Array size of anchors (for detecting overflow in
00220         debug mode)
00221         @return Number of anchors (without the END_POINT) */
00222     int AdjacentBlocks(SgPoint p, int maxLib, SgPoint anchors[],
00223                        int maxAnchors) const;
00224 
00225     /** %List anchor of each block of color 'c' adjacent to the
00226         empty point 'p'.
00227         Assert if 'p' is not empty.
00228         Fill an array of points, terminated by END_POINT. */
00229     void NeighborBlocks(SgPoint p, SgBlackWhite c, SgPoint anchors[]) const;
00230 
00231     /** %List anchor of each block of color 'c' with at most 'maxLib'
00232         liberties adjacent to the empty point 'p'.
00233         Assert if 'p' is not empty.
00234         Fill an array of points, terminated by END_POINT. */
00235     void NeighborBlocks(SgPoint p, SgBlackWhite c, int maxLib,
00236                         SgPoint anchors[]) const;
00237 
00238     /** Return the liberty of 'blockInAtari' which must have exactly
00239         one liberty. */
00240     SgPoint TheLiberty(SgPoint blockInAtari) const;
00241 
00242     /** Return the number of liberties of the block at 'p'.
00243         Not defined for empty or border points. */
00244     int NumLiberties(SgPoint p) const;
00245 
00246     /** Return whether block has at most n liberties. */
00247     bool AtMostNumLibs(SgPoint block, int n) const;
00248 
00249     /** Return whether block has at least n liberties. */
00250     bool AtLeastNumLibs(SgPoint block, int n) const;
00251 
00252     /** Return whether the number of liberties of the block at 'p' is one.
00253         Requires: Occupied(p) */
00254     bool InAtari(SgPoint p) const;
00255 
00256     /** Check if point is occupied and in atari.
00257         Faster than Occupied(p) || InAtari(p).
00258         May be called for border points. */
00259     bool OccupiedInAtari(SgPoint p) const;
00260 
00261     /** Return whether playing colour c at p can capture anything,
00262         ignoring any possible repetition. */
00263     bool CanCapture(SgPoint p, SgBlackWhite c) const;
00264 
00265     /** Checks whether all the board data structures are in a consistent
00266         state. */
00267     void CheckConsistency() const;
00268 
00269 private:
00270     /** Data related to a block of stones on the board. */
00271     struct Block
00272     {
00273     public:
00274         /** Upper limit for liberties.
00275             Proof? */
00276         static const int MAX_LIBERTIES = (SG_MAX_SIZE / 3) * 2 * SG_MAX_SIZE;
00277 
00278         typedef SgArrayList<SgPoint,MAX_LIBERTIES> LibertyList;
00279 
00280         typedef LibertyList::Iterator LibertyIterator;
00281 
00282         typedef GoPointList::Iterator StoneIterator;
00283 
00284         SgPoint m_anchor;
00285 
00286         SgBlackWhite m_color;
00287 
00288         LibertyList m_liberties;
00289 
00290         GoPointList m_stones;
00291 
00292         void InitSingleStoneBlock(SgBlackWhite c, SgPoint anchor)
00293         {
00294             SG_ASSERT_BW(c);
00295             m_color = c;
00296             m_anchor = anchor;
00297             m_stones.SetTo(anchor);
00298             m_liberties.Clear();
00299         }
00300 
00301         void InitNewBlock(SgBlackWhite c, SgPoint anchor)
00302         {
00303             SG_ASSERT_BW(c);
00304             m_color = c;
00305             m_anchor = anchor;
00306             m_stones.Clear();
00307             m_liberties.Clear();
00308         }
00309     };
00310 
00311     SgPoint m_lastMove;
00312 
00313     SgPoint m_secondLastMove;
00314 
00315     /** Point which is currently illegal for simple Ko rule. */
00316     SgPoint m_koPoint;
00317 
00318     /** Whose turn it is to play. */
00319     SgBlackWhite m_toPlay;
00320 
00321     SgArray<Block*,SG_MAXPOINT> m_block;
00322 
00323     /** Number of prisoners of each color */
00324     SgBWArray<int> m_prisoners;
00325 
00326     /** The current board position. */
00327     SgArray<int,SG_MAXPOINT> m_color;
00328 
00329     /** Number of black and white neighbors. */
00330     SgArray<int,SG_MAXPOINT> m_nuNeighborsEmpty;
00331 
00332     /** Number of black and white neighbors. */
00333     SgBWArray<SgArray<int,SG_MAXPOINT> > m_nuNeighbors;
00334 
00335     /** Data that's constant for this board size. */
00336     SgBoardConst m_const;
00337 
00338     /** The current board size. */
00339     SgGrid m_size;
00340 
00341     SgPointArray<Block> m_blockArray;
00342 
00343     mutable SgMarker m_marker;
00344 
00345     SgMarker m_marker2;
00346 
00347     GoPointList m_capturedStones;
00348 
00349     SgArray<bool,SG_MAXPOINT> m_isBorder;
00350 
00351     /** Not implemented. */
00352     GoUctBoard(const GoUctBoard&);
00353 
00354     /** Not implemented. */
00355     GoUctBoard& operator=(const GoUctBoard&);
00356 
00357     void AddLibToAdjBlocks(SgPoint p, SgBlackWhite c);
00358 
00359     void AddStoneToBlock(SgPoint p, Block* block);
00360 
00361     void CreateSingleStoneBlock(SgPoint p, SgBlackWhite c);
00362 
00363     void InitSize(const GoBoard& bd);
00364 
00365     bool IsAdjacentTo(SgPoint p, const Block* block) const;
00366 
00367     void MergeBlocks(SgPoint p, const SgArrayList<Block*,4>& adjBlocks);
00368 
00369     void RemoveLibAndKill(SgPoint p, SgBlackWhite opp,
00370                           SgArrayList<Block*,4>& ownAdjBlocks);
00371 
00372     void UpdateBlocksAfterAddStone(SgPoint p, SgBlackWhite c,
00373                                    const SgArrayList<Block*,4>& adjBlocks);
00374 
00375     void CheckConsistencyBlock(SgPoint p) const;
00376 
00377     bool FullBoardRepetition() const;
00378 
00379     void AddStone(SgPoint p, SgBlackWhite c);
00380 
00381     void KillBlock(const Block* block);
00382 
00383     bool HasLiberties(SgPoint p) const;
00384 
00385 public:
00386     friend class LibertyIterator;
00387     friend class StoneIterator;
00388 
00389     /** Iterate through all points on the given board. */
00390     class Iterator
00391         : public SgPointRangeIterator
00392     {
00393     public:
00394         Iterator(const GoUctBoard& bd);
00395     };
00396 
00397     /** Iterate through all the liberties of a block.
00398         Point 'p' must be occupied.
00399         Liberties should only be accessed for the current board position.
00400         No moves are allowed to be executed during the iteration. */
00401     class LibertyIterator
00402     {
00403     public:
00404         LibertyIterator(const GoUctBoard& bd, SgPoint p);
00405 
00406         /** Advance the state of the iteration to the next liberty. */
00407         void operator++();
00408 
00409         /** Return the current liberty. */
00410         SgPoint operator*() const;
00411 
00412         /** Return true if iteration is valid, otherwise false. */
00413         operator bool() const;
00414 
00415     private:
00416         GoUctBoard::Block::LibertyList::Iterator m_it;
00417 
00418         const GoUctBoard& m_board;
00419 
00420         /** Not implemented. */
00421         LibertyIterator(const LibertyIterator&);
00422 
00423         /** Not implemented. */
00424         LibertyIterator& operator=(const LibertyIterator&);
00425     };
00426 
00427     /** Iterate through all the stones of a block.
00428         Point 'p' must be occupied.
00429         Also, the stones can only be accessed for the current board position. */
00430     class StoneIterator
00431     {
00432     public:
00433         StoneIterator(const GoUctBoard& bd, SgPoint p);
00434 
00435         /** Advance the state of the iteration to the next stone. */
00436         void operator++();
00437 
00438         /** Return the current stone. */
00439         SgPoint operator*() const;
00440 
00441         /** Return true if iteration is valid, otherwise false. */
00442         operator bool() const;
00443 
00444     private:
00445         GoUctBoard::Block::StoneIterator m_it;
00446 
00447         const GoUctBoard& m_board;
00448 
00449         /** Not implemented. */
00450         StoneIterator(const StoneIterator&);
00451 
00452         /** Not implemented. */
00453         StoneIterator& operator=(const StoneIterator&);
00454     };
00455 };
00456 
00457 inline std::ostream& operator<<(std::ostream& out, const GoUctBoard& bd)
00458 {
00459     return GoWriteBoard(out, bd);
00460 }
00461 
00462 inline GoUctBoard::Iterator::Iterator(const GoUctBoard& bd)
00463     : SgPointRangeIterator(bd.BoardConst().BoardIterAddress(),
00464                            bd.BoardConst().BoardIterEnd())
00465 {
00466 }
00467 
00468 inline GoUctBoard::LibertyIterator::LibertyIterator(const GoUctBoard& bd,
00469                                                     SgPoint p)
00470     : m_it(bd.m_block[p]->m_liberties),
00471       m_board(bd)
00472 {
00473     SG_ASSERT(m_board.Occupied(p));
00474 }
00475 
00476 inline void GoUctBoard::LibertyIterator::operator++()
00477 {
00478     ++m_it;
00479 }
00480 
00481 inline SgPoint GoUctBoard::LibertyIterator::operator*() const
00482 {
00483     return *m_it;
00484 }
00485 
00486 inline GoUctBoard::LibertyIterator::operator bool() const
00487 {
00488     return m_it;
00489 }
00490 
00491 inline GoUctBoard::StoneIterator::StoneIterator(const GoUctBoard& bd,
00492                                                 SgPoint p)
00493     : m_it(bd.m_block[p]->m_stones),
00494       m_board(bd)
00495 {
00496     SG_ASSERT(m_board.Occupied(p));
00497 }
00498 
00499 inline void GoUctBoard::StoneIterator::operator++()
00500 {
00501     ++m_it;
00502 }
00503 
00504 inline SgPoint GoUctBoard::StoneIterator::operator*() const
00505 {
00506     return *m_it;
00507 }
00508 
00509 inline GoUctBoard::StoneIterator::operator bool() const
00510 {
00511     return m_it;
00512 }
00513 
00514 inline int GoUctBoard::AdjacentBlocks(SgPoint point, int maxLib,
00515                                       SgPoint anchors[], int maxAnchors) const
00516 {
00517     SG_DEBUG_ONLY(maxAnchors);
00518     SG_ASSERT(Occupied(point));
00519     const SgBlackWhite other = SgOppBW(GetStone(point));
00520     int n = 0;
00521     SgReserveMarker reserve(m_marker);
00522     SG_UNUSED(reserve);
00523     m_marker.Clear();
00524     for (StoneIterator it(*this, point); it; ++it)
00525     {
00526         if (NumNeighbors(*it, other) > 0)
00527         {
00528             SgPoint p = *it;
00529             if (IsColor(p - SG_NS, other)
00530                 && m_marker.NewMark(Anchor(p - SG_NS))
00531                 && AtMostNumLibs(p - SG_NS, maxLib))
00532                 anchors[n++] = Anchor(p - SG_NS);
00533             if (IsColor(p - SG_WE, other)
00534                 && m_marker.NewMark(Anchor(p - SG_WE))
00535                 && AtMostNumLibs(p - SG_WE, maxLib))
00536                 anchors[n++] = Anchor(p - SG_WE);
00537             if (IsColor(p + SG_WE, other)
00538                 && m_marker.NewMark(Anchor(p + SG_WE))
00539                 && AtMostNumLibs(p + SG_WE, maxLib))
00540                 anchors[n++] = Anchor(p + SG_WE);
00541             if (IsColor(p + SG_NS, other)
00542                 && m_marker.NewMark(Anchor(p + SG_NS))
00543                 && AtMostNumLibs(p + SG_NS, maxLib))
00544                 anchors[n++] = Anchor(p + SG_NS);
00545         }
00546     };
00547     // Detect array overflow.
00548     SG_ASSERT(n < maxAnchors);
00549     anchors[n] = SG_ENDPOINT;
00550     return n;
00551 }
00552 
00553 inline SgPoint GoUctBoard::Anchor(SgPoint p) const
00554 {
00555     SG_ASSERT(Occupied(p));
00556     return m_block[p]->m_anchor;
00557 }
00558 
00559 inline bool GoUctBoard::AreInSameBlock(SgPoint p1, SgPoint p2) const
00560 {
00561     return Occupied(p1) && Occupied(p2) && Anchor(p1) == Anchor(p2);
00562 }
00563 
00564 inline bool GoUctBoard::AtLeastNumLibs(SgPoint block, int n) const
00565 {
00566     return NumLiberties(block) >= n;
00567 }
00568 
00569 inline bool GoUctBoard::AtMostNumLibs(SgPoint block, int n) const
00570 {
00571     return NumLiberties(block) <= n;
00572 }
00573 
00574 inline const GoPointList& GoUctBoard::CapturedStones() const
00575 {
00576     return m_capturedStones;
00577 }
00578 
00579 inline bool GoUctBoard::CapturingMove() const
00580 {
00581     return ! m_capturedStones.IsEmpty();
00582 }
00583 
00584 inline int GoUctBoard::FirstBoardPoint() const
00585 {
00586     return m_const.FirstBoardPoint();
00587 }
00588 
00589 inline const SgBoardConst& GoUctBoard::BoardConst() const
00590 {
00591     return m_const;
00592 }
00593 
00594 inline SgPoint GoUctBoard::Get2ndLastMove() const
00595 {
00596     return m_secondLastMove;
00597 }
00598 
00599 inline SgBoardColor GoUctBoard::GetColor(SgPoint p) const
00600 {
00601     return m_color[p];
00602 }
00603 
00604 inline SgPoint GoUctBoard::GetLastMove() const
00605 {
00606     return m_lastMove;
00607 }
00608 
00609 inline SgBlackWhite GoUctBoard::GetStone(SgPoint p) const
00610 {
00611     SG_ASSERT(Occupied(p));
00612     return m_color[p];
00613 }
00614 
00615 inline bool GoUctBoard::HasDiagonals(SgPoint p, SgBoardColor c) const
00616 {
00617     return (IsColor(p - SG_NS - SG_WE, c)
00618             || IsColor(p - SG_NS + SG_WE, c)
00619             || IsColor(p + SG_NS - SG_WE, c)
00620             || IsColor(p + SG_NS + SG_WE, c));
00621 }
00622 
00623 inline bool GoUctBoard::HasEmptyNeighbors(SgPoint p) const
00624 {
00625     return m_nuNeighborsEmpty[p] != 0;
00626 }
00627 
00628 inline bool GoUctBoard::HasLiberties(SgPoint p) const
00629 {
00630     return NumLiberties(p) > 0;
00631 }
00632 
00633 inline bool GoUctBoard::HasNeighbors(SgPoint p, SgBlackWhite c) const
00634 {
00635     return (m_nuNeighbors[c][p] > 0);
00636 }
00637 
00638 inline bool GoUctBoard::HasNeighborsOrDiags(SgPoint p, SgBlackWhite c) const
00639 {
00640     return HasNeighbors(p, c) || HasDiagonals(p, c);
00641 }
00642 
00643 inline bool GoUctBoard::InAtari(SgPoint p) const
00644 {
00645     SG_ASSERT(Occupied(p));
00646     return AtMostNumLibs(p, 1);
00647 }
00648 
00649 inline bool GoUctBoard::IsInBlock(SgPoint p, SgPoint anchor) const
00650 {
00651     SG_ASSERT(Occupied(anchor));
00652     const Block* b = m_block[p];
00653     return (b != 0 && b->m_anchor == anchor);
00654 }
00655 
00656 inline bool GoUctBoard::IsLibertyOfBlock(SgPoint p, SgPoint anchor) const
00657 {
00658     SG_ASSERT(IsEmpty(p));
00659     SG_ASSERT(Occupied(anchor));
00660     SG_ASSERT(Anchor(anchor) == anchor);
00661     const Block* b = m_block[anchor];
00662     if (m_nuNeighbors[b->m_color][p] == 0)
00663         return false;
00664     return (   m_block[p - SG_NS] == b
00665             || m_block[p - SG_WE] == b
00666             || m_block[p + SG_WE] == b
00667             || m_block[p + SG_NS] == b);
00668 }
00669 
00670 inline bool GoUctBoard::CanCapture(SgPoint p, SgBlackWhite c) const
00671 {
00672     SgBlackWhite opp = SgOppBW(c);
00673     for (SgNb4Iterator nb(p); nb; ++nb)
00674         if (IsColor(*nb, opp) && AtMostNumLibs(*nb, 1))
00675             return true;
00676     return false;
00677 }
00678 
00679 inline bool GoUctBoard::IsSuicide(SgPoint p, SgBlackWhite toPlay) const
00680 {
00681     if (HasEmptyNeighbors(p))
00682         return false;
00683     SgBlackWhite opp = SgOppBW(toPlay);
00684     for (SgNb4Iterator it(p); it; ++it)
00685     {
00686         if (IsBorder(*it))
00687             continue;
00688         SgEmptyBlackWhite c = GetColor(*it);
00689         if (c == toPlay && NumLiberties(*it) > 1)
00690             return false;
00691         if (c == opp && NumLiberties(*it) == 1)
00692             return false;
00693     }
00694     return true;
00695 }
00696 
00697 inline bool GoUctBoard::IsBorder(SgPoint p) const
00698 {
00699     SG_ASSERT(p != SG_PASS);
00700     return m_isBorder[p];
00701 }
00702 
00703 inline bool GoUctBoard::IsColor(SgPoint p, int c) const
00704 {
00705     SG_ASSERT(p != SG_PASS);
00706     SG_ASSERT_EBW(c);
00707     return m_color[p] == c;
00708 }
00709 
00710 inline bool GoUctBoard::IsEmpty(SgPoint p) const
00711 {
00712     SG_ASSERT(p != SG_PASS);
00713     return m_color[p] == SG_EMPTY;
00714 }
00715 
00716 inline bool GoUctBoard::IsLegal(int p, SgBlackWhite player) const
00717 {
00718     SG_ASSERT_BW(player);
00719     if (p == SG_PASS)
00720         return true;
00721     SG_ASSERT(SgPointUtil::InBoardRange(p));
00722     if (! IsEmpty(p))
00723         return false;
00724     // Suicide
00725     if (IsSuicide(p, player))
00726         return false;
00727     // Repetition
00728     if (p == m_koPoint && m_toPlay == player)
00729         return false;
00730     return true;
00731 }
00732 
00733 inline bool GoUctBoard::IsLegal(int p) const
00734 {
00735     return IsLegal(p, ToPlay());
00736 }
00737 
00738 inline bool GoUctBoard::IsSingleStone(SgPoint p) const
00739 {
00740     return (Occupied(p) && NumNeighbors(p, GetColor(p)) == 0);
00741 }
00742 
00743 inline bool GoUctBoard::IsSuicide(SgPoint p) const
00744 {
00745     return IsSuicide(p, ToPlay());
00746 }
00747 
00748 inline bool GoUctBoard::IsValidPoint(SgPoint p) const
00749 {
00750     return SgPointUtil::InBoardRange(p) && ! IsBorder(p);
00751 }
00752 
00753 inline int GoUctBoard::LastBoardPoint() const
00754 {
00755     return m_const.LastBoardPoint();
00756 }
00757 
00758 inline int GoUctBoard::Left(SgPoint p) const
00759 {
00760     return m_const.Left(p);
00761 }
00762 
00763 inline SgGrid GoUctBoard::Line(SgPoint p) const
00764 {
00765     return m_const.Line(p);
00766 }
00767 
00768 inline void GoUctBoard::NeighborBlocks(SgPoint p, SgBlackWhite c, int maxLib,
00769                                        SgPoint anchors[]) const
00770 {
00771     SG_ASSERT(IsEmpty(p));
00772     SgReserveMarker reserve(m_marker);
00773     SG_UNUSED(reserve);
00774     m_marker.Clear();
00775     int i = 0;
00776     if (NumNeighbors(p, c) > 0)
00777     {
00778         if (IsColor(p - SG_NS, c) && m_marker.NewMark(Anchor(p - SG_NS))
00779             && AtMostNumLibs(p - SG_NS, maxLib))
00780             anchors[i++] = Anchor(p - SG_NS);
00781         if (IsColor(p - SG_WE, c) && m_marker.NewMark(Anchor(p - SG_WE))
00782             && AtMostNumLibs(p - SG_WE, maxLib))
00783             anchors[i++] = Anchor(p - SG_WE);
00784         if (IsColor(p + SG_WE, c) && m_marker.NewMark(Anchor(p + SG_WE))
00785             && AtMostNumLibs(p + SG_WE, maxLib))
00786             anchors[i++] = Anchor(p + SG_WE);
00787         if (IsColor(p + SG_NS, c) && m_marker.NewMark(Anchor(p + SG_NS))
00788             && AtMostNumLibs(p + SG_NS, maxLib))
00789             anchors[i++] = Anchor(p + SG_NS);
00790     }
00791     anchors[i] = SG_ENDPOINT;
00792 }
00793 
00794 inline int GoUctBoard::Num8Neighbors(SgPoint p, SgBlackWhite c) const
00795 {
00796     return NumNeighbors(p, c) + NumDiagonals(p, c);
00797 }
00798 
00799 inline int GoUctBoard::Num8EmptyNeighbors(SgPoint p) const
00800 {
00801     return NumEmptyNeighbors(p) + NumEmptyDiagonals(p);
00802 }
00803 
00804 inline int GoUctBoard::NuCapturedStones() const
00805 {
00806     return m_capturedStones.Length();
00807 }
00808 
00809 inline int GoUctBoard::NumDiagonals(SgPoint p, SgBoardColor c) const
00810 {
00811     int n = 0;
00812     if (IsColor(p - SG_NS - SG_WE, c))
00813         ++n;
00814     if (IsColor(p - SG_NS + SG_WE, c))
00815         ++n;
00816     if (IsColor(p + SG_NS - SG_WE, c))
00817         ++n;
00818     if (IsColor(p + SG_NS + SG_WE, c))
00819         ++n;
00820     return n;
00821 }
00822 
00823 inline int GoUctBoard::NumEmptyDiagonals(SgPoint p) const
00824 {
00825     return NumDiagonals(p, SG_EMPTY);
00826 }
00827 
00828 inline int GoUctBoard::NumEmptyNeighbors(SgPoint p) const
00829 {
00830     return m_nuNeighborsEmpty[p];
00831 }
00832 
00833 inline int GoUctBoard::NumLiberties(SgPoint p) const
00834 {
00835     SG_ASSERT(IsValidPoint(p));
00836     SG_ASSERT(Occupied(p));
00837     return m_block[p]->m_liberties.Length();
00838 }
00839 
00840 inline int GoUctBoard::NumNeighbors(SgPoint p, SgBlackWhite c) const
00841 {
00842     return m_nuNeighbors[c][p];
00843 }
00844 
00845 inline int GoUctBoard::NumPrisoners(SgBlackWhite color) const
00846 {
00847     return m_prisoners[color];
00848 }
00849 
00850 inline int GoUctBoard::NumStones(SgPoint block) const
00851 {
00852     SG_ASSERT(Occupied(block));
00853     return m_block[block]->m_stones.Length();
00854 }
00855 
00856 inline bool GoUctBoard::Occupied(SgPoint p) const
00857 {
00858     return (m_block[p] != 0);
00859 }
00860 
00861 inline bool GoUctBoard::OccupiedInAtari(SgPoint p) const
00862 {
00863     const Block* b = m_block[p];
00864     return (b != 0 && b->m_liberties.Length() <= 1);
00865 }
00866 
00867 inline SgBlackWhite GoUctBoard::Opponent() const
00868 {
00869     return SgOppBW(m_toPlay);
00870 }
00871 
00872 inline SgGrid GoUctBoard::Pos(SgPoint p) const
00873 {
00874     return m_const.Pos(p);
00875 }
00876 
00877 inline int GoUctBoard::Right(SgPoint p) const
00878 {
00879     return m_const.Right(p);
00880 }
00881 
00882 inline int GoUctBoard::Side(SgPoint p, int index) const
00883 {
00884     return m_const.Side(p, index);
00885 }
00886 
00887 inline SgGrid GoUctBoard::Size() const
00888 {
00889     return m_size;
00890 }
00891 
00892 inline SgPoint GoUctBoard::TheLiberty(SgPoint p) const
00893 {
00894     SG_ASSERT(Occupied(p));
00895     SG_ASSERT(NumLiberties(p) == 1);
00896     return m_block[p]->m_liberties[0];
00897 }
00898 
00899 inline SgBlackWhite GoUctBoard::ToPlay() const
00900 {
00901     return m_toPlay;
00902 }
00903 
00904 inline int GoUctBoard::Up(SgPoint p) const
00905 {
00906     return m_const.Up(p);
00907 }
00908 
00909 //----------------------------------------------------------------------------
00910 
00911 #endif // GOUCT_BOARD_H
00912 


Sun Mar 13 2011 Doxygen 1.7.1