1. Overview

In this project, you will:

  • Practice creating classes with inheritance
  • Working with pointers as they pertain to classes
  • Using polymorphism
  • Working with a large number of classes

2. Background

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

3. Requirements

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.

  • The project must be completed in C++. You may not use any libraries or data structures that we have not learned in class. Libraries we have learned include < iostream>, < fstream>, < iomanip>, < cmath>, < cstdlib>, < vector>, < ctime.h>, and < string>. You should only use namespace std.
  • Using the provided files, Farm.h, AgItem.h, Vegetable.h, Animal.h, Tree.h, Fruit.h, and proj4.cpp, create an simulation. You will need to create your own makefile for this project.
  • You may NOT modify the headers files.
  • There are six required classes in this project: Farm, Animal, AgItem, Fruit, Tree, and Vegetable. All functions listed in their class files must be implemented completely (even if you do not use them).
  • All agricultural items (AgItem) (and their subclasses) must be dynamically allocated (and deallocated).
  • All user input must be validated. For example, if a menu allows for 1, 2, or 3 to be entered and the user enters a 4, it will re-prompt the user. However, the user is expected to always enter the correct data type. i.e. If the user is asked to enter an integer, they will. If they are asked to enter a character, they will. You do not need to worry about checking for correct data types.
  • There is no file input for this project. There are no random numbers.
  • You will be using a single vector to store all agricultural items on the farm.

3.1. Class Requirements

3.1.1. AgItem (AgItem.h and AgItem.cpp)

  • The AgItem is an abstract class that is a common parent class to Vegetable, Animal, and Trees.
  • AgItems also have pure virtual functions for tick, harvest, and the overloaded operator.

3.1.2. Vegetables (Child of AgItem)

  • Vegetables are harvested when they have a size of 2
  • Vegetables are "seedlings" until size 0, then medium sized @1, then fully mature @2
  • Vegetables are always fed.
  • When vegetables are harvested, they produce one food for each size.

3.1.3. Animals (Child of AgItem)

  • Animals will start very small and eventually grow up so that they can be sold for a profit.
  • If an Animal is fed, then they:
    • Will grow every month until size 3
    • When adult, they will be harvested (which means sold in this case) for their worth * size
  • If an Animal is not fed (farm has no food), then they:
    • Do not grow.
    • If they are not fed two seasons in a row, they are harvested for worth * size

3.1.4. Trees (Child of AgItem)

  • These are fruit trees and they will produce fruit every season once they become mature.
  • Trees are considered "Seedling" until month 12
  • Trees are considered "Sapling" until month 24
  • Trees are considered "Pole" until month 36
  • Trees are considered "Mature" after 36.
  • Once a tree is mature, a single dynamically allocated "Fruit" object is added to the Tree m_fruit vector (don't forget to write a destructor!)
  • Once a tree reaches an age of 60, it is harvested for nothing. The wood has no value.

3.1.5. Fruit (Not a Child)

  • Fruit does not do anything else except grow on trees and can be harvested for one food

3.1.6. Farm

  • At its core, a farm is the container for the AgItems and the management of the farm itself.
  • The farm can do several things:
    • AddItem (Vegetables, Trees, and Animals)
    • Tick (which fires the tick function for each object in the garden and manages which month it is)
    • Manage the menu
    • Start the simulation
    • Display the status of the farm
  • As each of the AgItem is dynamically allocated, don't forget to write a destructor when you are finished with the farm.

4. Sample Input and Output

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)

Provided Files

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;
}
Academic Honesty!
It is not our intention to break the school's academic policy. Posted solutions are meant to be used as a reference and should not be submitted as is. We are not held liable for any misuse of the solutions. Please see the frequently asked questions page for further questions and inquiries.
Kindly complete the form. Please provide a valid email address and we will get back to you within 24 hours. Payment is through PayPal, Buy me a Coffee or Cryptocurrency. We are a nonprofit organization however we need funds to keep this organization operating and to be able to complete our research and development projects.