1.

Solve : Third time's a charm - Escape game?

Answer»

After another look at my code, and another "what the heck was I thinking" moment, I'm going to try again with the game. I won't make any promises on a completion date, or even on what days I'll make any progress whatsoever. I'm doing this in my spare time, as a student, so I don't think this'll be quick.

For any who missed the last two attempts: Escape is a C++ game I'm writing, command-line driven. It's intended to teach me Object-Oriented programming, as well as problem-solving on a larger scale than the typical "here's a program to illustrate an example" program you see in the average tutorial.

I'm doing this with the full knowledge that, as I post the code, I'm going to get corrections, things I can change and improve, and questions asking for why I did what I did. I need this feedback, as it helps me become a better programmer.

Without further ado, here's what I have so far. This is NOTHING more than the basic classes I'll be using, and the implementation code (I'm working on that). This also includes my brainstorming process as I began this project, which will help show where I'm coming from with my code, my variable and class names, etc.

Code: [Select]/*Program Name: Escape
Program Type: Command-line game
Description: Explore my old house, collect items and use them to formulate a plan to escape.
Program began: 11/17/2007
Program Ended: ??/??/????
*/

/*Brainstorming process

Will need "Room" objects, "Item" objects (for things that can be put into inventory), and
"Interact" objects that can be interacted with, but not put into inventory.

Room objects will need a String "name" that describes the room's purpose, e.g. "Family Room". They
should also have String "descriptions", which can be accessed by entering a "look around" command.

Item objects will need a "name", like Rooms, e.g. "Pencil". They should also have a description,
in case the player chooses to view a description. Some will need other properties, such as battery
life.

Interacts will need a "name". They should have descriptions. They will also need other properties,
depending on the object. These will be stored in vectors, i.e. a "boolean" vector for needed BOOLS,
"int" vector, "String", etc.

A Player class is needed. It should have room location as a variable, and an Inventory class as a
aggregated class. The Inventory class will be a vector, with references to Items as they are placed
in Inventory.

***A parser is needed in another header file*/

#include <vector>
using namespace std;
class Item;
class Interact;
enum flag { TRUE, FALSE, INVALID };

class Room
{
public:
/*At initial setup, vectors should be created with all needed objects, and
passed to the Room constructor.*/
Room(String name, vector<Item> itemCreate, vector<Interact> intCreate);
//Use Default destructor; not using the Free Store.

//Accessor functions
vector<Item> getItems() { return itsItems; } //Returns entire vector
Item findItem(string name); //Searches Items for certain names of Items

vector<Interact> getInteracts() { return itsInteracts; } //Returns entire vector
Interact findInteract(string name); //Searches Interacts for certain names

string getLocation() { return location; }

void describeRoom();
//Describe the room based on a description and items visible in the room.

private:
vector<Item> itsItems;
vector<Interact> itsInteracts;
string defaultDesc; //The default description of the room; doesn't mention items.
string location;
};

Room::Room(String name, vector<item> itemCreate, vector<Interact> intCreate)
{
/*In this PORTION of the code block, add code to parse a text file and
read in the desription in, adding it to defaultDesc*/
location = name;

for(int i = 0; i <= itemCreate.SIZE(); i++)
{
itsItems.push_back(itemCreate[i]);
}

for(i = 0; i <= intCreate.size(); i++)
{
itsInteracts.push_back(intCreate[i]);
}
}

Room::findItem(string name) //For "take item" type commands.
//Similar function for Inventory class should be used.
{
/*Search the vector array of Items for one with a particular name. Return the Item if
it can be found, and throw a NO_MATCHING_ITEM if it can't be found.*/

for(int i = 0; i <= itsItems.size(); i++)
{
if(itsItems[i].settings[0] == name)
return itsItems[i];
}
throw NO_MATCHING_ITEM;
}

Room::findInteract(string name) //For "use item" type commands for within a room.
{
/*Search the vector array of Items for one with a particular name. Return the Item if
it can be found, and throw a NO_MATCHING_INTERACT if it can't be found.*/

for(int i = 0; i <= itsInteracts.size(); i++)
{
if(itsInteracts[i].settings[0] == name)
return itsInteracts[i];
}
throw NO_MATCHING_INTERACT;
}


class Item
{
public:
Item();
/*The following variables are made public so that the findItem and findInteract
functions can work faster, by not requiring a "get" function to be called multiple
times in a loop.*/

vector<string> settings;
/*In the above vector, the first place is for the name; the second is the description.*/

vector<int> numbers;
/*Key:
0:Number of Items (ex: 3 dollars)
1:Battery Life (-1 for invalid)
2:Code (-1 for invalid)*/

//Accessor
flag getUsable() { return usable; }
private:
flag usable;
};


class Interact
{
public:

Interact();

/*The following variables are made public so that the findItem and findInteract
functions can work faster, by not requiring a "get" function to be called multiple
times in a loop.*/
vector<string> settings;
/*In the above vector, the first place is for the name; the second is the description.*/

vector<flag> flags;
/*Key:
0:On/Off
1:Locked/Unlocked
2:Open/Closed
3:Usable/Unusable (ex: a chair breaks. It can no longer be used.)*/
};

Obviously, I'm not done with this yet. Player and Inventory needs to be written, and implementations for each. Then, I need to design a command-parser (I'll probably want help with that one), and of course the actual story and game.Okay, I've modified portions of the code, and added more. The only changes to existing code is that I've added a "result" enum, and changed the return type of the "findItem" type functions. I've also added code for the Player class and the Inventory class, which has been assimilated into part of Player.

