HW12: Lunar Lander I

25 points; due Sat 5/17 @ 9am.

Goals

The goal of this assignment is to use object-oriented design techniques to create a lunar lander simulation game.

Setup and Requirements

This is an individual assignment.

Create a directory named lander that will contain your code for this project. All your work will be done in this directory.

Download these two files and put them in your lander directory:

This assignment and the next one will involve building a game that simulates a lunar landing craft — you may have played this game before, if you're into retro gaming. We'll implement a simple version of it. In our version, you are in control of a lunar lander that is descending toward the surface of the moon. Gravity steadily accelerates your craft downward. You have a single control: A button labeled “thrust”. Applying thrust slows your ship down (that is, it accelerates you upward). Your goal is to get your lander to be moving at a slow enough speed that it doesn't crash upon impact. However, you have a limited amount of fuel, and when that runs out, you can no longer apply thrust.

In addition to looking at the code that we've created in class and reading in the book, you may find it relevant to read through my tutorial on functions, classes, and methods a couple times.

Part 1: The Lunar Lander Class

Your task is to create a class that represents a lunar lander, containing all relevant information about a spacecraft attempting to safely land on the moon.

Create a file called lander.py. In that file, create a class named LunarLander. This class will represent the ship itself. It should keep track of the following information:

The LunarLander class must have the following methods, with precisely the signatures given:

A reflection on object-oriented design: note that the LunarLander class is responsible only for its own behavior. It doesn't interact with the user (either by taking input or by printing anything out), and it does all the work to assure that the user can rely on its interface — the user doesn't need to understand the internal details in order to use the methods successfully, just based on their interfaces.

Remember that the docstring is part of the interface. Every function (including class methods) and class that you write should have a docstring.

Testing Your Class

Write a main function in lander.py that is called only when this file is invoked as a Python program directly from the command line. In your main function, call another function, testLander() (your main function's body should be only one line long!). In this function, test your LunarLander class, similarly to how we've done so with our the classes we've written during lectures. Make sure to test all the different methods, and try a few different combinations of arguments and internal states to make sure everything works the way it's supposed to (according to the method descriptions above).

Part 2: The Lunar Lander Game

To be able to play our game, we'll need to set up code that will create a lander, then repeatedly ask a user how much fuel to spend on thrust, spending that much thrust, and all the time checking to see if our lander landed.

For this assignment, you'll use a pre-existing class to interact with the user through a text-based interface. Take a look at the TextLanderInterface class in interfaces.py; you'll be using it in this part of the assignment.

Create a class LanderGame in your lander.py module. For now, it will have a constructor and one other method: play(). The constructor should set the following instance variables:

The play() method should do the following things:

  1. As long as the self.lander has altitude above 0, loop and do the following things:
    • Ask the interface to show the current status of the lander (altitude, velocity, fuel).
    • Ask the interface to get a thrust amount from the user.
    • Update the lander's information with the returned amount.
  2. When the lander finally impacts the ground, check the lander's velocity. If its velocity is less than -10, the lander has crashed. If not, it has landed safely.

    Based on the result, ask the interface to either show the crash info or show the landing info.

  3. Finally, call the interface's close() method.

In your main function, comment out the call to your testing function, and instead write code that will create a LanderGame instance, then call its play() method to play the game.

Here is a sample run (by a person who's not very good at this game...):

Lander Status: Altitude 200, Velocity 0, Fuel 30
Thrust amount? 0
Lander Status: Altitude 198, Velocity -2, Fuel 30
Thrust amount? 0
Lander Status: Altitude 194, Velocity -4, Fuel 30
Thrust amount? 0
Lander Status: Altitude 188, Velocity -6, Fuel 30
Thrust amount? 0
Lander Status: Altitude 180, Velocity -8, Fuel 30
Thrust amount? 0
Lander Status: Altitude 170, Velocity -10, Fuel 30
Thrust amount? 0
Lander Status: Altitude 158, Velocity -12, Fuel 30
Thrust amount? 0
Lander Status: Altitude 144, Velocity -14, Fuel 30
Thrust amount? 0
Lander Status: Altitude 128, Velocity -16, Fuel 30
Thrust amount? 0
Lander Status: Altitude 110, Velocity -18, Fuel 30
Thrust amount? 0
Lander Status: Altitude 90, Velocity -20, Fuel 30
Thrust amount? 0
Lander Status: Altitude 68, Velocity -22, Fuel 30
Thrust amount? 0
Lander Status: Altitude 44, Velocity -24, Fuel 30
Thrust amount? 0
Lander Status: Altitude 18, Velocity -26, Fuel 30
Thrust amount? 0
Crash! Oh no!

Grading and Submission

Remember to put your name at the top of your source code!

Submit your program, lander.py, via Moodle.

Good luck, have fun, start early, and ask lots of questions!

This assignment originally designed by Andy Exley. Thanks for sharing, Andy!