Basic file input

Started by
11 comments, last by Shakedown 16 years, 10 months ago
So I have a text RPG and I have hundreds of rooms that I need to write descriptions for. The descriptions are simply a string. Rather than hard-coding them, I just want to write the descriptions in a .txt file using Notepad, then read from that file. How do I do this, particularly how do I make it read from a particular point in the .txt file, so I can have all the descriptions in one .txt file?
Advertisement
What language are you using?

If you're using C++, you can use an ifstream (found in the <fstream> header) object. Generally you'll read in all your data from the text file and store it in memory. To open up a file, parse it, and extract the exact data you need for a room every time you change a room will waste CPU cycles. If you store it in memory, you can look up the data very fast.
Quote:Original post by CrimsonSun
What language are you using?

If you're using C++, you can use an ifstream (found in the <fstream> header) object. Generally you'll read in all your data from the text file and store it in memory. To open up a file, parse it, and extract the exact data you need for a room every time you change a room will waste CPU cycles. If you store it in memory, you can look up the data very fast.


Yes, C++. I understand the process, I need help on the code. So far, the only thing I've got is the basic file input
#include <fstream>...string description;  ifstream descFile ("RoomDescriptions.txt");  if (descFile.is_open())  {    while (! myfile.eof() )    {      getline (myfile,description);      cout << description << endl;    }    myfile.close();  }
If you're using plain text files then file input is almost the same as console input (this changes for binary files).

data.txt:
1 2 3 4 5.55 abc



For the above data file, this code stores the value 1 into i1, 2 into i2, 3 into i3, 4 into i4, 5.55 into f1, and "abc" into str.
#include <fstream>int main(){  std::ifstream infile;  std::string str;  int i1, i2, i3, i4;  float f1;  infile.open("data.txt");    infile >> i1 >> i2 >> i3 >> i4 >> f1 >> str;}

So how do I make it read in strings on different lines.
Like this?

file.txt
This is the first description of foijfoijboijlknkjd flij gboij boifj boidbj odiksjn trj rlhjkjndskjn kvj nvkj nvksjn vskdj vnsdkj nvkdsj nvdskj nvsdkjn soeirj oig joij oij oi jvoij oij oijf oij foij oj ojnvkjn vkjn vu newnvkj nkjrvnkj vnk jrnkvniuen eu fnknxckj vkj k fjl f lkjsdf.This is the second description of foijfoijboijlknkjd flij gboij boifj boidbj odiksjn trj rlhjkjndskjn kvj nvkj nvksjn vskdj vnsdkj nvkdsj nvdskj nvsdkjn soeirj oig joij oij oi jvoij oij oijf oij foij oj ojnvkjn vkjn vu newnvkj nkjrvnkj vnk jrnkvniuen eu fnknxckj vkj k fjl f lkjsdf.This is the third description of foijfoijboijlknkjd flij gboij boifj boidbj odiksjn trj rlhjkjndskjn kvj nvkj nvksjn vskdj vnsdkj nvkdsj nvdskj nvsdkjn soeirj oig joij oij oi jvoij oij oijf oij foij oj ojnvkjn vkjn vu newnvkj nkjrvnkj vnk jrnkvniuen eu fnknxckj vkj k fjl f lkjsdf.This is the fourth description of foijfoijboijlknkjd flij gboij boifj boidbj odiksjn trj rlhjkjndskjn kvj nvkj nvksjn vskdj vnsdkj nvkdsj nvdskj nvsdkjn soeirj oig joij oij oi jvoij oij oijf oij foij oj ojnvkjn vkjn vu newnvkj nkjrvnkj vnk jrnkvniuen eu fnknxckj vkj k fjl f lkjsdf.


main.cpp
#include <fstream>  std::ifstream infile;  std::string desc1, desc2, desc3, desc4;  infile.open("text.txt");    infile >> desc1;  infile >> desc2;  infile >> desc3;  infile >> desc4;}

I just don't understand how it will know when to stop reading in the first description and start reading in the second description. Is there a way to tell it what lines to read from?

The >> operator extracts one word at a time, skipping spaces. If you did the above you would end up with
desc1 = "This"desc2 = "is"desc3 = "the"desc4 = "first"

