Main   Namespaces   Classes   Hierarchy   Annotated   Files   Compound   Global   Pages  

ProofUtil.hpp

Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 /** @file ProofUtil.hpp
00003  */
00004 //----------------------------------------------------------------------------
00005 
00006 #ifndef PROOFUTIL_HPP
00007 #define PROOFUTIL_HPP
00008 
00009 #include "Hex.hpp"
00010 #include "BenzeneSolver.hpp"
00011 #include "StoneBoard.hpp"
00012 #include "ICEngine.hpp"
00013 #include "SolverDB.hpp"
00014 #include "SortedSequence.hpp"
00015 
00016 _BEGIN_BENZENE_NAMESPACE_
00017 
00018 //----------------------------------------------------------------------------
00019 
00020 /** Deduce equivalent states, etc. */
00021 namespace ProofUtil 
00022 {
00023     /** Compute the maximum possible proof. */
00024     bitset_t MaximumProofSet(const HexBoard& brd, HexColor toPlay);
00025 
00026     /** The proof for a losing state is the union the proofs for each
00027         move. This function returns the proof defined by all opponent
00028         semi-connctions as well as any ice deductions. 
00029         @note The proof is for the opponent of toPlay.
00030         @todo Argh, document this better. */
00031     bitset_t InitialProofForOpponent(const HexBoard& brd, HexColor toPlay);
00032 
00033     /** Gives all cells outside of the proof to loser, computes fillin
00034         using ice, removes any cell in proof that is filled-in. 
00035         Returns true if proof was shrunk. */
00036     bool ShrinkProof(bitset_t& proof, const StoneBoard& board,
00037                      HexColor loser, const ICEngine& ice);
00038 
00039     /** Computes and stores in db the transpostions of this proof on
00040         the given boardstate. Returns number of db entries
00041         successfully added or updated. */
00042     template<class HASH, class DB, class DATA>
00043     int StoreTranspositions(SolverDB<HASH,DB,DATA>& db, const DATA& data,
00044                             const HexState& state, const bitset_t& proof, 
00045                             HexColor winner);
00046 
00047     /** Computes and stores in db the flipped transpostions of this
00048         proof on the given boardstate. Returns number of db entries
00049         successfully added or updated. */
00050     template<class HASH, class DB, class DATA>
00051     int StoreFlippedStates(SolverDB<HASH,DB,DATA>& db, const DATA& data,
00052                            const HexState& state, const bitset_t& proof, 
00053                            HexColor winner);
00054 }
00055 
00056 //----------------------------------------------------------------------------
00057 
00058 template<class HASH, class DB, class DATA>
00059 int ProofUtil::StoreTranspositions(SolverDB<HASH,DB,DATA>& db, 
00060                                    const DATA& data, const HexState& state,
00061                                    const bitset_t& proof, HexColor winner)
00062 {
00063     boost::function_requires< HasFlagsConcept<DATA> >();
00064     const StoneBoard& brd = state.Position();
00065 
00066     // Number of non-fillin game stones played
00067     int numBlack = (brd.GetPlayed(BLACK) & brd.Const().GetCells()).count();
00068     int numWhite = (brd.GetPlayed(WHITE) & brd.Const().GetCells()).count();
00069     HexAssert(numBlack + numWhite == brd.NumStones());
00070 
00071     // Loser can use all his stones as well as all those outside the proof
00072     HexColor loser = !winner;
00073     bitset_t outside = (~proof & brd.GetEmpty()) 
00074         | (brd.GetColor(loser) & brd.Const().GetCells());
00075 
00076     // Winner can use all of his stones
00077     bitset_t winners = brd.GetColor(winner) & brd.Const().GetCells();
00078 
00079     // Store the players' stones as lists of sorted indices  
00080     std::vector<HexPoint> black, white;
00081     std::vector<HexPoint>& lose_list = (loser == BLACK) ? black : white;
00082     std::vector<HexPoint>& winn_list = (loser == BLACK) ? white : black;
00083     BitsetUtil::BitsetToVector(outside, lose_list);
00084     BitsetUtil::BitsetToVector(winners, winn_list);
00085 
00086     HexAssert(black.size() >= (unsigned)numBlack);
00087     HexAssert(white.size() >= (unsigned)numWhite);
00088 
00089     // Write each transposition 
00090     int count = 0;
00091     HexState myState(state);
00092     StoneBoard& board = myState.Position();
00093     SortedSequence bseq(black.size(), numBlack);
00094     while (!bseq.finished()) 
00095     {
00096         SortedSequence wseq(white.size(), numWhite);
00097         while (!wseq.finished()) 
00098         {
00099             // Convert the indices into cells
00100             board.StartNewGame();
00101             for (int i = 0; i < numBlack; ++i)
00102                 board.PlayMove(BLACK, black[bseq[i]]);
00103             for (int i = 0; i < numWhite; ++i)
00104                 board.PlayMove(WHITE, white[wseq[i]]);
00105 
00106             // Mark state as transposition if the current one is not
00107             // the original.
00108             DATA ss(data);
00109             if (board.Hash() != brd.Hash())
00110                 ss.m_flags |= SolverDataFlags::TRANSPOSITION;
00111             db.Put(myState, ss);
00112             ++count;
00113             
00114             ++wseq;
00115         }
00116         ++bseq;
00117     }
00118     return count;
00119 }
00120 
00121 template<class HASH, class DB, class DATA>
00122 int ProofUtil::StoreFlippedStates(SolverDB<HASH,DB,DATA>& db, const DATA& data,
00123                                   const HexState& state, const bitset_t& proof,
00124                                   HexColor winner)
00125 {
00126     boost::function_requires< HasFlagsConcept<DATA> >();
00127     boost::function_requires< HasMirrorConcept<DATA> >();
00128     const StoneBoard& brd = state.Position();
00129 
00130     // Start by computing the flipped board position.
00131     // This involves mirroring the stones and *flipping their colour*.
00132     bitset_t flippedBlack = BoardUtils::Mirror(brd.Const(), 
00133                     brd.GetPlayed(WHITE) & brd.Const().GetCells());
00134     bitset_t flippedWhite = BoardUtils::Mirror(brd.Const(),
00135                     brd.GetPlayed(BLACK) & brd.Const().GetCells());
00136     StoneBoard flippedBrd(brd.Width(), brd.Height());
00137     flippedBrd.AddColor(BLACK, flippedBlack);
00138     flippedBrd.AddColor(WHITE, flippedWhite);
00139     flippedBrd.SetPlayed(flippedBlack | flippedWhite);
00140 
00141     
00142     HexColor flippedWinner = !winner;
00143     bitset_t flippedProof = BoardUtils::Mirror(brd.Const(), proof);
00144     bitset_t flippedOutside = (~flippedProof & flippedBrd.GetEmpty());
00145     
00146     // Determine what stones we can add or remove.
00147     bool canAddFlippedBlack = false;
00148     bitset_t flippedBlackToAdd;
00149     bool canRemoveFlippedWhite = false;
00150     bitset_t flippedWhiteToRemove;
00151     // To switch player to move (while keeping parity valid), we must
00152     // either add one stone to flippedBlack or else delete 1 stone
00153     // from flippedWhite. Note that we can always add winner stones or
00154     // delete loser stones without changing the value, and we can add
00155     // loser stones if the proof set does not cover all empty cells.
00156     if (flippedWinner == BLACK) 
00157     {
00158     canAddFlippedBlack = true;
00159     flippedBlackToAdd = flippedBrd.GetEmpty();
00160     canRemoveFlippedWhite = true;
00161     flippedWhiteToRemove = flippedWhite;
00162     } 
00163     else 
00164     {
00165     HexAssert(flippedWinner == WHITE);
00166     canAddFlippedBlack = flippedOutside.any();
00167     flippedBlackToAdd = flippedOutside;
00168     }
00169     HexAssert(canAddFlippedBlack != flippedBlackToAdd.none());
00170     HexAssert(BitsetUtil::IsSubsetOf(flippedBlackToAdd,flippedBrd.GetEmpty()));
00171     HexAssert(canRemoveFlippedWhite != flippedWhiteToRemove.none());
00172     HexAssert(BitsetUtil::IsSubsetOf(flippedWhiteToRemove,flippedWhite));
00173     
00174     // Now we can create and store the desired flipped states.
00175     DATA ss(data);
00176     ss.Mirror(brd.Const());
00177     ss.m_flags |= SolverDataFlags::TRANSPOSITION;
00178     ss.m_flags |= SolverDataFlags::MIRROR_TRANSPOSITION;
00179     
00180     int count = 0;
00181     if (canAddFlippedBlack) 
00182     {
00183     for (BitsetIterator i(flippedBlackToAdd); i; ++i) 
00184         {
00185         flippedBrd.PlayMove(BLACK, *i);
00186         HexAssert(!state.ToPlay() == flippedBrd.WhoseTurn());
00187         db.Put(HexState(flippedBrd, WHITE), ss);
00188         flippedBrd.UndoMove(*i);
00189             ++count;
00190     }
00191     }
00192     if (canRemoveFlippedWhite) 
00193     {
00194     for (BitsetIterator i(flippedWhiteToRemove); i; ++i) 
00195         {
00196         flippedBrd.UndoMove(*i);
00197         HexAssert(!state.ToPlay() == flippedBrd.WhoseTurn());
00198         db.Put(HexState(flippedBrd, WHITE), ss);
00199         flippedBrd.PlayMove(WHITE, *i);
00200             ++count;
00201     }
00202     }
00203     return count;
00204 }
00205 
00206 //----------------------------------------------------------------------------
00207 
00208 _END_BENZENE_NAMESPACE_
00209 
00210 #endif // PROOFUTIL_HPP


6 Jan 2011 Doxygen 1.6.3