00001 //---------------------------------------------------------------------------- 00002 /** @file GoSafetyCommands.cpp 00003 See GoSafetyCommands.h */ 00004 //---------------------------------------------------------------------------- 00005 00006 #include "SgSystem.h" 00007 #include "GoSafetyCommands.h" 00008 00009 #include "GoBensonSolver.h" 00010 #include "GoBoard.h" 00011 #include "GoGtpCommandUtil.h" 00012 #include "GoModBoard.h" 00013 #include "GoSafetySolver.h" 00014 #include "GoSafetyUtil.h" 00015 #include "SgPointSet.h" 00016 00017 using namespace std; 00018 using GoGtpCommandUtil::BlackWhiteArg; 00019 00020 //---------------------------------------------------------------------------- 00021 00022 GoSafetyCommands::GoSafetyCommands(const GoBoard& bd) 00023 : m_bd(bd) 00024 { 00025 } 00026 00027 void GoSafetyCommands::AddGoGuiAnalyzeCommands(GtpCommand& cmd) 00028 { 00029 cmd << 00030 "plist/Go Safe Dame Static/go_safe_dame_static\n" 00031 "gfx/Go Safe Benson/go_safe_gfx benson\n" 00032 "gfx/Go Safe Static/go_safe_gfx static\n" 00033 "gfx/Go Safe Winner/go_safe_winner\n" 00034 ; 00035 } 00036 00037 /** Return dame points after running static safety algorithm. */ 00038 void GoSafetyCommands::CmdDameStatic(GtpCommand& cmd) 00039 { 00040 cmd.CheckArgNone(); 00041 GoModBoard modBoard(m_bd); 00042 GoBoard& bd = modBoard.Board(); 00043 GoRegionBoard regionAttachment(bd); 00044 GoSafetySolver solver(bd, ®ionAttachment); 00045 SgBWSet safe; 00046 solver.FindSafePoints(&safe); 00047 SgPointSet dame = GoSafetyUtil::FindDamePoints(bd, m_bd.AllEmpty(), safe); 00048 cmd << SgWritePointSet(dame, "", false); 00049 } 00050 00051 /** Information about safe points optimized for graphical display in GoGui. 00052 This command is compatible with GoGui's analyze command type "gfx". 00053 Arguments: benson|static <br> 00054 Returns: GoGui gfx commands to display safe points and additional 00055 information in the status line 00056 - black and white territory: safe points 00057 - Color Magenta (#980098): dame points 00058 - Color Red: safe for black and white (should not happen) 00059 - Circle: unsurroundable 00060 - Status line: point counts, percentage of safe points */ 00061 void GoSafetyCommands::CmdGfx(GtpCommand& cmd) 00062 { 00063 string type = cmd.Arg(); 00064 int totalRegions = 0; 00065 SgBWSet safe = GetSafe(totalRegions, type); 00066 SgPointSet dame; 00067 SgPointSet unsurroundable; 00068 GoSafetyUtil::FindDameAndUnsurroundablePoints(m_bd, m_bd.AllEmpty(), safe, 00069 &dame, &unsurroundable); 00070 cmd << "BLACK"; 00071 for (SgSetIterator it(safe[SG_BLACK]); it; ++it) 00072 cmd << ' ' << SgWritePoint(*it); 00073 cmd << '\n'; 00074 cmd << "WHITE"; 00075 for (SgSetIterator it(safe[SG_WHITE]); it; ++it) 00076 cmd << ' ' << SgWritePoint(*it); 00077 cmd << '\n'; 00078 cmd << "COLOR #980098"; 00079 for (SgSetIterator it(dame); it; ++it) 00080 cmd << ' ' << SgWritePoint(*it); 00081 cmd << '\n'; 00082 cmd << "CIRCLE"; 00083 for (SgSetIterator it(unsurroundable); it; ++it) 00084 cmd << ' ' << SgWritePoint(*it); 00085 cmd << '\n'; 00086 SgPointSet blackAndWhite = safe[SG_WHITE] & safe[SG_BLACK]; 00087 if (blackAndWhite.Size() > 0) 00088 { 00089 // Shouldn't happen 00090 cmd << "COLOR red "; 00091 for (SgSetIterator it(blackAndWhite); it; ++it) 00092 cmd << ' ' << SgWritePoint(*it); 00093 cmd << '\n'; 00094 } 00095 int nuBlack = safe[SG_BLACK].Size(); 00096 int nuWhite = safe[SG_WHITE].Size(); 00097 int nuPoints = m_bd.AllPoints().Size(); 00098 cmd << "TEXT Solver: " << cmd.Arg(0) 00099 << " B: " << nuBlack << " (" << (100 * nuBlack / nuPoints) << " %)" 00100 << " W: " << nuWhite << " (" << (100 * nuWhite / nuPoints) << " %)" 00101 << " Both: " << (nuBlack + nuWhite) 00102 << " (" << (100 * (nuBlack + nuWhite) / nuPoints) << " %)" 00103 << " Regions: " << totalRegions; 00104 } 00105 00106 /** List of safe points. 00107 If no color is given, safe points of both colors are listed. 00108 Arguments: benson|static [black|white]<br> 00109 Returns: number of point followed bu list of points in one line. */ 00110 void GoSafetyCommands::CmdSafe(GtpCommand& cmd) 00111 { 00112 cmd.CheckNuArgLessEqual(2); 00113 string type = cmd.Arg(0); 00114 int totalRegions = 0; 00115 SgBWSet safe = GetSafe(totalRegions, type); 00116 SgPointSet set = 00117 (cmd.NuArg() == 2 ? safe[BlackWhiteArg(cmd, 1)] : safe.Both()); 00118 cmd << set.Size(); 00119 for (SgSetIterator it(set); it; ++it) 00120 cmd << ' ' << SgWritePoint(*it); 00121 } 00122 00123 void GoSafetyCommands::CmdWinner(GtpCommand& cmd) 00124 { 00125 cmd.CheckArgNone(); 00126 const SgEmptyBlackWhite winner = GoSafetyUtil::GetWinner(m_bd); 00127 if (winner == SG_BLACK) 00128 cmd << "black"; 00129 else if (winner == SG_WHITE) 00130 cmd << "white"; 00131 else 00132 cmd << "unknown"; 00133 } 00134 00135 SgBWSet GoSafetyCommands::GetSafe(int& totalRegions, const string& type) 00136 { 00137 GoModBoard modBoard(m_bd); 00138 GoBoard& bd = modBoard.Board(); 00139 GoRegionBoard regionAttachment(bd); 00140 SgBWSet safe; 00141 if (type == "benson") 00142 { 00143 GoBensonSolver solver(bd, ®ionAttachment); 00144 solver.FindSafePoints(&safe); 00145 } 00146 else if (type == "static") 00147 { 00148 GoSafetySolver solver(bd, ®ionAttachment); 00149 solver.FindSafePoints(&safe); 00150 } 00151 else 00152 throw GtpFailure() << "invalid safety solver: " << type; 00153 SgPointSet proved = safe.Both(); 00154 for (SgBWIterator it; it; ++it) 00155 { 00156 SgBlackWhite c = *it; 00157 for (SgVectorIteratorOf<GoRegion> it(regionAttachment.AllRegions(c)); 00158 it; ++it) 00159 if ((*it)->Points().SubsetOf(proved)) 00160 ++totalRegions; 00161 } 00162 return safe; 00163 } 00164 00165 void GoSafetyCommands::Register(GtpEngine& e) 00166 { 00167 Register(e, "go_safe", &GoSafetyCommands::CmdSafe); 00168 Register(e, "go_safe_dame_static", &GoSafetyCommands::CmdDameStatic); 00169 Register(e, "go_safe_gfx", &GoSafetyCommands::CmdGfx); 00170 Register(e, "go_safe_winner", &GoSafetyCommands::CmdWinner); 00171 } 00172 00173 void GoSafetyCommands::Register(GtpEngine& engine, 00174 const std::string& command, 00175 GtpCallback<GoSafetyCommands>::Method method) 00176 { 00177 engine.Register(command, 00178 new GtpCallback<GoSafetyCommands>(this, method)); 00179 } 00180 00181 //----------------------------------------------------------------------------