getline gets one line (surprise!) of text at a time including spaces, skipping line breaks (return/linefeed). That's in your second post. What you're missing there is a way to store the lines for future retrieval. So, to adjust what you wrote there...
#include <algorithm> // for std::copy#include <fstream>   // for std::ifstream#include <iostream>  // for std::cout, etc.#include <string>    // for std::string#include <vector>    // for std::vector...  vector<string> all_room_descriptions;  ifstream descFile("RoomDescriptions.txt");  if ( descFile.is_open() )  {    while ( !descFile.eof() )    {      string description;      getline(descFile, description);      all_room_descriptions.push_back(description);    }    descFile.close();  }  // Now all_room_descriptions holds the contents  // of the file, indexed by line number. Some  // examples of how to use it...  cout << all_room_desriptions[0] << "\n"; // displays the first line  cout << all_room_descriptions[3] << "\n"; // displays the fourth line  copy(all_room_descriptions.begin(),       all_room_descriptions.end(),       ostream_iterator<string>(cout,"\n")); // displays everything


If retreival by line number is not enough then you may want to store into something like a std::map instead, where you can give each entry a unique key.

Ok, here's what I have now, and my program crashes.
vector<string> room_descriptions;	ifstream descFile ("RoomDescriptions.txt");		if( descFile.is_open() )	{		while( !descFile.eof() )		{			string description;			getline( descFile, description );			room_descriptions.push_back(description);		}		descFile.close();	}	// Just to be simple for this examplecout << room_descriptions[0];cout << room_descriptions[1];


I have a textfile named "RoomDescriptions.txt" saved in the same folder as all the .h/.cpp files, and it looks like this:
This is the first room, read from the text file.This is the second room, read from the text file.


Like I said, it crashes, don't work. What's the dill? I'm using vectors correctly aren't I? And I've included the vector and fstream headers.
Your code works for me. I think your working directory for you project file may not contain the actual text file you're using. As a result, your vector is not filled with two elements and you end up calling elements that don't exist from the vector where you output your data to the console -- accessing out of bounds causes a crash.
Ok I don't know why this isn't working. I'll just give you my source code and tell you everything.

I currently have a file named "RoomDescriptions.txt" located in
C:...\VisualStudio 2005\Projects\MUDd\MUDd
along with all of my .h/.cpp files. And in the text file is written:
This is the first room, read from the text file.This is the second room, read from the text file.


The istream is in main

ColorText.h
#ifndef _COLORTEXT_#define _COLORTEXT_enum {BLACK, BLUE, GREEN, CYAN, RED, MAGENTA, BROWN, LIGHTGRAY, DARKGRAY, LIGHTBLUE, LIGHTGREEN, LIGHTCYAN, LIGHTRED, LIGHTMAGENTA, YELLOW, WHITE};void setColor(unsigned short color){	HANDLE hcon = GetStdHandle(STD_OUTPUT_HANDLE);	SetConsoleTextAttribute(hcon, color);}#endif


