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 x−coordinate of the player
∗ @param y y−coordinate 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 1−x 2 ) + abs(y 1−y 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.