Assignment 08 - Project

Due: Friday, Nov. 20, 2020, at noon, 100 points

For this assignment, you will submit multiple files containing a program written in C++. You may work in a group of two for this project. Be sure to divide the work equitably; we absolutely do not want to hear of people not contributing.

Resources: www.cplusplus.com

Foreground: It was stated in hw #7 that that assignment would lead into hw #8. We decided to go a different direction with hw #8. But the work you did in hw #7 is not for naught. It should certainly have given you a new appreciation for the dangers that genetically enhanced wildlife (esp. penguins!) might pose for our safety.

Background: For this assignment, you will be doing something very different from past assignments and past years' projects. In this assignment, you are not going to code up some silly, non-existent, ridiculous, program about Homer and some super-duper penguin people garbage! You're going to actually code up a very useful, pertinent, scientifically-based simulation that will add to the world's scientific body of knowledge that could have significant and ground-shaking implications. This is really important stuff, people!

Your program is to create a world where real penguins can swim about eating real fish so that they can have energy enough to escape the jaws of real killer whales1. To this end, you will create instances of classes described below in a program for which some parameters are given to you (we decide how many penguins, how many killer whales, etc) and one parameter is going to be determined by YOU. Herein, we will describe the "actors" (the world, penguins, fish, and killer whales) and you will set a simulation in motion and tune the simulation so as to create a sort of oscillating steady-state where penguin and fish and killer whale populations are stable. You'll have to run your program perhaps many, many times in order to figure out what values that parameter needs to be in order that the world doesn't run out of fish for the penguins to eat, doesn't fill up with overstuffed penguins, doesn't become a wasteland devoid of happy little penguins, etc. And when you finish this exercise, you will see from your efforts that you will have somewhat stable populations of fish and penguins - everyone living happily ever after. Welllll, the fish and penguins that live through the simulation will be happy. But even the fish and penguins that get eaten will die knowing that their sacrifices contributed to science.

Specifications: You need to build the following classes.

sea class:

  • member variables:

    • a 2-dim array of chars declared for MAX size of 25 x 25

    • a short integer describing the actual size of the sea world ( <= MAX). Your particular sea world object may not be as big as MAX x MAX, thus using only part of the array.

  • functions:

    • a constructor that allows you to pass in a grid size and defaults to MAX. This constructor will call private functions that will clear() the grid, then a populate() function that will place fish, penguins, and killer whales as described below.

    • an overloaded insertion operator.

    • appropriate accessor/mutator (set/get) functions if needed.

penguin class:

member variables:

  • a health value - an integer from 0 to 100.

  • a position in the sea - this could be two coordinates using two separate integers or one value using a struct for a 2-D location.

  • a boolean to indicate the penguin is alive or dead (active or not).

functions:

  • a default constructor that will initialize health randomly in the interval [60, 80], start the animal dead, and give them a position of (-1, -1).

  • a move() function that will act in accordance with their health value. This function, when called, will have the penguin move 5 cells in the sea if its health is 81 to 100, 4 cells if health is 61 to 80, 3 cells if health is 41 to 60, 2 cells if health is 21 to 40, 1 cell if health is 1 to 20. Penguins can "see" a (euclidean) distance of 8.0 around them and will chase fish to eat them. When a penguin moves into a cell (location in the sea) occupied by a fish, it will eat the fish, gaining the food value of the fish in a 1 - 1 parity (food value -> health value). That fishy disappears from the sea, of course. Also, the penguin will cease moving for that time frame since he/she needs to set a dinner plate, utensils, napkin, cook the fishy and digest in peace. yeah. (For ex., suppose penguin has 5 cells to move and catches a fish on the 3rd step, then he will stop there.). Thus, IF a penguin can see a fish, it will move towards it. IF it sees no fishies or killer whales, then the penguin's movement is random. IF it sees no fish but does see a killer whale, it will move away from the killer. IF it sees both, you decide how you want to code the behavior. There are lots of ways to deal with this situation. If the penguin's health reaches 0, they don't move...and become "chicken of the sea" for the whales. Also, for every cell the object moves through, it will lose 1 point of health.

fish class:

member variables:

  • food value - an integer in the interval [1, 10].

  • a location variable(s) for placement on the grid.

  • a boolean to indicate the fishy is alive or dead - active or not.

functions:

  • a default constructor that will initialize the food value of the fishy randomly, and place the fish at (-1, -1).

  • a move function that will move the fish one cell when called but in a random direction.

killer_whale class:

member variables:

  • a position (like above)

  • an int that tallies the number of penguins this guy ate. This is a status symbol for the animal. C'mon! They're killer whales! Besides, you are going to output this at the end just to know...

functions:

  • a default constructor that sets their kill tally appropriately and their position to (-1, -1).

  • a move() function that has them move 3 cells with each call to this function (i.e. they always move 3 cells when they move in a time-slice), unless they eat a penguin. They will seek out the closest penguin. You can pass the penguin array or the sea to the whale much like you could with the penguins and the fish. Warning: the next sentence may upset sensitive readers. The killer whale will eat the penguin. If so, moving is done for that time slice.

  • any other functionality needed to add to the kill tally, and output information needed for this program (as described below)