Menu.h
/***********************************************************************	Menu header file*	This file holds the Menu class**********************************************************************/#include <iostream>#include <windows.h>#include "ColorText.h"using std::cout;class Menu{public:	void DisplayIntro();	void DisplayWelcome();	void DisplayLevEd();	void DisplayCharGen();	void BattleMenu();	void Instructions();	void ClearScreen();};void Menu::DisplayIntro(){	cout << "*******************************************************************************\n";	cout << "*                                                                             *\n";	cout << "*                                                                             *\n";	cout << "*                                                                             *\n";	cout << "*                                                                             *\n";	cout << "*                                                                             *\n";	cout << "*                                                                             *\n";	cout << "*                                                                             *\n";	cout << "*                                                                             *\n";	cout << "*                                                                             *\n";	cout << "*                                                                             *\n";	cout << "*";	setColor(LIGHTRED);	cout << "                                  MUDd                                       ";	setColor(LIGHTGRAY);	cout << "*\n";	cout << "*";	setColor(WHITE);	cout << "                         Created By: Nate Wolfe                              ";	setColor(LIGHTGRAY);	cout << "*\n";	cout << "*                                                                             *\n";	cout << "*                                                                             *\n";	cout << "*                                                                             *\n";	cout << "*                                                                             *\n";	cout << "*                                                                             *\n";	cout << "*                                                                             *\n";	cout << "*                                                                             *\n";	cout << "*                                                                             *\n";	cout << "*                                                                             *\n";	cout << "*                                                                             *\n";	cout << "*                                                                             *\n";	cout << "*******************************************************************************";}/***********************************************************************	DisplayWelcome function*	This function displays the welcome menu**********************************************************************/void Menu::DisplayWelcome(){	cout << "\t\tMUDd\n";	cout << "a. Create Your Character\n";	cout << "b. View Your Character\n";	cout << "c. Start Your Journey!\n";	cout << "d. Level Editor\n";	cout << "e. Exit\n";	cout << "Choice: ";}/***********************************************************************	DisplayLevEd function*	This function displays the level editor menu**********************************************************************/void Menu::DisplayLevEd(){	cout << "\t\tHere you will create your Rooms.\n";	cout << "Each Room has 4 properties:\n";	cout << "Description - The description of the Room.\n";	cout << "Exit        - The way out of the Room, and into the next Room.\n";	cout << "Hint        - A hint to tell if the player cannot find the exit.\n";	cout << "Difficulty  - This decides the chance that their will be a monster in the room.\n";	cout << "			 - Either 1(Hard), 2(Medium), 3(Easy).\n\n";	cout << "\tFirst, enter how many Rooms you want to create: ";}/***********************************************************************	DisplayCharGen function*	This function displays the character generation menu**********************************************************************/void Menu::DisplayCharGen(){	cout << "\t\tHere you will choose your Character!\n\n";	cout << "\tEach unit in the game - Players and Monsters -\n";	cout << "\thas 5 attributes: Health, Attack, Defense, Agility, Initiative.\n\n";	cout << "Health .... Hit points, or HP. How much damage you can take before you die.\n";	cout << "Attack .... Attack Power. How much damage you inflict with a succesfull strike.\n";	cout << "Defense ... Armor. How much damage is reduced from an enemies strike.\n";	cout << "Agility ... This determines your ability to strike and dodge.\n";  	cout << "Initiative. This influences who strikes first at the beginning of each round.\n"; 	cout << "\n\t\tKeep these in mind when choosing your character!\n\n";}/***********************************************************************	BattleMenu function*	This function displays the players options during battle**********************************************************************/void Menu::BattleMenu(){	cout << "x. FIGHT!\n";	//cout << "y. USE ITEM!\n";	cout << "y. VIEW STATS!\n";	cout << "z. RUN!\n";	cout << "Choice: ";}/***********************************************************************	Instructions function*	This function displays the commands the player can enter**********************************************************************/void Menu::Instructions(){	cout << "\tThere are several commands you may enter anytime within the world:\n\n";	cout << "'hint' ... Will display a hint to help you find the exit\n";	cout << "'view' ... Will display your character information\n";	cout << "'help' ... Will display these commands again\n";	cout << "'quit' ... Will exit the game\n\n";}/***********************************************************************	ClearScreen function*	This function simply clears the screen**********************************************************************/void Menu::ClearScreen(){	system("CLS");}


