CSci 150: Foundations of computer science I
Home Syllabus Assignments Tests

Assignment 14: Ghost pirates

Due: 8:00am, Thursday, April 15. Value: 30 pts. Submit to Sauron.

The attached program creates a serene scene of a moonlit night with three ships, each ship containing three pirate ghosts wearing top hats. Note the sublime realism.

We'll modify this program so that the ships glide across the sea. When the user clicks the head of a pirate, it will turn green; and when the user manages to click all three pirates on the ship, the ship will sink. Thus, we'll end up with what one might call a game: Sink the ships with the fewest clicks.

Each ship is represented as a hierarchy of lists, represented by the below tree diagram. In the top-level list is a Polygon object corresponding to the ship's hull, a list containing shapes constituting the ship's sail, and two lists containing shapes constituting the two pirates on deck. Within the list for the sail is also a list containing shapes constituting a pirate standing on its yard.

Note, though, that nothing in the code you write should be specific to the diagram. For example, if I decided to put each pirate's head as part of the list currently representing the hat, then the program should still work properly.

Part 1: move_all

First complete the move_all function. This function is called repeatedly by the code I provide; but since the move_all function as provided doesn't do anything, the ships stay stationary. The move_all function is given three parameters: a hierarchy of lists holding shapes, a distance to move in the x direction, and a distance to move in a y direction. The function is to descend through all the shapes in the hierarchy and invoke each shape's move method to tell it to move as directed by the second and third parameters.

You should accomplish this using recursion: You will want a for loop to iterate through each element of the parameter list. Each time you find a list nested within the parameter list, you should recursively call your move_all function with that sub-list as a parameter, so that all shapes in that subhierarchy are moved. To help you identify when an element is itself a list, the provided code includes a function named is_list which returns True if its parameter is a list.

Build and test this function before proceeding. Once complete, you should find that each of the ships rolls quietly across the sea.

Part 2: check_hit

Now complete the check_hit function, which takes two parameters: The first is a hierarchy of shapes, while the second is a Point object representing a location where the user has clicked. The function's job is to go through each circle in the hierarchy, and for any circles containing the parameter point, the function should call mark_as_hit. (The mark_as_hit function will color the circle green, and the program is arranged so that after all three pirates' heads turn green, the ship will sink.)

Again, you should accomplish this using recursion. To help, I have provided two functions, is_circle_containing and mark_as_hit. The is_circle_containing function takes two parameters — an object which might be a circle and a point — and returns True if the first parameter is a circle and the point lies within it. The mark_as_hit function takes a single shape as a parameter, colors it green, and remembers that it has been hit so that later the code I provide will know when to sink the ship.