Hunt The Wumpus/C++: Difference between revisions
Content added Content deleted
m ({{collection|Hunt_The_Wumpus}}) |
mNo edit summary |
||
Line 16: | Line 16: | ||
MAX_ROOMS = 20, SAVED = 6, MAX_EXITS = 3, A_PATH_LEN = 5, MAX_ARROWS = 5; |
MAX_ROOMS = 20, SAVED = 6, MAX_EXITS = 3, A_PATH_LEN = 5, MAX_ARROWS = 5; |
||
class inOut |
|||
{ |
|||
public: |
|||
int getLetter( std::string s, int a, int b ) |
|||
{ |
|||
int c; |
|||
do |
|||
{ |
|||
msg( s ); |
|||
std::string r; std::cin >> r; |
|||
std::cin.clear(); std::cin.ignore(); |
|||
c = toupper( r[0] ); |
|||
} |
|||
while( c != a && c != b ); |
|||
return c; |
|||
} |
|||
int getNumber( std::string s ) |
|||
{ |
|||
int n = 0; std::string c; |
|||
while( true ) |
|||
{ |
|||
msg( s ); |
|||
std::getline( std::cin, c ); |
|||
std::stringstream strm( c ); |
|||
if( strm >> n ) break; |
|||
} |
|||
return n; |
|||
} |
|||
void msg( std::string s ) { std::cout << s; } |
|||
void msg( int i ) { std::cout << i; } |
|||
void wait() { std::cin.get(); } |
|||
}; |
|||
class room |
|||
{ |
|||
public: |
|||
int getExit( int i ) { return exits[i]; } |
|||
byte contains() { return obj; } |
|||
void clear( object o ) { obj ^= o; } |
|||
void clearRoom() { obj = NOTHING; } |
|||
void setExit( int i, int e ) { exits[i] = e; } |
|||
void populate( object o ) { obj |= o; } |
|||
private: |
|||
int exits[MAX_EXITS]; |
|||
byte obj; |
|||
}; |
|||
class cave |
class cave |
Revision as of 15:05, 22 October 2018
Hunt The Wumpus/C++ is part of Hunt_The_Wumpus. You may find other members of Hunt_The_Wumpus at Category:Hunt_The_Wumpus.
This version is based on the original game, but it diverges a little from the task!
C++
<lang cpp>
- include <time.h>
- include <iostream>
- include <sstream>
typedef unsigned char byte;
enum gameResult { FINISH, PLAY_NEW, PLAY_SAME }; enum object : byte { NOTHING, WUMPUS = 1, BAT = 2, PIT = 4, PLAYER = 8 };
const unsigned S_PLAYER = 0, S_WUMPUS = 1, S_BAT1 = 2, S_BAT2 = 3, S_PIT1 = 4, S_PIT2 = 5,
MAX_ROOMS = 20, SAVED = 6, MAX_EXITS = 3, A_PATH_LEN = 5, MAX_ARROWS = 5;
class cave
{
public:
cave() { int con[] = { 1, 4, 7, 0, 2, 9, 1, 3, 11, 2, 4, 13, 0, 3, 5, 4, 6, 14, 5, 7, 16, 0, 6, 8, 7, 9, 17, 1, 8, 10, 9, 11, 18, 2, 10, 12, 11, 13, 19, 3, 12, 14, 5, 13, 15, 14, 16, 19, 6, 15, 17, 8, 16, 18, 10, 17, 19, 12, 15, 18 }; for( int x = 0, r = 0; x < MAX_ROOMS; x++, r = x * MAX_EXITS ) { for( unsigned c = r, d = 0; c < r + MAX_EXITS; c++, d++ ) rooms[x].setExit( d, con[c] ); } clear(); }
void clear() { for( int x = 0; x < MAX_ROOMS; x++ ) rooms[x].clearRoom(); }
room* getRoom( int i ) { return &rooms[i]; }
private:
room rooms[MAX_ROOMS];
};
class wumpus { private:
inOut inOut; cave theCave; unsigned playerPos, wumpusPos, pathLen, arrowsCnt, exits[MAX_EXITS], arrowPath[A_PATH_LEN], saved[SAVED]; bool gameOver, playerWins;
void look() { room* r = theCave.getRoom( playerPos ); inOut.msg( "\n\n-----------------------------------\n" ); inOut.msg( "You are in room #" ); inOut.msg( playerPos + 1 ); inOut.msg( "\nTunnels lead to rooms #: " ); for( int x = 0; x < MAX_EXITS; x++ ) { inOut.msg( ( 1 + r->getExit( x ) ) ); inOut.msg( " " ); }
lookAround( r ); }
void shoot() { room* r = theCave.getRoom( playerPos ); unsigned e;
for( unsigned x = 0; x < pathLen; x++ ) { for( e = 0; e < MAX_EXITS; e++ ) if( r->getExit( e ) == arrowPath[x] ) break; if( e < MAX_EXITS ) r = theCave.getRoom( arrowPath[x] ); else r = theCave.getRoom( r->getExit( rand() % MAX_EXITS ) );
byte o = r->contains();
if( WUMPUS & o ) { gameOver = playerWins = true; return; } if( PLAYER & o ) { gameOver = true; playerWins = false; inOut.msg( "\n OUCH! Arrow got you!\n" ); return; } } inOut.msg( "\n Missed!\n\n" ); if( --arrowsCnt == 0 ) { inOut.msg( "\n You run out of arrows...\n" ); gameOver = true; playerWins = false; return; }
wumpusMove( playerPos ); }
gameResult showResult( bool pw ) { if( pw ) inOut.msg( "\n AHA! You got the Wumpus!\n HEE HEE HEE - The Wumpus'll getcha next time!!\n\n" ); else inOut.msg( " HA HA HA - You lose!\n\n" );
if( inOut.getLetter( "Play again (Y/N)? ", 'Y', 'N' ) == 'Y' ) { if( inOut.getLetter( "Same setup (Y/N)? ", 'Y', 'N' ) == 'Y' ) return PLAY_SAME; return PLAY_NEW; }
return FINISH; }
void lookAround( room* r ) { byte msg = 0, o; for( int x = 0; x < MAX_EXITS; x++ ) { o = theCave.getRoom( r->getExit( x ) )->contains(); msg += ( ( WUMPUS & o ) + ( BAT & o ) + ( PIT & o ) ); }
if( msg & WUMPUS ) inOut.msg( "\nYou smell something terrible nearby." ); if( msg & PIT ) inOut.msg( "\nYou feel a cold wind blowing from a nearby cavern." ); if( msg & BAT ) inOut.msg( "\nYou hear a rustling." ); }
bool checkExits( int e ) { for( int x = 0; x < MAX_EXITS; x++ ) if( e == exits[x] ) return true; return false; }
void getInput() { if( inOut.getLetter( "\n\nShoot or Move (S/M)? ", 'S', 'M' ) == 'M' ) { int e = inOut.getNumber( "Where to? " ) - 1; if( checkExits( e ) ) setPlayer( e ); else inOut.msg( "\nArrggh! --- You cannot go there!\n\n" ); } else { do pathLen = inOut.getNumber( "\nNumber of rooms (1-5)? " ); while( pathLen < 1 || pathLen > A_PATH_LEN );
for( unsigned i = 0; i < pathLen; i++ ) { arrowPath[i] = inOut.getNumber( "Room #" ) - 1; if( i <= 1 || arrowPath[i] != arrowPath[i - 2]) continue; inOut.msg( "\nArrows aren't that crooked! - Please, try another room.\n\n" ); i--; } shoot(); } }
void setPlayer( int pos ) { if( playerPos < MAX_ROOMS ) theCave.getRoom( playerPos )->clear( PLAYER );
if( hazards( pos ) ) return;
playerPos = pos; room* r = theCave.getRoom( playerPos ); r->populate( PLAYER ); for( int x = 0; x < MAX_EXITS; x++ ) exits[x] = r->getExit( x ); }
bool hazards( int pos ) { room* r = theCave.getRoom( pos ); byte o = r->contains();
if( WUMPUS & o ) { inOut.msg( "\n ...OOPS! Bumped a Wumpus!\n\n" ); if( wumpusMove( pos ) ) { inOut.msg( "\n TSK TSK TSK - Wumpus got you!\n" ); gameOver = true; playerWins = false; return true; } }
if( PIT & o ) { inOut.msg( "\n YYYYIIIIEEEE!!!! Fell in pit!\n"); gameOver = true; playerWins = false; return true; }
if( BAT & o ) { inOut.msg( "\n ZAP -- Super bat snatch! Elsewhereville for you!\n\n" ); setPlayer( rand() % MAX_ROOMS ); return true; } return false; }
bool wumpusMove( int pos ) { if( rand() % 100 < 75 ) { room* r = theCave.getRoom( wumpusPos ); r->clear( WUMPUS ); wumpusPos = r->getExit( rand() % MAX_EXITS ); theCave.getRoom( wumpusPos )->populate( WUMPUS ); } return ( pos == wumpusPos ); }
void initGame( gameResult gr ) { inOut.msg( "\n\n\n\nHUNT THE WUMPUS\n---------------\n" ); theCave.clear(); gameOver = false; arrowsCnt = MAX_ARROWS;
if( gr == PLAY_NEW ) { saved[S_PLAYER] = rand() % MAX_ROOMS; setPlayer( saved[S_PLAYER] ); saved[S_BAT1] = fillRoom( BAT ); saved[S_BAT2] = fillRoom( BAT ); saved[S_PIT1] = fillRoom( PIT ); saved[S_PIT2] = fillRoom( PIT ); wumpusPos = saved[S_WUMPUS] = fillRoom( WUMPUS ); } else { setPlayer( saved[S_PLAYER] ); wumpusPos = saved[S_WUMPUS]; theCave.getRoom( wumpusPos )->populate( WUMPUS ); theCave.getRoom( saved[S_BAT1] )->populate( BAT ); theCave.getRoom( saved[S_BAT2] )->populate( BAT ); theCave.getRoom( saved[S_PIT1] )->populate( PIT ); theCave.getRoom( saved[S_PIT2] )->populate( PIT ); } }
int fillRoom( object c ) { int i; room* r; do { i = rand() % MAX_ROOMS; r = theCave.getRoom( i ); } while( r->contains() ); r->populate( c ); return i; }
void printInstructions() { if( inOut.getLetter( "Instructions (Y/N)? ", 'Y', 'N' ) == 'N' ) return; inOut.msg( "\n\nWelcome to 'HUNT THE WUMPUS'\n\nThe Wumpus lives in a cave of 20 rooms: each room has 3 tunnels leading to\n" "other rooms. (Look at a Dodecahedron to see how this works, if you don't\nknow what a dodecahedron is, ask someone)\n" "\n\n HAZARDS:\n --------\n\nBottomless pits:\n----------------\nTwo rooms have bottomless pits in them.\n" "If you go there, you fall into the pit and lose!\n\nSuper bats:\n-----------\nTwo other rooms have super bats.\nIf you go there, " "a bat grabs you and takes you to some other room at random,\nwhich might be troublesome.\n\nWumpus:\n-------\nThe Wumpus is not " "bothered by the hazards, he has sucker feet and is too big\nfor a bat to lift.\nUsually he is asleep.\nTwo things wake him up: " "your entering his room or your shooting an arrow.\nIf the Wumpus wakes, he has 75% chance to move one room or 25% chance to stay\n" "still.\nAfter that, if he is where you are, he eats you up and you lose!\n\nYou:\n----\nEach turn you may move or shoot a crooked arrow.\n" "- Moving: you can move one room (thru one tunnel)\n- Arrows: you have 5 arrows. You lose when you run out.\n Each arrow can go from " "1 to 5 rooms, you aim by telling the computer the\n rooms #s you want the arrow to go to.\n If the arrow can't go that way (if no tunnel) " "it moves at random to the \n next room.\n If the arrow hits the Wumpus: you win, if the arrow hits you: you lose.\n" "\n\n WARNINGS:\n --------\nWhen you are one room away from Wumpus or any other hazard, the computer says:\nWumpus: 'You smell something " "terrible nearby.'\nBat: 'You hear a rustling.'\nPit: 'You feel a cold wind blowing from a nearby cavern.'\n\n\n\nPress return to play..." ); inOut.wait(); }
public:
void play() { playerPos = MAX_ROOMS; gameResult gr = PLAY_NEW; printInstructions();
while( gr != FINISH ) { initGame( gr ); while( !gameOver ) { look(); getInput(); } gr = showResult( playerWins ); } }
};
int main( int argc, char* argv[] ) {
srand( static_cast<unsigned>( time( NULL ) ) ); wumpus hw; hw.play(); return 0;
} </lang>