In: Computer Science
THIS IS A C++ QUESTION(SOME OTHER ASSIGNMENTS ARE DISPLAYED TO GIVE BACKGROUND INFO ON THIS QUESTION, ONLY THIS QUESTION SHOULD BE SOLVED):
Focus
Update
Problem:
Building on previous assignments, we will be reading a file of commands to create Nobles and Warriors, and sending them off to battle.
Previous Assignments(As Background info):
1) We will model a game of medieval times. Our world is filled with warriors. Naturally what warriors like to do is fight. To the death. So we happily let them.
Each warrior starts out with a name and a certain amount of strength. Each time he fights, he loses some strength. (He gets to keep his name.) If his opponent is stronger than he is, then he loses all of his strength, in which case he is dead, or at the very least pretty useless as a fighter. Otherwise he loses as much strength as his opponent had. Of course, if he and his opponent had the same strength then they are both losers.
Even losers are allowed to pick a fight. It doesn't require having any strength in order to do battle with someone else. Not that you stand much of a chance of winning anything, but perhaps it's worth getting beaten (again) just to have those 15 seconds of fame.
Your program will read in a file of commands. There are three types of commands:
2)
We will expand our Warrior a little. Each Warrior will have a weapon. He is "born" with it, i.e. the weapon is created together with the warrior. It can only be accessed by him. It provides him with his strength. In battle, weapons lose their edge and weaken. When a Warrior's weapon loses all of its strength, the Warrior himself dies.
Implementation
3)
We will [continue to] model a game of medieval times. Our world is filled with not only warriors but also nobles. Nobles don't have much to do except do battle with each other. (We'll leave the feasting and other entertainments for add-ons.) Warriors don't have much to do except hire out to a noble and fight in his behalf. Of course the nobles are pretty wimpy themselves and will lose if they don't have warriors to defend them. How does all this work?
Hiring and Firing
Death
It's a sad topic, but one we do have to address.
A test program and output are attached. Note that the output shown is what you are expected to generate. Pardon us, we don't like limiting your creativity, but having your output consistent with ours makes the first step of grading a bit easier. And also helps you to be more confident that your code works.
Key differences:
Commands
Our application is going to rely on each Noble having a unique name and each Warrior having a unique name. Otherwise, how would we be sure who we were hiring (or firing). Note that this is not a requirement of the Noble and Warrior classes themselves, just of this particular use of them, i.e. our application.
Whenever you are displaying a Noble or a Warrior, you will use the output operator for the class.
Handle errors!
Previously we promised that all of the commands we gave you the input would be valid. Now we would like you to take some responsibility for checking the input. First, we still guarantee that the format of the file will be correct. That means that the Warrior command will always have a name and a strength. The Battle command will always have two names. The Status command will not have any other information on it than just the word Status.
However, you will need to detect and report any issues indicating inconsistencies, such as:
We have not specified the format of these error messages, so we'll leave that up to you. (You get to be creative!)
Input:
"Noble King_Arthur
Noble Lancelot_du_Lac
Noble Jim
Noble Linus_Torvalds
Noble Bill_Gates
Warrior Tarzan 10
Warrior Merlin 15
Warrior Conan 12
Warrior Spock 15
Warrior Xena 20
Warrior Hulk 8
Warrior Hercules 3
Hire Jim Spock
Hire Lancelot_du_Lac Conan
Hire King_Arthur Merlin
Hire Lancelot_du_Lac Hercules
Hire Linus_Torvalds Xena
Hire Bill_Gates Hulk
Hire King_Arthur Tarzan
Status
Fire King_Arthur Tarzan
Status
Battle King_Arthur Lancelot_du_Lac
Battle Jim Lancelot_du_Lac
Battle Linus_Torvalds Bill_Gates
Battle Bill_Gates Lancelot_du_Lac
Status
Clear
Status"
Output:
"Status ====== Nobles: King_Arthur has an army of 2 Merlin: 15 Tarzan: 10 Lancelot_du_Lac has an army of 2 Conan: 12 Hercules: 3 Jim has an army of 1 Spock: 15 Linus_Torvalds has an army of 1 Xena: 20 Bill_Gates has an army of 1 Hulk: 8 Unemployed Warriors: NONE You don't work for me anymore Tarzan! -- King_Arthur. Status ====== Nobles: King_Arthur has an army of 1 Merlin: 15 Lancelot_du_Lac has an army of 2 Conan: 12 Hercules: 3 Jim has an army of 1 Spock: 15 Linus_Torvalds has an army of 1 Xena: 20 Bill_Gates has an army of 1 Hulk: 8 Unemployed Warriors: Tarzan: 10 King_Arthur battles Lancelot_du_Lac Mutual Annihalation: King_Arthur and Lancelot_du_Lac die at each other's hands Jim battles Lancelot_du_Lac He's dead, Jim Linus_Torvalds battles Bill_Gates Linus_Torvalds defeats Bill_Gates Bill_Gates battles Lancelot_du_Lac Oh, NO! They're both dead! Yuck! Status ====== Nobles: King_Arthur has an army of 1 Merlin: 0 Lancelot_du_Lac has an army of 2 Conan: 0 Hercules: 0 Jim has an army of 1 Spock: 15 Linus_Torvalds has an army of 1 Xena: 12 Bill_Gates has an army of 1 Hulk: 0 Unemployed Warriors: Tarzan: 10 Status ====== Nobles: NONE Unemployed Warriors: NONE"
program code to copy
main.cpp
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
class Noble;
class Warrior;
class Warrior
{
//display the warrior's name and strength
friend ostream& operator<<(ostream& os, const Warrior& war)
{
os << " " << war.name << ": " << war.strength;
return os;
}
public:
Warrior(const string& name, int strength) :
name(name), strength(strength)
{}
const Noble* getmaster() const { return master; }
const string& getname() const { return name; }
const int getstrength() const { return strength; }
void setmaster(Noble* themaster) { master = themaster; }
void setstrength(int stren) { strength = stren; }
private:
int strength;
string name;
Noble* master = nullptr;
};
class Noble
{
//display the noble and warriors' name and strength
friend ostream& operator<<(ostream& os, const Noble& nob)
{
os << nob.name << " has an army of " << nob.warriors.size() << endl;
for (size_t i = 0; i < nob.warriors.size(); ++i)
{
os << *nob.warriors[i] << endl;
}
return os;
}
public:
Noble(const string& name) :
name(name)
{}
const string& getname() const { return name; }
void hire(Warrior* war)
{
if (war->getmaster() == nullptr)
{//only hire no-master warrior
warriors.push_back(war);
war->setmaster(this);
totalstrength += war->getstrength();
}
}
void fire(Warrior* war)
{
if (war->getmaster() == this)
{
for (size_t i = 0; i < warriors.size(); ++i)
{
if (warriors[i] == war)
{
while (i < warriors.size() - 1)
{
swap(warriors[i], warriors[i + 1]);//make fired warriors to the end of vector
}
warriors.pop_back();
break;
}
}
war->setmaster(nullptr);//set the warrior avilable for hire
totalstrength -= war->getstrength();
cout << "You don't work for me anymore " << war->getname() << "! -- " << name << "." << endl;
}
else
{
//send out the error message if the warrior does not work for the noble
cout<<"Error: You don't work for me at all! " << war->getname() << "! -- " << name << "." << endl;
}
}
void setwarriors(float ratio)
{
for (Warrior* war : warriors)
{
war->setstrength(int(ratio * war->getstrength()));
}
}
//battle between two noble object
void battle(Noble& nob)
{
cout << name << " battles " << nob.name << endl;
if (totalstrength == nob.totalstrength)
{
cout << "Oh, NO! They're both dead! Yuck!" << endl;
setwarriors(0);
nob.setwarriors(0);
totalstrength = 0;
nob.totalstrength = 0;
}
else if (totalstrength == 0)
{
cout << "He's dead, " << nob.name << endl;
}
else if (nob.totalstrength == 0)
{
cout << "He's dead, " << name << endl;
}
else if (totalstrength > nob.totalstrength)
{
cout << name << " defeats " << nob.name << endl;
nob.setwarriors(0);
setwarriors(1 - nob.totalstrength / totalstrength);
totalstrength -= nob.totalstrength;
nob.totalstrength = 0;
}
else
{
cout << nob.name << " defeats " << name << endl;
setwarriors(0);
nob.setwarriors(1 - totalstrength / nob.totalstrength);
nob.totalstrength -= totalstrength;
totalstrength = 0;
}
}
private:
string name;
vector<Warrior*> warriors;
float totalstrength = 0;//total strength of the warriors
};
//return pointer to the warrior with the name; nullptr if none;
Warrior* getWarrior(const string& name, const vector<Warrior*>& warriors)
{
for (size_t index = 0; index < warriors.size(); ++index)
{
if (warriors[index]->getname() == name) { return warriors[index]; }
}
return nullptr;
}
//return pointer to the noble with the name; nullptr if none;
Noble* getNoble(const string& name, const vector<Noble*>& nobles)
{
for (size_t index = 0; index < nobles.size(); ++index)
{
if (nobles[index]->getname() == name) { return nobles[index]; }
}
return nullptr;
}
//display all the nobles in the vector;
void Nobledisplay(const vector<Noble*> nobles)
{
cout << "Nobles:" << endl;
if (nobles.size() == 0)
{
cout << "None" << endl;
}
else
{
for (size_t index = 0; index < nobles.size(); ++index)
{
cout << *nobles[index] << endl;
}
}
}
//display all the warriors in the vector;
void Warriordisplay(const vector<Warrior*> warriors)
{
bool is_empty = true;
cout << "Unemployed warriors:" << endl;
for (size_t index = 0; index < warriors.size(); ++index)
{
if (warriors[index]->getmaster() == nullptr)
{
is_empty = false;
cout << *warriors[index] << endl;
}
}
if (is_empty) { cout << "None" << endl; }
}
//clear all the noble pointers
void Nobleclear(vector<Noble*> nobles)
{
for (size_t index = 0; index < nobles.size(); ++index)
{
delete nobles[index];
}
}
//clear all the warrior pointers
void Warriorclear(vector<Warrior*> warriors)
{
for (size_t index = 0; index < warriors.size(); ++index)
{
delete warriors[index];
}
}
int main()
{
ifstream ifs("nobleWarriors.txt");
string type,noble_name,warrior_name,noble_name2;
vector<Noble*> nobles;
vector<Warrior*> warriors;
int strength;
Noble* noblep;
Noble* noblep2;
Warrior* warriorp;
while (ifs >> type)
{
if (type == "Noble")
{
ifs >> noble_name;
if (getNoble(noble_name, nobles)!=nullptr)
{
cout << "Error: noble already exists: " << noble_name << endl;
}
else
{
nobles.push_back(new Noble(noble_name));
}
}
else if (type == "Warrior")
{
ifs >> warrior_name >> strength;
if (getWarrior(warrior_name, warriors)!=nullptr)
{
cout << "Error: warrior already exists: " << warrior_name << endl;
}
else
{
warriors.push_back(new Warrior(warrior_name,strength));
}
}
else if (type == "Hire")
{
ifs >> noble_name >> warrior_name;
noblep = getNoble(noble_name, nobles);
if (noblep == nullptr)
{
cout << "Error: noble does not exist " << noble_name << endl;
}
else
{
warriorp = getWarrior(warrior_name,warriors);
if (warriorp == nullptr)
{
cout << "Error: warrior does not exist: " << warrior_name << endl;
}
else
{
noblep->hire(warriorp);
}
}
}
else if (type == "Fire")
{
ifs >> noble_name >> warrior_name;
noblep = getNoble(noble_name, nobles);
warriorp = getWarrior(warrior_name, warriors);
if (noblep == nullptr)
{
cout << "Error: noble does not exist " << noble_name << endl;
}
else
{
noblep->fire(warriorp);
}
}
else if (type == "Battle")
{
ifs >> noble_name >> noble_name2;
noblep = getNoble(noble_name, nobles);
noblep2 = getNoble(noble_name2, nobles);
if (noblep == nullptr || noblep2 == nullptr)
{
if (noblep == nullptr)
{
cout << "Error: noble does not exist: " << noble_name << endl;
}
if (noblep2 == nullptr)
{
cout << "Error: noble does not exist: " << noble_name2 << endl;
}
}
else
{
noblep->battle(*noblep2);
}
}
else if (type == "Status")
{
cout << "Status\n======" << endl;
Nobledisplay(nobles);
Warriordisplay(warriors);
}
else
{
Nobleclear(nobles);
Warriorclear(warriors);
nobles.clear();
warriors.clear();
}
}
}
==========================================================================
nobleWarriors.txt
Noble King_Arthur
Noble Lancelot_du_Lac
Noble Jim
Noble Linus_Torvalds
Noble Bill_Gates
Warrior Tarzan 10
Warrior Merlin 15
Warrior Conan 12
Warrior Spock 15
Warrior Xena 20
Warrior Hulk 8
Warrior Hercules 3
Hire Jim Spock
Hire Lancelot_du_Lac Conan
Hire King_Arthur Merlin
Hire Lancelot_du_Lac Hercules
Hire Linus_Torvalds Xena
Hire Bill_Gates Hulk
Hire King_Arthur Tarzan
Status
Fire King_Arthur Tarzan
Status
Battle King_Arthur Lancelot_du_Lac
Battle Jim Lancelot_du_Lac
Battle Linus_Torvalds Bill_Gates
Battle Bill_Gates Lancelot_du_Lac
Status
Clear
Status
sample output