00001 //---------------------------------------------------------------------------- 00002 /** @file SpMinLibPlayer.cpp 00003 See SpMinLibPlayer.h */ 00004 //---------------------------------------------------------------------------- 00005 00006 #include "SgSystem.h" 00007 #include "SpMinLibPlayer.h" 00008 00009 #include "SpAveragePlayer.h" 00010 #include "SgConnCompIterator.h" 00011 00012 //---------------------------------------------------------------------------- 00013 00014 /** Value corresponding to minimum liberties for EITHER color */ 00015 int SpMinLibMoveGenerator::LibertyMinimum(SgBlackWhite toplay) 00016 { 00017 int minlibs = INT_MAX; 00018 float sign = 1; 00019 SgBlackWhite opponent = SgOpp(toplay); 00020 const int size = m_board.Size(); 00021 for (SgConnCompIterator it(m_board.All(toplay), m_board.Size()); it; ++it) 00022 { 00023 // Subtract a little from liberties, 00024 // breaking ties to save own stones rather than attacking 00025 int libs = ((*it).Border(size) & m_board.AllEmpty()).Size() * 2 - 1; 00026 if (libs < minlibs) 00027 { 00028 minlibs = libs; 00029 sign = -1; // If we have minimum liberties that's bad 00030 } 00031 } 00032 00033 for (SgConnCompIterator it(m_board.All(opponent), m_board.Size()); 00034 it; ++it) 00035 { 00036 int libs = ((*it).Border(size) & m_board.AllEmpty()).Size() * 2; 00037 if (libs < minlibs) 00038 { 00039 minlibs = libs; 00040 sign = 1; // If opponent has minimum liberties that's good 00041 } 00042 } 00043 00044 // Evaluation is inversely proportional to minlibs value 00045 // with appropriate sign 00046 SG_ASSERT(minlibs != 0); 00047 float eval = 100.f * sign / float(minlibs); // in range [-100, 100] 00048 return static_cast<int>(eval); 00049 } 00050 00051 int SpMinLibMoveGenerator::Evaluate() 00052 { 00053 // We are Opponent since this is after executing our move 00054 SgBlackWhite player = m_board.Opponent(); 00055 int minlibscore = LibertyMinimum(player); 00056 00057 int avlibscore = 00058 ::LibertyAveragex10(m_board, player) 00059 - ::LibertyAveragex10(m_board, SgOppBW(player)); 00060 00061 // Select moves in priority order according to: 00062 // a) Minimum liberties (for either player) 00063 // b) Average liberties x 10 00064 00065 // Note that the 1/x scaling of minlibs means that avlibs can matter more 00066 // when |minlibs| is very high. Which is probably a good thing! 00067 int score = minlibscore * 100 + avlibscore; 00068 // roughly in range [-10000,10000] 00069 return score; 00070 } 00071 00072 //---------------------------------------------------------------------------- 00073