Homework 6
CS1210 Computer Science 1 - Fall 2021
Due Thursday, October 28, by 8:00pm
6 points

1. Create a Box class, representing rectangular 3D boxes. The boxes can be any size and can be located anywhere in 3D space, but in this simple version their orientations are fixed so that their edges are always aligned with/parallel to coordinate system axes. You class must implement all the methods below:
• __init__(self, centerX = 0.0, centerY = 0.0, centerZ = 0.0, width = 1.0, height = 1.0, depth = 1.0)
• setCenter(self, x, y, z)
• setWidth(self, width)
• setHeight(self, height)
• setDepth(self, depth)
• volume(self)
• surfaceArea(self)
• touches(self, otherBox). box1.touches(box2) should return True if the two 3D boxes touch/intersect at all, even they just touch exactly at their edges or corners. (Think of boxes as filled/solid objects so that if a box fully contains another, they are also considered to be touching.)
• contains(self, otherBox). box1.contains(box2) should return True if no point of box 2 is outside or even on the boundary of box2
• __repr__(self)
Note that "width" is a box's extent along the x dimension, while "height" and "depth" are the y and z extents, respectively.
Note: think carefully about the touches and contains methods. It is easy to get these wrong. I recommend (before you start coding) sketching some pictures to help you analyze the possibilities.

Use of the class in a Python shell might look like this:
```   >>> box1 = Box(10.0, 5.0, 0.0, 2.0, 1.0, 1.0)
>>> box1
< 2-by-1-by-1 3D box with center at (10.0, 5.0, 0.0) >
>>> box2 = Box(0, 0, 0, 3.5, 2.5, 1.0)
>>> box1.volume()
2.0
>>> box2.surfaceArea()
29.5
>>> box1.touches(box2)
False
>>> box1.setCenter(2.75, 0.0, 0.0)
>>> box1.touches(box2)
True
>>> box1.setCenter(2.76, 0.0, 0.0)
>>> box1.touches(box2)
False
>>> box1.setCenter(2.75, 1.75, 1.0)
>>> box1.touches(box2)
True
>>> box1.setCenter(0.0, 0.0, 0.0)
>>> box1.touches(box2)
True
>>> box1.setWidth(50.0)
>>> box1.touches(box2)
True
>>> box1.setDepth(50.0)
>>> box2.touches(box1)
True
>>> box3 = Box(0, 0, 0)
>>> box3.contains(box3)
False
>>> box4 = Box(0.5, 0.0, 0.0, 2.0, 3.0, 4.0)
>>> box4.contains(box3)
False
>>> box4.setWidth(2.1)
>>> box4.contains(box3)
True
```
2. Create a NimGame class that implements a two-player Nim-style game (see http://en.wikipedia.org/wiki/Nim for details of several variants). The game starts with one or more "heaps" of one or more items (we'll call them balls). Players take turns removing one or more balls from any heap. The player who removes the last item wins . You can play an interactive on-line version of the game here: here. Note that the on-line version is slightly different in that the player who removes the last item loses.

For this assignment, we'll keep things simple. Assume there's one human player playing against the computer and that the human always goes first.
To create the NimGame class, implement at least three methods:
1. an __init__ method, with one argument, a list specifying the number of balls in each heap initially
2. a __repr__ method that will print a nice human readable representation of the game state.
3. a remove method, with two arguments specifying a heap (by number, starting with 0) and how many balls the human player wishes to remove from that heap. This method should check that the specified heap and specified number of balls are valid. If the input is not valid, print an appropriate message but do not modify the game state. If the input is valid, remove the balls, and check whether or not the the player has won and the game is finished. If the game is not finished, the method should then automatically select a (legal) number of balls for the computer to remove from some heap, either randomly or through a "smart" strategy, and it should update the game state accordingly, including checking whether the computer has won and the game is finished. When the game is finished (whether won by the human or the computer), print an appropriate message. Note: you might want to add an additional internally-used method, gameOver, that returns True or False based on the current game state.
A sample use of the class might produce these results:
```>>> game = NimGame([2,3,4])
Nim game initialized with 3 heaps.
>>> game
< Nim game with 3 heaps.
Heap 0: 2 balls
Heap 1: 3 balls
Heap 2: 4 balls
>
>>> game.remove(0, 2)
You took 2 balls from heap 0.
Computer took 1 balls from heap 1
>>> game.remove(2,5)
You can't take that many balls from heap 2. Try again.
>>> game
< Nim game with 3 heaps.
Heap 0: 0 balls
Heap 1: 2 balls
Heap 2: 4 balls
>
>>> game.remove(1,2)
You took 2 balls from heap 1.
Computer took 4 balls from heap 2
Computer wins!

3. Add one additional subclass of Animal, including at least one new method, to
the code from animals.py.  Furthermore, modify testAnimal to create
two instances of your new class and include those in the loop.

Submit to ICON exactly one Python file.

```