Need some help. My game locks up when you go to load file and it just locks up. Please help.
/*
WumpusGame header file
Contains the WumpusGame Class. This is the main workhorse
of the program, and contains all of the global data,
including the master world map. WumpusGame also handles
the full user interface.
*/
#ifndef WUMPUS_H
#define WUMPUS_H
#include <iostream> //normal stream i/o (cout)
//#include <conio.h> //getch() and other dos console i/o
//not available under UNIX
#include <cstdio> //other IO routines
#include <fstream> //file i/o
#include <cstdlib> //atoi()
#include <cstring> //string
using namespace std;
#include "agent.h"
class WumpusGame
{
public:
void shell(); //outer control structure
void init(); //loads option file
void mainmenu();
void optionsmenu(); //select options
void agentmenu(); //select an agent
void filemenu(); //choose a new map file
void saveops(); //save current options to file
void playgame(int human); //play the game
void loadmap(); //loads the current map file into the game grid
void display(int); //GUI function (hahaha)
void makemap(); //inits the map to blank
void printline( int j, char sidebar [70]); //print one line of the map w/ sidebar
void printline( int j, char sidebar [70], int number); //overloaded to get around itoa
void displayPercepts(); //throws down current percepts
int getinput(int &); //player input control
int autopilot(int & code); //agent input control
int gank(); //grabs the arrow or gold if there
int fire(); //fires off an arrow if we have one
int trajectory(); //actually moves the arrow around
int moveAgentForward(); //walk the agent forward if possible
void informAgent(); //tells the agent wazzup
void highscore (int current_score); //locks in a new high score
void savescores(); //writes the high scores back out
void loadscores(); //loads the high score list
void Help(); //displays the help screen
void closeout(); //exits the game
private:
char map [22][22]; //holds the game world (loaded from file)
Agent MrMan; //our adverturous agent
char map_file[9]; //current map file
int agent_x,
agent_y;
int agent_dir; //stores the agent's direction
// 1=N,2=E,3=S,4=W
//option variables - loaded from another file
int op_walls,
op_pits,
op_gold,
op_wumpus,
op_arrow_stay,
op_arrow_num,
op_move_limit;
int op_agent; //which agent we're going to use
int debug; //debug mode on or off
//holds the high score - yes this is kinda dumb, but why else have points?
int score_val;
char score_name[20];
int moves; //total # of moves taken
};
//#include "wumpus.cpp"
#endif
/*
WumpusGame Implementation file
See wumpus.h for information on WumpusGame.
*/
#include "wumpus.h"
void WumpusGame::shell()
{
init();
mainmenu();
closeout();
return;
}
void WumpusGame::init()
{
ifstream opsfile ("wumpus.dat", ios::in);
opsfile >> op_walls;
opsfile >> op_pits;
opsfile >> op_gold;
opsfile >> op_wumpus;
opsfile >> op_arrow_stay;
opsfile >> op_arrow_num;
opsfile >> op_move_limit;
opsfile >> op_agent;
opsfile.close();
strcpy_s(map_file,"default"); //set default map_file name
makemap(); //load in blank map (with walls)
agent_x=1; agent_y = 1; //set agent start point
agent_dir = 3; //agent starts in upper left, pointing South
//these are the defaults, retained for reference
/* op_walls = 1;
op_pits = 1;
op_gold = 1;
op_wumpus = 1;
op_arrow_stay = 1;
op_arrow_num = 5;
op_move_limit = 0;*/
debug = 0;
srand(13); //seed the random # gen with my lucky number...
loadscores(); //load the high score
}
void WumpusGame::makemap()
{
//loads in a totally blank map
int i,j;
for (i = 0; i< 22; i++)
{
for (j=0; j<22; j++)
{
map[i][j] = '.';
}
}
//walls down sides
i=0;
for (j=0; j<22; j++)
map[i][j] = '#';
i=21;
for (j=0; j<22; j++)
map[i][j] = '#';
//walls on top and bottom
j=0;
for (i=0; i<22; i++)
map[i][j] = '#';
j=21;
for (i=0; i<22; i++)
map[i][j] = '#';
return;
}
void WumpusGame::mainmenu()
{
int done = 0;
char choice;
while (!done)
{
//clear the screen here if we could
cout << "Welcome to: "<<endl;
cout << "Wumpus World!"<<endl;
cout << "Written by: James Cox, 2012"<<endl;
cout << endl;
cout<< "Current High Score:"<<endl;
cout << score_name << " = " << score_val<<endl;
cout << endl;
cout << "Choose an Option:"<<endl;
cout << "1 - Play Hunt the Wumpus" <<endl;
cout << "2 - Watch Current Agent play Hunt the Wumpus"<<endl;
cout << "3 - Options Menu"<<endl;
cout << "4 - Help"<<endl;
cout << "5 - Quit"<<endl;
cout << ">";
cin >> choice;
switch (choice)
{
case '1':
playgame(1);
break;
case '2':
playgame(0);
break;
case '3':
optionsmenu();
break;
case '4':
Help();
break;
case '5':
done = 1;
break;
default:
break;
}
}
//cout << "Thanks for playing!!"<< endl;
return;
}
void WumpusGame::optionsmenu()
{
//clear the screen here too
char choice;
int done = 0;
int new_num;
while (!done)
{
//print menu screen
cout << "Options Menu"<<endl;
cout << "A> Current Agent is: ";
cout << op_agent << " ";
cout <<endl;
cout << "M> Current Map file is:";
cout << map_file;
cout << endl;
cout << "Game World Options:"<<endl;
cout << "1> Walls = ";
if (op_walls == 1)
cout << "ON"<<endl;
else
cout << "OFF"<<endl;
cout << "2> Pits = ";
if (op_pits == 1)
cout << "ON"<<endl;
else
cout << "OFF"<<endl;
cout << "3> Gold = ";
if (op_gold == 1)
cout << "ON"<<endl;
else
cout << "OFF"<<endl;
cout << "4> Wumpus = ";
if (op_wumpus == 1)
cout << "ON"<<endl;
else
cout << "OFF"<<endl;
cout << "5> Arrow_Stay = ";
if (op_arrow_stay == 1)
cout << "ON"<<endl;
else
cout << "OFF"<<endl;
cout << "6> Number of Arrows: ";
cout << op_arrow_num <<endl;
cout << "7> Move Limit: ";
if (op_move_limit == 0)
cout << "Infinite"<<endl;
else
cout << op_move_limit<<endl;
cout << "8> Save Current Options to File"<<endl;
cout << "9> Return to Main Menu"<<endl;
cout << endl;
cout << ">";
cin >> choice;
switch (choice)
{
case '1':
if (op_walls == 1)
op_walls = 0;
else
op_walls = 1;
break;
case '2':
if (op_pits == 1)
op_pits = 0;
else
op_pits = 1;
break;
case '43':
if (op_gold == 1)
op_gold = 0;
else
op_gold = 1;
break;
case '4':
if (op_wumpus == 1)
op_wumpus = 0;
else
op_wumpus = 1;
break;
case '5':
if (op_arrow_stay == 1)
op_arrow_stay = 0;
else
op_arrow_stay = 1;
break;
case '6':
cout << "Enter new number of arrows: ";
cin >> new_num;
op_arrow_num = new_num;
break;
case '7':
cout << "Enter new move limit (0 for none): ";
cin >> new_num;
op_move_limit = new_num;
break;
case '8':
saveops();
break;
case '9':
done = 1;
break;
case 'a':
case 'A':
agentmenu();
break;
case 'm':
case 'M':
filemenu();
break;
default:
break;
}//end switch
} //end while loop
return;
}
void WumpusGame::agentmenu()
{
int choice;
cout << "Choose an Agent!" << endl;
cout << "1> Dummy" <<endl;
cout << "2> Cautious" <<endl;
cout << "3> Explorer" <<endl;
cout << endl<< " >";
cin >> choice;
switch (choice) //provides some error checking
{
case 1:
op_agent = 1;
break;
case 2:
op_agent = 2;
break;
case 3:
op_agent = 3;
break;
default:
break;
}
}
void WumpusGame::filemenu()
{
cout << endl;
cout << "Enter a new file name:"<<endl;
char newfile[30];
cin >> newfile;
char name[30];
strcpy_s(name,newfile);
strcat_s(name,".map");
ifstream infile ("wumpus.dat", ios::in );
if (!infile) //check for input file
{
cout << "Fatal Error: - Failed to open input file: "<< name << endl;
return; //exit if file does not exist.
}
strcpy_s(map_file,newfile);
return;
}
void WumpusGame::saveops()
{
ofstream opsfile ("wumpus.dat", ios::out );
opsfile << op_walls <<endl;
opsfile << op_pits <<endl;
opsfile << op_gold <<endl;
opsfile << op_wumpus <<endl;
opsfile << op_arrow_stay <<endl;
opsfile << op_arrow_num <<endl;
opsfile << op_move_limit <<endl;
opsfile << op_agent << endl;
opsfile.close();
cout << "Options Saved!"<<endl;
return;
}
void WumpusGame::playgame(int human)
{
//load map file
cout << "Loading Map File"<<endl;
loadmap();
//reset location and direction
agent_x = 1;
agent_y = 1;
agent_dir = 3; //south, remember?
moves = 0;
int done=0;
int code=0;
//if manual, spawn manual interface
if (human)
{
MrMan.start(0,op_arrow_num); //init agent as human
while (!done)
{
MrMan.amihome(agent_x,agent_y); //tell agent if at home
informAgent(); //upadate percepts (and location)
display(code); //draw screen
done = getinput(code); //get user input and proform appropriate actions
}
display(code); //draw the last screen (so death messages show up)
//hit enter to continue
char temp;
cin >> temp;
highscore(MrMan.myScore() ); //update highscore if neccissary
}
//if agent, begin agent play with current agent
else if (!human)
{
MrMan.start(op_agent,op_arrow_num); //init agent to current agent
while (!done)
{
MrMan.amihome(agent_x,agent_y); //check if home
informAgent(); //update percepts
display(code); //do we need a different display routine?
//the agent plays the game
done = getinput(code);
}
display(code); //final screen so that user can see what happened
//press enter to contimue
highscore(MrMan.myScore()); //see if agent got the high score
}
return;
}
void WumpusGame::loadmap()
{
//cout << "Loading game:"<<endl;
char * name;
name = new char[12];
strcpy(name,map_file);
strcat(name,".map");
ifstream infile ("wumpus.dat", ios::in );
if (!infile) //check for input file
{
cout << "Fatal Error: - Failed to open input file: "<< name << endl;
//getch();
return;//exit(-1); //exit if file does not exist.
}
int i,j;
char temp;
infile >> temp;
i=1; j=1;
while (temp != '~')
{
switch (temp)
{
case '.':
map[i][j]='.';
break;
case '#':
if (op_walls == 1)
map[i][j]='#';
else
map[i][j]='.';
break;
case 'p':
if (op_pits == 1)
map[i][j]='p';
else
map[i][j]='.';
break;
case 'g':
if (op_gold == 1)
map[i][j]='g';
else
map[i][j]='.';
break;
case 'w':
if (op_wumpus == 1)
map[i][j]='w';
else
map[i][j]='.';
break;
case 'a':
if (op_arrow_stay == 1)
map[i][j]='a';
else
map[i][j]='.';
break;
case ';':
i=0;
j++;
default:
break;
}//end switch
i++;
infile >> temp;
} //end while
infile.close();
cout << "Game Loaded!"<<endl;
//getch();
return;
}
void WumpusGame::display(int code)
{
char current_message[70];
//int plist[8];
//load the current player message based on the status code
switch (code)
{
case 1:
strcpy_s(current_message," Your Path is Blocked.");
break;
case 2:
strcpy_s(current_message," You cannot climb out here.");
break;
case 3:
strcpy_s(current_message," You climb out of the maze and escape.");
break;
case 10:
strcpy_s(current_message," There is nothing to grab here.");
break;
case 11:
strcpy_s(current_message," You grab the arrow!");
break;
case 12:
strcpy_s(current_message," You grab the gold! (ka-ching!)");
break;
case 20:
strcpy_s(current_message," You fire into the darkness.");
break;
case 21:
strcpy_s(current_message," You fire into the darkness - and hear a SCREAM!.");
break;
case 22:
strcpy_s(current_message," You have no more arrows.");
break;
case 13:
strcpy_s(current_message, " Hey... I had some kinda error...");
break;
case 130:
strcpy_s(current_message, " What - you have something better to do?");
break;
case 131:
strcpy_s(current_message, " You have been eaten by the Wumpus! (crunch)");
break;
case 132:
strcpy_s(current_message, " You have fallen down a bottomless pit! (Ahhhh!)");
break;
case 136:
strcpy_s(current_message, " You have run out of moves!");
break;
default:
strcpy_s(current_message," ");
break;
}
char agent_message1[50];
char agent_message2[50];
char arrow_stat[15];
char score_stat[15];
char turn_stat[15];
// char temp[10];
if ( (MrMan.iamhuman() == 0) ) //if the robot is playing
{
strcpy_s(agent_message1, " Agent ");
strcat_s(agent_message1, MrMan.myName() );
strcat_s(agent_message1, " is playing.");
strcpy_s(agent_message2, " Press a Key to Advance");
}
else
{
strcpy_s(agent_message1, " ");
strcpy_s(agent_message2, " ");
}
strcpy_s(arrow_stat," Arrows Left: ");
//itoa(MrMan.myArrows(),temp,10);
//strcat(arrow_stat, temp);
strcpy_s(score_stat," Score: ");
//itoa(MrMan.myScore(),temp,10);
//strcat(score_stat, temp);
strcpy_s(turn_stat," Moves: ");
//itoa(moves,temp,10);
//strcat(turn_stat, temp);
//note to self - itoa is not avaialble under UNIX (argh)
//line 0:
//cout << "######################" << " Gabe's Amazing Wumpus Simulator" << endl;
printline(0," Wumpus World");
//note: the space needs to be the first character, since the string starts immediately after the map
printline(1, agent_message1);
printline(2, agent_message2);
printline(3, " ");
printline(4, " Commands:");
printline(5, " ");
printline(6, " 8 - Advance");
printline(7, " 4 - Turn Left");
printline(8, " 6 - Turn Right");
printline(9, " C - Climb out of Maze");
printline(10, " G - Grab (gold or arrow)");
printline(11, " S - Shoot Arrow");
printline(12, " ");
printline(13, " Q or 5 - Quit");
printline(14, " H - Help");
printline(15, " ");
printline(16, turn_stat, moves);
printline(17, arrow_stat, MrMan.myArrows() );
printline(18, score_stat, MrMan.myScore() );
printline(19, " Status:");
printline(20, current_message);
//cout << "######################" << endl;
printline(21, " ");
cout << "Current Percept Sequence:" << endl;
displayPercepts();
int temp_code;
temp_code = code / 10;
if ( (temp_code) == 13)
cout << "Press Enter to return to main menu." << endl;
else if( code == 3 ) //the player actually escaped
{
cout << endl<<"You've made it! Final score = " << MrMan.myScore() << endl;
cout << "Press a key to return to the main menu." <<endl;
}
else
cout << "Command? ";// << endl;
return;
}
void WumpusGame::printline( int j, char sidebar [70])
{
int i;
char agent_map[22][22];
MrMan.getmap(agent_map); //yes, this really wastes memory space
for (i=0; i<22; i++)
{
if ( (i==agent_x) && (j==agent_y) )
{
switch (agent_dir)
{
case 1:
cout << '^';
break;
case 2:
cout << '>';
break;
case 3:
cout << 'v';
break;
case 4:
cout << '<';
break;
default:
cout << "X";
break;
}
}
else if (debug == 1)
cout << map[i][j];
else
cout << agent_map[i][j];
}
cout << sidebar;
cout << endl;
return;
}
void WumpusGame::printline( int j, char sidebar [70], int number)
//we have to overload printlien for this reason:
//some of the sidebars need to print numbers from an int
{
int i;
char agent_map[22][22];
MrMan.getmap(agent_map); //yes, this really wastes memory space
for (i=0; i<22; i++)
{
if ( (i==agent_x) && (j==agent_y) )
{
switch (agent_dir)
{
case 1:
cout << '^';
break;
case 2:
cout << '>';
break;
case 3:
cout << 'v';
break;
case 4:
cout << '<';
break;
default:
cout << "X";
break;
}
}
else if (debug == 1)
cout << map[i][j];
else
cout << agent_map[i][j];
}
cout << sidebar;
cout << number;
cout << endl;
return;
}
void WumpusGame::displayPercepts()
{
int plist[8];
MrMan.getpercepts(plist);
cout << '\t';
if (plist[0] == 1)
cout << "BUMP, ";
else
cout << "bump, ";
if (plist[1] == 1)
cout << "BREEZE, ";
else
cout << "breeze, ";
if (plist[3] == 1)
cout << "GLITTER, ";
else
cout << "glitter, ";
if (plist[4] == 1)
cout << "SMELL, ";
else
cout << "smell, ";
if (plist[5] == 1)
cout << "ARROW, ";
else
cout << "arrow, ";
if (plist[6] == 1)
cout << "SCREAM, ";
else
cout << "scream, ";
if (plist[7] == 1)
cout << "HOME";
else
cout << "home";
cout <<endl;
//cout << '\t' << "bump, breeze, glitter, smell, arrow, scream, home" << endl;
}
int WumpusGame::getinput(int & code)
{
int err;
char first;
char in;
moves ++; //increment the move counter
if (op_move_limit > 0)
if (moves > op_move_limit)
{
code = 136;
return 1;
}
cin >> first;
if ( (MrMan.iamhuman() == 0) ) //if the robot is playing
{
switch (first)
{
case 'd':
case 'D':
case 'q':
case 'Q':
case '5':
case 'h':
case 'H':
in = first;
break;
default:
in = MrMan.action(); //get the agent's action
break;
}//end switch
}
else
in = first;
switch (in)
{
case '8': //move forward;
err = moveAgentForward();
//if (err == 1)
// cout << "Your path is blocked"<<endl;
break;
case '6': //turn right
agent_dir ++;
if (agent_dir == 5)
agent_dir = 1;
break;
case '4': //turn left
agent_dir --;
if (agent_dir == 0)
agent_dir = 4;
break;
case 'C':
case 'c':
if (MrMan.amihome(agent_x,agent_y) == 1)
{
MrMan.bailed(); //tell the agent it escaped
code = 3; //signal that we climbed out (just pretend it makes sense...)
return 1; //return code to exit loop
}
else
err = 2; //not home
break;
case 'g':
case 'G':
//grab either arrows or gold
err = gank(); //nothing like functions
break;
case 's':
case 'S':
err = fire(); //fire an arrow (if we have one)
break;
case 'd':
case 'D':
//we're cheating and have turned on debug mode
if (debug == 1)
debug =0;
else
debug = 1;
break;
case 'h':
case 'H':
Help();
break;
case 'q':
case 'Q':
case '5':
code = 130;
return 1;
break;
}
code = err;
//if (err == 131 || err == 132)
int temp_code = err / 10;
if ( temp_code == 13 )
return 1; //player is dead
return 0;
}
int WumpusGame::gank()
{
if (map[agent_x][agent_y] == 'a')
{
map[agent_x][agent_y] = '.';
MrMan.grabArrow();
return 11;
}
else if (map[agent_x][agent_y] == 'g')
{
map[agent_x][agent_y] = '.';
MrMan.grabGold();
return 12;
}
else
return 10;
}
int WumpusGame::fire()
{
if (MrMan.myArrows() > 0 )
{
MrMan.shoot();
return trajectory();
}
else
return 22;
}
int WumpusGame::trajectory()
{
int done = 0;
int x = agent_x;
int y = agent_y;
int lag_x = agent_x;
int lag_y = agent_y;
//set xy to next square
switch (agent_dir)
{
case 1:
y--;
break;
case 2:
x++;
break;
case 3:
y++;
break;
case 4:
x--;
break;
}
while (!done)
{
char nextS = map[x][y];
char thisS = map[lag_x][lag_y];
switch (nextS)
{
case 'w':
//arrow encounters and vaporizes the Wumpus
map[x][y] = 'g'; //and the Wumpus drops his wallet (or something)
MrMan.hearScream();
done=1;
return 21;
break;
case '#':
//the arrow goes till it hits a wall, and then drops if the square is empty, otherwise it vanishes
if ( (thisS == '.') && (op_arrow_stay == 1 ) )
map[lag_x][lag_y] = 'a';
done = 1;
cout << "Thud\n";
return 20;
break;
default:
break;
}
//advance sqaures
switch (agent_dir)
{
case 1:
y--;
lag_y--;
break;
case 2:
x++;
lag_x++;
break;
case 3:
y++;
lag_y++;
break;
case 4:
x--;
lag_x--;
break;
}
}//end while
return 13;
}
int WumpusGame::moveAgentForward()
{
int retval =0; //the return value 0=fine 1=illegal move 131=player dead by Wumpus 132=fell down pits
switch (agent_dir)
{
case 1: //move north
if (map[agent_x][agent_y-1] != '#')
agent_y--;
else
retval = 1;
break;
case 2: //move east
if (map[agent_x+1][agent_y] != '#')
agent_x++;
else
retval = 1;
break;
case 3: //move south
if (map[agent_x][agent_y+1] != '#')
agent_y++;
else
retval = 1;
break;
case 4: //move west
if (map[agent_x-1][agent_y] != '#')
agent_x--;
else
retval = 1;
break;
default:
break;
}
//check to see if that killed the player
if ( (map[agent_x][agent_y] == 'w') )
retval = 131;
if (map[agent_x][agent_y] == 'p')
retval = 132;
return retval;
}
void WumpusGame::informAgent()
{
char N, S, E, W;
int status[6];
for (int i = 0; i<6; i++)
status[i] = 0; //percepts null by default
//get the surreounding squares
N = map[agent_x] [agent_y-1];
E = map[agent_x+1] [agent_y];
S = map[agent_x] [agent_y+1];
W = map[agent_x-1] [agent_y];
//bump
switch (agent_dir)
{
case 1:
if (N == '#')
status[0] = 1;
break;
case 2:
if (E == '#')
status[0] = 1;
break;
case 3:
if (S == '#')
status[0] = 1;
break;
case 4:
if (W == '#')
status[0] = 1;
break;
}
//breeze
if ( (N == 'p') || (E == 'p') || (S == 'p') || (W == 'p') )
status[1] =1;
//squeak
//glitter
if (map[agent_x][agent_y] == 'g')
status[3] = 1;
//smell
if ( (N == 'w') || (E == 'w') || (S == 'w') || (W == 'w') )
status[4] =1;
//arrow
if (map[agent_x][agent_y] == 'a')
status[5] = 1;
MrMan.wazzup(status,agent_x,agent_y,agent_dir);
return;
}
void WumpusGame::highscore(int current_score)
{
//this would be a keen place to clrscr()
if (current_score < score_val)
return;
if (MrMan.iamhuman() == 1)
{
score_val = current_score;
cout << "You've gotten the new high score!"<<endl;
cout << "What's your name, adventurer? "<<endl;
cin >> score_name;
}
else
{
score_val = current_score;
cout << "Agent " << MrMan.myName() << " has the new high score!"<<endl;
strcpy_s(score_name,MrMan.myName() );
}
return;
}
void WumpusGame::savescores()
{
ofstream score_file ("wumpus.dat", ios::out );
score_file << score_name << endl;
score_file << score_val << endl;
score_file.close();
return;
}
void WumpusGame::loadscores()
{
ifstream score_file ("wumpus.dat", ios::in );
score_file >> score_name;
score_file >> score_val;
score_file.close();
return;
}
void WumpusGame::Help()
{
cout <<endl;
cout << "Wumpus World Help Screen"<<endl;
cout<< endl << "Well, the readme file is probably a better bet, actually."<<endl;
cout <<"Map Key:"<<endl;
cout << "^ > v < = Your Agent (facing the direction of the point)"<<endl;
cout << " = unknown square"<<endl;
cout << ".= visited and empty square"<<endl;
cout << ",= unvisited square, thought to be empty"<<endl;
cout << endl;
cout << "#= Wall"<<endl;
cout << "p= Confirmed pit"<<endl;
cout << "@= Unvisited, thought to be pit"<<endl;
cout << "b= Confirmed bat"<<endl;
cout << "*= Unvisited, thought to be bat"<<endl;
cout << "w= Confirmed Wumpus"<<endl;
cout << "!= Unvisited, thought to be Wumpus"<<endl;
cout << "a= Arrow"<<endl;
cout << "g= Gold"<<endl;
cout << endl;
cout << "Press a key to return"<<endl;
char temp;
cin >> temp;
return;
}
void WumpusGame::closeout()
{
savescores();
cout << "Thanks for playing!" <<endl;
//exit(0);
}
/*
Agent header file
The Agent Class handles everything the agent knows about the
world, whether the agent is the computer or a human player.
Agent also handles infering the location of hazards (in
updatemap() ) and the AI logic routines (in Action() )
*/
#ifndef AGENT_H
#define AGENT_H
#include <cstdlib>
using namespace std;
class Agent
{
private:
int human;
int agent_code;
int my_map[22][22];
int me_x,
me_y; //where the agent thinks it is
int me_dir; //the direction the agent thinks it's facing
//current percepts
/*int bump,
breeze,
squeak,
glitter,
smell,
arrow,
scream,
home;*/
int percepts[8];
int quiver; //current quiver count
int score; //oh yeah - it's points time
int shot; //remembers if we fired last turn
void updatemap(); //updates my_map based on current percepts
void setneighbors(char thing); //sets empty neighbor squares to thing
public:
void start(int start_code, int arrow_num); //starts the agent based on start code 0=human (and arrow number)
void getpercepts(int plist[8]); //returns current percepts
void getmap(char what_I_know[22][22]); //hands out the current contents of the agent's map
void setarrows(int num); //sets the current arrow count to max
void grabArrow(); //takes the arrow here
int myArrows(); //returns number of arrows in quiver
void shoot(); //decrements arrow count by 1
void grabGold(); //take the gold here
int myScore(); //returns current score
char * myName(); //returns agent's name
int iamhuman(); //returns 1 if the agent is human
int amihome(int x,int y); //checks to see if agent is at home
void wazzup (int here[6],int x,int y,int dir); //tells the agent about everything but home and scream
void hearScream(); //the Wumpus be dead
void bailed(); //the agent has escaped
void batsHere(int x, int y); //tells the agent that there really are bats in that square
char action(); //returns the "keypress" of the agent playing
int blocked(char temp); //returns blocking code for character
char blockedSide(char side); //returns contents of sqaure to right or left
char nextSquare(); //returns the contents of the next square in the direciton that the agent is facing
};
#endif
#include "agent.h"
/*
Agent Implementation file
See agent.h for information on the Agent class.
*/
void Agent::updatemap()
{
if (my_map[me_x][me_y] != '.')
score += 2; //points for each new square
//mark square as visited
my_map[me_x][me_y] = '.';
//throw down objects (overrides visited yet empty '.' )
if (percepts[3] == 1)
my_map[me_x][me_y] = 'g'; //set gold
if (percepts[5] == 1)
my_map[me_x][me_y] = 'a'; //set arrows
//put down walls
if (percepts[0] == 1)
{
switch (me_dir)
{
case 1:
my_map[me_x] [me_y-1] = '#';
break;
case 2:
my_map[me_x+1] [me_y] = '#';
break;
case 3:
my_map[me_x] [me_y+1] = '#';
break;
case 4:
my_map[me_x-1] [me_y] = '#';
break;
}
}
//process surroundings
if (percepts[1] == 1)
setneighbors('@'); //mark maybe pits
else if (percepts[4] == 1)
setneighbors('!'); //mark maybe wumpus
else
setneighbors(',');
return;
}
void Agent::setneighbors(char thing)
{
char temp;
temp = my_map[me_x] [me_y-1];
//if ( (temp != '#') && (temp != '.') && (temp != ',') && (temp != 'a') && (temp != 'g') )
if ( (temp == ' ') || (temp == '@') || (temp == '*') || (temp == '!') )
my_map[me_x] [me_y-1] = thing;
temp = my_map[me_x+1] [me_y];
if ((temp == ' ') || (temp == '@') || (temp == '*') || (temp == '!'))
my_map[me_x+1] [me_y] = thing;
temp = my_map[me_x] [me_y+1];
if ((temp == ' ') || (temp == '@') || (temp == '*') || (temp == '!'))
my_map[me_x] [me_y+1] = thing;
temp = my_map[me_x-1] [me_y];
if ((temp == ' ') || (temp == '@') || (temp == '*') || (temp == '!'))
my_map[me_x-1] [me_y] = thing;
return;
}
void Agent::start(int start_code, int arrow_num)
{
if (start_code == 0)
human = 1;
else
human = 0;
agent_code = start_code;
//clear internal map
//any similarities between this and the WumpusGame::makemap() function should be ignored...
int i,j;
for (i = 0; i< 22; i++)
{
for (j=0; j<22; j++)
{
my_map[i][j] = ' ';
}
}
//walls down sides
i=0;
for (j=0; j<22; j++)
my_map[i][j] = '#';
i=21;
for (j=0; j<22; j++)
my_map[i][j] = '#';
//walls on top and bottom
j=0;
for (i=0; i<22; i++)
my_map[i][j] = '#';
j=21;
for (i=0; i<22; i++)
my_map[i][j] = '#';
me_x=1; //we always start at home (yes we do)
me_y=1;
me_dir = 3;
setarrows(arrow_num);
score=0;
//set all percepts to 0 (not present)
/*bump =0;
breeze =0;
squeak =0;
glitter =0;
smell =0;
arrow =0;
scream =0;
home =0;*/
for (int p =0; p<8; p++)
{
percepts[p] = 0;
}
return;
}
void Agent::getpercepts(int plist[8])
{
for (int i=0; i<8; i++)
plist[i] = percepts[i];
return;
}
void Agent::getmap(char what_I_know[22][22])
{
int i,j;
for (i = 0; i<22; i++)
{
for (j=0; j<22; j++)
what_I_know[i][j] = my_map[i][j];
}
return;
}
void Agent::setarrows(int num) //sets the current arrow count to max
{
num = 1;
quiver = num;
return;
}
void Agent::grabArrow() //takes the arrow here
{
quiver++;
my_map[me_x][me_y] = '.';
score += 1; //get a point per arrow
return;
}
int Agent::myArrows()
{
return quiver;
}
void Agent::shoot()
{
quiver--;
score -= 5; //loose points per shot
return;
}
void Agent::grabGold() //take the gold here
{
score = score + 100;
my_map[me_x][me_y] = '.';
return;
}
int Agent::myScore()
{
return score;
}
char * Agent::myName()
{
switch (agent_code)
{
case 1:
return "Dummy";
break;
case 2:
return "Cautious";
break;
case 3:
return "Explorer";
break;
}
return "Nobody";
}
int Agent::iamhuman()
{
return human;
}
int Agent::amihome(int x, int y)
{
if (x == 1 && y == 1)
{
percepts[7]=1;
return 1;
}
else
{
percepts[7]=0;
return 0;
}
}
void Agent::wazzup(int here[6],int x,int y,int dir)
{
for (int i = 0; i<6; i++)
percepts[i] = here[i];
me_x = x;
me_y = y;
me_dir = dir;
updatemap();
return;
}
void Agent::hearScream()
{
percepts[6] =1;
//the scream percept stays set so that the agent remembers that the wumpus is still dead
//this all breaks down, of course, if there is more that one Wumpus
//but there won't be more than one... ;)
score += 1000; //we only get a scream if the wumpus is dead...
return;
}
void Agent::bailed()
{
score +=100;
return;
}
void Agent::batsHere(int x, int y)
{
my_map[x][y] = 'b';
return;
}
char Agent::action()
{
char my_move;
switch (agent_code) //allows for multiple agents
{
case 1: //Dummy
//grab anything there
if (percepts[3] == 1 || percepts[5] == 1)
{
my_move = 'g';
return my_move;
}
//fire if we smell the wumpus
if (percepts[4] == 1)
{
my_move = 's';
return my_move;
}
//turn right if bump, else go forward
if (percepts[0] == 0)
my_move = '8';
else
my_move = '6';
break;
case 2: //Cautious
//grab anything there
if (percepts[3] == 1 || percepts[5] == 1)
{
my_move = 'g';
return my_move;
}
//if we're facing the wumpus, and we havn't already shot, fire
if ( (blocked( nextSquare() ) == 1) && (shot == 0 ) )
{
my_move = 's';
shot = 1; //rember that we shot last turn
return my_move;
}
//clear the shot bit before we move
if (shot == 1)
shot = 0;
//this agent will avoid everything
if ( blocked( nextSquare() ) > 0)
my_move = '6'; //turn right when blocked
else
my_move = '8';
//climb out if at home and the wumpus is dead
if ((percepts[7] == 1) && (percepts[6] == 1))
my_move = 'c';
break;
case 3: //Explorer - tries to go everywhere, shoots when sure, avoids obstacles
//grab anything there
if (percepts[3] == 1 || percepts[5] == 1)
{
my_move = 'g';
return my_move;
}
//first we try to go new places
if (blocked( nextSquare() ) == 0) //move fwd if clear and new
my_move = '8';
else if ( blocked( blockedSide('r') ) == 0) //else turn right if thats clear and new
my_move = '6';
else if ( blocked( blockedSide('l') ) == 0) //finally, turn left if thats clear and new
my_move = '4';
//then we go to old places if we have to
else if (blocked( nextSquare() ) == -1) //move fwd if clear
{
my_move = '8';
//but, to break out of endless wandering, there is a 1/5 chance of rt turn in old areas
if ((rand() % 5) == 1)
my_move = '6';
}
//swap order for old places (take different path)
else if ( (blocked( blockedSide('l') ) == -1) && (blocked( blockedSide('r') ) == -1) )
//if old on all sides, 50-50 shot
{
if ( (rand() % 10) > 5 )
my_move = '6';
else
my_move = '4';
}
//otherwise turn towards free side
else if ( blocked( blockedSide('r') ) == -1) //turn right if thats clear
my_move = '6';
else if ( blocked( blockedSide('l') ) == -1) // turn left if thats clear
my_move = '4';
else //else just pick one randomly
{
if ( (rand() % 10) > 5 )
my_move = '6';
else
my_move = '4';
}
if ( (percepts[7] == 1) && (score > 100) ) //climb out if it has >1 golds
my_move = 'c';
break;
//attack conditions:
//smell it and sides clear (ie, facing wumpus and know it)
if ( (percepts[4] == 1) )
if ( (blocked(blockedSide('r')) != 1) && (blocked(blockedSide('l')) != 1) )
my_move = 's';
default:
my_move = 'q';
break;
}
return my_move;
}
int Agent::blocked(char temp)
//-1 - already visited '.'
//0 - empty and open ','
//1 - the wumpus
//2 - walls
//3 - pits
//4 - bats
{
//char temp;
//temp = nextSquare();
switch (temp)
{
case '#':
return 2;
break;
case 'b':
case '*':
return 4;
break;
case '@':
return 3;
break;
case '!':
return 1;
break;
case '.':
return -1;
break;
default:
return 0;
break;
}
}
char Agent::nextSquare()
{
char temp;
switch (me_dir)
{
case 1:
temp = my_map[me_x] [me_y-1];
break;
case 2:
temp = my_map[me_x+1] [me_y];
break;
case 3:
temp = my_map[me_x] [me_y+1];
break;
case 4:
temp = my_map[me_x-1] [me_y];
break;
}
return temp;
}
char Agent::blockedSide(char side) //side can be r or l - boy I'm sick of int codes...
{
char right, left, N, S, E, W;
N = my_map[me_x] [me_y-1]; //get surrounding squares
E = my_map[me_x+1] [me_y];
S = my_map[me_x] [me_y+1];
W = my_map[me_x-1] [me_y];
switch (me_dir) //which direction we're facing
{
case 1: //N
right = E;
left = W;
break;
case 2: //E
right = S;
left = N;
break;
case 3://S
right = W;
left = E;
break;
case 4://W
right = N;
left = S;
break;
}
if (side == 'r')
return right;
else
return left;
}
/*
This is the main shell file of the progam.
All code and work in this program was designed and developed by
Gabriel Helman. Really. The AIMA code was fairly useless, so I
eneded up designing it all from scratch.
The C++ libraries included are listed at the top of wumpus.h,
along with why they were included.
*/
#include "wumpus.h"
void main()
{
WumpusGame OhSoFun;
OhSoFun.shell();
return;
}
Thanks in advance.