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