Project 2: Ants Vs. SomeBees
The bees are coming!
Create a better soldier
With inherit-ants.
Introduction
Introduction
Important submission note: For full credit,
- Submit with Phases 1 & 2 complete by 4/18/21 (worth 4 pts).
- Submit with Phases 3 & 4 complete by 4/29/21
You will get two extra credit points for submitting the entire project by 4/27/21.
You may work with one other partner for the entire project.
In this project, you will create a tower defense game called Ants Vs. SomeBees. As the ant queen, you populate your colony with the bravest ants you can muster. Your ants must protect their queen from the evil bees that invade your territory. Irritate the bees enough by throwing leaves at them, and they will be vanquished. Fail to pester the airborne intruders adequately, and your queen will succumb to the bees' wrath. This game is inspired by PopCap Games' Plants Vs. Zombies.
This project combines functional and object-oriented programming paradigms, focusing on the material from Chapter 2.5 of Composing Programs. The project also involves understanding, extending, and testing a large program.
Download starter files
The ants.zip archive contains several files, but all of your
changes will be made to ants.py
.
ants.py
: The game logic of Ants Vs. SomeBeesants_plans.py
: Some additional logic for game setupants_gui.py
: The original GUI for Ants Vs. SomeBeesgui.py
: A new GUI for Ants Vs. SomeBeesgraphics.py
: Utilities for displaying simple two-dimensional animationsstate.py
: Abstraction for gamestate forgui.py
utils.py
: Some functions to facilitate the game interfaceucb.py
: Utility functions for CS 88assets
: A directory of images and files used bygui.py
img
: A directory of images used byants_gui.py
ok
: The autograderproj2.ok
: Theok
configuration filetests
: A directory of tests used byok
mytests.rst
: A space for you to add your custom tests; see section on adding your own tests
You can obtain all the files needed for this project by downloading this zip archive.
Logistics
This is a project. You may work with one other partner. You should not share your code with students who are not your partner or copy from anyone else's solutions.
In the end, you will submit one project for both partners. The project is worth 60 points.
The project is worth 60 points. 54 points are assigned for correctness, 4 point for submitting Phases 1-2 by the checkpoint date, and 2 points for the overall composition.
You will turn in the following files:
ants.py
mytests.rst
(ungraded)
You do not need to modify or turn in any other files to complete the project. To submit the project, run the following command:
python3 ok --submit
You will be able to view your submissions on the Ok dashboard.
For the functions that we ask you to complete, there may be some initial code that we provide. If you would rather not use that code, feel free to delete it and start from scratch. You may also add new function definitions as you see fit.
However, please do not modify any other functions. Doing so may result in your code failing our autograder tests. Also, please do not change any function signatures (names, argument order, or number of arguments).
Testing
Throughout this project, you should be testing the correctness of your code. It is good practice to test often, so that it is easy to isolate any problems.
We have provided an autograder called ok
to help you with
testing your code and tracking your progress.
The primary purpose of ok
is to test your implementations, but there
is a catch. At first, the test cases are locked. To unlock tests,
run the following command from your terminal:
python3 ok -u
This command will start an interactive prompt that looks like:
===================================================================== Assignment: Ants Vs. SomeBees OK, version ... ===================================================================== ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Unlocking tests At each "? ", type what you would expect the output to be. Type exit() to quit --------------------------------------------------------------------- Question 0 > Suite 1 > Case 1 (cases remaining: 1) >>> Code here ?
At the ?
, you can type what you expect the output to be.
If you are correct, then this test case will be available the next time
you run the autograder.
The idea is to understand conceptually what your program should do first, before you start writing any code.
Once you have unlocked some tests and written some code, you can check the correctness of your program using the tests that you have unlocked:
python3 ok
Most of the time, you will want to focus on a particular question.
Use the -q
option as directed in the problems below.
The tests
folder is used to store autograder tests, so make sure
not to modify it. You may lose all your unlocking progress if you
do. If you need to get a fresh copy, you can download the
zip archive and copy it over, but you
will need to start unlocking from scratch.
If you are ever stuck on a problem, you should add print statements to your code to help debug.
Use print("DEBUG:", variable)
to see the value of variable and still have your tests pass.
The Game
A game of Ants Vs. SomeBees consists of a series of turns. In each turn, new bees may enter the ant colony. Then, new ants are placed to defend their colony. Finally, all insects (ants, then bees) take individual actions. Bees either try to move toward the end of the tunnel or sting ants in their way. Ants perform a different action depending on their type, such as collecting more food, or throwing leaves at the bees. The game ends either when a bee reaches the ant queen (you lose), or the entire bee fleet has been vanquished (you win).
Core concepts
The Colony. This is where the game takes place. The colony consists of several places that are chained together to form a tunnel where bees can travel through. The colony has some quantity of food that can be expended to deploy ant troops.
Places. A place links to another place to form a tunnel. The player can place a single ant into each place. However, there can be many bees in a single place.
The Hive. This is the place where bees originate. Bees exit the beehive to enter the ant colony.
Ants. Ants are the usable troops in the game that the player places into
the colony. Each type of ant takes a different action and requires a different
amount of food to place. The two most basic ant types are the HarvesterAnt
,
which adds one food to the colony during each turn, and the ThrowerAnt
, which
throws a leaf at a bee each turn. You will be implementing many more.
Bees. Bees are the antagonistic troops in the game that the player must defend the colony from. Each turn, a bee either advances to the next place in the tunnel if no ant is in its way, or it stings the ant in its way. Bees win when at least one bee reaches the end of a tunnel.
Queen Ant: There is one queen ant in the whole colony. She is able to attack bees but she also has a special ability of fortifying the other ant troops. Bees can also win if they destroy the queen ant.
Core classes
The concepts described above each have a corresponding class that encapsulates the logic for that concept. Here is a summary of the main classes involved in this game:
AntColony
: Represents the colony and some state information about the game, including how much food is available, how much time has elapsed, where theQueenAnt
resides, and all thePlace
s in the game.Place
: Represents a single place that holds insects. At most oneAnt
can be in a single place, but there can be manyBee
s.Place
objects have anexit
and anentrance
which are also places. Bees travel through a tunnel by moving to aPlace
'sexit
.Hive
: Represents the place whereBee
s start out.Insect
: A superclass forAnt
andBee
. All insects have anarmor
attribute, their remaining health, and aplace
attribute, thePlace
where they are currently located. Each turn, every activeInsect
in the game performs itsaction
.Ant
: Represents ants. EachAnt
subclass has special attributes or a specialaction
that distinguish it from otherAnt
types. For example, aHarvesterAnt
gets food for the colony and aThrowerAnt
attacksBee
s. Each ant type also has afood_cost
attribute that indicates how much it costs to deploy one unit of that type of ant.Bee
: Represents bees. Each turn, a bee either moves to theexit
of its currentPlace
if no ant blocks its path, or stings an ant that blocks its path.
Game Layout
Below is a visualization of an AntColony. As you work through the unlocking tests and problems, we recommend drawing out similar diagrams to help your understanding.
Playing the game
The game can be run in two modes: as a text-based game or using a graphical user interface (GUI). The game logic is the same in either case, but the GUI enforces a turn time limit that makes playing the game more exciting. The text-based interface is provided for debugging and development.
The files are separated according to these two modes. ants.py
knows
nothing of graphics or turn time limits.
To start a text-based game, run
python3 ants.py
To start a graphical game, run
python3 gui.py
To start an older version of the graphics, run
python3 ants_gui.py
When you start the graphical version, a new browser window should appear. In the
starter implementation, you have unlimited food and your ants can only throw leaves
at bees in their current Place
. Try playing the game anyway! You'll need to
place a lot of ThrowerAnt
s (the second type) in order to keep the bees from
reaching your queen.
The game has several options that you will use throughout the project,
which you can view with python3 ants.py --help
.
usage: ants.py [-h] [-d DIFFICULTY] [-w] [--food FOOD]
Play Ants vs. SomeBees
optional arguments:
-h, --help show this help message and exit
-d DIFFICULTY sets difficulty of game (test/easy/medium/hard/extra-hard)
-w, --water loads a full layout with water
--food FOOD number of food to start with when testing
Your own test cases
Adding your own tests is entirely optional; you will not lose points if you submit an empty
mytests.rst
file.
We highly recommend that you add your own tests as you work through the project. It's a really helpful way to speed up the debugging process and improve your understanding of the code.
The course staff has also made an instructional video summarizing the information below.
Adding tests
Adding tests is easy. Directly edit the mytests.rst
file included with the
Ants project. We provide a sample structure to start from, but the test format
is actually quite flexible. Here are some simple rules to follow:
- Follow standard Python doctest format. This is what we mostly use for the Ok tests, so feel free to use those as examples.
- For the most part, you may use whitespace as you'd like, but we recommend keeping it organized for your own sake.
- Generally, smaller, simpler tests will be more useful than larger, more complex tests.
Ok
test case, a good first step would be to
break it up into small parts and test them out yourself in mytests.rst
.
Running tests
To run all your tests in mytests.rst
with verbose results:
python3 ok -t -v
If you put your tests in a different file or split your tests up into multiple files:
python3 ok -t your_new_filename.rst
To run just the tests from suite 1 case 1 in mytests.rst
:
python3 ok -t --suite 1 --case 1
You might have noticed that there's a "test coverage" percentage for your tests (note that coverage statistics are only returned when running all tests). This is a measure of your test's code coverage. If you're interested, you can find more information in our reference guide.
Phase 1: Basic gameplay
Important submission note: For full credit,
- Submit with Phases 1-2 complete by 4/18/21 (worth 4 pt).
In the first phase you will complete the implementation that will allow for
basic gameplay with the two basic Ant
s: the HarvesterAnt
and the
ThrowerAnt
.
Problem 0: Intro (0 pt)
Answer the following questions with your partner after you have read the
entire ants.py
file. If you cannot answer these questions, read the file
again, consult the core concepts/classes sections above, or ask a question in
the Question 0 thread on Piazza.
- What is the significance of an insect's
armor
attribute? Does this value change? If so, how? - What are all of the attributes of the
Insect
class? - Is the
armor
attribute of theAnt
class an instance attribute or class attribute? Why? - Is the
damage
attribute of anAnt
subclass (such as ThrowerAnt) an instance attribute or class attribute? Why? - Which class do both
Ant
andBee
inherit from? - What do instances of
Ant
and instances ofBee
have in common? - How many insects can be in a single
Place
at any given time (until Problem 9 is complete)? - What does a
Bee
do during its turn? - When does the game end?
You can test your understanding by running
python3 ok -q 00 -u
Problem 1: Food Cost (3 pt)
Before writing any code, read the instructions and test your understanding of the problem:
python3 ok -q 01 -u
First, add food costs and implement harvesters. Currently, there is no cost
for deploying any type of Ant
, and so there is no challenge to the
game. You'll notice that Ant
starts out with a base food_cost
of
zero. Override this value in each of the subclasses listed below with
the correct costs.
Class | Food Cost | Armor |
HarvesterAnt |
2 | 1 |
ThrowerAnt |
3 | 1 |
Now that deploying Ant
s cost food, we need to be able gather more food!
To fix this issue, implement the HarvesterAnt
class. A HarvesterAnt
is a
type of Ant
that adds one food to the colony.food
total as its action
.
After writing code, test your implementation:
python3 ok -q 01
Try playing the game by running python3 gui.py
. Once you have placed a
HarvesterAnt
, you should accumulate food each turn. You can also place
ThrowerAnt
s, but you'll see that they can only attack bees that are in their
Place
, so it'll be a little difficult to win.
Problem 2: Place
(6 pt)
Before writing any code, read the instructions and test your understanding of the problem:
python3 ok -q 02 -u
Complete the Place
constructor by adding code that tracks entrances. Right
now, a Place
keeps track only of its exit
. We would like a Place
to keep
track of its entrance as well. A Place
needs to track only one entrance
.
Tracking entrances will be useful when an Ant
needs to see what Bee
s are in
front of it in the tunnel.
However, simply passing an entrance to a Place
constructor will be
problematic; we would need to have both the exit and the entrance before
creating a Place
! (It's a chicken or the
egg
problem.) To get around this problem, we will keep track of entrances in the
following way instead. The Place
constructor should specify that:
- A newly created
Place
always starts with itsentrance
asNone
. - If the
Place
has anexit
, then theexit
'sentrance
is set to thatPlace
.
Hint: Remember that when inside the definition of an
__init__
method, the nameself
is bound to the newly created object.
Hint: Try drawing out two
Place
s next to each other if things get confusing. In the GUI, a place'sentrance
is to its right while the exit is to its left.
After writing code, test your implementation:
python3 ok -q 02
Problem 3: ThrowerAnt
(5 pt)
Before writing any code, read the instructions and test your understanding of the problem:
python3 ok -q 03 -u
In order for a ThrowerAnt
to attack, it must know which bee it should hit.
The provided implementation of the nearest_bee
method in the ThrowerAnt
class only allows them to hit bees in the same Place
. Your job is to fix it
so that a ThrowerAnt
will throw_at
the nearest bee in front of it that is
not still in the Hive
.
The nearest_bee
method returns a random Bee
from the nearest place that
contains bees. Places are inspected in order by following their entrance
attributes.
- Start from the current
Place
of theThrowerAnt
. - For each place, return a random bee if there is any, or consider the
next place that is stored as the current place's
entrance
. - If there is no bee to attack, return
None
.
Hint: The
random_or_none
function provided inants.py
returns a random element of a sequence orNone
if the sequence is empty.Hint: Having trouble visualizing the test cases? Try drawing them out on paper! The example diagram provided in Game Layout shows the first test case for this problem.
After writing code, test your implementation:
python3 ok -q 03
After implementing nearest_bee
, a ThrowerAnt
should be able to throw_at
a
Bee
in front of it that is not still in the Hive
. Make sure that your ants
do the right thing! To start a game with ten food (for easy testing):
python3 gui.py --food 10
Phase 2: Ants!
Now that you've implemented basic gameplay with two types of Ant
s, let's
add some flavor to the ways ants can attack bees. In this phase, you'll be
implementing several different Ant
s with different offensive capabilities.
After you implement each Ant
subclass in this section, you'll need to set its
implemented
attribute to True
so that that type of ant will show up in the
GUI. Feel free to try out the game with each new ant to test the functionality!
With your Phase 2 ants, try python3 gui.py -d easy
to play against a
full swarm of bees in a multi-tunnel layout and try -d normal
, -d hard
, or
-d extra-hard
if you want a real challenge! If the bees are too numerous to
vanquish, you might need to create some new ants.
Problem 4: Long and Short Throwers (4 pt)
Before writing any code, read the instructions and test your understanding of the problem:
python3 ok -q 04 -u
The ThrowerAnt
is a great offensive unit, but it'd be nice to have a cheaper
unit that can throw. Implement two subclasses of ThrowerAnt
that are less
costly but have constraints on the distance they can throw:
- The
LongThrower
can onlythrow_at
aBee
that is found after following at least 5entrance
transitions. It cannot hitBee
s that are in the samePlace
as it or the first 4Place
s in front of it. If there are twoBees
, one too close to theLongThrower
and the other within its range, theLongThrower
should throw past the closerBee
, instead targeting the farther one, which is within its range. - The
ShortThrower
can onlythrow_at
aBee
that is found after following at most 3entrance
transitions. It cannot throw at any ants further than 3Place
s in front of it.
Neither of these specialized throwers can throw_at
a Bee
that is exactly 4
Place
s away. Placing a single one of these (and no other ants) should never
win a default game.
Class | Food Cost | Armor |
ShortThrower |
2 | 1 |
LongThrower |
2 | 1 |
A good way to approach the implementation to ShortThrower
and LongThrower
is to have it inherit the nearest_bee
method from the base ThrowerAnt
class. The logic of choosing which bee a thrower ant will attack is essentially
the same, except the ShortThrower
and LongThrower
ants have maximum and
minimum ranges, respectively.
To implement these behaviors, you may need to modify the nearest_bee
method
to reference min_range
and max_range
attributes, and only return a bee that
is in range.
The original ThrowerAnt
has no minimum or maximum range, so make sure that
its min_range
and max_range
attributes should reflect that. Then,
implement the subclasses LongThrower
and ShortThrower
with appropriately
constrained ranges and correct food costs.
Hint:
float('inf')
returns an infinite positive value represented as a float that can be compared with other numbers.
Don't forget to set the implemented
class attribute of LongThrower
and
ShortThrower
to True
.
Note! Please make sure your variables are called
max_range
andmin_range
rather thanmaximum_range
andminimum_range
or something. The tests directly reference this variable name.
After writing code, test your implementation (rerun the tests for 03 to make sure they still work):
python3 ok -q 03
python3 ok -q 04
👩🏽💻👨🏿💻 Pair programming? Remember to alternate between driver and navigator roles! The driver controls the keyboard; the navigator watches, asks questions, and suggests ideas.
Problem 5: FireAnt
(6 pt)
Before writing any code, read the instructions and test your understanding of the problem:
python3 ok -q 05 -u
Implement the FireAnt
, which does damage when it receives damage. Specifically,
if it is damaged by x
armor units, and does not die, it does a damage of
x
to all bees in its place (reflected damage).
If it dies, it does an additional amount of damage, which is specified by its damage
attribute (by default 3).
To implement this, we have to override the FireAnt
's
reduce_armor
method. Normally, Insect.reduce_armor
will decrement the
insect's armor
by the given amount
and remove the insect from its place if
armor
reaches zero or lower. However, FireAnt
also does damage to all the
bees in its place when it receives damage, with a special bonus when its damage
drops to 0, before being removed from its place
.
Class | Food Cost | Armor |
FireAnt |
5 | 3 |
Hint: To damage a
Bee
, call thereduce_armor
method inherited fromInsect
.Hint: Damaging a bee may cause it to be removed from its place. If you iterate over a list, but change the contents of that list at the same time, you may not visit all the elements. This can be prevented by making a copy of the list. You can either use a list slice, or use the built-in
list
function.>>> lst = [1,2,3,4] >>> lst[:] [1, 2, 3, 4] >>> list(lst) [1, 2, 3, 4] >>> lst[:] is not lst and list(lst) is not lst True
Once you've finished implementing the FireAnt
, give it a class attribute
implemented
with the value True
.
Note, even though you are overriding the
Insect.reduce_armor
function, you can still use it in your implementation by calling it directly (rather than viaself
). Note that this is not recursion (why?)
After writing code, test your implementation:
python3 ok -q 05
You can also test your program by playing a game or two! A FireAnt
should
destroy all co-located Bees when it is stung. To start a game with ten food
(for easy testing):
python3 gui.py --food 10
Problem 6: HungryAnt
(5 pt)
Before writing any code, read the instructions and test your understanding of the problem:
python3 ok -q 06 -u
Implement the HungryAnt
, which will select a random Bee
from its place
and eat it whole. After eating a Bee
, it must spend 3 turns digesting before
eating again. If there is no bee available to eat, it will do nothing.
Class | Food Cost | Armor |
HungryAnt |
4 | 1 |
Give HungryAnt
a time_to_digest
class attribute that holds the number of
turns that it takes a HungryAnt
to digest (default to 3). Also, give each
HungryAnt
an instance attribute digesting
that counts the number of turns
it has left to digest (default is 0, since it hasn't eaten anything at the
beginning).
Implement the action
method of the HungryAnt
to check if it's digesting; if
so, decrement its digesting
counter. Otherwise, eat a random Bee
in its
place
by reducing the Bee
's armor to 0 and restart the digesting
timer.
After writing code, test your implementation:
python3 ok -q 06
Problem 7: NinjaAnt
(4 pt)
Before writing any code, read the instructions and test your understanding of the problem:
python3 ok -q 07 -u
Implement the NinjaAnt
, which damages all Bee
s that pass by, but can never
be stung.
Class | Food Cost | Armor |
NinjaAnt |
5 | 1 |
A NinjaAnt
does not block the path of a Bee
that flies by. To implement
this behavior, first modify the Ant
class to include a new class attribute
blocks_path
that is True
by default. Set the value of blocks_path
to
False
in the NinjaAnt
class.
Second, modify the Bee
's method blocked
to return False
if either
there is no Ant
in the Bee
's place
or if there is an Ant
, but
its blocks_path
attribute is False
. Now Bee
s will just fly past
NinjaAnt
s.
Finally, we want to make the NinjaAnt
damage all Bee
s that fly past.
Implement the action
method in NinjaAnt
to reduce the armor of all Bee
s
in the same place
as the NinjaAnt
by its damage
attribute. Similar to
the FireAnt
, you must iterate over a list of bees that may change.
Hint: Having trouble visualizing the test cases? Try drawing them out on paper! See the example in Game Layout for help.
After writing code, test your implementation:
python3 ok -q 07
For a challenge, try to win a game using only HarvesterAnt
and NinjaAnt
.
Submission Reminder!
Phases 1 and 2 are due by 4/18/21 for 4 points.
Make sure to submit by the earlier deadline using the following command
python3 ok --submit
You can check to ensure that you have completed Phase 1-2's problems by running
python3 ok --score
Congratulations! You have finished Phases 1 and 2 of this project!
Phase 3: More Ants!
Important submission note: For full credit,
- Submit with Phases 3-4 complete by 4/29/21.
You will get 2 extra credit points for submitting the entire project by 4/27/21
We now have some great offensive troops to help vanquish the bees, but let's make sure we're also keeping our defensive efforts up. In this phase you will implement ants that have special defensive capabilities such as increased armor and the ability to protect other ants.
👩🏽💻👨🏿💻 Pair programming? Remember to alternate between driver and navigator roles! The driver controls the keyboard; the navigator watches, asks questions, and suggests ideas.
Problem 8: WallAnt
(4 pt)
Before writing any code, read the instructions and test your understanding of the problem:
python3 ok -q 08 -u
We are going to add some protection to our glorious AntColony
by implementing
the WallAnt
, which is an ant that does nothing each turn. A WallAnt
is
useful because it has a large armor
value.
Class | Food Cost | Armor |
WallAnt |
4 | 4 |
Unlike with previous ants, we have not provided you with a class header.
Implement the WallAnt
class from scratch. Give it a class attribute name
with the value 'Wall'
(so that the graphics work) and a class attribute
implemented
with the value True
(so that you can use it in a game).
After writing code, test your implementation:
python3 ok -q 08
Problem 9: Bodyguard Ant
(8 pt)
Before writing any code, read the instructions and test your understanding of the problem:
python3 ok -q 09 -u
Right now, our ants are quite frail. We'd like to provide a way to help them
last longer against the onslaught of the bees. Enter the BodyguardAnt
.
Class | Food Cost | Armor |
BodyguardAnt |
4 | 2 |
A BodyguardAnt
differs from a normal ant because it is a container; it can
contain another ant and protect it, all in one Place
. When a Bee
stings the
ant in a Place
where one ant contains another, only the container is
damaged. The ant inside the container can still perform its original action.
If the container perishes, the contained ant still remains in the place (and
can then be damaged).
Each BodyguardAnt
has an instance attribute contained_ant
that stores the ant it
contains. It initially starts off as None
, to indicate that no ant is being
protected. Implement the contain_ant
method so that it sets the bodyguard's
contained_ant
instance attribute to the passed in ant
argument. Also implement the
BodyguardAnt
's action
method to perform its contained_ant
's action if it is currently
containing an ant.
In addition, you will need to make the following modifications throughout your program so that a container and its contained ant can both occupy a place at the same time (a maximum of two ants per place), but only if exactly one is a container:
- Add an
Ant.is_container
class attribute that indicates whether a subclass ofAnt
is a container. For allAnt
instances, except forBodyguardAnt
instances,is_container
should beFalse
. TheBodyguardAnt.is_container
attribute should beTrue
. Implement the method
BodyguardAnt.can_contain
which takes another
ant as an argument and returnsTrue
if:- This ant does not already contain another ant.
- The other ant is not a container.
Currently
Ant.can_contain
returns False by default; it needs to be overridden inBodyguardAnt
Modify
Place.add_insect
to allow a container and a non-container ant to occupy the same place according to the following rules:- If the
ant
currently occupying aPlace
can contain theinsect
(anAnt
) passed toadd_insect
, then it does. - If the
insect
(anAnt
) passed toadd_insect
can contain theant
currently occupying aPlace
, then it does. Also, set thePlace
'sant
to be the container insect. - If neither
Ant
can contain the other, raise the sameAssertionError
as before (the one already present in the starter code).
- If the
After writing code, test your implementation:
python3 ok -q 09
Problem 10: TankAnt
(3 pt)
Before writing any code, read the instructions and test your understanding of the problem:
python3 ok -q 10 -u
The BodyguardAnt
provides great defense, but they say the best defense is a
good offense. The TankAnt
is a container that protects an ant in its place
and also deals 1 damage to all bees in its place each turn.
Class | Food Cost | Armor |
TankAnt |
6 | 2 |
You should not need to modify any code outside of the TankAnt
class. If you
find yourself needing to make changes elsewhere, look for a way to write your
code for the previous question such that it applies not just to BodyguardAnt
and TankAnt
objects, but to container ants in general.
After writing code, test your implementation:
python3 ok -q 10
👩🏽💻👨🏿💻 Pair programming? Remember to alternate between driver and navigator roles! The driver controls the keyboard; the navigator watches, asks questions, and suggests ideas.
Phase 4: Water and Might
In the final phase, you're going to add one last kick to the game by introducing a new type of place and new ants that are able to occupy this place. One of these ants is the most important ant of them all: the queen of the colony.
Problem 11: Water Place (3 pt)
Before writing any code, read the instructions and test your understanding of the problem:
python3 ok -q 11 -u
Let's add water to the colony! Currently there are only two types of places, the
Hive
and a basic Place
. To make things more interesting, we're going to
create a new type of Place
called Water
.
Only an ant that is watersafe can be deployed to a Water
place. In order
to determine whether an Insect
is watersafe, add a new attribute to the
Insect
class named is_watersafe
that is False
by default. Since bees can fly,
make their is_watersafe
attribute True
,
overriding the default.
Now, implement the add_insect
method for Water
. First, add the insect to
the place regardless of whether it is watersafe. Then, if the insect is not
watersafe, reduce the insect's armor to 0. Do not repeat code from elsewhere
in the program. Instead, use methods that have already been defined.
After writing code, test your implementation:
python3 ok -q 11
Once you've finished this problem, play a game that includes water. To access
the wet_layout
which includes water, add the --water
option (or -w
for
short) when you start the game.
python3 gui.py --water
Problem 12 ScubaThrower
(3 pt)
Before writing any code, read the instructions and test your understanding of the problem:
python3 ok -q 12 -u
Currently there are no ants that can be placed on Water
. Implement the
ScubaThrower
, which is a subclass of ThrowerAnt
that is more costly and
watersafe, but otherwise identical to its base class. A ScubaThrower
should
not lose its armor when placed in Water
.
Class | Food Cost | Armor |
ScubaThrower |
6 | 1 |
We have not provided you with a class header. Implement the ScubaThrower
class from scratch. Give it a class attribute name
with the value 'Scuba'
(so that the graphics work) and remember to set the class attribute
implemented
with the value True
(so that you can use it in a game).
After writing code, test your implementation:
python3 ok -q 12
Extra Credit
Be warned that this extra credit problem can be very time-consuming!
During Office Hours and Project Parties, the staff will prioritize helping students with required questions. We will not be offering help with this question unless there are no other questions.
Queen Ant (2 pt)
Before writing any code, read the instructions and test your understanding of the problem:
python3 ok -q ec1 -u
Finally, implement the QueenAnt
. The queen is a waterproof ScubaThrower
that inspires her fellow ants through her bravery. The QueenAnt
doubles the
damage of all the ants behind her each time she performs an action. Once an
ant's damage has been doubled, it is not doubled again for subsequent turns.
Note that the reflected damage of a fire ant should not be doubled, only the extra damage it deals when its armor is reduced to 0
Class | Food Cost | Armor |
QueenAnt |
7 | 1 |
However, with great power comes great responsibility. The QueenAnt
is
governed by three special rules:
- If the queen ever has its armor reduced to 0, the bees win. The bees also
still win if any bee reaches the end of a tunnel. You can call
bees_win()
to signal to the simulator that the game is over. - There can be only one true queen. Any queen instantiated beyond the first one is an impostor, and should have its armor reduced to 0 upon taking its first action, without doubling any ant's damage or throwing anything. If an impostor dies, the game should still continue as normal.
- The true (first) queen cannot be removed. Attempts to remove the queen
should have no effect (but should not cause an error). You will need to
modify the
remove_insect
method ofPlace
to enforce this condition.
Some hints:
- All instances of the same class share the same class attributes. How can you use this information to tell whether a QueenAnt instance is the true QueenAnt?
- You can find each
Place
in a tunnel behind theQueenAnt
by starting at the ant'splace.exit
and then repeatedly following itsexit
. Theexit
of aPlace
at the end of a tunnel isNone
. - To avoid doubling an ant's damage twice, keep track of all the ants who
have been buffed in a way that persists across calls to
QueenAnt.action
. - When buffing the ants' damage, keep in mind that there can be more than one ant in one place!
- Assume there can be only one game running at a time (so there can never be two true queen ants).
After writing code, test your implementation:
python3 ok -q ec1
Submission
Again, you will be turning in the following files:
ants.py
mytests.rst
(ungraded)
Please run the following command to submit the project:
python3 ok --submit
You can check to ensure that you have completed all the problems by running
python3 ok --score
Then, go to your OK dashboard and verify that your submission
was successful. You should see something like this:
You can click on the name of the assignment for more information about your submission. If you're experiencing issues with the autograder, remember that you can submit manually online.
Conclusion
You are now done with the project! If you haven't yet, you should try playing the game! There are two GUIs that you can use. The first is a new browser GUI that has fancy graphics and animations. The command to run it is:
python3 gui.py [-h] [-d DIFFICULTY] [-w] [--food FOOD]
The second is an older, but tried-and-true interface that we have been using over the past few years. The command to run it is:
python3 ants_gui.py [-h] [-d DIFFICULTY] [-w] [--food FOOD]
Acknowledgments: Tom Magrino and Eric Tzeng developed this project with John DeNero. Jessica Wan contributed the original artwork. Joy Jeng and Mark Miyashita invented the queen ant. Many others have contributed to the project as well!
Colin Schoen developed the new browser GUI. The beautiful new artwork was drawn by the efforts of Alana Tran, Andrew Huang, Emilee Chen, Jessie Salas, Jingyi Li, Katherine Xu, Meena Vempaty, Michelle Chang, and Ryan Davis.