rooms.hpp
Code: [Select]/*Program Name: Escape
Program Type: Command-line game
Description: Explore my old house, collect items and use them to formulate a plan to escape.
Program began: 11/17/2007
Program Ended: ??/??/????
*/

/*Brainstorming process

Will need "Room" objects, "Item" objects (for things that can be put into inventory), and
"Interact" objects that can be interacted with, but not put into inventory.

Room objects will need a String "name" that describes the room's purpose, e.g. "Family Room". They
should also have String "descriptions", which can be accessed by entering a "look around" command.

Item objects will need a "name", like Rooms, e.g. "Pencil". They should also have a description,
in case the player chooses to view a description. Some will need other properties, such as battery
life.

Interacts will need a "name". They should have descriptions. They will also need other properties,
depending on the object. These will be stored in vectors, i.e. a "boolean" vector for needed BOOLS,
"int" vector, "String", etc.

A Player class is needed. It should have room location as a variable, and an Inventory class as a
aggregated class. The Inventory class will be a vector, with references to Items as they are placed
in Inventory.

***A parser is needed in another header file*/

#include <vector>
using namespace std;
class Item;
class Interact;
enum flag { TRUE, FALSE, INVALID };
enum result { SUCCESS, FAILURE, ERROR }

class Room
{
public:
/*At initial setup, vectors should be created with all needed objects, and
passed to the Room constructor.*/
Room(String name, vector<Item> itemCreate, vector<Interact> intCreate);
//Use Default destructor; not using the Free Store.

//Accessor functions
vector<Item> getItems() { return itsItems; } //Returns entire vector
result findItem(string name); //Searches Items for certain names of Items

vector<Interact> getInteracts() { return itsInteracts; } //Returns entire vector
result findInteract(string name); //Searches Interacts for certain names

string getLocation() { return location; }

void describeRoom();
//Describe the room based on a description and items visible in the room.

private:
vector<Item> itsItems;
vector<Interact> itsInteracts;
string defaultDesc; //The default description of the room; doesn't mention items.
string location;
};

