00001
00002
00003
00004
00005
00006
00007 #include "SgSystem.h"
00008 #include "SpDumbTacticalPlayer.h"
00009
00010 #include "GoBensonSolver.h"
00011 #include "GoBoardUtil.h"
00012 #include "GoLadder.h"
00013 #include "SgEvaluatedMoves.h"
00014 #include "SgNbIterator.h"
00015
00016 using GoLadderUtil::LadderStatus;
00017
00018
00019
00020 SpDumbTacticalMoveGenerator::SpDumbTacticalMoveGenerator(GoBoard& board)
00021 : SpStaticMoveGenerator(board), m_useLadders(false)
00022 { }
00023
00024 int SpDumbTacticalMoveGenerator::Score(SgPoint p)
00025 {
00026 SG_UNUSED(p);
00027
00028
00029 SG_ASSERT(false);
00030 return INT_MIN;
00031 }
00032
00033 void SpDumbTacticalMoveGenerator::GenerateMoves(SgEvaluatedMoves& eval,
00034 SgBlackWhite toPlay)
00035 {
00036 GoRestoreToPlay restoreToPlay(m_board);
00037 m_board.SetToPlay(toPlay);
00038
00039 GoRestoreSuicide restoreSuicide(m_board, false);
00040 GenerateDefendMoves(eval);
00041 GenerateAttackMoves(eval);
00042
00043
00044
00045 }
00046
00047 void SpDumbTacticalMoveGenerator::GenerateDefendMoves(SgEvaluatedMoves& eval)
00048 {
00049 const int stoneweight = 1000;
00050
00051 for (GoBlockIterator anchorit(m_board); anchorit; ++anchorit)
00052 {
00053
00054 if (m_board.IsColor(*anchorit, m_board.Opponent()))
00055 continue;
00056
00057
00058 if (! m_board.InAtari(*anchorit))
00059 continue;
00060
00061
00062 if (m_useLadders)
00063 {
00064 GoLadderStatus status = LadderStatus(m_board, *anchorit, false);
00065 if (status == GO_LADDER_CAPTURED)
00066 continue;
00067 }
00068
00069 int score = stoneweight * m_board.NumStones(*anchorit);
00070
00071
00072 eval.AddMove(m_board.TheLiberty(*anchorit), score);
00073
00074
00075 for (GoAdjBlockIterator<GoBoard> adjbit(m_board, *anchorit, 1);
00076 adjbit; ++adjbit)
00077 {
00078 int bonus = stoneweight * m_board.NumStones(*adjbit);
00079 if (m_board.InAtari(*adjbit))
00080
00081 {
00082 eval.AddMove(m_board.TheLiberty(*adjbit), score + bonus);
00083 }
00084 }
00085 }
00086 }
00087
00088 void SpDumbTacticalMoveGenerator::GenerateAttackMoves(SgEvaluatedMoves& eval)
00089 {
00090 const int capturestoneweight = 100;
00091 const int firstlibweight = 100;
00092 const int secondlibweight = 20;
00093 const int stoneweight = 1;
00094
00095
00096 SgBWSet safepoints;
00097 GoBensonSolver benson(m_board);
00098 benson.FindSafePoints(&safepoints);
00099
00100
00101 for (GoBlockIterator anchorit(m_board); anchorit; ++anchorit)
00102 {
00103
00104 if (m_board.IsColor(*anchorit, m_board.ToPlay()))
00105 continue;
00106
00107
00108 if (safepoints[m_board.Opponent()].Contains(*anchorit))
00109 continue;
00110
00111
00112 if (m_useLadders)
00113 {
00114 SgPoint tocapture, toescape;
00115 GoLadderStatus status = LadderStatus(m_board, *anchorit, false,
00116 &tocapture, &toescape);
00117 if (status == GO_LADDER_CAPTURED)
00118 {
00119 int score = m_board.NumStones(*anchorit) * capturestoneweight;
00120 eval.AddMove(tocapture, score);
00121 }
00122 }
00123
00124
00125
00126
00127
00128
00129 int firstlibs = m_board.NumLiberties(*anchorit);
00130 int size = m_board.NumStones(*anchorit);
00131 for (GoBoard::LibertyIterator libit(m_board, *anchorit); libit;
00132 ++libit)
00133 {
00134 int secondlibs = 0;
00135 for (SgNb4Iterator nbit(*libit); nbit; ++nbit)
00136 {
00137 if (m_board.IsValidPoint(*nbit) && m_board.IsEmpty(*nbit))
00138 {
00139 secondlibs++;
00140 }
00141 }
00142 int score = size * stoneweight
00143 + secondlibs * secondlibweight
00144 - firstlibs * firstlibweight;
00145 eval.AddMove(*libit, score);
00146 }
00147 }
00148 }
00149
00150