In this homework you will get familiar with Inheritance, Polymorphism and Abstract class concepts in Object Oriented programming.
Keywords: OOP, Inheritance, Abstract class, Polymorphism
1 Problem Definition
In this homework, you are going to simulate a treasure hunt game. In this game, there are players (abstract class) with different classes (implementations) divided in two teams. The hunt commences on a square grid of size N which is the Board class. The top left square of the grid has the coordinate (0,0) while the bottom right square has coordinates(N-1,N-1). X axis is the horizontal axis and Y axis is the vertical axis. One of the squares contains the treasure, some of them contains the characters and other squares are empty. The classes you are going to define are Player (and its implementations), Board, Game and Input Parser. They are explained below.
2 Class Definitions
2.1 Player
Player is an abstract class. There are 5 types of players, namely, Fighter, Archer, Tank, Priest and Scout. Each player can be in the barbarian team or the knight team. Each type of player has different HP, attack damage, heal power and goal priority (will be explained later in the game class). The class and method definitions of Player is written below. After that there are subsections that explains the sub-classes of Player.
class Player{ protected :
const uint id;
Coordinate coordinate; int HP;
Team team;
//DO NOT MODIFY THE UPPER PART
//ADD YOU OWN PROVATE METHODS/PROPERTIES BELOW
public :
/
Main constructor
@param id id of the player .
@param x xcoordinate of the player
@param y ycoordinate of the player
@param team team of the player , BARBARIAN or KNIGHT
/
Player(uint id, int x, int y, Team team) ; virtual Player() = default ;
uint getID() const ; const Coordinate& getCoord() const ; int getHP() const ;
Team getTeam() const ;
/
@return the board ID of the player , If the ID is single digit add a prefix 0 , otherwise just turn it into a string .
Example :
3 > 03 12 > 12
/ std : : string getBoardID() ; virtual int getAttackDamage() const = 0; virtual int getHealPower() const = 0; virtual int getMaxHP() const = 0;
/
For each subclass of Player there are different priority l i s t s defined that controls the next action to take for that Player . It is given in the header of the subclasses .
@return the goal priority l i s t for the Player
/ virtual std : : vector<Goal> getGoalPriorityList() ;
/
@return the class abbreviation of player , i f the player is on the barbarian team , the abbreviation will consist of uppercase characters , otherwise it will consist of lowercase characters .
/
virtual const std : : string getClassAbbreviation() const ;
/
Attack the given player .
Enemy HP should decrease as much as the attack damage of attacker . Print the boardID of the attacker and the attack and the amount of damage as below
.
Player 01 attacked Player 05 (75)
@param enemy player that is attacked .
@return true i f the opponent | is dead false | i f alive . | |||
/bool attack(Player enemy) ;/ | |||||
Heal the given player by | the | adding amount | of heal power of this character | ||
to the HP of ally . Print below . | the | boardID of the | healer and healed | players as | |
Player 01 healed Player | 05 | ||||
Healed player should not/ void heal(Player ally) ; / | have | more HP than | its max HP. | ||
@Important The coordinates may not be on the board . | |||||
@return the coordinates that the unit is able to attack given of the unit . Empty vector i f the unit cannot attack ./virtual std : : vector<Coordinate> getAttackableCoordinates() ; | the | position |
/ @Important The coordinates may not be on the board .
@return the coordinates the unit is able to move given the position of the unit . Empty vector i f the unit cannot move.
/ virtual std : : vector<Coordinate> getMoveableCoordinates() ; /
@return the coordinates the unit is able to heal a l l i e s given the position of the unit . Empty vector i f none available .
/ virtual std : : vector<Coordinate> getHealableCoordinates() ;
/
Move player to coordinate . Print the boardID of the player and the old and new
coordinates as below :
Player 01 moved from (0/1) to (0/2)
@Important before calling this method you must verify that this coordinate
is valid to move
/ void movePlayerToCoordinate(Coordinate c) ;
/ Decide whether the player is dead .
@return true i f the player s HP <= 0 , false otherwise .
/ bool isDead() const ;
};
3.1.1 Archer class Archer : public Player{
/
Attack damage 50
Heal power 0
Max HP 200
Goal Priorities > {ATTACK} Class abbreviation > ar or AR Not able to move at all .
Can attack to a range of 2 squares directly up , down, l e f t or right , from its coordinate .
/
};
3.1.2 Fighter class Fighter : public Player{
/
Attack damage 100
Heal power 0
Max HP 400
Goal Priorities > {ATTACK,TOENEMY,CHEST} in decreasing order
Class abbreviation > f i or FI
Can move to adjacent up , down, l e f t or right square Can attack to adjacent up , down, l e f t or right square
/
};
3.1.3 Priest class Priest : public Player{
/
Attack damage 0
Heal power 50
Max HP 150
Goal Priorities > {HEAL,TO ALLY,CHEST} in decreasing order
Class abbreviation > pr or PR
Can move to all adjacent squares , including diagonals . Can heal all adjacent squares , including diagonals .
/
};
3.1.4 Scout class Scout : public Player{
/
Attack damage 25
Heal power 0
Max HP 125
Goal Priorities > {CHEST,TO ALLY,ATTACK} in decreasing order
Class abbreviation > sc or SC
Can move to all adjacent squares , including diagonals . Can attack all adjacent squares , including diagonals .
/
};
3.1.5 Tank class Tank : public Player{
/
Attack damage 25
Heal power 0
Max HP 1000
Goal Priorities > {TOENEMY,ATTACK,CHEST} in decreasing order
Class abbreviation > ta or TA
Can move to adjacent up , down, l e f t or right square Can attack to adjacent up , down, l e f t or right square
/
};
2.2 Board
Board holds size of the board, players and position of the chest. Its methods are concerned with printing the contents of the field and returning the properties of coordinates. The class header is given below.
class Board{
private : uint size;
std : : vector<Player> players; Coordinate chest;
//DO NOT MODIFY THE UPPER PART
//ADD YOU OWN PROVATE METHODS/PROPERTIES BELOW
public :
Board(uint _size, std : : vector<Player> _players, Coordinate chest) ;
Board() ; / @return true i f the coordinate is in the board limits , false otherwise .
/ bool isCoordinateInBoard( const Coordinate& c) ; / @return true i f there is a player on the given coordinate , false otherwise .
/ bool isPlayerOnCoordinate( const Coordinate& c) ;
/
@return pointer to the player at the given coordinate . Return NULL i f no player is there .
/
Player operator [ ] ( const Coordinate& c) ;
/
@return the chest coordinate
/ Coordinate getChestCoordinates() ; /
Print the board with character ID s .
For each empty square print two underscore characters .
For the squares with a player on it , print the board id of the player .
For the square with the chest , print the string Ch.
If a character is on the square with the chest , only print the ID of the character .
For each row print a new line , for each column print a space character .
void printBoardwithID() ; /
For each empty square print two underscore characters .
For the squares with a player on it , print the class abbreviation of the player .
For the square with the chest , print the string Ch.
If a character is on the square with the chest , only print the abbreviation of the character .
To separate each row print a new line , to separate each column print a space character . Example :
PR
Ch
/ void printBoardwithClass() ;
};
2.3 Game
Game class is responsible for running the game and managing the memory. The most important method here is the playTurnForPlayer method which computes the moves for the players given their different goal priorities.
class Game{
private :
Board board; uint turnNumber; uint maxTurnNumber; std : : vector<Player> players;
//DO NOT MODIFY THE UPPER PART
//ADD YOU OWN PROVATE METHODS/PROPERTIES BELOW
public : /
Costructor for Game class .
Game manages the memory allocated for future contents the vector (added players ) .
Pass a pointer to the players vector to board constructor sowill not miss the addition of players to the game. @param maxTurnNumber turn number to end the game @param boardSize size of the board @param chest coordinate of the chest/Game(uint maxTurnNumber, uint boardSize, Coordinate chest) ; | that | the board | ||
Game() ;/ | ||||
Add a new player to the game. Add a pointer to players vector . | the new player | to | the this> | |
Do not forget that Game will manage the memory @param id ID of the new player . @param x x coordinate of the new player . @param y y coordinate of the new player . @param team team of the new player ./void addPlayer( int id, int x, int y, Team team ) ;/ The game ends when either of these happens : All barbarians die ( knight victory ) All knights die ( barbarian victory ) | allocated for | the | players . | |
A barbarian gets to the square containing the | chest | ( barbarian | victory ) | |
maxTurnNumber of turns played ( knight victory ) | ||||
If the game ends announce it py printing the reason , victor as in the following examples : | turn number and the | |||
Game ended at turn 13. All barbarians dead . Knight victory . Game ended at turn 121. All knights dead . Barbarian victory . Game ended at turn 52. Chest captured . Barbarian victory . Game ended at turn 215. Maximum turn number reached . Knight victory . @return true i f any of the above is satisfied , false otherwise | ||||
/ bool isGameEnded() ;
/
Play a turn for each player .
Actions are taken in the order of ID numbers of players ( player with smaller ID acts f i r s t ) .
At the start of the turn it announces that the turn has started by printing to stdout . Turn numbers starts with 1.
Ex: Turn 13 has started . Call playTurnForPlayer for every player .
/ void playTurn() ; /
Play a turn for the player with the given ID.
If the player is dead announce its death by printing the boardID of the player
as in Player 07 died .. Remove that player from the board and release its resources .
Each player has a goal l i s t sorted by its priority for that player .
When a player plays a turn it iterates over its goal l i s t and tries to take an action . Valid actions are attack , move and heal . A player can take only
one action in a turn , and i f there is no action it can take it stops and does nothing .
Before moving a player you must check i f the coordinate to move is valid . Meaning that , the coordinate is in the bounds of the board and there are no players there .
IMPORTANT NOTE: every usage of the word nearest is referencing smallest the Manhattan
distance , which is formulated as (abs(x 1x 2 ) + abs(y 1y 2 ) ) . operator
overloaded in Coordinate .h computes exactly that , so you can use that method
to
calculate the distance between two coordinates .
Below are the explanations for goals :
ATTACK:
If there are any enemies in the attack range of the player attack to it . If there are more than 1 enemy in the range attack to the one with lowest ID. If there is no one to attack try the next goal .
CHEST:
Move to the direction of the chest , i f both vertical and horizontal moves
are available , pick the horizontal one . If the horizontal move is blocked
but the vertical move is not , move vertically . If all directions towards the chest is blocked try the next goal .
TOENEMY:
Move towards the nearest enemy. If there are more than one enemies with the same distance
move towards the one with the smallest ID. If both vertical and horizontal moves
are available , pick the horizontal one . If | an enemy is in the squares |
that the player can move or every move that | brings the player closer to |
the selected enemy is blocked , try the next TO ALLY: | goal . |
Move towards the nearest ally . If there are the same distance | more than one a l l i e s with |
move towards the one with the smallest ID. horizontal moves | If both vertical and |
are available , pick the horizontal one . If | an ally is in the squares |
that the player can move or every move that | brings the player closer to |
the selected ally is blocked , try the next HEAL: | goal . |
If there are any a l l i e s in the healing range heal all of them . i f there is no one to heal try the next goal . @return the goal that the action was taken upon . NO GOAL i f no action was taken ./ |
Goal playTurnForPlayer(Player player) ;
};
2.4 InputParser
Reads the standard input and creates a Game object. Details are explained in the header.
class InputParser{ public :
/
Parse the i n i t i a l parameters of the game from stdin . | |||
The input will be as follows . First line contains the size of the board . Second line contains the coordinates of the chest . | |||
Third line contains the number of players , P. | |||
Each of the next P lines contains a description | for | a player as follows . | |
ID of the player , class of the player , team of coordinate , . | the | player , x coordinate , | y |
Call the addPlayer method of the Game class to Example input : 6 3 3 2 12 ARCHER BARBARIAN 3 5 11 FIGHTER KNIGHT 1 1 | add | the players . | |
@returns Pointer to the Dynamically allocated Game object |
/ static Game parseGame() ;
};
3 Extras
The enumerations you need are defined in the Constants.h header. You can use them from there.
The Game class owns every player and vector of players in terms of memory management and is responsible for the destruction of these.
In order to get full grade from each part your code should not have any memory leak. This will be checked with valgrind. While grading your classes will be used with the correct implementations, therefore they are expected to work as commented in the code.
Reviews
There are no reviews yet.