Main   Namespaces   Classes   Hierarchy   Annotated   Files   Compound   Global   Pages  

TwoDistance.cpp

Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 /** @file
00003  */
00004 //----------------------------------------------------------------------------
00005 
00006 #include "Hex.hpp"
00007 #include "BitsetIterator.hpp"
00008 #include "TwoDistance.hpp"
00009 #include "VCSet.hpp"
00010 
00011 using namespace benzene;
00012 
00013 //----------------------------------------------------------------------------
00014 
00015 TwoDistance::TwoDistance(NeighbourType ntype)
00016     : m_brd(0),
00017       m_ntype(ntype),
00018       m_score(0)
00019 {
00020 }
00021 
00022 TwoDistance::~TwoDistance()
00023 {
00024 }
00025 
00026 //----------------------------------------------------------------------------
00027 
00028 void TwoDistance::Evaluate(const HexBoard& brd)
00029 {
00030     m_brd = &brd;
00031     for (BWIterator it; it; ++it)
00032         ComputeScores(*it, m_scores[*it]);
00033     ComputeScore();
00034 }
00035 
00036 void TwoDistance::ComputeScores(HexColor color, HexEval* out)
00037 {
00038     HexEval dist[2][BITSETSIZE];
00039     ComputeDistanceToEdge(color, HexPointUtil::colorEdge1(color), dist[0]);
00040     ComputeDistanceToEdge(color, HexPointUtil::colorEdge2(color), dist[1]);
00041 
00042     for (BoardIterator it(m_brd->Const().Interior()); it; ++it) 
00043     {
00044         if (m_brd->GetPosition().IsOccupied(*it))
00045             out[*it] = 0;
00046         else 
00047             out[*it] = TwoDistUtil::AddDistance(dist[0][*it], dist[1][*it]);
00048             //out[*it] = dist[0][*it];
00049     }
00050 }
00051 
00052 void TwoDistance::FindBest(HexEval* po, HexPoint& who, int& count)
00053 {
00054     HexEval best = EVAL_INFINITY;
00055     who = INVALID_POINT;
00056     count = 1;
00057 
00058     for (BitsetIterator it(m_brd->GetPosition().GetEmpty()); it; ++it) 
00059     {
00060         if (po[*it] < best) 
00061         {
00062             best = po[*it];
00063             who = *it;
00064             count=1;
00065         }
00066         else if (po[*it] == best) 
00067             count++;
00068     }
00069 
00070     HexAssert(who != INVALID_POINT);
00071     HexAssert(best != EVAL_INFINITY);
00072 }
00073 
00074 void TwoDistance::ComputeScore()
00075 {
00076     HexPoint black, white;
00077     int black_count, white_count;
00078     int SCALE_FACTOR = 1; // FIXME: what is a good value?
00079 
00080     FindBest(m_scores[BLACK], black, black_count);
00081     FindBest(m_scores[WHITE], white, white_count);
00082 
00083     m_score = (black - white)*SCALE_FACTOR + (black_count - white_count);
00084 }
00085 
00086 //----------------------------------------------------------------------------
00087 
00088 bool TwoDistance::IsAdjacent(HexColor color, HexPoint p1, HexPoint p2)
00089 {
00090     VC vc;
00091     if (m_brd->Cons(color).SmallestVC(p1, p2, VC::FULL, vc)) {
00092         switch(m_ntype) {
00093         case ADJACENT: return vc.IsEmpty(); 
00094         case  FULL_VC: return true;
00095         }
00096     }
00097     return false;
00098 }
00099 
00100 void TwoDistance::ComputeDistanceToEdge(HexColor color,
00101                                         HexPoint edge, 
00102                                         HexEval* out)
00103 {
00104     SetAllToInfinity(out);
00105     
00106     //
00107     // FIXME: how to sort queue by increasing order without using
00108     // negative priorities?  
00109     //
00110     //    q(std::less<std::pair<int, HexPoint> >)
00111     //
00112     // doesn't seem to work.
00113     //
00114 
00115     std::priority_queue<std::pair<int, HexPoint> > q;
00116     std::set<HexPoint> done;
00117     std::set<HexPoint> once;
00118 
00119     // add immediate neighbours of edge
00120     for (BitsetIterator it(m_brd->GetPosition().GetEmpty()); it; ++it) 
00121     {
00122         if (IsAdjacent(color, *it, edge)) 
00123         {
00124             out[*it] = 1;
00125             q.push(std::make_pair(-1, *it));
00126             done.insert(*it);
00127         }
00128     }
00129 
00130     while (!q.empty()) {
00131         std::pair<int, HexPoint> pp = q.top();
00132         q.pop();
00133 
00134         int dist = -pp.first;        
00135         HexPoint p = pp.second;
00136                   
00137         for (BitsetIterator it(m_brd->GetPosition().GetEmpty()); it; ++it) 
00138         {
00139             if (IsAdjacent(color, *it, p)) 
00140             {
00141                 // it has been seen at least twice before, ignore it.
00142                 if (done.count(*it))
00143                     continue;
00144                 // it has been seen once before, add it to queue
00145                 // and add to 'done'.
00146                 else if (once.count(*it)) 
00147                 {
00148                     out[*it] = dist+1;
00149                     q.push(std::make_pair(-(dist+1), *it));
00150                     done.insert(*it);
00151                 } 
00152                 // it hasn't been seen before: add it to 'once'.
00153                 else
00154                     once.insert(*it);
00155             }
00156         }
00157     }
00158 }
00159 
00160 void TwoDistance::SetAllToInfinity(HexEval* out)
00161 {
00162     for (BoardIterator it(m_brd->Const().Interior()); it; ++it)
00163         out[*it] = EVAL_INFINITY;
00164 }
00165 
00166 //----------------------------------------------------------------------------
00167 
00168 HexEval TwoDistUtil::AddDistance(HexEval a, HexEval b)
00169 {
00170     if (a == EVAL_INFINITY || b == EVAL_INFINITY)
00171         return EVAL_INFINITY;
00172     return a + b;
00173 }
00174 
00175 //----------------------------------------------------------------------------


6 Jan 2011 Doxygen 1.6.3