Unit.h
/***********************************************************************	Monster header file*	This file holds the Monster class**********************************************************************/#include <string>#include <iostream>#include "Menu.h"using std::cout;using std::endl;const std::string defaultnames[13] = { "Troll", "Ogre", "Large Bat", "Rabid Hound", "Orc", "King Snake", "Large Spider", "Goblin", "Dragon Whelp", "Spined Basilisk", "Skeleton Warrior", "Huge Rat", "Small Chimaera" };const int ExpRequiredForNextLevel[10] = {3, 6, 9, 12, 16, 20, 24, 28, 33, 38};class Unit							// Base class for any Unit in the game{protected:	int m_Health;					// All Units have a Health, or HP	int m_savedHP;					// This value is set to m_Health upon entering combat. Once combat exits, m_Health is set to this	int m_Attack;					// All Units have an Attack, or AP	int m_Defense;					// All Units have a Defense, or Armor	int m_Initiative;				// All Units have an Initiative	int m_Agility;					// Agility determines your ability to dodge attacks	float m_Gold;					// All Units carry some gold	std::string m_Name;				// All Units have a name	bool dead;						// This is the Unit's dead flag	void saveHealth(){ m_savedHP = m_Health; }		// This will store the combatants health before battle, allowing max HP to be restored	void isNowDead(){ dead = true; }				// This will set the dead flag when a Unit has died						public:	// Constructors	Unit();	// Setters	void setName(std::string name){ m_Name = name; }	void resetHealth(){ m_Health = m_savedHP; }	float TakeGoldFrom(Unit& deadguy);	// Getters	std::string getName() const { return m_Name; }	int getHealth() const { return m_Health; }	int getSavedHP() const { return m_savedHP; }	int getAttack() const { return m_Attack; }	int getDefense() const { return m_Defense; }	int getInitiative() const { return m_Initiative; }	int getAgility() const { return m_Agility; }	float getGold() const { return m_Gold; }	bool isDead() const { return dead; }	// Combat functions	float Attack() const { return m_Attack * ((float)(rand()%11)/10.0); }	float Defend() const { return m_Defense * ((float)(rand()%11)/10.0); }	float Initiative() const { return m_Initiative * ((float)(rand()%11)/10.0);  }	float Agility() const { return m_Agility * ((float)(rand()%11)/10.0); }	bool kill(Unit& opponent);	Unit& versus(Unit& opponent);};class Player : public Unit{private:	int m_Level;					// All Players have a Level	int m_Exp;						// All Players have Experience pointspublic:	// Default Constructor	Player();	// Getters	int getLevel() const { return m_Level; }	int getXP() const { return m_Exp; }	int getExpRequiredForNextLevel() const { return ExpRequiredForNextLevel[m_Level-1]; }	// Non-combat functions	bool UpdatePlayer();	void LevelUp();};/***********************************************************************	Player default constructor*	This constructor calls the Unit constructor and sets other values**********************************************************************/Player::Player(){	Unit();	m_Level = 1;	m_Exp = 0;}/***********************************************************************	UpdatePlayer function*	This function updates the player after combat**********************************************************************/bool Player::UpdatePlayer(){	if(!dead)	{		++m_Exp;		if(m_Exp == ExpRequiredForNextLevel[m_Level - 1])			return true;		else			return false;	}	else		return false;}/***********************************************************************	LevelUp function*	This function increments the players level and attributes**********************************************************************/void Player::LevelUp(){	++m_Level;	m_Exp = 0;	m_Health += rand() % 5 + 1;	m_Attack += rand() % 5 + 1;	m_Defense += rand() % 5 + 1;	m_Initiative += rand() % 5 + 1;}/***********************************************************************	Unit default constructor*	This constructor randomly assigns values to the attributes**********************************************************************/Unit::Unit(){	m_Name = defaultnames[ rand() % 12 ];	m_Health =     rand() % 11 + 10;	m_Attack =	   rand() % 11 + 10;	m_Defense =	   rand() % 11 + 10;	m_Initiative = rand() % 11 + 10;	m_Agility =	   rand() % 11 + 10;	m_Gold = (float)(rand() % 11)/1.0f;	dead = false;}/***********************************************************************	TakeGoldFrom function*	This function adds the deadguy's gold to the players and returns*	how much was added**********************************************************************/float Unit::TakeGoldFrom(Unit& deadguy){	float temp = deadguy.m_Gold;	m_Gold += deadguy.m_Gold;	deadguy.m_Gold = 0.0;	return temp;}/***********************************************************************	kill function*	This function modifies the health of the Unit and returns true or false**********************************************************************/bool Unit::kill(Unit& opponent){	system("CLS");	//Calculate whether the Unit hits the opponent	if(Agility() < opponent.Agility())	{				setColor(WHITE);		cout << "\n\n\n\t\t" <<m_Name << "(";		setColor(GREEN);		cout << m_Health;		setColor(WHITE);		cout << ")";		setColor(LIGHTGRAY);		cout << "'s attack is evaded by ";		setColor(WHITE);		cout << opponent.getName() << "(";		setColor(GREEN);		cout << opponent.getHealth();		setColor(WHITE);		cout << ")";		setColor(LIGHTGRAY);		cout << "!\n\n";		Sleep(2000);		return false;	}	else	{		int hit = Attack() - opponent.Defend();		opponent.m_Health -= (hit <= 0)? 1 : hit;		setColor(WHITE);		cout << "\n\n\n\t\t" << m_Name << "(";		setColor(GREEN);		cout << m_Health;		setColor(WHITE);		cout << ")";		setColor(LIGHTGRAY);		cout << " struck ";		setColor(WHITE);		cout << opponent.getName() << "(";		setColor(GREEN);		cout << opponent.getHealth();		setColor(WHITE);		cout << ")";		setColor(LIGHTGRAY);		cout << " for ";		setColor(RED);		cout << ((hit <= 0)? 1 : hit) << " damage!\n";		setColor(LIGHTGRAY);		cout << "\n\t\t\t" << opponent.getName() << " has ";		setColor(GREEN);		cout << opponent.getHealth() << " health";		setColor(LIGHTGRAY);		cout << " left!\n\n";		Sleep(2000);		return( opponent.m_Health <= 0 );	}}/***********************************************************************	versus function*	This function simulates battle between two Units and returns the winner**********************************************************************/Unit& Unit::versus(Unit& opponent){	this->saveHealth();	opponent.saveHealth();	while( true )	{		int UnitInitiative = Initiative();		int OpponentInitiative = opponent.Initiative();		bool IGoFirst = UnitInitiative >= OpponentInitiative;		Unit& attacker = IGoFirst? *this : opponent;		Unit& defender = IGoFirst? opponent : *this;		if( attacker.kill(defender) )		{			attacker.resetHealth();			defender.isNowDead();			return attacker;		}		if( defender.kill(attacker) )		{			attacker.isNowDead();			defender.resetHealth();			return defender;		}	}}


