CSCI 235 Fall 2023 Term Project
Algorithmic Adventures II: The Exponential Creature Odyssey
You will now define different types of Creatures
. You will implement 3 new classes that derive from the Creature
class but also have additional attributes and methods specific to their type:
Dragons are majestic and powerful creatures with a strong connection to elemental forces. Each Dragon may have an affinity to a specific element, a number of heads, and an optional choice of being able to fly.
Ghouls are nightmarish creatures that feed on the living. Each Ghoul has a level of decay (e.g. none, minimal, moderate, advanced), a faction that they belong to: Fleshgorgers, Shadowstalkers, or Plagueweavers (e.g, berserkers, assassins, and necromancers). Ghouls may or may not have a transformation, where they can evolve temporarily into a more powerful and resistant form.
Mindflayers are otherworldly beings with powerful psionic abilities. Each Mindflayer is equipped with a limited source of ammunition "that they got from a friend". This ammunition comes in the form of different types of psychic projectiles (eg. psionic, telepathic, illusionary). A Mindflayer may or may not be able to summon a Thoughtspawn. Each Mindflayer also has a list of affinities, which increases the damage dealt with a projectile of the same type.
The link to accept the GitHub Classroom assignment can be found on Blackboard
Work through the tasks sequentially (implement and test). Only move on to a task when you are positive that the previous one has been completed correctly. Remember that the names of classes and methods must exactly match those in this specification (FUNCTION NAMES, PARAMETER TYPES, RETURNS, PRE AND POST CONDITIONS MUST MATCH EXACTLY).
Remember, you must thoroughly document your code!!!
Dragon
class
The Dragon
class must define the following type defined publicly inside the class:
enum Element {NONE, FIRE, WATER, EARTH, AIR};
The Dragon
class must have the following private member variables:
xxxxxxxxxx
- An Element representing their affinity
- An integer representing the number of heads
- A boolean indicating if they can fly
x/**
Default constructor.
Default-initializes all private members.
Default Category: MYSTICAL
Default element: NONE
Default number of head(s): 1
Booleans are default-initialized to False.
*/
/**
Parameterized constructor.
@param : The name of the Dragon (a reference to string)
@param : The category of the Dragon (a Category enum) with default value MYSTICAL
@param : The Dragon's hitpoints (an integer), with default value 1 if not provided, or if the value provided is 0 or negative
@param : The Dragon's level (an integer), with default value 1 if not provided, or if the value provided is 0 or negative
@param : A flag indicating whether the Dragon is tame, with default value False
@param : The element (an Element enum), with default value NONE if not provided
@param : The number of heads (an integer), with default value 1 if not provided, or if the value provided is 0 or negative
@param : A flag indicating whether the Dragon can fly, with default value False
@post : The private members are set to the values of the corresponding parameters.
Hint: Notice the default arguments in the parameterized constructor.
*/
xxxxxxxxxx
/**
Getter for the element.
@return : The element (a string representation of the Element enum)
*/
getElement
/**
Setter for the element.
@param : A reference to the element (an Element enum)
@post : The element is set to the value of the parameter.
*/
setElement
/**
Getter for the number of heads.
@return : The number of heads (an integer)
*/
getNumberOfHeads
/**
Setter for the number of heads.
@param : A reference to the number of heads (an integer)
@pre : The number of heads is > 0. Do nothing for invalid values.
@post : The number of heads is set to the value of the parameter.
@return : True if the number of heads is set, false otherwise.
*/
setNumberOfHeads
/**
Getter for the flight flag.
@return : The flight flag (a boolean)
*/
getFlight
/**
Setter for the flight flag.
@param : A reference to the flight flag (a boolean)
@post : The flight flag is set to the value of the parameter.
*/
setFlight
Ghoul
class
The Ghoul
class must have the following type defined publicly inside the class:
xxxxxxxxxx
enum Faction {NONE, FLESHGORGER, SHADOWSTALKER, PLAGUEWEAVER};
The Ghoul
class must have the following private member variables:
xxxxxxxxxx
- An integer representing their level of decay
- A Faction representing their faction
- A boolean indicating if they can transform
The Ghoul
class must have the following public member functions:
xxxxxxxxxx
/**
Default constructor.
Default-initializes all private members.
Default Category: UNDEAD
Default decay: 0
Default faction: NONE
Booleans are default-initialized to False.
*/
/**
Parameterized constructor.
@param : The name of the Ghoul (a reference to string)
@param : The category of the Ghoul (a Category enum) with default value UNDEAD
@param : The Ghoul's hitpoints (an integer), with default value 1 if not provided, or if the value provided is 0 or negative
@param : The Ghoul's level (an integer), with default value 1 if not provided, or if the value provided is 0 or negative
@param : A flag indicating whether the Ghoul is tame, with default value False
@param : The level of decay (an integer), with default value 0 if not provided, or if the value provided is negative
@param : The faction (a Faction enum), with default value NONE if not provided
@param : A flag indicating whether the Ghoul can transform, with default value False
@post : The private members are set to the values of the corresponding parameters.
Hint: Notice the default arguments in the parameterized constructor.
*/
xxxxxxxxxx
/**
Getter for the level of decay.
@return : The level of decay (an integer)
*/
getDecay
/**
Setter for the level of decay.
@param : A reference to the level of decay (an integer)
@pre : The level of decay must be >= 0 (do nothing otherwise)
@post : The level of decay is set to the value of the parameter.
@return : true if the level of decay was set, false otherwise
*/
setDecay
/**
Getter for the faction.
@return : The faction (a string representation of the Faction enum)
*/
getFaction
/**
Setter for the faction.
@param : A reference to the faction (a Faction enum)
@post : The faction is set to the value of the parameter.
*/
setFaction
/**
Getter for the transformation.
@return : The transformation (a boolean)
*/
getTransformation
/**
Setter for the transformation.
@param : A reference to the transformation (a boolean)
@post : The transformation is set to the value of the parameter.
*/
setTransformation
Mindflayer
classThe Mindflayer
class must have the following types defined publicly inside the class:
xxxxxxxxxx
enum Variant {PSIONIC, TELEPATHIC, ILLUSIONARY};
struct Projectile
{
Variant type_;
int quantity_;
};
The Mindflayer
class must have the following private member variables:
xxxxxxxxxx
- A vector of Projectiles
- A vector of Variants representing their affinities
- A boolean indicating if they are able to summon a Thoughtspawn
xxxxxxxxxx
/**
Default constructor.
Default-initializes all private members.
Default Category: ALIEN
Default summoning: False
*/
/**
Parameterized constructor.
@param : A reference to the name of the Mindflayer (a string)
@param : The category of the Mindflayer (a Category enum) with default value ALIEN
@param : The Mindflayer's hitpoints (an integer), with default value 1 if not provided, or if the value provided is 0 or negative
@param : The Mindflayer's level (an integer), with default value 1 if not provided, or if the value provided is 0 or negative
@param : A flag indicating whether the Mindflayer is tame, with default value False
@param : The projectiles (a vector of Projectile structs), with default value an empty vector if not provided
@param : A flag indicating whether the Mindflayer can summon, with default value False
@param : The affinities (a vector of Variant enums), with default value an empty vector if not provided
@post : The private members are set to the values of the corresponding parameters.
Hint: Notice the default arguments in the parameterized constructor.
*/
xxxxxxxxxx
/**
Getter for the projectiles.
@return : The projectiles (a vector of Projectile structs)
*/
getProjectiles
/**
Setter for the projectiles.
@param : A reference to the projectiles (a vector of Projectile structs)
@post : The projectiles are set to the value of the parameter. There should not be any duplicate projectiles in Mindflayer's projectiles vector.
: For example, if the vector in the given parameter contains the following Projectiles: {{PSIONIC, 2}, {TELEPATHIC, 1}, {PSIONIC, 1}, {ILLUSIONARY, 3}},
: the projectiles vector should be set to contain the following Projectiles: {{PSIONIC, 3}, {TELEPATHIC, 1}, {ILLUSIONARY, 3}}.
: If the quantity of a projectile is 0 or negative, it should not be added to the projectiles vector.
: Note the order of the projectiles in the vector.
*/
setProjectiles
/**
Getter for the summoning.
@return : The summoning (a boolean)
*/
getSummoning
/**
Setter for the summoning.
@param : A reference to the summoning (a boolean)
@post : The summoning is set to the value of the parameter.
*/
setSummoning
/**
Getter for the affinities.
@return : The affinities (a vector of Variant enums)
*/
getAffinities
/**
Setter for the affinities.
@param : A reference to the affinities (a vector of Variant enums)
@post : The affinities are set to the value of the parameter.
: There should not be any duplicate affinities in Mindflayer's affinities vector.
: For example, if the vector in the given parameter contains the following affinities: {PSIONIC, TELEPATHIC, PSIONIC, ILLUSIONARY},
: the affinities vector should be set to contain the following affinities: {PSIONIC, TELEPATHIC, ILLUSIONARY}.
: Note the order of the affinities in the vector.
*/
setAffinities
/**
@param : A reference to the Variant
@return : The string representation of the variant
*/
variantToString
Note: This class uses a struct type. Struct is just short for "structure" and it is a user-defined type, much like a class. It is not a full fledged class, however. We use it to bundle data items with no or very few functions (none in this case). When initializing a new projectile you may use Projectile
as the data type. For example for int x
, int
is our primitive data type. If we want to make a projectile called p1 we would write Projectile p1
.
To set the data members of the struct we use the dot operator. For example, if we want to set the type of the projectile we would write p1.type_ = PSIONIC
. If we want to set the quantity of the projectile we would write p1.quantity_ = 5
.
Similarly, to access the data members of the struct we use the dot operator. For example, if we want to access the type of the projectile we would write p1.type_
. If we want to access the quantity of the projectile we would write p1.quantity_
.
For more on structs, see the "Additional resources" section at the top of this document.
To give you some feel and guide into testing, we have added a testing task to this project. To be clear, the task below is not a thorough test of your classes. You must test every function you implement with valid and invalid values, and make sure it behaves as specified. This is only intended to motivate you into building a methodical and incremental testing practice.
Write a testing program as described below and name the file test.cpp
.
Instantiate the following creature objects that derive from the Creature class. For each creature object, print out the creature's information - including private member variables that are unique to their subclass - using the appropriate getter functions in the format:
Format for Dragons:
xxxxxxxxxx
NAME: [NAME]\n
CATEGORY: [CATEGORY]\n
HP: [HITPOINTS]\n
LVL: [LEVEL]\n
TAME: [TAME]\n
ELEMENT: [ELEMENT]\n
HEADS: [NUMBER OF HEADS]\n
FLIGHT: [FLIGHT]\n
Format for Ghouls:
xxxxxxxxxx
NAME: [NAME]\n
CATEGORY: [CATEGORY]\n
HP: [HITPOINTS]\n
LVL: [LEVEL]\n
TAME: [TAME]\n
DECAY: [DECAY]\n
FACTION: [FACTION]\n
TRANSFORM: [TRANSFORM]\n
Format for Mindflayers: For the Projectiles, print out the type and quantity of each projectile in the format: [TYPE]: [QUANTITY] for each projectile in the vector, where the type is the string equivalent of the Variant (eg. "PSIONIC"/"TELEPATHIC"/"ILLUSIONARY"). If there are no projectiles, don't print anything.
For the Affinities, print out each affinity in the format: [AFFINITY 1]\n[AFFINITY 2]\n for each Affinity in the vector, where the Affinity is the string equivalent of the Variant (eg. "PSIONIC"/"TELEPATHIC"/"ILLUSIONARY"). If there are no affinities, don't print anything, including the label "AFFINITIES:".
xxxxxxxxxx
NAME: [NAME]\n
CATEGORY: [CATEGORY]\n
HP: [HITPOINTS]\n
LVL: [LEVEL]\n
TAME: [TAME]\n
SUMMONING: [SUMMONING]\n
[PROJECTILE TYPE 1]: [QUANTITY 1]\n
[PROJECTILE TYPE 2]: [QUANTITY 2]\n
AFFINITIES: \n
[AFFINITY 1]\n
[AFFINITY 2]\n
xxxxxxxxxx
2.1.1 Instantiate a default Dragon
- Print out the information for the default Dragon based on the format above
2.1.2 Instantiate a Dragon with the parameterized constructor with the following creature details:
Name: Smog
- Print out the information for Smog based on the format above
2.1.3 Instantiate a Dragon with the parameterized constructor with the following creature details:
Name: BURNY
Category: UNDEAD
Hitpoints: 100
Level: 10
Tame: True
Element: FIRE
Number of heads: 1
Flight: True
- Print out the information for Burny based on the format above
2.1.4 Make the following changes to Burny using the appropriate setter functions:
- Set the element to WATER
- Set the number of heads to 2
- Set the number of heads to 0
- Set the flight flag to False
- Print out the information for Burny based on the format above
2.2.1 Instantiate a default Ghoul
- Print out the information for the default Ghoul based on the format above
2.2.2 Instantiate a Ghoul with the parameterized constructor with the following creature details:
Name: Homph
- Print out the information for Homph based on the format above
2.2.3 Instantiate a Ghoul with the parameterized constructor with the following creature details:
Name: CHOMPER
Category: ALIEN
Hitpoints: 100
Level: 10
Tame: True
Decay: 3
Faction: FLESHGORGER
Transform: True
- Print out the information for Chomper based on the format above
2.2.4 Make the following changes to Chomper using the appropriate setter functions:
- Set the decay to 2
- Set the decay to -20
- Set the faction to SHADOWSTALKER
- Set the transformation flag to False
- Print out the information for Chomper based on the format above
2.3.1 Instantiate a default Mindflayer
- Print out the information for the default Mindflayer based on the format above
2.3.2 Instantiate a Mindflayer with the parameterized constructor with the following creature details:
Name: BIGBRAIN
Category: MYSTICAL
Hitpoints: 100
Level: 10
Tame: True
Projectiles: {{PSIONIC, 2}, {TELEPATHIC, 1}, {PSIONIC, 1}, {ILLUSIONARY, 3}}
Summoning: True
Affinities: {PSIONIC, TELEPATHIC, PSIONIC, ILLUSIONARY}
- Print out the information for Bigbrain based on the format above
How to compile with your Makefile:
In terminal, in the same directory as your Makefile and your source files, use the following command
xxxxxxxxxx
make rebuild
This assumes you did not rename the Makefile
and that it is the only one in the current directory.
You must always implement and test your programs INCREMENTALLY!!! What does this mean? Implement and TEST one method at a time. For each class:
Implement one function/method and test it thoroughly (write a main file with multiple test cases + edge cases if applicable).
Only when you are certain that function works correctly and matches the specification, move on to the next.
Implement the next function/method and test in the same fashion.
How do you do this? Write your own main()
function to test your classes. Choose the order in which you implement your methods so that you can test incrementally: i.e. implement constructors then accessor functions, then mutator functions. Thoroughly test with valid and invalid input to check thet your function behaves as expected in each case. Pay special attention to edge cases. Sometimes functions depend on one another. If you need to use a function you have not yet implemented, you can use stubs: a dummy implementation that always returns a single value for testing. Don’t forget to go back and implement the stub!!! If you put the word STUB in a comment, some editors will make it more visible.
Correctness 80% (distributed across unit testing of your submission)
Documentation 15%
Style and Design 5% (proper naming, modularity, and organization)
Important: You must start working on the projects as soon as they are assigned to detect any problems with submitting your code and to address them with us well before the deadline so that we have time to get back to you before the deadline.
We will grade the following :
Dragon.hpp
Dragon.cpp
Mindflayer.hpp
Mindflayer.cpp
Ghoul.hpp
Ghoul.cpp
test.cpp
Although Gradescope allows multiple submissions, it is not a platform for testing and/or debugging and it should not be used for that. You MUST test and debug your program locally. To help you not rely too much on Gradescope for testing, we will only allow 5 submissions per day. Before submitting to Gradescope you MUST ensure that your program compiles using the provided Makefile
and runs correctly on the Linux machines in the labs at Hunter (see detailed instructions on how to upload, compile and run your files in the “Programming Guidelines” document). That is your baseline, if it runs correctly there it will run correctly on Gradescope, and if it does not, you will have the necessary feedback (compiler error messages, debugger or program output) to guide you in debugging, which you don’t have through Gradescope. “But it ran on my machine!” is not a valid argument for a submission that does not compile. Once you have done all the above you submit it to Gradescope.
This project is due on 2/19.
No late submissions will be accepted.
You must start working on the projects as soon as they are assigned to detect any problems and to address them with us well before the deadline so that we have time to get back to you before the deadline. There will be no extensions and no negotiation about project grades after the submission deadline.
Help is available via drop-in tutoring in Lab 1001B (see website for schedule). You will be able to get help if you start early and go to the lab early. We only have 3 UTAs in the lab, the days leading up to the due date will be crowded and you will not be able to get much help then.
Authors: Georgina Woo, Tiziana Ligorio