In this project, you will:
You've inherited your grandfather's old farm plot in Stardew Valley. Armed with hand-me-down tools and a few coins, you set out to begin your new life!
For this assignment, we are going to implement a simple text-based version of Stardew Valley. The game is open-ended, allowing players to take on activities such as growing crops, raising livestock, crafting goods, mining for ores, selling produce, and socializing with the townspeople, including marriage and having children.
As this project is focused on inheritance and polymorphism, there is an inheritance chain as defined in the figure below. We will have animals, trees, fruits, and vegetables in our version of this project. You will plant vegetables and they will grow until harvest. Animals will mature until they are ready to be sold. Trees will bear fruit when they are old enough.
Figure: see image.
In addition to these classes, there is a farm class that manages the
Type | Max Size | When Harvested | Notes |
Vegetable | 2 | Adds 1 to Food | None |
Animal | 3 | Adds worth * size to Money | Eats 1 food per season. If not fed for 2 season, is harvested. |
Tree | 4 | Nothing | Has age variable. Creates fruit when mature. At age 60, is cut down for no benefit. |
Fruit | 1 | Adds 1 per to Food | Created when tree is mature |
This is a list of the requirements of this application. For this project, it is up to you exactly how you want to implement it. For you to earn all the points, however, you will need to meet all the defined requirements.
3.1.1. AgItem (AgItem.h and AgItem.cpp)
3.1.2. Vegetables (Child of AgItem)
3.1.3. Animals (Child of AgItem)
3.1.4. Trees (Child of AgItem)
3.1.5. Fruit (Not a Child)
3.1.6. Farm
For this project, input files are not too challenging. For this project, there are no data files so you will not need to load, parse, or import any data.
In the sample output below, user input is colored blue for clarity. After compiling and running proj4, a run where we have a single animal (we start with 6 food) would look like this:
./proj4
Welcome to Stardew Valley Simulator
1. Add Item to Farm
2. Add Two of Each Item to Farm
3. Simulate Time
4. Farm Status
5. Quit
1
Which agricultural item are you interested in?
1. Animal
2. Vegetable
3. Tree
1
New Animal added to the farm.
1. Add Item to Farm
./proj4
Welcome to Stardew Valley Simulator
1. Add Item to Farm
2. Add Two of Each Item to Farm
3. Simulate Time
4. Farm Status
5. Quit
1
Which agricultural item are you interested in?
1. Animal
2. Vegetable
3. Tree
1
New Animal added to the farm.
1. Add Item to Farm
2. Add Two of Each Item to Farm
3. Simulate Time
4. Farm Status
5. Quit
3
How many seasons to simulate?
4
SEASON: 1
1: **** Farm Status ****
Food: 5
Money: 0
Season: 1
Agricultural Items:
Animal | Chicken | Not Harvestable | Infant | Fed
SEASON: 2
1: **** Farm Status ****
Food: 4
Money: 0
Season: 2
Agricultural Items:
Animal | Chicken | Not Harvestable | Juvenile | Fed
SEASON: 3
1: **** Farm Status ****
Food: 3
Money: 0
Season: 3
Agricultural Items:
Animal | Chicken | Not Harvestable | Adult | Fed
SEASON: 4
1: The Animal was harvested
**** Farm Status ****
Food: 2
Money: 3
Season: 4
Agricultural Items:
None
1. Add Item to Farm
2. Add Two of Each Item to Farm
3. Simulate Time
4. Farm Status
5. Quit
4
**** Farm Status ****
Food: 2
Money: 3
Season: 6
Agricultural Items:
None
1. Add Item to Farm
2. Add Two of Each Item to Farm
3. Simulate Time
4. Farm Status
5. Quit
Here is a slightly longer run:
Welcome to Stardew Valley Simulator
1. Add Item to Farm
2. Add Two of Each Item to Farm
3. Simulate Time
4. Farm Status
5. Quit
2
New Animal added to the farm.
New Animal added to the farm.
New Vegetable added to the farm.
New Vegetable added to the farm.
New Tree added to the farm.
New Tree added to the farm.
1. Add Item to Farm
2. Add Two of Each Item to Farm
3. Simulate Time
4. Farm Status
5. Quit
3
How many seasons to simulate?
5
SEASON: 1
**** Farm Status ****
Food: 4
Money: 0
Season: 1
Agricultural Items:
Animal | Chicken | Not Harvestable | Infant | Fed
Animal | Chicken | Not Harvestable | Infant | Fed
Vegetable | Not Harvestable | Medium
Vegetable | Not Harvestable | Medium
Tree | Sapling | Not Harvestable | Not Fruiting | Fruit Count: 0
Tree | Sapling | Not Harvestable | Not Fruiting | Fruit Count: 0
SEASON: 2
**** Farm Status ****
Food: 2
Money: 0
Season: 2
Agricultural Items:
Animal | Chicken | Not Harvestable | Juvenile | Fed
Animal | Chicken | Not Harvestable | Juvenile | Fed
Vegetable | Not Harvestable | Fully Mature
Vegetable | Not Harvestable | Fully Mature
Tree | Sapling | Not Harvestable | Not Fruiting | Fruit Count: 0
Tree | Sapling | Not Harvestable | Not Fruiting | Fruit Count: 0
SEASON: 3
The Vegetable was harvested
The Vegetable was harvested
**** Farm Status ****
Food: 2
Money: 0
Season: 3
Agricultural Items:
Animal | Chicken | Not Harvestable | Adult | Fed
Animal | Chicken | Not Harvestable | Adult | Fed
Tree | Sapling | Not Harvestable | Not Fruiting | Fruit Count: 0
Tree | Sapling | Not Harvestable | Not Fruiting | Fruit Count: 0
SEASON: 4
The Animal was harvested
The Animal was harvested
**** Farm Status ****
Food: 0
Money: 6
Season: 4
Agricultural Items:
Tree | Sapling | Not Harvestable | Not Fruiting | Fruit Count: 0
Tree | Sapling | Not Harvestable | Not Fruiting | Fruit Count: 0
SEASON: 5
**** Farm Status ****
Food: 0
Money: 6
Season: 5
Agricultural Items:
Tree | Pole | Not Harvestable | Not Fruiting | Fruit Count: 0
Tree | Pole | Not Harvestable | Not Fruiting | Fruit Count: 0
1. Add Item to Farm
2. Add Two of Each Item to Farm
3. Simulate Time
4. Farm Status
5. Quit
5
Thank you for simulating Stardew Valley!
Here is a run with a bit of validation:
valgrind ./proj4
==1991527== Memcheck, a memory error detector
==1991527== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==1991527== Using Valgrind-3.16.0 and LibVEX; rerun with -h for copyright info
==1991527== Command: ./proj4
==1991527==
Welcome to Stardew Valley Simulator
1. Add Item to Farm
2. Add Two of Each Item to Farm
3. Simulate Time
4. Farm Status
5. Quit
0
1. Add Item to Farm
2. Add Two of Each Item to Farm
3. Simulate Time
4. Farm Status
5. Quit
6
1. Add Item to Farm
2. Add Two of Each Item to Farm
3. Simulate Time
4. Farm Status
5. Quit
1
Which agricultural item are you interested in?
1. Animal
2. Vegetable
3. Tree
0
Which agricultural item are you interested in?
1. Animal
2. Vegetable
3. Tree
4
Which agricultural item are you interested in?
1. Animal
2. Vegetable
3. Tree
1
New Animal added to the farm.
1. Add Item to Farm
2. Add Two of Each Item to Farm
3. Simulate Time
4. Farm Status
5. Quit
5
Thank you for simulating Stardew Valley!
==1991527==
==1991527== HEAP SUMMARY:
==1991527== in use at exit: 0 bytes in 0 blocks
==1991527== total heap usage: 5 allocs, 5 frees, 74,824 bytes allocated
==1991527==
==1991527== All heap blocks were freed -- no leaks are possible
==1991527==
==1991527== For lists of detected and suppressed errors, rerun with: -s
==1991527== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Farm.h
//Title: Farm.h
//Description: Farm class that manages the simulation
#ifndef FARM_H
#define FARM_H
#include "AgItem.h"
#include "Vegetable.h"
#include "Tree.h"
#include "Animal.h"
#include < iostream>
#include < string>
using namespace std;
class Farm {
public:
// Name: Farm (Default constructor)
// Desc: Creates a Farm (with 6 food, 0 money, season = 1)
// Preconditions: None
// Postconditions: A farm is created
Farm();
// Name: Farm (Destructor)
// Desc: Deallocates everything in the farm
// Preconditions: None
// Postconditions: The farm is cleared out
~Farm();
// Name: ChooseItem
// Desc: Allows the user to choose either an animal, vegetable, or tree
// Preconditions: None
// Postconditions: returns 1 (animal), 2 (vegetable), or 3 (tree) (reprompts for anything else)
int ChooseItem();
// Name: AddItem (int type, int quantity)
// Desc: Dynamically allocates new animals, vegetables, or trees and adds to m_farm
// Preconditions: None
// Postconditions: Adds 1 (animal), 2 (vegetable), or 3 (tree) to m_farm
void AddItem(int type, int quantity);
// Name: Tick (int season)
// Desc: Simulates a specific number of seasons
// For each season:
// 1. Calls Tick for each item in m_farm
// 2. Tries to harvest mature items (vegetables and fruit add food; animals money)
// 3. Removes anything harvested from m_farm
// 4. Displays the status automatically
// Preconditions: None
// Postconditions: Time passes
void Tick(int);
// Name: Menu
// Desc: Displays a menu with the following:
// 1. Add Item to Farm (adds a single item to m_farm)
// 2. Add Two of Each Item to Farm (Adds two of each item to m_farm)
// 3. Simulate Time (Asks the user how many seasons to simulate)
// 4. Farm Status (Displays the status of the farm)
// 5. Quit (Quits the simulation)
// Preconditions: None
// Postconditions: If returns 5, quits
int Menu();
// Name: StartSimulation
// Desc: Manages the introduction, menu, and quitting
// Preconditions: Displays welcome message
// Postconditions: As long as menu doesn't return 5, keeps running
void StartSimulation();
// Name: Status
// Desc: Displays farm food, money, season, and each agricultural item
// Preconditions: None
// Postconditions: Displays farm data
void Status();
private:
vector < AgItem*> m_farm; //Container for all AgItems (vegetables, trees, or animals)
int m_food; //Food for the animals (from fruit and vegetables) - start with 6
int m_money; //Money from selling animals
int m_season; //Number of seasons elapsed (starts at 1)
};
#endif
AgItem.h
//Title: AgItem.h
//Description: Describes the parent class (Agricultural Items - animals, vegetables, and trees)
#ifndef AG_ITEM_H
#define AG_ITEM_H
#include < iostream>
#include < string>
using namespace std;
const string CONCAT = " | ";
const int BASE_WORTH = 1;
class AgItem {
public:
// Name: AgItem (Default constructor)
// Desc: Creates an AgItem with size 0, Base_Worth of 1 and not harvestable
// Preconditions: Abstract class
// Postconditions: Abstract class so used with child classes only.
AgItem();
// Name: AgItem (Overloaded constructor)
// Desc: Creates an AgItem with size, worth, and IsHarvestable passed
// Preconditions: Abstract class
// Postconditions: Abstract class so used with child classes only.
AgItem(int, int, bool);
// Name: ~AgItem (Destructor
// Desc: Deletes anything dynamically allocated
// Preconditions: AgItem
// Postconditions: Can be trivially implemented but required for subclass (tree)
virtual ~AgItem();
//Accessors
// Name: GetSize
// Desc: Returns m_size
// Preconditions: None
// Postconditions: None
int GetSize();
// Name: GetWorth
// Desc: Returns m_worth
// Preconditions: None
// Postconditions: None
int GetWorth();
// Name: GetIsHarvestable
// Desc: Returns m_isHarvestable
// Preconditions: None
// Postconditions: None
bool GetIsHarvestable();
// Name: SetSize
// Desc: Sets the size of an AgItem
// Preconditions: None
// Postconditions: m_size is set
void SetSize(int size);
// Name: SetIsHarvestable
// Desc: Sets m_isHarvestable
// Preconditions: None
// Postconditions: m_isHarvestable is set
void SetIsHarvestable(bool isAlive);
// Name: SetWorth
// Desc: Sets m_worth
// Preconditions: None
// Postconditions: m_worth is set
void SetWorth(int worth);
// Name: Tick (Purely Virtual)
// Desc: Calls Tick on the subtype (not implemented here)
// Preconditions: None
// Postconditions: Implemented in child classes
virtual void Tick(bool) = 0;
// Name: Harvest (Purely Virtual)
// Desc: Calls Harvest on the subtype (not implemented here)
// Preconditions: None
// Postconditions: Implemented in child classes
virtual int Harvest() = 0;
// Name: GetType (Purely Virtual)
// Desc: Returns the name of the subtype (not implemented here)
// Preconditions: None
// Postconditions: Implemented in child classes
virtual string GetType() = 0;
// Name: overloaded operator<< (Purely Virtual)
// Desc: Allows AgItems objects to be outputted
// **NOTE** - Must be called with (*m_farm.at(i)) << cout << endl; (In this order)
// Preconditions: None
// Postconditions: Implemented in child classes
virtual ostream& operator<<(ostream& os) = 0;
private:
int m_size; //Current size
int m_worth; //Worth of item
bool m_isHarvestable; //Current status
};
#endif
Vegetable.h
//Title: Vegetable.h
//Description: Describes the child class Vegetable (Parent AgItem)
#ifndef VEGETABLE_H
#define VEGETABLE_H
#include "AgItem.h"
//Constants
const string Veg_Size[] {"Seedling", "Medium", "Fully Mature"}; //Names of the sizes
const int MAX_VEG_SIZE = 2; //1 = seedling 2 = medium 3 = fully mature
class Vegetable : public AgItem {
public:
// Name: Vegetable (Default constructor)
// Desc: Creates a vegetable with size 0
// Preconditions: Uses AgItem default constructor
// Postconditions: A vegetable is created.
Vegetable();
// Name: Harvest
// Desc: If the vegetable is harvestable (fully mature), returns size to increase farm's food
// Preconditions: IsHarvestable
// Postconditions: Returns integer size of vegetable for food
virtual int Harvest();
// Name: Tick
// Desc: A season passes in the vegetable's life if they are fully mature, IsHarvestable flipped
// Preconditions: If the size is less than the maximum vegetable size, increases size
// Postconditions: Vegetable either grows or becomes harvestable
// Assume that a vegetable is always fed.
virtual void Tick(bool);
// Name: GetType
// Desc: Returns the name of the subtype (Vegetable)
// Preconditions: None
// Postconditions: Returns string name of the subtype (Vegetable)
virtual string GetType();
// Name: overloaded operator<<
// Desc: Allows Vegetable objects to be outputted
// Preconditions: None
// Postconditions: Returns output stream with this format
// Vegetable | Not Harvestable | Seedling
virtual ostream& operator<<(ostream&);
};
#endif
Animal.h
//Title: Animal.h
//Description: Describes the class Animal (parent AgItem)
#ifndef ANIMAL_H
#define ANIMAL_H
#include < iostream>
#include < string>
#include < vector>
#include "AgItem.h"
using namespace std;
const string ANIMAL_SIZE[] = { "Born", "Infant", "Juvenile", "Adult" }; //Names of the animal sizes
const int ANIMAL_MAX_SIZE = 3; //Born = 0, Infant = 1, Juvenile = 2, Adult = 3
class Animal : public AgItem {
public:
// Name: Animal (Default constructor)
// Desc: Creates an Animal with size 0
// Preconditions: Uses AgItem default constructor
// Postconditions: An animal (chicken) is created.
Animal();
// Name: Tick
// Desc: A season passes is the animal's life (passed boolean if it was fed - eats "farm's food")
// Preconditions: If farm has food, animal is automatically fed
// Postconditions: One of the following occurs
// 1. Animal is fed and size increases (not max yet)
// 2. Animal is fed hits max size and is made harvestable
// 3. Animal is not fed. Size does not increase. If second no feed, is harvested (small).
virtual void Tick(bool);
// Name: Harvest
// Desc: If the animal is harvestable (adult), returns worth * size to increase farm's money
// Preconditions: IsHarvestable
// Postconditions: Animal harvested and money is gained (worth * size)
int Harvest();
// Name: GetType
// Desc: Returns the name of the subtype (Animal)
// Preconditions: None
// Postconditions: Returns string name of the subtype (Animal)
virtual string GetType();
// Name: overloaded operator<<
// Desc: Allows Animal objects to be outputted
// Preconditions: None
// Postconditions: Returns output stream with this format:
// Animal | Chicken | Not Harvestable | Born | Fed
virtual ostream& operator<<(ostream&);
private:
string m_name; //Name of the type of animal (chicken by default)
bool m_IsHungry; //Keeps track if animal not fed previous season (true = not fed)
};
#endif
Tree.h
#ifndef TREE_H
#define TREE_H
#include "AgItem.h"
#include "Fruit.h"
#include < vector>
const string TREE_SIZE[] = { "Seedling", "Sapling", "Pole", "Mature" }; //age 0-3 = seedling
const int SEASONS_TO_FRUIT = 12; //Roughly 4 years to produce fruit (when age = 12, fruit)
const int SEASONS_TO_SIZE = 4; //Roughly every 4 seasons they move to next size (up to mature)
const int SEASONS_TO_HARVEST = 60; //Roughly every 15 years cut down (when age = 60)
class Tree : public AgItem {
public:
// Name: Tree (Default constructor)
// Desc: Creates a tree with size 0 and age of 0
// Preconditions: Uses AgItem default constructor
// Postconditions: A tree is created.
Tree();
// Name: ~Tree
// Desc: Destructor for tree (and importantly fruit)
// Preconditions: Tree exists
// Postconditions: All fruit is purged from tree.
~Tree();
// Name: Tick
// Desc: A season passes is the tree's life (always fed)
// Preconditions: Tree exists
// Postconditions: Returns amount of fruit harvested each season.
// One of the following occurs:
// 1. Tree is not Mature yet and ages. Every 4 seasons, size increases til age 12 when fruits
// 2. Tree is Mature and grows a one fruit a season. Fruit is harvested every season.
// 3. Tree is 60 seasons old and is cut down (IsHarvesteable)
virtual void Tick(bool);
// Name: Harvest
// Desc: If there is fruit, removes last fruit and returns 1. If 60 seasons old, returns 0
// Preconditions: Tree exists
// Postconditions: Fruit is returned(1 farm food) or dead tree (0 worth and 0 farm food)
virtual int Harvest();
// Name: GetType
// Desc: Returns the name of the subtype (Tree)
// Preconditions: None
// Postconditions: Returns string name of the subtype (Tree)
virtual string GetType();
// Name: overloaded operator<<
// Desc: Allows Tree objects to be outputted
// Preconditions: None
// Postconditions: Returns output stream with this format:
// Tree | Seedling | Not Harvestable | Not Fruiting | Fruit Count: 0
virtual ostream& operator<<(ostream&);
private:
vector < Fruit*> m_fruit; //Hold fruit objects
int m_age; //Trees are not harvested when they are mature - they make fruit
};
#endif
Fruit.h
#ifndef FRUIT_H
#define FRUIT_H
#include < string>
using namespace std;
class Fruit {
public:
// Name: Fruit
// Desc: Creates a fruit with a color
// Preconditions: None
// Postconditions: A fruit is created that is red (cannot access the color anyway)
Fruit();
private:
string m_color;
};
#endif
proj4.cpp
//Description: Builds a farm and starts the simulation (nothing random)
#include < iostream>
#include < string>
using namespace std;
#include "Farm.h"
int main() {
Farm farm;
farm.StartSimulation();
return 0;
}