//****************************************************************// // // // Copyright (c) 1997. // // Dr. Michael A. Redmond // // // // This software may not be distributed further without permission from // // Dr Michael A. Redmond. // // // // This software is distributed WITHOUT ANY WARRANTY. No claims are made // // as to its functionality or purpose. // // // // Title: Tw_Game.h // Description: abstraction for twixt Game, includes board, player names, // number moves so far, whose turn it is, and how the player // moves (human or program) // Author: Dr Michael A. Redmond // // Date: 4/10/97 // // // // //****************************************************************// #include // #include // #include #include "list.h" #include "my-math.h" #include "point.h" #include "tw-color.h" #include "tw-peg.h" #include "tw-link.h" #include "tw-board.h" #include "tw-game.h" // constructors - // first - 0 or 1 args - starts a game with a new board // unknown player names // default empty board generated by board constructor Tw_Game::Tw_Game(int size = 20) : board(size), play1name("Player 1"), play2name("Player 2"), num_moves_so_far(0), play1typ(human), play2typ(human), max_width_search(1),max_depth_search(1) { } // second - 2 or 3 args - starts a game with a new board // known player names Tw_Game::Tw_Game(char player1[], char player2[], const int size = 20) : board(size), play1name(player1), play2name(player2), num_moves_so_far(0), play1typ(human), play2typ(human), max_width_search(1),max_depth_search(1) { } // third - 4 args - game in progress - board known w/ // pegs, black links and white links, and board size // player names specified, along with number of moves // so far Tw_Game::Tw_Game(Tw_Board& gameboard, char player1[], char player2[], int num_moves) : board(gameboard), play1name(player1), play2name(player2), num_moves_so_far(num_moves), play1typ(human), play2typ(human), max_width_search(1),max_depth_search(1) { } // inspectors // mutators - establish new values of attributes (data members) // facilitators // run the game Tw_Color Tw_Game::Play() { Tw_Link potent_links[8]; bool accepted = false; int move_num; Tw_Peg new_move; Welcome(); while (WhoWon() == empty) { // assumes validation board.DrawBoard(cout); // prompt user until they enter a valid peg accepted = false; while (!accepted) { // knows which player to prompt because game object knows new_move = PromptForPeg(); clog << "DEBUG - got your move " << new_move << endl; accepted = board.PlacePeg(new_move); clog << "DEBUG - placed your peg? " << accepted << endl; } int num_potent_link = board.FindLegalPotentialLinksForPosition(new_move, potent_links); clog << "DEBUG - num_potent_link: " << num_potent_link << endl; for (int cnt = 0;cnt < num_potent_link;cnt++) { bool placeit = PromptForLinkYN(potent_links[cnt]); clog << "DEBUG - placeit: " << placeit << endl; if (placeit) { clog << "DEBUG - Ready to place link" << endl; board.PlaceLink(potent_links[cnt]); } } // give user a chance to specify another link // perhaps they chjanged their mind on an earlier NO Tw_Link new_link = PromptForLink(); board.PlaceLink(new_link); // really should keep on going until they stop giving us one // having them tell us to quit though might require a separate // prompt though since this one is retruning a link object move_num = IncrNumMoves(); } board.DrawBoard(cout); // also handles a draw Congrats(); GoodBye(); } // some stream facilitators // protected interface can be used by objects that are in class, // and objects that are in a subtype class (derived class) // inspectors // report if there is any winner // depends on board version Tw_Color Tw_Game::WhoWon() const { return board.WhoWon(); } ostream& Tw_Game::DisplayPlayerName(const int playnum, ostream& sout) const { if (playnum == 1) { sout << play1name; } if (playnum == 2) { sout << play2name; } } // report whose turn it is int Tw_Game::WhoseTurn() const { if ((num_moves_so_far % 2) == 0) { return 1; } else return 2; } // report whose turn it is Tw_Color Tw_Game::WhichColorsTurn() const { if ((num_moves_so_far % 2) == 0) { return black; } else return white; } // report who just moved int Tw_Game::WhoJustMoved() const { if ((num_moves_so_far % 2) == 0) { return 2; } else return 1; } // mutators // increment the number of moves so far int Tw_Game::IncrNumMoves() { num_moves_so_far++; return num_moves_so_far; } // facilitators // greet players at beginning of game void Tw_Game::Welcome() const { cout << endl << endl; cout << "Welcome to the World Series of Twixt" << endl; cout << " Play Hard, Play Fair, Nobody Hurt" << endl; cout << endl; cout << endl; cout << " Black Plays First " << endl; cout << endl; cout << " Black builds horizontal " << endl; cout << " White builds vertical " << endl; cout << endl; } // sign off at end of game void Tw_Game::GoodBye() const { cout << endl << endl << "Thank you for playing, come again" << endl; } // congratulate winner // wait - may have been a tie void Tw_Game::Congrats() const { int whichwon = WhoJustMoved(); cout << " Congratulations "; // cout << DisplayPlayerName(whichwon,cout); DisplayPlayerName(whichwon,cout); cout << " on your victory" << endl; cout << endl << "very well played!! " << endl; } // ask player for peg // really should reprompt until they give me a valid one Tw_Peg Tw_Game::PromptForPeg() const { int whichturn = WhoseTurn(); Point return_pos; Tw_Color return_color = WhichColorsTurn(); cout << " Your turn "; // cout << DisplayPlayerName(whichturn,cout); DisplayPlayerName(whichturn,cout); cout << endl << "Where would you like to place your " << return_color << " peg? (in form (row,col) " << flush; cin >> return_pos; Tw_Peg return_peg(return_pos,return_color); return return_peg; } // ask player for link Tw_Link Tw_Game::PromptForLink() const { char response; int whichturn = WhoseTurn(); Tw_Link return_link; Tw_Color return_color = WhichColorsTurn(); // cout << DisplayPlayerName(whichturn,cout); DisplayPlayerName(whichturn,cout); cout << " Would you like to place any other links on this turn? (y or n) " << flush; cin >> response; if ((response == 'y') || (response == 'Y')) { cout << endl << "Where would you like to place your " << return_color << " link? (in form (row,col):color:color:(row,col):color) " << flush; cin >> return_link; } else return_link = Tw_Link(); return return_link; } // ask player if they want to place a link that has been identified // as placeable bool Tw_Game::PromptForLinkYN(const Tw_Link& potent_link) const { char answer; // really should keep prompting until they enter y,Y, n, or N cout << "Do you want to place the following link on the board (Y or N)? " << potent_link << flush; cin >> answer; if ((answer == 'y') || (answer == 'Y')) { return true; } else if ((answer == 'n') || (answer == 'N')) { return false; } else return PromptForLinkYN(potent_link); } // display current situation void Tw_Game::Display() const { cout << endl << "Completed Move Number " << num_moves_so_far << endl << endl; } // dont think I need these for Game // below overloads standard c++ operators so that they can be used // with tw_game class objects, so syntax is like with ints floats etc // // Tw_Game ADT: auxiliary operator description // // ostream& operator<<(ostream &sout, const Tw_Board &s); // istream& operator>>(istream &sin, Tw_Board &r);