Room::Room(String name, vector<item> itemCreate, vector<Interact> intCreate)
{
/*In this portion of the code block, add code to parse a text file and
read in the desription in, adding it to defaultDesc*/
location = name;

for(int i = 0; i <= itemCreate.size(); i++)
{
itsItems.push_back(itemCreate[i]);
}

for(i = 0; i <= intCreate.size(); i++)
{
itsInteracts.push_back(intCreate[i]);
}
}

Room::findItem(string name) //For "take item" type commands.
//Similar function for Inventory class should be used.
{
/*Search the vector array of Items for one with a particular name. Return SUCCESS if
it can be found, and FAILURE if it can't be found.*/

for(int i = 0; i <= itsItems.size(); i++)
{
if(itsItems[i].settings[0] == name)
return SUCCESS;
}
return FAILURE;
}

Room::findInteract(string name) //For "use item" type commands for within a room.
{
/*Search the vector array of Interacts for one with a particular name. Return SUCCESS if
it can be found, and FAILURE if it can't be found.*/

for(int i = 0; i <= itsInteracts.size(); i++)
{
if(itsInteracts[i].settings[0] == name)
return SUCCESS;
}
return FAILURE;
}


class Item
{
public:
Item();
/*The following variables are made public so that the findItem and findInteract
functions can work faster, by not requiring a "get" function to be called multiple
times in a loop.*/

vector<string> settings;
/*In the above vector, the first place is for the name; the second is the description.*/

vector<int> numbers;
/*Key:
0:Number of Items (ex: 3 dollars)
1:Battery Life (-1 for invalid)
2:Code (-1 for invalid)*/

//Accessor
flag getUsable() { return usable; }
private:
flag usable;
};


class Interact
{
public:

Interact();

/*The following variables are made public so that the findItem and findInteract
functions can work faster, by not requiring a "get" function to be called multiple
times in a loop.*/
vector<string> settings;
/*In the above vector, the first place is for the name; the second is the description.*/

vector<flag> flags;
/*Key:
0:On/Off
1:Locked/Unlocked
2:Open/Closed
3:Usable/Unusable (ex: a chair breaks. It can no longer be used.)*/
};

class Player
{
/*As of 11/18/2007, the concept of a Inventory class is suspended. A vector of Items, with
refrences as the elements in the vector, will be used; it is more direct.*/
public:

//Accessor
string getRoom() { return curr_room; }
vector<Item> getInventory() { return inventory; } //Accessor
result findInventory(Item match); //Searches Inventory for an item that matches.
result findInventory(Item match, Item second); //For when two items are required.
//Used to check if the player has a needed Item in inventory.
private:

string curr_room; //The player's location.
vector<Item> inventory; //REFERENCES ONLY!
};

Player::findInventory(Item match)
{
/*Check each item in the Inventory vector for the Item specified. If it finds it, return
SUCCESS; otherwise, FAILURE.*/

for(int i = 0; i <= inventory.size(); i++)
{
if(inventory[i]==match)
return SUCCESS;
}
return FAILURE; //Couldn't find a match in the loop.
}

