00001 //---------------------------------------------------------------------------- 00002 /** @file FuegoMain.cpp 00003 Main function for Fuego */ 00004 //---------------------------------------------------------------------------- 00005 00006 #include "SgSystem.h" 00007 00008 #include <iostream> 00009 #include <boost/foreach.hpp> 00010 #include <boost/format.hpp> 00011 #include <boost/filesystem/path.hpp> 00012 #include <boost/program_options/options_description.hpp> 00013 #include <boost/program_options/cmdline.hpp> 00014 #include <boost/program_options/variables_map.hpp> 00015 #include <boost/program_options/parsers.hpp> 00016 #include <boost/utility.hpp> 00017 #include "FuegoMainEngine.h" 00018 #include "FuegoMainUtil.h" 00019 #include "GoInit.h" 00020 #include "SgDebug.h" 00021 #include "SgException.h" 00022 #include "SgInit.h" 00023 00024 using namespace std; 00025 using boost::filesystem::path; 00026 using boost::format; 00027 namespace po = boost::program_options; 00028 00029 //---------------------------------------------------------------------------- 00030 00031 namespace { 00032 00033 /** @name Settings from command line options */ 00034 // @{ 00035 00036 bool g_noHandicap = false; 00037 00038 bool g_noBook = false; 00039 00040 bool g_quiet = false; 00041 00042 int g_fixedBoardSize; 00043 00044 int g_maxGames; 00045 00046 string g_config; 00047 00048 path g_programDir; 00049 00050 const char* g_programPath; 00051 00052 int g_srand; 00053 00054 vector<string> g_inputFiles; 00055 00056 // @} // @name 00057 00058 /** Get program directory from program path. 00059 @param programPath Program path taken from @c argv[0] in 00060 @c main. According to ANSI C, this can be @c 0. */ 00061 path GetProgramDir(const char* programPath) 00062 { 00063 if (programPath == 0) 00064 return ""; 00065 return path(programPath, boost::filesystem::native).branch_path(); 00066 } 00067 00068 void Help(po::options_description& desc, ostream& out) 00069 { 00070 out << "Usage: fuego [options] [input files]\n" << desc << "\n"; 00071 exit(0); 00072 } 00073 00074 void ParseOptions(int argc, char** argv) 00075 { 00076 po::options_description normalOptions("Options"); 00077 normalOptions.add_options() 00078 ("config", 00079 po::value<std::string>(&g_config)->default_value(""), 00080 "execuate GTP commands from file before starting main command loop") 00081 ("help", "Displays this help and exit") 00082 ("maxgames", 00083 po::value<int>(&g_maxGames)->default_value(-1), 00084 "make clear_board fail after n invocations") 00085 ("nobook", "don't automatically load opening book") 00086 ("nohandicap", "don't support handicap commands") 00087 ("quiet", "don't print debug messages") 00088 ("srand", 00089 po::value<int>(&g_srand)->default_value(0), 00090 "set random seed (-1:none, 0:time(0))") 00091 ("size", 00092 po::value<int>(&g_fixedBoardSize)->default_value(0), 00093 "initial (and fixed) board size"); 00094 po::options_description hiddenOptions; 00095 hiddenOptions.add_options() 00096 ("input-file", po::value<vector<string> >(&g_inputFiles), 00097 "input file"); 00098 po::options_description allOptions; 00099 allOptions.add(normalOptions).add(hiddenOptions); 00100 po::positional_options_description positionalOptions; 00101 positionalOptions.add("input-file", -1); 00102 po::variables_map vm; 00103 try 00104 { 00105 po::store(po::command_line_parser(argc, argv).options(allOptions). 00106 positional(positionalOptions).run(), vm); 00107 po::notify(vm); 00108 } 00109 catch (...) 00110 { 00111 Help(normalOptions, cerr); 00112 } 00113 if (vm.count("help")) 00114 Help(normalOptions, cout); 00115 if (vm.count("nobook")) 00116 g_noBook = true; 00117 if (vm.count("nohandicap")) 00118 g_noHandicap = true; 00119 if (vm.count("quiet")) 00120 g_quiet = true; 00121 } 00122 00123 void PrintStartupMessage() 00124 { 00125 SgDebug() << 00126 "Fuego " << FuegoMainUtil::Version() << "\n" 00127 "Copyright (C) 2009-2011 by the authors of the Fuego project.\n" 00128 "This program comes with ABSOLUTELY NO WARRANTY. This is\n" 00129 "free software and you are welcome to redistribute it under\n" 00130 "certain conditions. Type `fuego-license' for details.\n\n"; 00131 } 00132 00133 } // namespace 00134 00135 //---------------------------------------------------------------------------- 00136 00137 int main(int argc, char** argv) 00138 { 00139 if (argc > 0 && argv != 0) 00140 { 00141 g_programPath = argv[0]; 00142 g_programDir = GetProgramDir(argv[0]); 00143 try 00144 { 00145 ParseOptions(argc, argv); 00146 } 00147 catch (const SgException& e) 00148 { 00149 SgDebug() << e.what() << "\n"; 00150 return 1; 00151 } 00152 } 00153 if (g_quiet) 00154 SgDebugToNull(); 00155 try 00156 { 00157 SgInit(); 00158 GoInit(); 00159 PrintStartupMessage(); 00160 SgRandom::SetSeed(g_srand); 00161 FuegoMainEngine engine(g_fixedBoardSize, g_programPath, g_noHandicap); 00162 GoGtpAssertionHandler assertionHandler(engine); 00163 if (g_maxGames >= 0) 00164 engine.SetMaxClearBoard(g_maxGames); 00165 if (! g_noBook) 00166 FuegoMainUtil::LoadBook(engine.Book(), g_programDir); 00167 if (g_config != "") 00168 engine.ExecuteFile(g_config); 00169 if (! g_inputFiles.empty()) 00170 { 00171 for(size_t i = 0; i < g_inputFiles.size(); i++) 00172 { 00173 string file = g_inputFiles[i]; 00174 ifstream fin(file.c_str()); 00175 if (! fin) 00176 throw SgException(format("Error file '%1%'") % file); 00177 GtpInputStream in(fin); 00178 GtpOutputStream out(cout); 00179 engine.MainLoop(in, out); 00180 } 00181 } 00182 else 00183 { 00184 GtpInputStream in(cin); 00185 GtpOutputStream out(cout); 00186 engine.MainLoop(in, out); 00187 } 00188 } 00189 catch (const GtpFailure& e) 00190 { 00191 SgDebug() << e.Response() << '\n'; 00192 return 1; 00193 } 00194 catch (const std::exception& e) 00195 { 00196 SgDebug() << e.what() << '\n'; 00197 return 1; 00198 } 00199 return 0; 00200 } 00201 00202 //---------------------------------------------------------------------------- 00203