// File: p4main4.cpp // // Last update: 02/26/2007 20:02 // Last update: 04/08/2007 20:02 // Last update: 05/02/2007 // // See Project 2 & 4 description for documentation. // #include #include #include #include #include "Thing.h" #include "RaceCourse.h" #include "PitStop.h" #include "ScriptedCar.h" using namespace std ; //-------------------------------------------------------------------- // Load answer key // Use Global variables to keep students code from munging this array unsigned int AnswerRow[] = { 1, 1, 7, 7, 6, 6, 7, 7, 6, 6, 7, 6, 10, 6, 7, 6, 10, 6, 7, 6, 36, 16, 7, 20, 36, 16, 7, 20, 36, 13, 6, 20, 23, 13, 6, 6, 23, 17, 6, 6, 36, 17, 6, 6, 36, 12, 10, 6, 27, 12, 10, 6, 27, 19 } ; unsigned int AnswerCol[] = { 6, 56, 6, 56, 6, 56, 6, 41, 1, 56, 6, 41, 1, 56, 6, 55, 23, 59, 20, 41, 23, 59, 20, 41, 19, 51, 20, 60, 19, 51, 20, 37, 19, 2, 1, 37, 10, 2, 1, 39, 10, 15, 1, 33, 17, 15, 1, 33, 17, 29, 23, 1, 29, 29 } ; unsigned int AnswerFuel[] = { 65, 66, 11986, 57, 61, 0, 11981, 112, 61, 0, 11981, 111, 57, 0, 11981, 92, 35, 27, 11967, 78, 9, 42, 11967, 64, 30, 59, 11967, 45, 55, 81, 11966, 22, 42, 57, 11947, 8, 33, 53, 11947, 6, 20, 40, 11947, 0, 38, 35, 11943, 0, 29, 21, 11921, 38, 17, 14 } ; //-------------------------------------------------------------------- // BatCar derives from ScriptedCar. // // it keeps the test program simple if I put it // all in one place. -R. class BatCar : public ScriptedCar { public: BatCar() { /* no code */ } ; BatCar(unsigned int row, unsigned int col) : ScriptedCar(row, col, 'b', 12000, "luldrdru") { /* no code */ } void encounter(Car *ptr) { ptr->IncFuelLevel(1) ; } } ; // Vampire cars derive from ScriptedCar. // // If you bump into a Vampire car it sucks all your fuel. // If Vampire cars run out of fuel, they rest for 1 turn // and their fuel regenerates. // // This stuff should be in a different file, but // it keeps the test program simple if I put it // all in one place. -R. class Vampire : public ScriptedCar { public: Vampire() ; Vampire(unsigned int row, unsigned int col) ; void encounter(Car *ptr) ; void MakeMove() ; bool IsRested() ; protected: bool rested ; // rested one turn? static const unsigned int initfuel ; } ; const unsigned int Vampire::initfuel = 70 ; Vampire::Vampire() : rested(false) { // do nothing } Vampire::Vampire(unsigned int row, unsigned int col) : ScriptedCar(row,col,'V',initfuel,"u"), rested(false) { // do nothing more } void Vampire::encounter(Car *ptr) { unsigned int f ; f = ptr->GetFuelLevel() ; ptr->DecFuelLevel(f) ; // sucks fuel from victim Car IncFuelLevel(initfuel) ; // replenishes own fuel tank rested = false ; } void Vampire::MakeMove() { // Check if we are out of fuel unsigned int f = GetFuelLevel() ; if ((f == 0) && !rested) { // if out of fuel rest for 3 days rested = true ; move-- ; // might not have finished moving that direction return ; } else if ( (f == 0) && rested) { // if rested, fuel regenerates SetFuelLevel(initfuel) ; rested = false ; } switch (move % 6) { case 0 : Car::ZoomRight() ; break ; case 1 : Car::ZoomLeft() ; break ; case 2 : Car::ZoomUp() ; break ; case 3 : Car::ZoomRight() ; break ; case 4 : Car::ZoomLeft() ; break ; case 5 : Car::ZoomDown() ; break ; } move++ ; } bool Vampire::IsRested() { return rested ; } // This function initializes the obstacle vector. // The "input" is almost WYSIWYG. // // Warning! Does not check for size compatibility // with RaceCourse constructor. // // Make sure all the rows are the same length. void SetObstacles(vector& obs) { vector V ; // WYSIWYG Obstacle Constructor?? // // 01234567890123456789012345678901234567890123456789012345678901 V.push_back("##############################################################") ; //0 V.push_back("# # # #") ; //1 V.push_back("# #") ; //2 V.push_back("# ################################################ #") ; //3 V.push_back("# ## #") ; //4 V.push_back("## ############### #################### ##") ; //5 V.push_back("# # #") ; //6 V.push_back("# # ############### # # #") ; //7 V.push_back("# ################# ############### #") ; //8 V.push_back("# #") ; //9 V.push_back("# ### # #") ; //10 V.push_back("####### # # #") ; //1 V.push_back("# # # #") ; //2 V.push_back("# #") ; //3 V.push_back("# # # #") ; //4 V.push_back("# # # # #") ; //5 V.push_back("# #") ; //6 V.push_back("# # # #") ; //7 V.push_back("### # #") ; //8 V.push_back("# ######## #### #### ######### #") ; //9 V.push_back("# # % # #") ; //20 V.push_back("# ########### #### #### ##### ########## #") ; //1 V.push_back("# # # #") ; //2 V.push_back("# # # # #") ; //3 V.push_back("# # #") ; //4 V.push_back("# #") ; //5 V.push_back("# # # # #") ; //6 V.push_back("# # # #") ; //7 V.push_back("# # #") ; //8 V.push_back("# #") ; //9 V.push_back("# # # #") ; //30 V.push_back("# # # #") ; //1 V.push_back("# #") ; //2 V.push_back("# # # # #") ; //3 V.push_back("# #") ; //4 V.push_back("# #") ; //5 V.push_back("# #") ; //6 V.push_back("# ################################################ #") ; //7 V.push_back("# #") ; //8 V.push_back("# #") ; //9 V.push_back("# #") ; //40 V.push_back("##############################################################") ; // Set obstacles // No need to set outside perimeter unsigned int i, j, rows, cols ; rows = V.size() ; assert(rows > 0) ; cols = V.at(0).length() ; for (i=1 ; i < rows-1 ; i++) { assert( cols == V.at(i).length() ); for (j = 1 ; j < cols-1 ; j++) { if (V.at(i).at(j) == '#') { obs.push_back(new Wall(i,j)) ; } } } } void UpdateScreen(RaceCourse& R, vector& Cars) { #ifdef VT100 cout << "\033[2J\033[H" ; // VT100 erase screen, goto HOME #endif R.PrettyPrintCourse() ; RaceStatus s = R.GetRaceStatus() ; switch(s) { case WAITING : cout << "Status: WAITING\n" ; break ; case STARTED : cout << "Status: STARTED\n" ; break ; case FINISHED : cout << "Status: FINISHED\n" ; break ; default: cout << "Status: UNKNOWN (Bad)\n" ; } for(unsigned int i=0 ; i < Cars.size() ; i++) { cout << "Car #" << Cars[i]->DrawMe() << " at " ; cout << "(" << Cars[i]->GetRow() << "," << Cars[i]->GetCol() << ")" ; cout << " fuel=" << Cars[i]->GetFuelLevel() << "\n" ; } } bool CheckAnswer(Car *Cptr, int i, int move, unsigned int AnswerRow[], unsigned int AnswerCol[], unsigned int AnswerFuel[] ) { // return true ; unsigned int r, c, f ; bool pass = true ; r = Cptr->GetRow() ; c = Cptr->GetCol() ; f = Cptr->GetFuelLevel() ; if (r != AnswerRow[i] || c != AnswerCol[i]) { pass = false ; cerr << "Error in move " << move << ": " ; cerr << "Car " << Cptr->DrawMe() << " position should be: (" << AnswerRow[i] << "," << AnswerCol[i] << ")\n" ; cerr << " Position reported: (" << r << "," << c << ")\n" ; } if (f != AnswerFuel[i]) { pass = false ; cerr << "Error in move " << move << ": " ; cerr << " Fuel level should be: " << AnswerFuel[i] << "\n" ; cerr << " Fuel level reported: " << f << "\n" ; } return pass ; } //----------------------------------------------------------------------- int main() { vector obs, morethings ; vector Cars ; ScriptedCar *cptr ; Goal *gptr ; bool AddOK ; int errors=0, index ; // Initialize RaceCourse R RaceCourse R(40, 60) ; // Set up some walls SetObstacles(obs) ; // Set up winning location gptr = new Goal(20, 29) ; obs.push_back(gptr) ; // Add a Pit Stops obs.push_back( new PitStop(36,18) ) ; obs.push_back( new PitStop( 6,60) ) ; obs.push_back( new PitStop(37,59) ) ; obs.push_back( new PitStop(17,59) ) ; obs.push_back( new PitStop(12,51) ) ; obs.push_back( new PitStop(13, 1) ) ; obs.push_back( new PitStop(16,50) ) ; // Tell RaceCourse R to put in the walls, etc. AddOK = R.AddThings(obs) ; if (!AddOK) { cerr << "Something went wrong with AddThings()\n" ; errors++ ; // exit(1) ; } // Now we set up some cars // Scripted paths for each car to follow // vector script(4) ; // 0123456789012345678901234567890 script[0] = "rdldrdlluldrurur" ; script[1] = "ldrrrdluldrurdld" ; // Make some Cars // We need both Thing pointers and ScriptedCar pointers // because AddThings takes vector of Thing * only // cptr = new ScriptedCar(1, 1, '0', 70, script[0]) ; Cars.push_back(cptr) ; morethings.push_back(cptr) ; cptr = new ScriptedCar(1, 60, '1', 70, script[1]) ; Cars.push_back(cptr) ; morethings.push_back(cptr) ; cptr = new BatCar(7, 20) ; Cars.push_back(cptr) ; morethings.push_back(cptr) ; cptr = new Vampire(7, 43) ; Cars.push_back(cptr) ; morethings.push_back(cptr) ; // Tell RaceCourse R to put in the walls, etc. AddOK = R.AddThings(morethings) ; if (!AddOK) { cerr << "Something went wrong with AddThings()\n" ; errors++ ; // exit(1) ; } // Print out starting line up // UpdateScreen(R, Cars) ; cout << "\n\nInitial Race Course: \n" ; cout << "#Rows=" << R.GetNumOfRows() << endl ; cout << "#Cols=" << R.GetNumOfCols() << endl ; cout << "-----------------------------------------\n\n" ; #ifdef VT100 // #define VT100 for "interactive" version. cout << "Type \"enter\" to continue\n" ; cin.ignore(10000, '\n') ; #endif R.StartRace() ; index = 0 ; for (unsigned int move=0 ; move < 16 ; move++) { for (unsigned int i=0 ; i < Cars.size() ; i++) { Cars[i]->MakeMove() ; UpdateScreen(R, Cars) ; if (!CheckAnswer(Cars[i], index++, move, AnswerRow, AnswerCol, AnswerFuel)) { errors++ ; } // cout << "index: " << index << "\n" ; /* // Generate answer key cout << "Row: " << Cars[i]->GetRow() << "\n" ; cout << "Col: " << Cars[i]->GetCol() << "\n" ; cout << "Fuel: " << Cars[i]->GetFuelLevel() << "\n" ; */ if (i <= 1) { cout << "\nCar #" << Cars[i]->DrawMe() << ", Move #" << move << " was '" << script[i][move] << "'\n\n" ; } else { cout << "\nCar #" << Cars[i]->DrawMe() << ", Move #" << move << "\n\n" ; } // Check for winner if (gptr->GetWinner() != NULL) { cout << "And the winer is, Car #" << gptr->GetWinner()->DrawMe() << "!!\n" ; break ; } cout << "-----------------------------------------\n\n\n" ; #ifdef VT100 // #define VT100 for "interactive" version. cout << "Type \"enter\" to continue\n" ; cin.ignore(10000, '\n') ; #endif // bail when solution would have finished if (index >= 54) break ; } if (R.GetRaceStatus() == FINISHED) break ; // bail when solution would have finished if (index >= 54) break ; } Car *winner = gptr->GetWinner() ; if (winner == NULL) { cerr << "Winner should be Car 1, but no winner reported by Step 54.\n" ; errors++ ; } else if (winner->DrawMe() != '1') { cerr << "Winner should be Car 1, but was reported as Car " << winner->DrawMe() << "\n" ; errors++ ; } cerr << "\n\nTotal # of errors = " << errors << "\n" ; // Deallocate memory for cars & Walls // for (unsigned int i=1; i < Cars.size() ; i++) { delete Cars[i] ; } for (unsigned int j=1; j < obs.size() ; j++) { delete obs[j] ; } }