adding cs142 code
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "FighterInterface.h"
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
WARNING: It is expressly forbidden to modify any part of this document, including its name
|
||||
*/
|
||||
class ArenaInterface
|
||||
{
|
||||
public:
|
||||
ArenaInterface(){}
|
||||
virtual ~ArenaInterface(){}
|
||||
|
||||
/*
|
||||
addFighter(string)
|
||||
|
||||
Adds a new fighter to the collection of fighters in the arena. Do not allow
|
||||
duplicate names. Reject any string that does not adhere to the format
|
||||
outlined in the lab specs.
|
||||
|
||||
Return true if a new fighter was added; false otherwise.
|
||||
*/
|
||||
virtual bool addFighter(string info) = 0;
|
||||
|
||||
/*
|
||||
removeFighter(string)
|
||||
|
||||
Removes the fighter whose name is equal to the given name. Does nothing if
|
||||
no fighter is found with the given name.
|
||||
|
||||
Return true if a fighter is removed; false otherwise.
|
||||
*/
|
||||
virtual bool removeFighter(string name) = 0;
|
||||
|
||||
/*
|
||||
getFighter(string)
|
||||
|
||||
Returns the memory address of a fighter whose name is equal to the given
|
||||
name. Returns NULL if no fighter is found with the given name.
|
||||
|
||||
Return a memory address if a fighter is found; NULL otherwise.
|
||||
*/
|
||||
virtual FighterInterface* getFighter(string name) = 0;
|
||||
|
||||
/*
|
||||
getSize()
|
||||
|
||||
Returns the number of fighters in the arena.
|
||||
|
||||
Return a non-negative integer.
|
||||
*/
|
||||
virtual int getSize() = 0;
|
||||
};
|
||||
@@ -0,0 +1,176 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <cstdio>
|
||||
#include "FighterInterface.h"
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
WARNING: It is expressly forbidden to modify any part of this document, including its name
|
||||
*/
|
||||
//=======================================================================================
|
||||
FighterInterface* fight(FighterInterface*, FighterInterface*, bool);
|
||||
void takeTurn(FighterInterface*, FighterInterface*, bool);
|
||||
void speak(string);
|
||||
//=======================================================================================
|
||||
/*
|
||||
fight(FighterInterface, FighterInterface, bool)
|
||||
|
||||
Runs through the fighting algorithm for the two given fighters.
|
||||
|
||||
Each fighter takes a turn using its special ability, attacking, and regenerating. If
|
||||
the other fighter's current hit points falls to or drops below 0, then the other
|
||||
fighter has lost. This process repeats until one fighter has fallen or 100 rounds
|
||||
have occurred with neither fighter falling.
|
||||
|
||||
If the given bool is true, this function will print a great deal of information
|
||||
during the battle. This can be useful for testing.
|
||||
|
||||
Returns the winner of the fight; null if the fight ends in a draw.
|
||||
*/
|
||||
FighterInterface* fight(FighterInterface* c1, FighterInterface* c2, bool verbose)
|
||||
{
|
||||
if(verbose)
|
||||
{
|
||||
stringstream stream;
|
||||
stream << "----------";
|
||||
stream << c1->getName();
|
||||
stream << " vs ";
|
||||
stream << c2->getName();
|
||||
stream << "----------";
|
||||
speak(stream.str());
|
||||
}
|
||||
|
||||
c1->reset();
|
||||
c2->reset();
|
||||
|
||||
for(int i=0; i<100; i++)
|
||||
{
|
||||
//C1's turn
|
||||
takeTurn(c1, c2, verbose);
|
||||
if(c2->getCurrentHP() <= 0)
|
||||
{
|
||||
if(verbose)
|
||||
{
|
||||
stringstream stream;
|
||||
stream << c1->getName();
|
||||
stream << " wins! (";
|
||||
stream << c1->getCurrentHP();
|
||||
stream << "/";
|
||||
stream << c1->getMaximumHP();
|
||||
stream << " HP left)";
|
||||
speak(stream.str());
|
||||
}
|
||||
return c1;
|
||||
}
|
||||
|
||||
//C2's turn
|
||||
takeTurn(c2, c1, verbose);
|
||||
if(c1->getCurrentHP() <= 0)
|
||||
{
|
||||
if(verbose)
|
||||
{
|
||||
stringstream stream;
|
||||
stream << c2->getName();
|
||||
stream << " wins! (";
|
||||
stream << c2->getCurrentHP();
|
||||
stream << "/";
|
||||
stream << c2->getMaximumHP();
|
||||
stream << " HP left)";
|
||||
speak(stream.str());
|
||||
}
|
||||
return c2;
|
||||
}
|
||||
}
|
||||
if(verbose)
|
||||
{
|
||||
speak("After 100 rounds, neither fighter has fallen. It's a draw!");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
//=======================================================================================
|
||||
/*
|
||||
takeTurn(FighterInterface*, FighterInterface*, bool)
|
||||
|
||||
Runs through a single turn for [attacker] attacking [defender]. Each turn consists of
|
||||
[attacker] trying to use its special ability, attacking [defender], and regenerating.
|
||||
*/
|
||||
void takeTurn(FighterInterface* attacker, FighterInterface* defender, bool verbose)
|
||||
{
|
||||
//Header
|
||||
if(verbose)
|
||||
{
|
||||
stringstream stream;
|
||||
stream << "It's ";
|
||||
stream << attacker->getName();
|
||||
stream << "'s turn! (";
|
||||
stream << attacker->getCurrentHP();
|
||||
stream << "/";
|
||||
stream << attacker->getMaximumHP();
|
||||
stream << " HP).";
|
||||
speak(stream.str());
|
||||
}
|
||||
|
||||
//Use Ability
|
||||
if(!attacker->isSimplified())
|
||||
{
|
||||
bool ability = attacker->useAbility();
|
||||
if(ability && verbose)
|
||||
{
|
||||
stringstream stream;
|
||||
stream << "\t";
|
||||
stream << attacker->getName();
|
||||
stream << " uses a special ability!";
|
||||
speak(stream.str());
|
||||
}
|
||||
}
|
||||
|
||||
//Attack
|
||||
int damage = attacker->getDamage();
|
||||
int before_attack = defender->getCurrentHP();
|
||||
defender->takeDamage(damage);
|
||||
int after_attack = defender->getCurrentHP();
|
||||
if(verbose)
|
||||
{
|
||||
stringstream stream;
|
||||
stream << "\t";
|
||||
stream << attacker->getName();
|
||||
stream << " attacks with ";
|
||||
stream << damage;
|
||||
stream << " damage, and ";
|
||||
stream << defender->getName();
|
||||
stream << " takes ";
|
||||
stream << (before_attack-after_attack);
|
||||
stream << " damage.";
|
||||
speak(stream.str());
|
||||
}
|
||||
|
||||
//Regenerate
|
||||
if(!attacker->isSimplified())
|
||||
{
|
||||
int before_regen = attacker->getCurrentHP();
|
||||
attacker->regenerate();
|
||||
int after_regen = attacker->getCurrentHP();
|
||||
if(verbose)
|
||||
{
|
||||
stringstream stream;
|
||||
stream << "\t";
|
||||
stream << attacker->getName();
|
||||
stream << " regenerates ";
|
||||
stream << (after_regen-before_regen);
|
||||
stream << " HP.";
|
||||
speak(stream.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
//=======================================================================================
|
||||
/*
|
||||
speak(string)
|
||||
|
||||
Displays a given message.
|
||||
*/
|
||||
void speak(string message)
|
||||
{
|
||||
printf("%s\n", message.c_str());
|
||||
}
|
||||
//=======================================================================================
|
||||
@@ -0,0 +1,7 @@
|
||||
#include "Factory.h"
|
||||
#include "arena.h"
|
||||
|
||||
ArenaInterface* Factory::createArena()
|
||||
{
|
||||
return new arena();
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
#include "ArenaInterface.h"
|
||||
/*
|
||||
WARNING: It is expressly forbidden to modify any part of this document, including its name
|
||||
*/
|
||||
//=======================================================================================
|
||||
/*
|
||||
createArena()
|
||||
|
||||
Creates and returns an object whose class extends ArenaInterface.
|
||||
This should be an object of a class you have created.
|
||||
|
||||
Example: If you made a class called "Arena", you might say, "return new Arena();".
|
||||
*/
|
||||
class Factory
|
||||
{
|
||||
public:
|
||||
static ArenaInterface* createArena();
|
||||
};
|
||||
|
||||
//=======================================================================================
|
||||
@@ -0,0 +1,200 @@
|
||||
#pragma once
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
WARNING: It is expressly forbidden to modify any part of this document, including its name
|
||||
*/
|
||||
|
||||
/*
|
||||
This class specifies the methods for a fighter.
|
||||
|
||||
All fighters have the following attributes:
|
||||
Name - The fighter's name.
|
||||
Hit Points - The amount of health the fighter has, with a specified maximum. Reaching 0 is equivalent to death.
|
||||
Strength - Physical power, used to determine hit point regeneration.
|
||||
Speed - Dexterity and physical movement, used to reduce damage when being attacked.
|
||||
Magic - Magical prowess, used for some special abilities.
|
||||
|
||||
The three fighter types have unique abilities:
|
||||
Robot - Relies on strength to deal damage. Also can use stored electricity to temporarily increase damage (max electricity equal to 2*magic).
|
||||
Archer - Relies on speed to deal damage. Also can increase its speed for the remainder of the battle (no max bonus speed).
|
||||
Cleric - Relies on magic to deal damage. Also can heal itself using mana, restoring hit points (max mana equal to 5*magic).
|
||||
|
||||
More details about how stats are used and how abilities work can be found in the comments below.
|
||||
*/
|
||||
|
||||
/*
|
||||
ROBOT_ABILITY_COST
|
||||
The amount of energy a Robot needs to perform its special ability.
|
||||
*/
|
||||
const int ROBOT_ABILITY_COST = 5;
|
||||
|
||||
/*
|
||||
CLERIC_ABILITY_COST
|
||||
The amount of mana a Cleric needs to perform its special ability.
|
||||
*/
|
||||
const int CLERIC_ABILITY_COST = 25;
|
||||
|
||||
class FighterInterface
|
||||
{
|
||||
public:
|
||||
FighterInterface(){}
|
||||
virtual ~FighterInterface(){}
|
||||
|
||||
/*
|
||||
getName()
|
||||
|
||||
Returns the name of this fighter.
|
||||
*/
|
||||
virtual string getName() = 0;
|
||||
|
||||
/*
|
||||
getMaximumHP()
|
||||
|
||||
Returns the maximum hit points of this fighter.
|
||||
*/
|
||||
virtual int getMaximumHP() = 0;
|
||||
|
||||
/*
|
||||
getCurrentHP()
|
||||
|
||||
Returns the current hit points of this fighter.
|
||||
*/
|
||||
virtual int getCurrentHP() = 0;
|
||||
|
||||
/*
|
||||
getStrength()
|
||||
|
||||
Returns the strength stat of this fighter.
|
||||
*/
|
||||
virtual int getStrength() = 0;
|
||||
|
||||
/*
|
||||
getSpeed()
|
||||
|
||||
Returns the speed stat of this fighter.
|
||||
*/
|
||||
virtual int getSpeed() = 0;
|
||||
|
||||
/*
|
||||
getMagic()
|
||||
|
||||
Returns the magic stat of this fighter.
|
||||
*/
|
||||
virtual int getMagic() = 0;
|
||||
|
||||
/*
|
||||
getDamage()
|
||||
|
||||
Returns the amount of damage a fighter will deal.
|
||||
|
||||
Robot:
|
||||
This value is equal to the Robot's strength plus any additional damage added for having just used its special ability.
|
||||
|
||||
Archer:
|
||||
This value is equal to the Archer's speed.
|
||||
|
||||
Cleric:
|
||||
This value is equal to the Cleric's magic.
|
||||
*/
|
||||
virtual int getDamage() = 0;
|
||||
|
||||
/*
|
||||
takeDamage(int)
|
||||
|
||||
Reduces the fighter's current hit points by an amount equal to the given
|
||||
damage minus one fourth of the fighter's speed. This method must reduce
|
||||
the fighter's current hit points by at least one. It is acceptable for
|
||||
this method to give the fighter negative current hit points.
|
||||
|
||||
Examples:
|
||||
damage=10, speed=7 => damage_taken=9
|
||||
damage=10, speed=9 => damage_taken=8
|
||||
damage=10, speed=50 => damage_taken=1
|
||||
*/
|
||||
virtual void takeDamage(int damage) = 0;
|
||||
|
||||
/*
|
||||
reset()
|
||||
|
||||
Restores a fighter's current hit points to its maximum hit points.
|
||||
|
||||
Robot:
|
||||
Also restores a Robot's current energy to its maximum value (which is 2 times its magic).
|
||||
Also resets a Robot's bonus damage to 0.
|
||||
|
||||
Archer:
|
||||
Also resets an Archer's current speed to its original value.
|
||||
|
||||
Cleric:
|
||||
Also restores a Cleric's current mana to its maximum value (which is 5 times its magic).
|
||||
*/
|
||||
virtual void reset() = 0;
|
||||
|
||||
/*
|
||||
regenerate()
|
||||
|
||||
Increases the fighter's current hit points by an amount equal to one sixth of
|
||||
the fighter's strength. This method must increase the fighter's current hit
|
||||
points by at least one. Do not allow the current hit points to exceed the
|
||||
maximum hit points.
|
||||
|
||||
Cleric:
|
||||
Also increases a Cleric's current mana by an amount equal to one fifth of the
|
||||
Cleric's magic. This method must increase the Cleric's current mana by at
|
||||
least one. Do not allow the current mana to exceed the maximum mana.
|
||||
*/
|
||||
virtual void regenerate() = 0;
|
||||
|
||||
/*
|
||||
useAbility()
|
||||
|
||||
Attempts to perform a special ability based on the type of fighter. The
|
||||
fighter will attempt to use this special ability just prior to attacking
|
||||
every turn.
|
||||
|
||||
Robot: Shockwave Punch
|
||||
Adds bonus damage to the Robot's next attack (and only its next attack) equal to (strength * ((current_energy/maximum_energy)^4)).
|
||||
Can only be used if the Robot has at least [ROBOT_ABILITY_COST] energy.
|
||||
Decreases the Robot's current energy by [ROBOT_ABILITY_COST] (after calculating the additional damage) when used.
|
||||
Examples:
|
||||
strength=20, current_energy=20, maximum_energy=20 => bonus_damage=20
|
||||
strength=20, current_energy=15, maximum_energy=20 => bonus_damage=6
|
||||
strength=20, current_energy=10, maximum_energy=20 => bonus_damage=1
|
||||
strength=20, current_energy=5, maximum_energy=20 => bonus_damage=0
|
||||
Robot Note:
|
||||
The bonus damage formula should be computed using double arithmetic, and only
|
||||
the final result should be cast into an integer.
|
||||
|
||||
Archer: Quickstep
|
||||
Increases the Archer's speed by one point each time the ability is used.
|
||||
This bonus lasts until the reset() method is used.
|
||||
This ability always works; there is no maximum bonus speed.
|
||||
|
||||
Cleric: Healing Light
|
||||
Increases the Cleric's current hit points by an amount equal to one third of its magic.
|
||||
Can only be used if the Cleric has at least [CLERIC_ABILITY_COST] mana.
|
||||
Will be used even if the Cleric's current HP is equal to their maximum HP
|
||||
Decreases the Cleric's current mana by [CLERIC_ABILITY_COST] when used.
|
||||
Cleric Note:
|
||||
This ability, when successful, must increase the Cleric's current hit points
|
||||
by at least one. Do not allow the current hit points to exceed the maximum
|
||||
hit points.
|
||||
|
||||
Return true if the ability was used; false otherwise.
|
||||
*/
|
||||
virtual bool useAbility() = 0;
|
||||
|
||||
/*
|
||||
isSimplified()
|
||||
|
||||
Returns true if you have not completed the useAbility() and/or the regenerate()
|
||||
methods for this type of fighter. This allows the test driver to award points
|
||||
for Part 3 even if Part 4 is incomplete.
|
||||
|
||||
Return true if the testing is to be simplified; false otherwise.
|
||||
*/
|
||||
virtual bool isSimplified() = 0;
|
||||
};
|
||||
@@ -0,0 +1,33 @@
|
||||
CXXFLAGS= -Wall -g
|
||||
OBJECTS=main.o arena.o Factory.o archer.o fighter.o util.o cleric.o robot.o
|
||||
EXE=main
|
||||
|
||||
all: $(EXE)
|
||||
|
||||
|
||||
$(EXE): main.o
|
||||
$(CXX) $(CXXFLAGS) $(OBJECTS) -o $@
|
||||
|
||||
main.o: main.cpp Factory.o arena.o fighter.o archer.o util.o cleric.o robot.o
|
||||
|
||||
Factory.o: Factory.cpp Factory.h
|
||||
|
||||
arena.o: arena.cpp arena.h
|
||||
fighter.o: fighter.cpp fighter.h
|
||||
archer.o: archer.cpp archer.h fighter.h
|
||||
cleric.o: cleric.cpp cleric.h fighter.h
|
||||
robot.o: robot.cpp robot.h fighter.h
|
||||
util.o: util.cpp util.h
|
||||
|
||||
run: $(EXE)
|
||||
@./$(EXE)
|
||||
|
||||
clean:
|
||||
@rm -vf *.o
|
||||
@rm -vf $(EXE)
|
||||
|
||||
debug: $(EXE)
|
||||
gdb ./$(EXE)
|
||||
|
||||
valgrind: $(EXE)
|
||||
valgrind --tool=memcheck --leak-check=yes ./$(EXE)
|
||||
@@ -0,0 +1,21 @@
|
||||
#include "archer.h"
|
||||
archer::archer(string name, int max_hp, int strength, int speed, int magic) :
|
||||
fighter(name, max_hp, strength, speed, magic), original_speed(speed) {}
|
||||
|
||||
int archer::getDamage() {
|
||||
return speed;
|
||||
}
|
||||
|
||||
void archer::reset() {
|
||||
hp = max_hp;
|
||||
speed = original_speed;
|
||||
}
|
||||
|
||||
bool archer::useAbility() {
|
||||
speed++;
|
||||
return true;
|
||||
}
|
||||
|
||||
int archer::get_original_speed() {
|
||||
return original_speed;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef __ARCHER_H__
|
||||
#define __ARCHER_H__
|
||||
|
||||
#include "fighter.h"
|
||||
|
||||
class archer : public fighter {
|
||||
private:
|
||||
int original_speed;
|
||||
public:
|
||||
archer(string, int, int, int, int);
|
||||
|
||||
string get_type() { return "A"; };
|
||||
|
||||
int getDamage();
|
||||
void reset();
|
||||
bool useAbility();
|
||||
|
||||
int get_original_speed();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,111 @@
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
|
||||
#include "arena.h"
|
||||
#include "fighter.h"
|
||||
#include "archer.h"
|
||||
#include "cleric.h"
|
||||
#include "robot.h"
|
||||
#include "util.h"
|
||||
|
||||
arena::~arena() {
|
||||
fighter * f = NULL;
|
||||
for(vector<FighterInterface *>::iterator it = fighters.begin();
|
||||
it != fighters.end();
|
||||
it++) {
|
||||
f = dynamic_cast<fighter *>(*it);
|
||||
delete f;
|
||||
}
|
||||
}
|
||||
|
||||
bool arena::contains(string name) {
|
||||
fighter * f = NULL;
|
||||
for(unsigned int i = 0; i < fighters.size(); i++) {
|
||||
f = dynamic_cast<fighter *>(fighters[i]);
|
||||
if(f->getName() == name) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool arena::addFighter(string info) {
|
||||
fighter * f = NULL;
|
||||
|
||||
string name;
|
||||
string type;
|
||||
int max_hp;
|
||||
int strength;
|
||||
int speed;
|
||||
int magic;
|
||||
|
||||
bool worked;
|
||||
worked = parse_n_load(info, name, type, max_hp, strength, speed, magic);
|
||||
if(not worked) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(contains(name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(type == "A") {
|
||||
f = new archer(name, max_hp, strength, speed, magic);
|
||||
}
|
||||
else if(type == "C") {
|
||||
f = new cleric(name, max_hp, strength, speed, magic);
|
||||
}
|
||||
else if(type == "R") {
|
||||
f = new robot(name, max_hp, strength, speed, magic);
|
||||
}
|
||||
|
||||
fighters.push_back(f);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool arena::removeFighter(string name) {
|
||||
fighter * f = NULL;
|
||||
for(vector<FighterInterface *>::iterator it = fighters.begin();
|
||||
it != fighters.end();
|
||||
it++) {
|
||||
f = dynamic_cast<fighter *>(*it);
|
||||
if(f->getName() == name) {
|
||||
delete f;
|
||||
fighters.erase(it);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
FighterInterface * arena::getFighter(string name) {
|
||||
fighter * f = NULL;
|
||||
for(vector<FighterInterface *>::iterator it = fighters.begin();
|
||||
it != fighters.end();
|
||||
it++) {
|
||||
f = dynamic_cast<fighter *>(*it);
|
||||
if(f->getName() == name) {
|
||||
return dynamic_cast<FighterInterface *>(f);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int arena::getSize() {
|
||||
return fighters.size();
|
||||
}
|
||||
|
||||
ostream & operator<<(ostream & os, arena & a) {
|
||||
os << "[";
|
||||
for(vector<FighterInterface * >::iterator it = a.fighters.begin();
|
||||
it != a.fighters.end();
|
||||
it++) {
|
||||
os << *(dynamic_cast<fighter *>( *it));
|
||||
if (it != a.fighters.end() - 1) {
|
||||
os << ", ";
|
||||
}
|
||||
}
|
||||
os << "]";
|
||||
return os;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef __ARENA_H__
|
||||
#define __ARENA_H__
|
||||
|
||||
#include <vector>
|
||||
#include "ArenaInterface.h"
|
||||
|
||||
class arena : public ArenaInterface {
|
||||
private:
|
||||
std::vector<FighterInterface *> fighters;
|
||||
bool contains(string name);
|
||||
public:
|
||||
arena(){}
|
||||
~arena();
|
||||
bool addFighter(string info);
|
||||
bool removeFighter(string name);
|
||||
FighterInterface * getFighter(string name);
|
||||
int getSize();
|
||||
|
||||
friend ostream & operator<<(ostream &, arena &);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,59 @@
|
||||
#include "FighterInterface.h"
|
||||
#include "cleric.h"
|
||||
|
||||
cleric::cleric(string name, int max_hp, int strength, int speed, int magic) :
|
||||
fighter(name, max_hp, strength, speed, magic), mana(5*magic) {}
|
||||
|
||||
int cleric::getDamage() {
|
||||
return magic;
|
||||
}
|
||||
|
||||
void cleric::reset() {
|
||||
hp = max_hp;
|
||||
mana = 5 * magic;
|
||||
}
|
||||
|
||||
void cleric::regenerate() {
|
||||
fighter::regenerate();
|
||||
|
||||
int increase = magic / 5;
|
||||
|
||||
if(increase < 0) {
|
||||
increase = 0;
|
||||
}
|
||||
else if(increase == 0) {
|
||||
increase = 1;
|
||||
}
|
||||
if(mana + increase < magic * 5) {
|
||||
mana += increase;
|
||||
}
|
||||
else {
|
||||
mana = 5 * magic;
|
||||
}
|
||||
}
|
||||
|
||||
bool cleric::useAbility() {
|
||||
// a.k.a. Healing light
|
||||
if(mana - CLERIC_ABILITY_COST >= 0) {
|
||||
int increase = magic / 3;
|
||||
if(increase < 0) {
|
||||
increase = 0;
|
||||
}
|
||||
else if(increase == 0) {
|
||||
increase = 1;
|
||||
}
|
||||
if(hp + increase < max_hp) {
|
||||
hp += increase;
|
||||
}
|
||||
else {
|
||||
hp = max_hp;
|
||||
}
|
||||
mana -= CLERIC_ABILITY_COST;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int cleric::get_mana() {
|
||||
return mana;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef __CLERIC_H__
|
||||
#define __CLERIC_H__
|
||||
|
||||
#include "fighter.h"
|
||||
|
||||
class cleric : public fighter {
|
||||
private:
|
||||
int original_speed;
|
||||
int mana;
|
||||
public:
|
||||
cleric(string, int, int, int, int);
|
||||
|
||||
string get_type() { return "A"; };
|
||||
|
||||
int getDamage();
|
||||
void reset();
|
||||
bool useAbility();
|
||||
void regenerate();
|
||||
|
||||
int get_original_speed();
|
||||
int get_mana();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,72 @@
|
||||
#include "fighter.h"
|
||||
|
||||
fighter::fighter(string name, int max_hp, int strength, int speed, int magic) :
|
||||
name(name), max_hp(max_hp), hp(max_hp), strength(strength),
|
||||
speed(speed), magic(magic) {}
|
||||
|
||||
string fighter::getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
int fighter::getMaximumHP() {
|
||||
return max_hp;
|
||||
}
|
||||
|
||||
int fighter::getCurrentHP() {
|
||||
return hp;
|
||||
}
|
||||
|
||||
int fighter::getStrength() {
|
||||
return strength;
|
||||
}
|
||||
|
||||
int fighter::getSpeed() {
|
||||
return speed;
|
||||
}
|
||||
|
||||
int fighter::getMagic() {
|
||||
return magic;
|
||||
}
|
||||
|
||||
void fighter::regenerate() {
|
||||
int increase = strength / 6;
|
||||
|
||||
if(increase < 0) {
|
||||
increase = 0;
|
||||
}
|
||||
else if(increase == 0) {
|
||||
increase = 1;
|
||||
}
|
||||
|
||||
if(hp + increase <= max_hp) {
|
||||
hp += increase;
|
||||
}
|
||||
else {
|
||||
hp = max_hp;
|
||||
}
|
||||
}
|
||||
|
||||
void fighter::takeDamage(int damage) {
|
||||
int hurt = damage - (speed / 4);
|
||||
if (hurt <= 0) {
|
||||
hurt = 1;
|
||||
}
|
||||
hp -= hurt;
|
||||
}
|
||||
|
||||
bool fighter::isSimplified() {
|
||||
return false;
|
||||
}
|
||||
|
||||
ostream & operator<<(ostream & os, fighter & f) {
|
||||
os << "{\n"
|
||||
<< " \"name\": \"" << f.name << "\",\n"
|
||||
<< " \"type\": \"" << f.get_type() << "\",\n"
|
||||
<< " \"hp\": " << f.hp << ",\n"
|
||||
<< " \"max hp\": " << f.max_hp << ",\n"
|
||||
<< " \"strength\": " << f.strength << ",\n"
|
||||
<< " \"speed\": " << f.speed << ",\n"
|
||||
<< " \"magic\": " << f.magic << ",\n"
|
||||
<< "}";
|
||||
return os;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
#ifndef __FIGHTER_H__
|
||||
#define __FIGHTER_H__
|
||||
|
||||
#include <ostream>
|
||||
#include "FighterInterface.h"
|
||||
|
||||
class fighter : public FighterInterface
|
||||
{
|
||||
private:
|
||||
string name;
|
||||
|
||||
protected:
|
||||
int max_hp;
|
||||
int hp;
|
||||
int strength;
|
||||
int speed;
|
||||
int magic;
|
||||
|
||||
public:
|
||||
fighter(string, int, int, int, int);
|
||||
// virtual ~fighter();
|
||||
|
||||
string getName();
|
||||
|
||||
int getMaximumHP();
|
||||
int getCurrentHP();
|
||||
int getStrength();
|
||||
int getSpeed();
|
||||
int getMagic();
|
||||
|
||||
virtual string get_type() = 0;
|
||||
|
||||
virtual int getDamage() = 0;
|
||||
void takeDamage(int damage);
|
||||
virtual void reset() = 0;
|
||||
virtual void regenerate();
|
||||
virtual bool useAbility() = 0;
|
||||
|
||||
bool isSimplified();
|
||||
|
||||
friend ostream & operator<<(ostream & os, fighter & a);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,205 @@
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#include "Battle.h"
|
||||
#include "Factory.h"
|
||||
#include "arena.h"
|
||||
#include "archer.h"
|
||||
#include "cleric.h"
|
||||
#include "robot.h"
|
||||
|
||||
void test_fighter() {
|
||||
archer a = archer("bilbo", 100, 60, 1, 5);
|
||||
a.takeDamage(90);
|
||||
a.regenerate();
|
||||
assert(a.getCurrentHP() == 20);
|
||||
archer b = archer("frodo", 100, 0, 1, 5);
|
||||
b.takeDamage(90);
|
||||
b.regenerate();
|
||||
}
|
||||
|
||||
void test_archer() {
|
||||
archer a("stephen", 666, 66, 6, 0);
|
||||
a.takeDamage(100);
|
||||
assert(a.getCurrentHP() == 567);
|
||||
assert(a.get_original_speed() == 6);
|
||||
assert(a.getSpeed() == 6);
|
||||
}
|
||||
|
||||
void test_cleric() {
|
||||
cleric a("Derek", 666, 66, 6, 20);
|
||||
assert(a.getDamage() == 20);
|
||||
assert(a.get_mana() == 100);
|
||||
a.takeDamage(100);
|
||||
assert(a.getCurrentHP() == 567);
|
||||
a.reset();
|
||||
assert(a.getCurrentHP() == 666);
|
||||
|
||||
cleric b("SaintColleen", 100, 90, 4, 60);
|
||||
b.takeDamage(100);
|
||||
b.useAbility();
|
||||
assert(b.getCurrentHP() == 21);
|
||||
|
||||
cleric c("Vanessa", 100, 90, 4, 1);
|
||||
c.takeDamage(100);
|
||||
c.useAbility();
|
||||
assert(c.getCurrentHP() == 1);
|
||||
|
||||
cleric d("Vanessa", 100, 90, 4, 5);
|
||||
d.takeDamage(100);
|
||||
d.useAbility();
|
||||
assert(d.getCurrentHP() == 2);
|
||||
}
|
||||
|
||||
void test_robot() {
|
||||
robot a("Derek", 100, 20, 10, 10);
|
||||
assert(a.getDamage() == 20);
|
||||
a.useAbility();
|
||||
assert(a.getDamage() == 40);
|
||||
assert(a.getDamage() == 20);
|
||||
a.useAbility();
|
||||
assert(a.getDamage() == 26);
|
||||
a.takeDamage(100);
|
||||
assert(a.getCurrentHP() == 2);
|
||||
a.reset();
|
||||
assert(a.getCurrentHP() == 100);
|
||||
}
|
||||
|
||||
void test_input_parser() {
|
||||
ArenaInterface * A = Factory::createArena();
|
||||
arena * a = dynamic_cast<arena *>(A);
|
||||
|
||||
string input = "Xephos A 200 13 21 10";
|
||||
assert(a->addFighter(input));
|
||||
|
||||
input = "Stephen A 200 13 21 10";
|
||||
assert(a->addFighter(input));
|
||||
|
||||
input = "Billy Bob Thorton A 0 13 21 10";
|
||||
assert(not a->addFighter(input));
|
||||
|
||||
input = "Xephos a 200 13 21 10";
|
||||
assert(not a->addFighter(input));
|
||||
|
||||
input = "Derek A 200 13 21 a10";
|
||||
assert(not a->addFighter(input));
|
||||
|
||||
input = "Derek A 200 13 stupid21 10";
|
||||
assert(not a->addFighter(input));
|
||||
|
||||
delete A;
|
||||
}
|
||||
|
||||
void test_add() {
|
||||
ArenaInterface * A = Factory::createArena();
|
||||
arena * a = dynamic_cast<arena *>(A);
|
||||
|
||||
string input = "Xephos A 200 13 21 10";
|
||||
assert(a->addFighter(input));
|
||||
|
||||
input = "Stephen A 200 13 21 10";
|
||||
assert(a->addFighter(input));
|
||||
|
||||
// do not allow for duplicate fighers
|
||||
input = "Xephos A 200 13 21 10";
|
||||
bool double_add = a->addFighter(input);
|
||||
assert(not double_add);
|
||||
|
||||
input = "Stephen A 0 13 21 10";
|
||||
assert(not a->addFighter(input));
|
||||
|
||||
input = "Derek A 200 13 21 10";
|
||||
assert(a->addFighter(input));
|
||||
|
||||
// another attempt for not allowing duplicate fighters
|
||||
input = "Stephen A 200 13 21 10";
|
||||
assert(not a->addFighter(input));
|
||||
delete A;
|
||||
}
|
||||
|
||||
void test_remove() {
|
||||
ArenaInterface * A = Factory::createArena();
|
||||
arena * a = dynamic_cast<arena *>(A);
|
||||
|
||||
string input = "Michael A 200 13 21 10";
|
||||
a->addFighter(input);
|
||||
input = "Derek A 200 13 21 10";
|
||||
a->addFighter(input);
|
||||
input = "Bryan A 200 13 21 10";
|
||||
a->addFighter(input);
|
||||
|
||||
assert(not a->removeFighter("Zaphodbeblebrox"));
|
||||
|
||||
bool remove_non_existant = a->removeFighter("Stephen");
|
||||
assert(not remove_non_existant);
|
||||
assert(a->getSize() == 3);
|
||||
|
||||
bool remove_fighter = a->removeFighter("Michael");
|
||||
assert(remove_fighter);
|
||||
assert(a->getSize() == 2);
|
||||
|
||||
a->removeFighter("Derek");
|
||||
a->removeFighter("Bryan");
|
||||
assert(a->getSize() == 0);
|
||||
delete a;
|
||||
}
|
||||
|
||||
void test_find() {
|
||||
ArenaInterface * A = Factory::createArena();
|
||||
arena * a = dynamic_cast<arena *>(A);
|
||||
|
||||
string input = "Michael A 200 13 21 10";
|
||||
a->addFighter(input);
|
||||
input = "Derek A 200 13 21 10";
|
||||
a->addFighter(input);
|
||||
input = "Bryan A 200 13 21 10";
|
||||
a->addFighter(input);
|
||||
|
||||
fighter * f;
|
||||
f = dynamic_cast<fighter *>(a->getFighter("Stephen"));
|
||||
assert(not f);
|
||||
f = dynamic_cast<fighter *>(a->getFighter("Derek"));
|
||||
assert(f);
|
||||
|
||||
delete a;
|
||||
}
|
||||
|
||||
void test_archer_reset() {
|
||||
archer a("stephen", 666, 66, 6, 0);
|
||||
a.takeDamage(100);
|
||||
assert(a.getCurrentHP() == 567);
|
||||
a.reset();
|
||||
assert(a.getCurrentHP() == a.getMaximumHP());
|
||||
assert(a.getSpeed() == a.get_original_speed());
|
||||
assert(a.getSpeed() == 6);
|
||||
assert(a.get_original_speed() == 6);
|
||||
}
|
||||
|
||||
void test_archer_usability() {
|
||||
archer a("stephen", 666, 66, 6, 0);
|
||||
assert(a.getSpeed() == 6);
|
||||
a.useAbility();
|
||||
assert(a.getSpeed() == 7);
|
||||
}
|
||||
|
||||
void test_battle() {
|
||||
archer a("stephen", 200, 66, 60, 100);
|
||||
robot b("derek", 1000, 20, 15, 200);
|
||||
fight(&a, &b, true);
|
||||
}
|
||||
|
||||
int main() {
|
||||
test_fighter();
|
||||
test_archer();
|
||||
test_cleric();
|
||||
test_robot();
|
||||
test_input_parser();
|
||||
test_add();
|
||||
test_remove();
|
||||
test_find();
|
||||
test_archer_reset();
|
||||
test_archer_usability();
|
||||
test_battle();
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#include <cmath>
|
||||
#include "FighterInterface.h"
|
||||
#include "robot.h"
|
||||
|
||||
robot::robot(string name, int max_hp, int strength, int speed, int magic) :
|
||||
fighter(name, max_hp, strength, speed, magic),
|
||||
max_energy(2 * magic), cur_energy(2 * magic), extra_damage(0) {}
|
||||
|
||||
int robot::getDamage() {
|
||||
int damage = strength + extra_damage;
|
||||
extra_damage = 0;
|
||||
return damage;
|
||||
}
|
||||
|
||||
void robot::reset() {
|
||||
hp = max_hp;
|
||||
cur_energy = max_energy;
|
||||
}
|
||||
|
||||
bool robot::useAbility() {
|
||||
if(cur_energy - ROBOT_ABILITY_COST >= 0) {
|
||||
double a = cur_energy/double(max_energy);
|
||||
double b = pow(a, 4.0);
|
||||
double increase = strength * b;
|
||||
extra_damage = int(increase);
|
||||
cur_energy -= ROBOT_ABILITY_COST;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef __ROBOT_H__
|
||||
#define __ROBOT_H__
|
||||
|
||||
#include "fighter.h"
|
||||
|
||||
class robot : public fighter {
|
||||
private:
|
||||
int max_energy;
|
||||
int cur_energy;
|
||||
int extra_damage;
|
||||
public:
|
||||
robot(string, int, int, int, int);
|
||||
|
||||
string get_type() { return "A"; };
|
||||
|
||||
int getDamage();
|
||||
void reset();
|
||||
bool useAbility();
|
||||
|
||||
int get_original_speed();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,60 @@
|
||||
#include <vector>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
#include <cstdlib>
|
||||
#include "util.h"
|
||||
|
||||
vector<string> tokenize(const string & str, const string & delimiters) {
|
||||
vector<string> tokens;
|
||||
string::size_type lastPos = str.find_first_not_of(delimiters, 0);
|
||||
string::size_type pos = str.find_first_of(delimiters, lastPos);
|
||||
while (string::npos != pos || string::npos != lastPos)
|
||||
{
|
||||
tokens.push_back(str.substr(lastPos, pos - lastPos));
|
||||
lastPos = str.find_first_not_of(delimiters, pos);
|
||||
pos = str.find_first_of(delimiters, lastPos);
|
||||
}
|
||||
return tokens;
|
||||
}
|
||||
|
||||
bool parse_n_load(const string & input, string & name, string & type,
|
||||
int & max_hp, int & strength, int & speed, int & magic) {
|
||||
vector<string> tokens = tokenize(input);
|
||||
vector<string> tokens2 = tokenize(input, ".");
|
||||
|
||||
if (tokens.size() != 6 or tokens2.size() > 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
name = tokens[0];
|
||||
|
||||
string parsed_type = tokens[1];
|
||||
if(parsed_type.size() != 1) {
|
||||
return false;
|
||||
}
|
||||
if (not ( parsed_type == "A"
|
||||
or parsed_type == "C"
|
||||
or parsed_type == "R")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
type = parsed_type;
|
||||
|
||||
|
||||
int parsed_max_hp = atoi(tokens[2].c_str());
|
||||
int parsed_strength = atoi(tokens[3].c_str());
|
||||
int parsed_speed = atoi(tokens[4].c_str());
|
||||
int parsed_magic = atoi(tokens[5].c_str());
|
||||
|
||||
if (parsed_max_hp == 0 or parsed_strength == 0 or parsed_speed == 0 or
|
||||
parsed_magic == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
max_hp = parsed_max_hp;
|
||||
strength = parsed_strength;
|
||||
speed = parsed_speed;
|
||||
magic = parsed_magic;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef __UTIL_H__
|
||||
#define __UTIL_H__
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
void print(const string & in);
|
||||
vector<string> tokenize(const string & str, const string & delimiters=" ");
|
||||
bool parse_n_load(const string & input, string & name, string & type,
|
||||
int & max_hp, int & strength, int & speed, int & magic);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user