I am attempting to implement the simple subtype functions in this program, but I
ID: 3859482 • Letter: I
Question
I am attempting to implement the simple subtype functions in this program, but I can't seem to get them to work. I am not entirely sure what I am doing wrong.
My assignment states to :Add sub type functions to the Sub types of the Actor base type.
These functions are as follows:
Roar() - for the Monster subtype
Rally() - for the Hero subtype
Hide() - for the villager subtype
All I need them to do is print out:
"Hero: rallies those around him."
"Monster: roars fiercely"
"Villager: *hides*"
by using the lines that are similar to std::cout << "Monster: " << message << std::endl;
Can someone help me get these working? Thanks in advance.
#include<iostream>
#include<fstream>
#include<cstdlib>
#include<string>
#include<map>
#include<vector>
void tokenize(const std::string& str,
std::vector<std::string>& tokens,
const std::string& delimiters = " ") {
// Skip delimiters at beginning.
std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
// Find first "non-delimiter".
std::string::size_type pos = str.find_first_of(delimiters, lastPos);
while (std::string::npos != pos || std::string::npos != lastPos)
{
// Found a token, add it to the vector.
tokens.push_back(str.substr(lastPos, pos - lastPos));
// Skip delimiters. Note the "not_of"
lastPos = str.find_first_not_of(delimiters, pos);
// Find next "non-delimiter"
pos = str.find_first_of(delimiters, lastPos);
}
}
class Actor;
class InvItem;
typedef std::map<std::string,Actor*> ActorMap;
typedef std::vector<InvItem> InvBag;
typedef std::vector<std::string> TokenVector;
std::ostream& operator<<(std::ostream& o,TokenVector v) {
for(int i=0; i<v.size(); i++)
o << v[i] << " ";
return o;
}
typedef struct {
int health,manna,stamina,intel;
} VitalStruct;
typedef struct {
std::string name, type;
} EntityInfo;
std::ostream& operator<<(std::ostream& o,VitalStruct v) {
o << "health:" << v.health << std::endl;
o << "manna:" << v.manna << std::endl;
o << "stamina:" << v.stamina << std::endl;
o << "intel:" << v.intel << std::endl;
return o;
}
class Actor {
protected:
VitalStruct vitals;
InvBag inventory;
EntityInfo info;
public:
VitalStruct get_vitals();
InvBag get_inventory();
EntityInfo set_type(const EntityInfo& attribute);
EntityInfo get_type();
EntityInfo set_name(const EntityInfo& attribute);
EntityInfo get_name();
void set_inventory(const InvBag&);
virtual void speak(const std::string &message)=0;
//created a function that all subtypes can use
virtual void hit(const std::string &message)=0;
};
class InvItem {
};
InvBag& operator<<(InvBag& bag,InvItem iv) {
bag.push_back(iv);
return bag;
}
EntityInfo Actor::set_type(const EntityInfo& attribute) {
info.type = attribute.type;
return info;
}
EntityInfo Actor::set_name(const EntityInfo& attribute) {
info.name = attribute.name;
return info;
}
EntityInfo Actor::get_name() {
return info;
}
EntityInfo Actor::get_type() {
return info;
}
VitalStruct Actor::get_vitals() {
return vitals;
}
void Actor::set_inventory(const InvBag& ivbag) {
inventory = ivbag;
}
InvBag Actor::get_inventory() {
return inventory;
}
class Monster : public Actor {
public:
void speak(const std::string& message);
void hit(const std::string& message);
void roar(const std::string& message);
};
void Monster::roar(const std::string& message) {
std::cout << "Monster: " << message << std::endl;
}
void Monster::speak(const std::string& message) {
std::cout << "Monster: " << message << std::endl;
}
void Monster::hit(const std::string& message) {
std::cout << "Monster: " << message << std::endl;
}
class Hero : public Actor {
void speak(const std::string& message);
void hit(const std::string& message);
void rally(const std::string& message);
};
void Hero::rally(const std::string& message) {
std::cout << "Hero: " << message << std::endl;
}
void Hero::speak(const std::string& message) {
std::cout << "Hero: " << message << std::endl;
}
void Hero::hit(const std::string& message) {
std::cout << "Hero: " << message << std::endl;
}
class Villager : public Actor {
void speak(const std::string& message);
void hit(const std::string& message);
void hide(const std::string& message);
};
void Villager::hit(const std::string& message) {
std::cout << "Villager: " << message << std::endl;
}
void Villager::speak(const std::string& message) {
std::cout << "Villager: " << message << std::endl;
}
void Villager::hide(const std::string& message) {
std::cout << "Villager: " << message << std::endl;
}
int main() {
ActorMap actormap;
InvBag bag;
EntityInfo type;
EntityInfo name;
std::ifstream in_file("./characters.txt");
if(in_file.fail()) {
std::cout << "Cannot open file";
exit(1);
}
std::string buf="";
while(!in_file.eof()) {
std::getline(in_file,buf);
if(buf.at(0) == '-') {
break;
}
TokenVector tokens;
tokenize(buf,tokens,":");
std::string name = tokens[0];
std::string type = tokens[1];
if(type == "Hero") {
actormap[name] = new Hero();
//set name
//set type
}
else if(type == "Monster") {
actormap[name] = new Monster();
}
else if(type == "Villager") {
actormap[name] = new Villager();
}
actormap[name]->speak("I speak");
actormap[name]->hit("*swings to hit*");
actormap[name]->get_name();
}
actormap["trundle"] = new Monster();
//testing of my type / naming storage
// It worked!
std::cout << std::endl;
std::cout << "Testing Type / Name Storage: " << std::endl;
EntityInfo e;
e.name = "Trundle";
e.type="Monster";
actormap["trundle"]->set_type(e);
actormap["trundle"]->set_name(e);
EntityInfo s = actormap["trundle"]->get_type();
std::cout << s.name << " " << s.type << std::endl;
std::cout << "End of Test ";
std::cout << std::endl;
actormap["tim"] = new Hero();
actormap["penelope"] = new Villager();
bag << InvItem();
actormap["trundle"]->set_inventory(bag);
std::cout << actormap["trundle"]->get_vitals();
actormap["trundle"]->speak("I am trundle, prepare to meet your maker!");
actormap["penelope"]->speak("Where's my hero?");
actormap["tim"]->speak("Let's roll!");
return 0;
}
Explanation / Answer
make following changes in your respectice classes and methods, IF YOU WANT THESE MESSGES TO BE DEFAULT
TO THE STRINGS GIVEN. i.e whenever you call monster->roar() it should print roars fiercely and so on.
add an instance variable message in monster class and initialize it as follows
string message="roars fiercely "
void Monster::roar() {
std::cout << " "Monster: " << this->message <<" " "<<std::endl;
}
add an instance variable message in hero class and initialize it as follows
string message= "rallies those around him."
void Hero::rally() {
std::cout << " "Hero: " << this->message <<" " "<<std::endl;
}
add an instance variable message in villager class and initialize it as follows
message="*hides"
void Villager::hide() {
std::cout << " "Villager: " << this->message <<" " "<<std::endl;
}
IF YOU DONT WANT THEM TO BE DEAFULT
THEN JUST LET THE METHODS AS THEY ARE AND IN MAIN METHOD DO THE FOLLOWING.
actormap["trundle"]->roar("roars fiercely") and so on.
Related Questions
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.