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


17 Jun 2010 Doxygen 1.4.7