Room.h
/***********************************************************************	Room header file*	This file holds the Room class**********************************************************************/#include "Unit.h"#include <iostream>using namespace std;class Room{public:	std::string description;		// This holds the description of the room	std::string exit;				// This is one exit to the next room 	std::string hint;				// This holds a hint for how to get to the next room	Room* next;						// This is a pointer to the next room	Room* prev;						// This is a pointer to the previous room	Unit* ptr_Monster;				// This is a pointer to a monster	void UpdateMonster();	~Room(){ delete ptr_Monster; }};// Initialize the head and tail of the linked-list to NULLRoom* head = NULL;Room* tail = NULL;/***********************************************************************	UpdateMonster function*	This function checks to see if its monster is dead, if it is, delete**********************************************************************/void Room::UpdateMonster(){	if((ptr_Monster)->isDead())	{		delete ptr_Monster;		ptr_Monster = NULL;	}}	/***********************************************************************	AddRoom function*	This function adds a Room to the linked list**********************************************************************/void AddRoom(std::string description, std::string exit, std::string hint, int DIFFICULTY){	if(head == NULL)				// If there is not a head Room...	{		head = new Room;			// Create a new Room...		tail = head;				// Assign the head to tail since there's only one room, so it is both the head and the tail		tail->next = NULL;			// Assign the next pointer to NULL		tail->prev = NULL;			// Assign the previous pointer to NULL		tail->ptr_Monster = NULL;	// Assign the pointer-to-a-Monster to NULL	}	else							// Since there is already a head...	{		tail->next = new Room;		// Create a new Room...					tail->next->prev = tail;	// Assign the new Room's previous pointer to tail		tail = tail->next;			// Assign the tail of the linked list to this new Room		tail->next = NULL;			// Assign the next pointer to NULL		tail->ptr_Monster = NULL;	// Assign the pointer-to-Monster to NULL	}	tail->description = description;// Assign the description passed to the function in the parameter as the new Room's description	tail->exit = exit;				// Assign the exit passed to the function in the parameter as the new Room's exit	tail->hint = hint;				// Assign the hint passed to the function in the parameter as the new Room's hint		if((tail != head) && ((rand() % DIFFICULTY) == 0))		tail->ptr_Monster = new Unit;}/***********************************************************************	DeleteRooms function*	This function goes through the entire linked list and deletes all *	rooms, then resets the head and tail to NULL**********************************************************************/void DeleteAllRooms(){	Room* thisRoom = head;			// Create a pointer to a Room named thisRoom and set it to point to the head. Iterates through all rooms	Room* eraseRoom = NULL;			// Create a pointer to a Room named eraseRoom and set it to NULL. This is the room that will be deleted		while(thisRoom != NULL)			// Go through the entire linked list	{		eraseRoom = thisRoom;		// Assign thisRoom to eraseRoom		thisRoom = thisRoom->next;	// Assign thisRoom to the next Room in the linked list		delete eraseRoom;			// Delete eraseRoom	}	head = NULL;					// Reset the head to NULL	tail = NULL;					// Reset the tail to NULL}/***********************************************************************	GetInputString function*	This function reads from the input stream and returns a string,*	effectively removing the '\n' that is left in the buffer**********************************************************************/std::string GetInputString(istream& is){	std::string line;	while(line.empty())		getline(is, line);	return line;}/***********************************************************************	GetInputChar function*	This function reads from the input stream and returns a char,*	effectively removing the '\n' that is left in the buffer**********************************************************************/char GetInputChar(istream& is){	std::string line;	while(line.empty())		getline(is, line);	return line[0];}


