00001 //---------------------------------------------------------------------------- 00002 /** @file ProofUtil.cpp 00003 */ 00004 //---------------------------------------------------------------------------- 00005 00006 #include "Hex.hpp" 00007 #include "BoardUtils.hpp" 00008 #include "BitsetIterator.hpp" 00009 #include "DfsSolver.hpp" 00010 #include "ProofUtil.hpp" 00011 #include "SortedSequence.hpp" 00012 00013 using namespace benzene; 00014 00015 //---------------------------------------------------------------------------- 00016 00017 bitset_t ProofUtil::MaximumProofSet(const HexBoard& brd, HexColor toPlay) 00018 { 00019 return brd.GetPosition().GetEmpty() 00020 | brd.GetPosition().GetPlayed(toPlay) 00021 | brd.GetInferiorCells().DeductionSet(toPlay); 00022 } 00023 00024 bitset_t ProofUtil::InitialProofForOpponent(const HexBoard& brd, 00025 HexColor toPlay) 00026 { 00027 // Add opponent played stones and deduction set. 00028 const InferiorCells& inf = brd.GetInferiorCells(); 00029 bitset_t proof = brd.GetPosition().GetPlayed(!toPlay); 00030 proof |= inf.DeductionSet(!toPlay); 00031 00032 // Add all semi-connections from the mustplay. 00033 const VCList& lst = brd.Cons(!toPlay).GetList(VC::SEMI, 00034 HexPointUtil::colorEdge1(!toPlay), 00035 HexPointUtil::colorEdge2(!toPlay)); 00036 const bool useGreedy = brd.Builder().Parameters().use_greedy_union; 00037 proof |= useGreedy ? lst.getGreedyUnion() : lst.getUnion(); 00038 00039 // Add reversable reversers. 00040 // The carriers do NOT need to be included in the proof, since 00041 // they are captured by the (losing) player, not his opponent (for 00042 // whom we are building the proof set). 00043 // TODO: Currently, we just add the first reverser: we should see 00044 // if any reverser is already in the proof, since then we wouldn't 00045 // need to add one. 00046 for (BitsetIterator p(inf.Reversible()); p; ++p) 00047 { 00048 const std::set<HexPoint>& reversers = inf.Reversers(*p); 00049 proof.set(*reversers.begin()); 00050 } 00051 // Add vulnerable killers and their carriers. 00052 // TODO: Currently, we just add the first killer: we should see if 00053 // any killer is already in the proof, since then we wouldn't need 00054 // to add one. 00055 for (BitsetIterator p(inf.Vulnerable()); p; ++p) 00056 { 00057 const std::set<VulnerableKiller>& killers = inf.Killers(*p); 00058 proof.set((*killers.begin()).killer()); 00059 proof |= ((*killers.begin()).carrier()); 00060 } 00061 return proof; 00062 } 00063 00064 bool ProofUtil::ShrinkProof(bitset_t& proof, const StoneBoard& board, 00065 HexColor loser, const ICEngine& ice) 00066 { 00067 StoneBoard brd(board.Width(), board.Height()); 00068 PatternState pastate(brd); 00069 Groups groups; 00070 00071 // Give loser all cells outside proof 00072 bitset_t cells_outside_proof = (~proof & brd.Const().GetCells()); 00073 brd.AddColor(loser, cells_outside_proof); 00074 00075 // Give winner only his stones inside proof; 00076 HexColor winner = !loser; 00077 brd.AddColor(winner, board.GetPlayed(winner) & proof); 00078 pastate.Update(); 00079 GroupBuilder::Build(brd, groups); 00080 00081 // Compute fillin and remove captured cells from the proof 00082 InferiorCells inf; 00083 ice.ComputeFillin(loser, groups, pastate, inf, 00084 HexColorSetUtil::Only(loser)); 00085 HexAssert(inf.Captured(winner).none()); 00086 00087 bitset_t filled = inf.Dead() | inf.Captured(loser); 00088 bitset_t shrunk_proof = proof - filled; 00089 bool shrunkTheProof = shrunk_proof.count() < proof.count(); 00090 proof = shrunk_proof; 00091 return shrunkTheProof; 00092 } 00093 00094 //----------------------------------------------------------------------------