Sign in to follow this  

Basic file input

This topic is 3842 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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?

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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();
}

Share this post


Link to post
Share on other sites
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;
}


Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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 example
cout << 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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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 points

public:
// 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 NULL
Room* 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 Menu
MainMenu();

// Start the player at the head of the linked list
Room* 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 - [P]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;
}



Share this post


Link to post
Share on other sites
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[i], "door", "Try the door.", DIFFICULTY);



Share this post


Link to post
Share on other sites
I didn't have time to read all that code, but just wanted to double check the most likely problem first:

1) when you run a program from within visual studio its current working folder is the same folder as the EXE file, NOT the source code. So if your source code is "...\MUDd\MUDd" then your DEBUG exe is probable in "...\MUDd\MUDd\debug" or some such. Copy your input file into the same directories (release and debug) as your output files (exe file).

Share this post


Link to post
Share on other sites
I've tried putting it in every directory. Just to make sure, I put a copy in every folder within the project, and it still crashes. Later today, when I have time, I'll try creating and writing to a file, and the reading from the file just to make sure everything is working correctly.

Share this post


Link to post
Share on other sites
So, I did what I said and I wrote to a file with ostream, and it created the file in the same directory with all my .h/.cpp files, NOT with the executable. AND, the file did not have a ".txt" suffix, it was just "RoomDescriptions." So, now it works.

Share this post


Link to post
Share on other sites

This topic is 3842 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this