Player::findInventory(Item match, Item second) //Need two Items to return SUCCESS.
{
bool first_match_found = false; //Set true if the first loop is a success.

for(int i = 0; i <=inventory.size(); i++) //Look for the first item.
{
if(inventory[i]==match)
{
first_match_found = true;
break;
}
}
if(first_match_found==true) //Found first item, look for second.
{
for(i = 0; i <= inventory.size(); i++
{
if(inventory[i]==second)
{
return SUCCESS; //Found both items
}
}
}
return FAILURE; //Either no items can be found, or only one prerequisite is present.
}

I'm sure that there are errors that I need to correct, but the meat of this header is finished, I believe. I'm currently writing parse.hpp, which will be considerably longer. Please, if you are a programmer, point out flaws in my code, or things I can improve. It only makes me a better programmer, and causes less headaches later, at Compile Time. Okay, I've hit a brick wall. I just realized that I have no idea, at this point, where to write the code that actually does things within the game. I need to be able to write functions that can modify the state of certain Items, only allow such action if they are in the correct location (and possibly have prerequisite items, and/or have certain Interacts at appropriate settings).

For example, the Unlock Door command should set the current room's Door Item to unlocked, if and only if they are in the proper room, have a key, and have a light on so they can see what they're doing.

I'm royally stuck. Here's parse.hpp so far; it's not much code yet.

Code: [Select]// *****************PARSE.HPP*****************

/*This file is to be a header including a command parser. It will also include a text-file parser,
so that default descriptions can be read into the game, as can action text. (This makes it easier
to edit story text, even as the program is running, and keeps the .cpp file a lot less cluttered.*/

/*Brainstorming process:

***COMMAND PARSER***

A seperate parser for each room would prove useful, as it allows commands to be performed in one room
and not the other. Also, it's better organization. Finally, if I use seperate instances of a Parser
class, then I can use multiple text files, one for each room. Doing that makes less of a headache
when building the Text Parser in all its glory.

I need some flexibility in what is considered a valid command. I think it would be prudent to make
a list of possible actions, and what commands can be used to invoke them. Care must be taken not to
make duplicate commands in multiple actions, though.

Actions:
Look Around: Look, Look Around, Examine Room, Look Room
Take Item: Take x, Grab x
Examine Item (Inventory): Inventory x
Use Item: Use x on y, Use x with y, Use x y, Use x
Open/Close Interacts: (Open | close) x
Turn on/off Interacts: Turn x (on | off), Turn (on | off) x
Lock/Unlock Interacts: (Lock | Unlock) x, (Lock | Unlock) x with y
Enter Codes: Enter Code, Use Keypad, Enter numbers
Examine Interact: Look x, Look at x, Examine x
Leave Room: Go to [room], Go [room], Enter [room]

These commands will be in a text file, one for each room (ex: familyRoom.txt contains info for a
"Take Chair" command. All commands should be converted to lowercase first, and all commands listed in
the text file should also be lowercase.

***TEXT PARSER***

This should be in the same text file as the commands. They will be story-related flavor text, such as
"You pick up the [item] and put it in your inventory." They will also be room descriptions, i.e.
"The living room is rather plainly decorated, and has little to interest you. However, there is a..."
Also, action-related story text should go here, such as "The lights in the room go out. It is very
dark now, and difficult to see."

There should be optional Tutorial Text, such as, "to use your flashlight, type 'Turn on Flashlight'.",
or "You have obtained a four-digit code. This can be used to unlock a door with a electronic lock
somewhere in the house." This can be turned on or off before the game starts.

Basically, this all comes down to file streaming, and making use of re-writing a similar text
parser I wrote a while ago.
*/
#include "rooms.hpp"
#include <iostream>
#include <fstream>
enum match { FOUND, MISSING, ERROR }
class Parser
{
public:

result parseStory(string startTag, string endTag); // Finds and reads in story text.

private:
string filename; //What text file will the commands be read in from?
};I decided to go back and test some of my current functions. I am happy to report that the following code has been tested to work as expected:

Code: [Select]class Item
{
public:
Item(string name, string desc, int num, int batt, int code);
/*The following variables are made public so that the findItem and findInteract
functions can work faster, by not requiring a "get" function to be called multiple
times in a loop.*/

vector<string> settings;
/*In the above vector, the first place is for the name; the second is the description.*/

vector<int> numbers;
/*Key:
0:Number of Items (ex: 3 dollars)
1:Battery Life (-1 for invalid)
2:Code (-1 for invalid)*/

//Accessor
flag getUsable() { return usable; }
private:
flag usable;
};

Item::Item(string name, string desc, int num, int batt, int code)
{
settings.push_back(name);
settings.push_back(desc);
numbers.push_back(num);
numbers.push_back(batt);
numbers.push_back(code);
}


class Interact
{
public:

Interact(string name, string desc, flag on, flag lock, flag open, flag usable);

/*The following variables are made public so that the findItem and findInteract
functions can work faster, by not requiring a "get" function to be called multiple
times in a loop.*/
vector<string> settings;
/*In the above vector, the first place is for the name; the second is the description.*/

vector<flag> flags;
/*Key:
0:On/Off
1:Locked/Unlocked
2:Open/Closed
3:Usable/Unusable (ex: a chair breaks. It can no longer be used.)*/
};

Interact::Interact(string name, string desc, flag on, flag lock, flag open, flag usable)
{
settings.push_back(name);
settings.push_back(desc);
flags.push_back(on);
flags.push_back(lock);
flags.push_back(open);
flags.push_back(usable);
}

class Room
{
public:
/*At initial setup, vectors should be created with all needed objects, and
passed to the Room constructor.*/
Room(string name, vector<Item> itemCreate, vector<Interact> intCreate);
//Use Default destructor; not using the Free Store.

//Accessor functions
vector<Item> getItems() { return itsItems; } //Returns entire vector
result findItem(string name); //Searches Items for certain names of Items

vector<Interact> getInteracts() { return itsInteracts; } //Returns entire vector
result findInteract(string name); //Searches Interacts for certain names

string getLocation() { return location; }

private:
vector<Item> itsItems;
vector<Interact> itsInteracts;
string defaultDesc; //The default description of the room; doesn't mention items.
string location;
};

Room::Room(string name, vector<Item> itemCreate, vector<Interact> intCreate)
{
/*In this portion of the code block, add code to parse a text file and
read in the desription in, adding it to defaultDesc*/
location = name;

for(int i = 0; i < itemCreate.size(); i++)
{
itsItems.push_back(itemCreate[i]);
}

for(int i = 0; i < intCreate.size(); i++)
{
itsInteracts.push_back(intCreate[i]);
}
}

result Room::findItem(string name) //For "take item" type commands.
//Similar function for Inventory class should be used.
{
/*Search the vector array of Items for one with a particular name. Return SUCCESS if
it can be found, and FAILURE if it can't be found.*/

for(int i = 0; i <= itsItems.size(); i++)
{
if(itsItems[i].settings[0] == name)
return SUCCESS;
}
return FAILURE;
}

result Room::findInteract(string name) //For "use item" type commands for within a room.
{
/*Search the vector array of Interacts for one with a particular name. Return SUCCESS if
it can be found, and FAILURE if it can't be found.*/

for(int i = 0; i <= itsInteracts.size(); i++)
{
if(itsInteracts[i].settings[0] == name)
return SUCCESS;
}
return FAILURE;
}Sheesh, this thread is dead. Either way, I'll KEEP posting this, so people can step in if they wish to correct something, or if they know a better way of doing something.

Anyway, all of rooms.hpp has been tested, and works flawlessly. I had to change/add a few things, though.

Code: [Select]// *****************ROOMS.HPP*****************

/*Program Name: Escape
Program Type: Command-line game
Description: Explore my old house, collect items and use them to formulate a plan to escape.
Program began: 11/17/2007
Program Ended: ??/??/????
*/

/*Brainstorming process

Will need "Room" objects, "Item" objects (for things that can be put into inventory), and
"Interact" objects that can be interacted with, but not put into inventory.

Room objects will need a String "name" that describes the room's purpose, e.g. "Family Room". They
should also have String "descriptions", which can be accessed by entering a "look around" command.

Item objects will need a "name", like Rooms, e.g. "Pencil". They should also have a description,
in case the player chooses to view a description. Some will need other properties, such as battery
life.

Interacts will need a "name". They should have descriptions. They will also need other properties,
depending on the object. These will be stored in vectors, i.e. a "boolean" vector for needed BOOLS,
"int" vector, "String", etc.

A Player class is needed. It should have room location as a variable, and an Inventory class as a
aggregated class. The Inventory class will be a vector, with references to Items as they are placed
in Inventory.

***A parser is needed in another header file*/

#include <vector>
#include <string>
using namespace std;
enum flag { TRUE, FALSE, INVALID };
enum result { SUCCESS, FAILURE, ERROR };

class Item
{
public:
Item(string name, string desc, int num, int batt, int code);
/*The following variables are made public so that the findItem and findInteract
functions can work faster, by not requiring a "get" function to be called multiple
times in a loop.*/

vector<string> settings;
/*In the above vector, the first place is for the name; the second is the description.*/

vector<int> numbers;
/*Key:
0:Number of Items (ex: 3 dollars)
1:Battery Life (-1 for invalid)
2:Code (-1 for invalid)*/

//Accessor
flag getUsable() { return usable; }

//For Comparison purposes
bool operator==(Item rhs);
private:
flag usable;
};

Item::Item(string name, string desc, int num, int batt, int code)
{
settings.push_back(name);
settings.push_back(desc);
numbers.push_back(num);
numbers.push_back(batt);
numbers.push_back(code);
}

bool Item::operator==(Item rhs)
{
for(int i = 0; i < numbers.size(); i++)
{
if(numbers[i] != rhs.numbers[i])
return false;
}
for(int i = 0; i < settings.size(); i++)
{
if(settings[i] != rhs.settings[i])
return false;
}
if(getUsable() != rhs.getUsable())
return false;
return true; //All checks are made, we're clear.
}


class Interact
{
public:

Interact(string name, string desc, flag on, flag lock, flag open, flag usable);

/*The following variables are made public so that the findItem and findInteract
functions can work faster, by not requiring a "get" function to be called multiple
times in a loop.*/
vector<string> settings;
/*In the above vector, the first place is for the name; the second is the description.*/

vector<flag> flags;
/*Key:
0:On/Off
1:Locked/Unlocked
2:Open/Closed
3:Usable/Unusable (ex: a chair breaks. It can no longer be used.)*/
};

Interact::Interact(string name, string desc, flag on, flag lock, flag open, flag usable)
{
settings.push_back(name);
settings.push_back(desc);
flags.push_back(on);
flags.push_back(lock);
flags.push_back(open);
flags.push_back(usable);
}

class Room
{
public:
/*At initial setup, vectors should be created with all needed objects, and
passed to the Room constructor.*/
Room(string name, vector<Item> itemCreate, vector<Interact> intCreate);
//Use Default destructor; not using the Free Store.

//Accessor functions
vector<Item> getItems() { return itsItems; } //Returns entire vector
result findItem(string name); //Searches Items for certain names of Items

vector<Interact> getInteracts() { return itsInteracts; } //Returns entire vector
result findInteract(string name); //Searches Interacts for certain names

string getLocation() { return location; }

private:
vector<Item> itsItems;
vector<Interact> itsInteracts;
string defaultDesc; //The default description of the room; doesn't mention items.
string location;
};

Room::Room(string name, vector<Item> itemCreate, vector<Interact> intCreate)
{
/*In this portion of the code block, add code to parse a text file and
read in the desription in, adding it to defaultDesc*/
location = name;

for(int i = 0; i < itemCreate.size(); i++)
{
itsItems.push_back(itemCreate[i]);
}

for(int i = 0; i < intCreate.size(); i++)
{
itsInteracts.push_back(intCreate[i]);
}
}

result Room::findItem(string name) //For "take item" type commands.
//Similar function for Inventory class should be used.
{
/*Search the vector array of Items for one with a particular name. Return SUCCESS if
it can be found, and FAILURE if it can't be found.*/

for(int i = 0; i <= itsItems.size(); i++)
{
if(itsItems[i].settings[0] == name)
return SUCCESS;
}
return FAILURE;
}

result Room::findInteract(string name) //For "use item" type commands for within a room.
{
/*Search the vector array of Interacts for one with a particular name. Return SUCCESS if
it can be found, and FAILURE if it can't be found.*/

for(int i = 0; i <= itsInteracts.size(); i++)
{
if(itsInteracts[i].settings[0] == name)
return SUCCESS;
}
return FAILURE;
}




class Player
{
/*As of 11/18/2007, the concept of a Inventory class is suspended. A vector of Items, with
refrences as the elements in the vector, will be used; it is more direct.*/
public:


Player(string room);
//Accessor
string getRoom() { return curr_room; }
Item getInventory(int i) { return inventory.at(i); } //Accessor

result findInventory(Item match); //Searches Inventory for an item that matches.
result findInventory(Item match, Item second); //For when two items are required.
//Used to check if the player has a needed Item in inventory.
vector<Item> inventory; //REFERENCES ONLY!
//Action functions
void takeItem(string command);
void useItem(string command);
void inventoryItem(string command);
void lookAround();
void lockInteract(string command);
void activateInteract(string command);
void enterCode(string command);
void examineInteract(string command);
void goToRoom(string command);
private:

string curr_room; //The player's location.

};

Player::Player(string room)
{
curr_room = room;
}

result Player::findInventory(Item match)
{
/*Check each item in the Inventory vector for the Item specified. If it finds it, return
SUCCESS; otherwise, FAILURE*/

for(int i = 0; i < inventory.size(); i++)
{
if(getInventory(i)==match)
return SUCCESS;
}
return FAILURE; //Couldn't find a match in the loop.
}

result Player::findInventory(Item match, Item second) //Need two Items to return SUCCESS.
{
bool first_match_found = false; //Set true if the first loop is a success.

for(int i = 0; i <inventory.size(); i++) //Look for the first item.
{
if(getInventory(i)==match)
{
first_match_found = true;
break;
}
}
if(first_match_found==true) //Found first item, look for second.
{
for(int i = 0; i < inventory.size(); i++)
{
if(getInventory(i)==second)
{
return SUCCESS; //Found both items
}
}
}
return FAILURE; //Either no items can be found, or only one prerequisite is present.
}

This is just a header file, too. Time to write the parser.Did you notice those "Action Commands" that were given PROTOTYPES, but not actually written, in the above code? As it happens, they are part of the command parser, which deals with user input from the command-line. As it happens, this is the bulk of the coding left to do. After that, I need to write the story parser, and create the text files for the story (which will be read in by the Story Parser), i.e. "you take the [object]." or "the room you are in is ...".

Anyway, writing these action commands has forced me to come to grips with a powerful aspect of C++ that I didn't ever quite learn perfectly: The pointer. References won't do here, as the pointer needs to not be constant. I have changed the Player member variable "string curr_room" to "Room *itsRoom", so that I can use the current Room in logic, such as the takeItem method I just finished:

Code: [Select]void Player::takeItem(string command)
{
/*Get the Item to be taken into a string variable, then check against current room's Items.
If the item can be found, make sure it's not already in the player's inventory.*/
string theItem = command.substr(5); //Discount the "Take "
bool itemExists = false;
for(int i = 0; i < itsRoom->getItems().size(); i++)
{
if(itsRoom->getItems()[i].settings[0] == theItem)//The item exists in the room
{
itemExists = true;
if(findInventory(itsRoom->getItems()[0]) != SUCCESS) //If he doesn't have it already
{
Item & newInventoryItem = itsRoom->getItems()[i];
inventory.push_back(newInventoryItem);
//Code to parse the story here.
break;
}
else //He already has the item
{
cout << "You already have this item in inventory.\n";
}
}

}

if(!itemExists)
{
cout << "No such item exists.\n";
}
}
I'm slowly making my way through this, but it will take some time to complete the command parser. Once I have, and once it's all checked for errors, I will be considerably happier about this project, as this is the wall that stopped me twice in a row, now. Not this time, though.



Discussion

No Comment Found