main.cpp
/***********************************************************************	Main source file*	This is the main file for the MUDd program**********************************************************************/#include "Room.h"#include <cstdlib>#include <ctime>#include <fstream>#include <vector>const int REROLLS_ALLOWED = 5;enum {HARD = 1, MEDIUM, EASY};bool done = false;bool ForcePlayerToUseCharacter = true;Menu menu;Player* player = NULL;void CreateCharacter(){	menu.ClearScreen();	menu.DisplayCharGen();	system("PAUSE");	int ReRollsAllowed = REROLLS_ALLOWED;	char input;	while(true)	{		if(player) delete player;		player = new Player;		while(true)		{			menu.ClearScreen();			cout << "\t\tYou have " << ReRollsAllowed << " re-rolls left.\n";			cout << "    Health: " << player->getHealth() << endl;			cout << "    Attack: " << player->getAttack() << endl;			cout << "   Defense: " << player->getDefense() << endl;			cout << "   Agility: " << player->getAgility() << endl;			cout << "Initiative: " << player->getInitiative() << endl;			cout << "\n\t[K]eep or [R]e-Roll? ";			if(ReRollsAllowed == 0)			break;			input = tolower(GetInputChar(cin));			if(input == 'k' || input == 'r')				break;		}		if(ReRollsAllowed == 0)			break;		if(input == 'k')			break;		if(input == 'r' && ReRollsAllowed > 0)			--ReRollsAllowed;	} 	if(ReRollsAllowed == 0)		cout << "\n\n\tThis is your character!\n";	cout << "\nCharacter name: ";	player->setName(GetInputString(cin));	menu.ClearScreen();}void ViewCharacter(){	menu.ClearScreen();	cout << "Name: " << player->getName() << "\tGold: " << player->getGold() << endl;	cout << "Level: " << player->getLevel() << "\tXP: " << player->getXP() << "/" << player->getExpRequiredForNextLevel() << endl << endl;	cout << "Health: " << player->getHealth() << endl;	cout << "Agility: " << player->getAgility() << "\tInitiative: " << player->getInitiative() << endl;	cout << "Attack: " << player->getAttack() << "\tDefense: " << player->getDefense() << endl << endl;	system("PAUSE");	menu.ClearScreen();}void GenerateRooms(int DIFFICULTY){		vector<string> room_descriptions;                   <---------------------------- PROBLEM HERE	ifstream descFile ("RoomDescriptions.txt");		if( descFile.is_open() )	{		while( !descFile.eof() )		{			string description;			getline( descFile, description );			room_descriptions.push_back(description);		}		descFile.close();	}		// Initialize the various Rooms.  	// The first parameter is the description, 	// the second parameter is the exits, and 	// the third parameter is the hint.	// the fourth parameter is the chance that a monster will spawn in the room	AddRoom(room_descriptions[0], "door", "Try the door.", DIFFICULTY);	AddRoom(room_descriptions[1], "hole", "Try the hole.", DIFFICULTY);	AddRoom("This is the third room.", "trapdoor", "Try the trapdoor.", DIFFICULTY);	AddRoom("This is the fourth room.", "door", "none.", DIFFICULTY);	AddRoom("This is the fifth room.", "door", "none.", DIFFICULTY);	AddRoom("This is the sixth room.", "ladder", "none.", DIFFICULTY);	AddRoom("This is the seventh room.", "window", "none.", DIFFICULTY);	AddRoom("This is the eigth room.", "tree", "none.", DIFFICULTY);	AddRoom("This is the ninth room.", "hole", "none.", DIFFICULTY);	AddRoom("This is the tenth room.", "door", "none.", DIFFICULTY);	AddRoom("This is the 11 room.", "window", "none.", DIFFICULTY);	AddRoom("This is the 12 room.", "tree", "none.", DIFFICULTY);	AddRoom("This is the 13 room.", "stair", "none.", DIFFICULTY);	AddRoom("This is the 14 room.", "ladder", "none.", DIFFICULTY);	AddRoom("This is the 15 room.", "door", "none.", DIFFICULTY);	AddRoom("This is the 16 room.", "car", "none.", DIFFICULTY);	AddRoom("This is the 17 room.", "hole", "none.", DIFFICULTY);	AddRoom("This is the 18 room.", "door", "none.", DIFFICULTY);	AddRoom("This is the 19 room.", "car", "none.", DIFFICULTY);	AddRoom("This is the 20 room.", "window", "none.", DIFFICULTY);	AddRoom("This is the 21 room.", "car", "none.", DIFFICULTY);	AddRoom("This is the 22 room.", "car", "none.", DIFFICULTY);	AddRoom("This is the 23 room.", "car", "none.", DIFFICULTY);	AddRoom("This is the 24 room.", "car", "none.", DIFFICULTY);	AddRoom("This is the 25 room.", "car", "none.", DIFFICULTY);	AddRoom("This is the 26 room.", "car", "none.", DIFFICULTY);	AddRoom("This is the 27 room.", "car", "none.", DIFFICULTY);	AddRoom("This is the 28 room.", "car", "none.", DIFFICULTY);	AddRoom("This is the 29 room.", "car", "none.", DIFFICULTY);	AddRoom("This is the 30 room.", "car", "none.", DIFFICULTY);	AddRoom("This is the 31 room.", "car", "none.", DIFFICULTY);	AddRoom("This is the 32 room.", "car", "none.", DIFFICULTY);	AddRoom("This is the 33 room.", "car", "none.", DIFFICULTY);	AddRoom("This is the 34 room.", "car", "none.", DIFFICULTY);	AddRoom("This is the 35 room.", "car", "none.", DIFFICULTY);}void LevelEditor(){	menu.ClearScreen();	menu.DisplayLevEd();		int numRooms;		cin >> numRooms;		for(int i = 1; i <= numRooms; i++)		{				string description, exit, hint;			int diff;			char keep;			menu.ClearScreen();			do{				cout << "**Room " << i << "**" << endl;				cout << "Description:\n";				description = GetInputString(cin);				cout << "Exit:\n";				exit = GetInputString(cin);				cout << "Hint:\n";				hint = GetInputString(cin);				cout << "Difficulty: ";				cin >> diff;				cout << "Would you like to keep these(y or n)? ";			}while(tolower(GetInputChar(cin)) != 'y');			AddRoom(description, exit, hint, diff);		}}void MainMenu(){char choice;while(true){	menu.ClearScreen();	menu.DisplayWelcome();	choice = tolower(GetInputChar(cin));	if(choice == 'a' || choice == 'b' || choice == 'c' || choice == 'd' || choice == 'e')		break;}switch( choice ){	case 'a':		if(player && !ForcePlayerToUseCharacter)		{			cout << "\n\tContinuing will delete your current character.\n";			cout << "\tContinue? ";			char input;			while(true)			{				input = tolower(GetInputChar(cin));				if(input == 'y' || input == 'n')					break;			}			if(input == 'n')				break;		}		if(player && ForcePlayerToUseCharacter)		{			cout << "\n\tYou've already made your character! Start your journey!\n\n";			system("PAUSE");			break;		}		CreateCharacter();		break;	case 'b':		if(player == NULL)		{			cout << "You must create your character first!\n\n";			system("PAUSE");			//menu.ClearScreen();			break;		}		ViewCharacter();		break;	case 'c':		if(player == NULL)		{			cout << "You must create your character first!\n\n";			system("PAUSE");			//menu.ClearScreen();			break;		}		else		{		cout << "Difficulty: [E]asy, [M]edium, [H]ard? ";		int DIFFICULTY;		char D = tolower(GetInputChar(cin));		switch(D)		{		case 'e': DIFFICULTY = EASY;		case 'm': DIFFICULTY = MEDIUM;		case 'h': DIFFICULTY = HARD;		}		GenerateRooms(DIFFICULTY);		}		menu.ClearScreen();		menu.Instructions();		system("PAUSE");		break;			case 'd':		if(player == NULL)		{			cout << "You must create your character first!\n\n";			system("PAUSE");			//menu.ClearScreen();			break;		}		LevelEditor();		menu.ClearScreen();		menu.Instructions();		system("PAUSE");		break;	case 'e':		done = true;		break;	default:		break;}}void Battle(Unit* monster){		//menu.ClearScreen();		//cout << "You've encountered a ";		//setColor(WHITE);		//cout <<  monster->getName();		//setColor(LIGHTGRAY);		//cout << "!\n\n";		Unit& winner = player->versus( *monster );		setColor(WHITE);		cout << "\t\t" << winner.getName();		setColor(LIGHTGRAY);		cout << " has won!\n";			if(player->isDead())		{			cout << "\n\n\t\t\tYou have died! Better luck next time!\n\n";			done = true;		}		if(!player->isDead())		{			if(player->UpdatePlayer())			{				system("PAUSE");				menu.ClearScreen();				player->LevelUp();				cout << "\tCONGRATULATIONS! You have leveled up!\n";				cout << "Here are your new stats:\n";				cout << "     Level: " << player->getLevel() << endl;				cout << "    Health: " << player->getHealth() << endl;				cout << "    Attack: " << player->getAttack() << endl;				cout << "   Defense: " << player->getDefense() << endl;				cout << "Initiative: " << player->getInitiative() << endl;			}				cout << "\n\t\tYou have taken ";		setColor(YELLOW);		cout << player->TakeGoldFrom(*monster) << " gold";		setColor(LIGHTGRAY);		cout << " from the dead ";		setColor(WHITE);		cout << monster->getName();		setColor(LIGHTGRAY);		cout << ".\n";		}		system("PAUSE");		menu.ClearScreen();}int main(){srand(time(NULL));menu.DisplayIntro();Sleep(5000);menu.ClearScreen();while( !done ){// Start the MenuMainMenu();// Start the player at the head of the linked listRoom* you = head;string userinput;// the Main game loop. Once user reaches end of linked list or they quit, exit.while( you != NULL && !done ){	menu.ClearScreen();		while( !done )	{		// If there's a monster in the room and its alive		if( (you->ptr_Monster) && !(you->ptr_Monster->isDead()) )		{			char c;			while(true)			{				menu.ClearScreen();				// Ask the user if they want to fight the monster or return to the previous room				cout << "Upon entering, you are met by the menacing stare of a " << you->ptr_Monster->getName() << "!\n\n";				cout << "Do you have the [C]ourage to fight!\n";				cout << "Or will you [R]un back to the previous room? ";				c = tolower(GetInputChar(cin));				if(c == 'c' || c == 'r')					break;			}			if(c == 'c')			{				Battle(you->ptr_Monster);				you->UpdateMonster();			}			else			{				you = you->prev;				break;			}		}				// If the player has died from combat(where the done flag will be set to true), break out of the loop		if(done) break;		// Output the description of your current location		cout << you->description << endl;		// Output the exit leading to the next room		cout << "Exits: " << you->exit;		// If there's a previous room, output the exit to that room 		if(you->prev)			cout << " / " << you->prev->exit;		// Read in the user's input		cout << "\nInput: ";		userinput = GetInputString(cin);		// If there's no previous room and the user enters the next exit,		// move them to the next room		if(!you->prev && (userinput == you->exit))		{			you = you->next;			break;		}		// If there IS a previous room and the user enters the next exit		// and the exit of your current location is not the same as the exit of the previous room,		// move them to the next room		else if(you->prev && (userinput == you->exit) && (you->exit != you->prev->exit))		{			you = you->next;			break;		}				// If there is a previous room and the user enters the next exit		// and the exit of your current location IS the same as the exit of the previous room,		// prompt the user as to which exit they intended, then move them accordingly		else if(you->prev && (userinput == you->exit) && (you->exit == you->prev->exit))		{			cout << "Which exit - revious or [N]ext? ";			char c = GetInputChar(cin);				if(tolower(c) == 'p')					you = you->prev;				if(tolower(c) == 'n')					you = you->next;			break;		}		// If there's a previous room and the user enters the prev exit,		// move them to the previous room		else if(you->prev && (userinput == you->prev->exit))		{			you = you->prev;			break;		}		// If user entered "hint," output the hint for their current location		else if(userinput == "hint")		{			menu.ClearScreen();			cout << "\t" << you->hint << "\n" << endl;		}		// If the user enters "view," call the ViewCharacter() function		else if(userinput == "view")			ViewCharacter();		// If the user enters "help," show the Instructions again		else if(userinput == "help")		{			menu.ClearScreen();			menu.Instructions();			system("PAUSE");			menu.ClearScreen();		}		// If the user enters "quit," then set the done flag to true and		// break out of the loop		else if(userinput == "quit")		{			done = true;			break;		}		// If the user enters something that is not recognized,		// output "Invalid"		else		{			menu.ClearScreen();			cout << "\tInvalid.\n" << endl;		}	}		if( done )	{		break;	}		}}delete player;DeleteAllRooms();return 0;}
Like I said, your data file is not in the same working directory as your executable because it lies in the C:...\VisualStudio 2005\Projects\MUDd\MUDd directory. If I remember correctly, visual studio 2005 creates subfolders called release and debug based upon the build you're making. You need to put the data file in that directory (ie, C:...\VisualStudio 2005\Projects\MUDd\MUDd\release or C:...\VisualStudio 2005\Projects\MUDd\MUDd\debug, whichever build you're making).

A good practice is to start safely using vectors. You should never know that there is a 0 element or 1 element. Instead, you should either use iterators or use the size() vector method to determine how many elements you actually have. So, replace this
AddRoom(room_descriptions[0], "door", "Try the door.", DIFFICULTY);AddRoom(room_descriptions[1], "hole", "Try the hole.", DIFFICULTY);


with either this:

for(std::vector<std::string>::iterator iter = room_descriptions.begin(); iter != room_descriptions.end(); iter++)  AddRoom(*iter, "door", "Try the door.", DIFFICULTY);


or this:

for(int i = 0; i < room_descriptions.size(); i++)  AddRoom(room_descriptions, "door", "Try the door.", DIFFICULTY);

This topic is closed to new replies.

Advertisement