General Notes:

  1. All movements are only up, down, left or right or diagonal. In this program description, when we say an actor moves one "step" or one "cell", it means they have moved to an adjacent cell up, down, right or left or diagonal (incremented one or both of their coordinates by 1 or -1).

  2. In each time frame, all fish move first, penguins move next, killer whales move last.

  3. When any actor (fish, penguin, killer whale) moves, it must be aware of the cells it is moving into. Thus, any of them cannot move out of the sea boundaries. They cannot move through or over other actors, unless they are going to eat them.

  4. Your actors are to have characters representing them on the sea (grid, array, thingy). I suggest the mysterious code: P, F, and K. See if you can figure out what they mean.

  5. When a penguin calls its move function, its first inclination is to go for a fish to eat. You may pass the array of fish to that function so the penguin may "search the sea" for the closest fish by looking into the array for fish locations. IF there is a fish close enough (with in sight - less than 8.0 away), they will move towards it. You may also pass the sea to the penguin, if you want/need.

  6. For both penguins and fish: If one of these is eaten, then their symbol is removed from the sea (grid). Also, they must be designated as dead and their coordinates reset to (-1, -1).

  7. Penguins will spawn...if at any time a penguin reaches a health value above 70, another penguin is generated. That will be accomplished by choosing a dead penguin in the penguin array and reincarnating it with a new random health value and placed randomly in the grid. At the same time, the penguin that spawned loses half its health. The spawning penguin should implement this functionality (the spawn).

  8. Fish will spawn. The simulation will do this. This mechanism will be determined by you and use a global spawn rate that YOU are to determine. Again, a new fish is placed at random in the sea.

  9. There is a small chance that some actor may not be able to move; perhaps a fish completely surrounded by other fish or whales or penguins. So, if this happens, follow these rules: 1) if any fish can't move, they forfeit their move in that time slice; 2) if a penguin can't move, it forfeits; 3) if a penguin can't move in the direction it wants, it moves in some available direction; 4) if a killer whale can't move, it either "eats its way out" of that situation or forfeits that turn to move.

  10. Though an entity can move more than one square per turn, it has to have a valid path consisting of adjacent cells (immediately adjacent, diagonal ok) to get there; how it finds that path is up to you.

  11. We have dictated some methodologies for this simulation. But you are going to have to figure out the code to accomplish this. There are a variety of implementations of this project for you to discover. In other words, you have a LOT of leeway to code. Your design should be good. An example of a bad design would be to make one class a friend of another class simply to circumvent an accessibility issue. So, don't use friend classes. If you don't know what this means, good! Besides, penguins and fish and killer whales are NOT friends. Feel free to add members and functions to any class in the project.

The simulation: Ok, now that you know the setup, here's how the simulation will start. You will declare a sea object of size 17 x 17. You will declare an array of 50 penguins. You will declare two killer whales. You will declare an array of 200 fishy fishes..s. Now, the world has to be set up. This is to be accomplished by the populate() function of the sea class, as called by the constructor of the sea. It will be passed the arrays of actors, and place the two killer whales, scatter 35 fish, and scatter 20 penguins, all randomly. (Needless to say, you can't have two objects occupying one cell.....we don't care what Heisenberg thinks!) Now, set things in motion. Start a time loop (meaning a loop for which every iteration represents a unit of time) wherein all the actors move according to their move functions as described above in the order dictated. The loop will stop if all the penguins are dead, or you reach a maximum number of iterations of 10,000. The goal of the program is for you to determine the minimum spawn rate of the fish for the simulation that will keep the population of penguins alive but not overwhelming the sea. In other words, determine how fast (but not too fast) fish reproduce and get introduced into the sea so that the penguins stay alive and their population doesn't grow without bound. You will likely run this simulation many times, fine tuning the rate. Some runs might have penguins dying out fast, some with penguins taking over the world.

You should code this to have the world output to the screen at the end of each time slice - after all actors have moved. You might want/need to modify this, but that's up to you and your needs. In this way, you can see how the actors are moving and surviving (or not). Do this: #include <unistd.h> and put a block of code in your loop like this

usleep(200000);

cout<<the_sea<<endl;

This will output the grid (assuming you have overloaded the << op) and pause for .2 seconds. You can adjust the number of micro seconds you pass. (That function is "mu" sleep - micro sleep.) The output should look really cool.

Also, when the loop ends, have your code output the number of penguins and fish in the simulation that are still alive. This will also indicate your success or failure. And, output the number of penguins each killer has eaten.

The starting parameters ...

  • Start with 20 penguins

  • Start with 35 fishies (fishy fish)

  • Start with 2 killer whales

  • make the minimum health value for a penguin to spawn 70

You are tasked with determining the way to spawn fish and at what rate. New fish are to be scattered at random in some empty spot, and you cannot exceed the max number of fishies, or penguins, as dictated by the size of the arrays of fish and penguins.

1The use of the word real in this sentence is subject to interpretation. We'd really like you to know that we really don't know what is real and what is not real. But, oh well! Don't forget to feed the penguins.