Improving and extending the predator-prey simulation

Your program MUST be based on the original program, and keep the structure of this program (i.e. keep and only modify the Island, Animal, Prey and Predator classes, and add four new sub-classes for the four animal types as discussed below).
3-dimensional grid with different size in each dimension - 3 marks
Modify the program such that the simulation works in a 3-dimensional environment rather than in two dimensions only. This requires you to modify the code in various places. The 3-dimensional grid allows us to simulate the air above the island as well, and we will use this to introduce more animal types in task 3. We assume that the third dimension (z) is the one going upwards into the air (i.e. height above the island).
Your program must allow the setting of grids of different sizes in each dimension (i.e. three parameters, one per dimension, need to be given for the size of the grid, not just the single parameter ncurrently used to create a square grid).
Specifically, the __init__ method of the Island class should take the following parameters: x, y, z, wolf_count, eagle_count, rabbit_count, and pigeon_count (see below for more details on these four types of animals).
For printing an island, modify the __str__ method such that it prints the 3-dimensional grid horizontally, with the highest layer (or plane) first and the lowest (with z=0) last. Each layer/plane corresponds to a matrix of dimension x x y cells.

Random movement of animals - 2 marks
Modify the program such that animals move in random directions rather than in a specific way as with the original program.
You need to modify the check_grid method in the Animal class and possibly in the child classes of Animal. Also keep in mind that we will have both birds and land animals (see below), where the land animals have limitations in the directions they can move.
Specifically, to allow random movements, the check_grid method now should randomly select one of the possible neighbouring locations and not just the first one as in the check_grid method in the original program. Check the random module to find a function which allows you to choose one element of a list in a random fashion.
Important: Add at the top of your program (after the line: import random) the instruction: random.seed() which initialises the random number generator in a specific way and allows us to create repeatable simulations.

New animals: wolves, eagles, rabbits and pigeons - 3 marks
In the original program we only had a Prey and a Predator class. We want to extend our simulation to allow both birds and land animals. Wolfs and eagles are predator animals, while rabbits and pigeons are prey animals. In this task you have to develop classes for these four animals based on the Prey and Predator classes. All four animal types should have the same funcionalities as the predator and prey animals in the original program, but they can either move in three dimensions (eagles and pigeons) or only in two dimensions (wolves and rabbits).
The possible movement for birds must include all possible neighbouring grid cells, including all possible diagonal cells (i.e. a maximum of 26 neighbouring cells).
Specifically, you have to implement four animal classes, two based on the Predator class (name these classes Eagle and Wolf) and two based on the Prey class (name these classes Rabbit and Pigeon). The land based animals can only move on land, i.e. their z coordinate value can only be z=0. On the other hand, birds (eagles and pigeons) can have any z-coordinate value, including 0.

New eating strategies - 2 marks
We now assume that the land-based prey animals (rabbits) can be eaten by both wolves and eagles (it weould be unlikely for eagles to eat the moose from the original program). Modify the code such that eagles and wolves can eat both rabbits and pigeons (following the same eating criterion as in the original program: if a neighbouring cell of a predator animal has a prey animal then a predator can eat the prey animal).
Additionally, also modify your program so that wolves can eat eagles but not the other way around.

Calculate statistics of the simulation - 3 marks
To gather more information, extend your program such that for each animal your keep information about how long an animal was alive (in number of clock ticks) before it gets eaten or it starves, and how many offspring an animal produced. At the end of your simulation, your program must print for each animal type: (a) the total number of animals of this type that were alive throghout the simulation (including those still alive at the end of the simulation); (b) the minimum, maximum, average, and median life time (in clock ticks) of animals of this type, and (c) the minimum, maximum, average, and median number of offspring produced by this animal type.
Specifically, similar to the initialisation of class attributes for breeding and starving times in the main part of the original program, initialise for each of the four animal classes a life_timeand a num_offspring list as class attributes, add a life_time and num_offspring counter to each individual animal (i.e. each instance), and in each clock time increase the life time of all animals by one. If an animal breeds increase the number of offspring by the parent animal by one.
If an animal starves or is eaten, take its life span and number of offspring values and append them to the corresponding class attributes.
At the end of the simulation print the statistics described above.
Specifically, implement a function calc_statistics(animal_class) which calculates and prints the statistics for the animal class given as input.

Additional tasks You will need to extend your program in two different ways:.
Eating ststistics - 1 mark
Write a function calc_eating_stats(predator_class) which for the given predator class (Eagle or Wolf) prints information about how many animals from which class were eaten by predator animals of the given class. Again, provide the minimum, maximum, average, and median number of animals eaten. The output should be in tabular form such as (for example for eagles):

Animal eaten by eagles:
Prey Minimum Maximum Average Median
Rabbit 0 42 13.6 7
Pigeon 1 12 4.2 3

Remember that wolves can also eat eagles. Similar to task 5 above, you will need to add code that allows you to gather statistics about how many other animals a prey animal has eaten. In the final printed statistics you also need to include the values from the still alive predator animals.
Predators searching for prey - 2 marks
Write a method predator_prey_grid_search() for the Predator class (and if necessary for the Wolf and/or Eagle classes) that allows the following functionality: Rather than only checking the direct neighbouring grid cells for prey animals, in this method you should also check the grid cells that are two movements away, and if a cell with a prey animal is found two cells away, then the predator animal should move towards this prey animal (i.e move to a grid cell between its current position and the position of the prey animal).
Powered by