I've created a few text adventures in plain C, whereby every 'area' was a function with its own switch statement to get user input. Instead of traditional "commands" the user is given options e.g. "1. Go north 2. Go south 3. Examine note" etc. This resulted in great flexibitly and options within an area but serious code bloat and ugliness. I'm now trying it in C++ and really like OOP, I've built a class for characters and the areas which takes care of the displaying and world navigation aspects, but I'm now finding the whole approach really inflexible and don't know how to add all my extra content and options to each area. For instance in the test code below I've created 2 areas, once you look around in the plains area, you can see option 6. Examine paper - but how will I add this functionality in an elegant way without resorting back to my old functions for areas mess?
Main.CPP
#include "character.hpp"
#include "area.hpp"
void setupareas();
extern area* current;
area* plains = new area; area* town = new area; area* swamp = new area;
area* chapel = new area; area* mountain = new area;
void setupareas()
{
std::vector<std::string> plainsmenu1 {"1. (Plains) Look Around\n\n", "2. Go North\n\n", "3. Go East\n\n", "4. Go South\n\n", "5. Go West\n\n\n> "};
std::vector<std::string> plainsmenu2 {"1. (Plains) Look Around\n\n", "2. Go North\n\n", "3. Go East\n\n", "4. Go South\n\n", "5. Go West\n\n6. Examine paper\n\n\n> "};
std::vector<std::string> chapelmenu1 {"1. (Chapel) Look Around\n\n", "2. Go North\n\n", "3. Go East\n\n", "4. Go South\n\n", "5. Go West\n\n\n> "};
std::vector<std::string> chapelmenu2 {"1. (Chapel) Look Around\n\n", "2. Go North\n\n", "3. Go East\n\n", "4. Go South\n\n", "5. Go West\n\n6. Open door\n\n\n> "};
plains->setdesc("You are standing in a wide plain\n\n1. Back\n\n\n> ");
plains->setmenu1(plainsmenu1); plains->setmenu2(plainsmenu2);
plains->setdoors(chapel, mountain, swamp, town);
chapel->setdesc("You are outside a chapel\n\n1. Back\n\n\n> ");
chapel->setmenu1(chapelmenu1); chapel->setmenu2(chapelmenu2);
chapel->setdoors(NULL, NULL, plains, NULL);
}
int main(void)
{
setupareas();
current = plains;
while (1) {
current->getinput();
}
return 0;
}
area.HPP
class area {
public:
area();
~area();
std::vector<std::string> menu1;
std::vector<std::string> menu2;
std::string desc;
short seen;
area *north, *east, *south, *west;
void setmenu1(std::vector<std::string>);
void setmenu2(std::vector<std::string>);
void setdesc(std::string);
void display();
void look();
void getinput();
void setdoors(area*,area*,area*,area*);
};
area* current;
area::area()
{
this->seen = 0;
}
area::~area()
{
}
void area::setmenu1(std::vector<std::string> line)
{
for (std::string s : line)
{
this->menu1.push_back(s);
}
}
void area::setmenu2(std::vector<std::string> line)
{
for (std::string s : line)
{
this->menu2.push_back(s);
}
}
void area::display()
{
if (this->seen == 0) {
for (std::string s : this->menu1)
{
print(s);
}
}
else {
for (std::string s : this->menu2)
{
print(s);
}
}
}
void area::getinput()
{
char choice;
bool here = true;
while (here) {
system("cls"); std::cout << TITLE;
this->display();
std::cin>>choice;
switch(choice)
{
case '1': this->look(); break;
case '2': if (this->north != NULL) {current = this->north; here = false; break;} else {print("\n\nCan't go North"); Sleep(2500); break;}
case '3': if (this->east != NULL) {current = this->east; here = false; break;} else {print("\n\nCan't go East"); Sleep(2500); break;}
case '4': if (this->south != NULL) {current = this->south; here = false; break;} else {print("\n\nCan't go South"); Sleep(2500); break;}
case '5': if (this->west != NULL) {current = this->west; here = false; break;} else {print("\n\nCan't go West"); Sleep(2500); break;}
}
}
}
void area::look()
{
system("cls"); this->seen = 1; std::cout << TITLE;
print(this->desc); char c; std::cin>>c;
}
void area::setdesc(std::string desc)
{
this->desc = desc;
}
void area::setdoors(area* north, area* east, area* south, area* west)
{
this->north = north;
this->east = east;
this->south = south;
this->west = west;
}