int main(int argc, char **argv) { int debugVal, minimaxLevel, bookDepth; string boardClassString, outputFileName; const BoardClass *brdCls; Board *board; View *view; ofstream outFile; Book *book = new Book(); debugVal = argc > 1 ? atoi(argv[1]) : 0; cout << "Enter boardType, level, depth, and filename: "; cin >> boardClassString >> minimaxLevel >> bookDepth >> outputFileName; if (!cin) exit(1); if (!(brdCls = dynamic_cast<const BoardClass *> (Class::ForName(boardClassString)))) { cerr << "Unknown type " << boardClassString << endl; exit(1); } if (!(board = dynamic_cast<Board *> (brdCls->NewInstance()))) { cerr << "Could not create the Board" << endl; exit(1); } if (!(view = dynamic_cast<View *>(brdCls->GetViewClass()->NewInstance()))) { cerr << "Could not create the View" << endl; exit(1); } view->SetModel(board); outFile.open(outputFileName.c_str(), ios::out | ios::binary | ios::trunc); if (!outFile.is_open()) { cerr << "Could not open file for writing" << endl; exit(1); } book->SetLevel(minimaxLevel); BuildBook(book, board, view, minimaxLevel, bookDepth, debugVal); cout << "Writing book..."; book->Write(outFile); cout << " done" << endl; cout << "Before clearing book, moves/keys: " << Board::Move::GetOutstanding() << "/" << Board::Key::GetOutstanding() << endl; delete book; book = 0; cout << "Final count, moves/keys: " << Board::Move::GetOutstanding() << "/" << Board::Key::GetOutstanding() << endl; delete board; delete view; return 0; }
// [Staley] Write a program “MakeBook” that works like the sample executable // [Staley] provided. MakeBook prompts for and accepts a single line of input // [Staley] of the form: // [Staley] // [Staley] BoardClass level depth fileName // [Staley] // [Staley] MinimaxLevel is the minimax lookahead to use when determining a // [Staley] best move for each board key. BookDepth indicates how many boards // [Staley] to generate. Specifically, it tells how many halfmoves from the // [Staley] starting board should be covered by the bookFile file. A level // [Staley] of 5 and a depth of 2 indicate that you should generate a best // [Staley] move for the initial board and all boards reachable from it in two // [Staley] halfmoves (something like 257 boards for Pylos), and that for each // [Staley] such board you should do a lookahead-5 minimax exploration to // [Staley] determine the best move. // [Staley] // [Staley] I generated the boards using recursion, and you'll almost certainly // [Staley] have to as well. The optimal move for each board is determined by // [Staley] calling Minimax with the lookahead specified, so in fact MakeBook // [Staley] uses double-recursion. // [Staley] // [Staley] When the bookFile is complete, write it to a binary "bookFile file" having // [Staley] the specified fileName. In milestone 3 you’ll use this bookFile file // [Staley] to avoid minimax computations for common board positions early in // [Staley] the game as described above. // [Staley] // [Staley] My MakeBook executable accepts a single commandline argument giving // [Staley] a “debugging log level”. (Yours need not do so.) The only allowed // [Staley] value presently is 1. If you run MakeBook with no argument, you // [Staley] get the output that you must match. However, if you run it thus: // [Staley] // [Staley] MakeBook 1 // [Staley] // [Staley] then you get a blow-by-blow description of the minimax run, with // [Staley] each subcall indented according to its level. The leaf calls // [Staley] are the leftmost, the root calls the rightmost. Each call gets one // [Staley] line of output showing the move it evaluated, and the results it // [Staley] arrived at for that move. // [Staley] // [Staley] You can differentiate between testing your MakeBook and your // [Staley] transposition table by using a non-transposition board type like // [Staley] MancalaBoard to test just the MakeBook and non-transposition // [Staley] minimax, // [Staley] // [Staley] You will find it necessary to track all the Keys you've generated // [Staley] thus far as you fill in the bookFile, so as to avoid entering the same // [Staley] Key twice in the bookFile (two different sequences of moves might // [Staley] generate the same board). Note the "Duplicate. No bookFile entry." // [Staley] announcements in my output. You must have these in yours as well. // [Staley] // [Staley] A hint on how to duplicate my key count: When I analyze a board, I // [Staley] first get a key for it. Then I output the current move/key count, // [Staley] and then I analyze the board using the key. int main() { // Restrictions: // 1. Your entire MakeBook.cpp can be at most 90 lines (mine is 75). // Use the 'smartcount' bin in your CPE305 folder to measure this. // // 2. No game name may appear in any of your source except for files with // that game in their name. // // 3. Your MakeBook must work correctly with my Othello classes, object // files for which are supplied. I will require an exact match with my // binary file only for Othello, not for the other games. Exact match // of my text output is required for all games. // // 4. MakeBook.cpp may only use "new" for creating a Book object. Boards, // Views, etc. are created using Class and BoardClass. // // 5. Your MakeBook executable must run in at most twice the time mine takes // for a given bookFile generation. const BoardClass *boardClass = NULL; View *view = NULL; Board *board = NULL; int level = -1, depth = -1; string boardType(""), filename(""); Book *bookFile = new Book(); ofstream out; // First, prompt the user for commands of the following usage: cout << "Enter boardType, level, depth, and filename: "; cin >> boardType >> level >> depth >> filename; // Use reflection to instantiate the correct board, or give an error // message if that BoardClass type doesn't exist. if ((boardClass = dynamic_cast<const BoardClass *>(BoardClass::ForName( boardType))) == NULL || (board = dynamic_cast<Board *>( boardClass->NewInstance())) == NULL || (view = dynamic_cast<View *>( boardClass->GetViewClass()->NewInstance())) == NULL) { cout << "Unknown type " << boardType << endl; return -1; } bookFile->SetLevel(level); view->SetModel(board); // Create the "bookFile file". This is where all the work happens. ConstructBookFileDFS(board, view, bookFile, boardClass->UseTransposition(), level, depth); // When the bookFile is complete (after you finish running the DFS), write it // to a binary "bookFile file" having the specified fileName. cout << "Writing book... "; out.open(filename.c_str()); bookFile->Write(out); cout << "done" << endl; cout << "Before clearing book, moves/keys: " << Board::Move::GetOutstanding() << "/" << Board::Key::GetOutstanding() << endl; delete bookFile; cout << "Final count, moves/keys: " << Board::Move::GetOutstanding() << "/" << Board::Key::GetOutstanding() << endl; return 0; }