Moonlander
Overview
The aim of the game is to collect some target amount of cheese and make it back to the lander to export the moon cheese back to Earth! Movement has an oxygen cost and to collect the cheese we may have to navigate around rocks and avoid running out of oxygen completely (a player can drop off cheese and refill their oxygen tank at the lander).
We will begin by setting up the board, then add the ability to move around it to play the game and in the final few stages we will also implement moonquakes and some more interesting methods of travel but we will leave that as a surprise for the moment...
Getting Started
- Create a new folder for your assignment. Here is an example:
mkdir ass1 cd ass1
- Fetch the starter code using the command below. Alternatively download the starter code here.
1511 fetch-activity cs_moonlander
- Check that everything works by running the autotest.
1511 autotest cs_moonlander
(These should fail initially. If you want to exit running the autotest midway, press [ctrl-c]
)
Initial Code and Data Structures
The starter code for this assignment includes some functions and defined types:
- A
print_board()
function:- This prints out the current state of the board, which ensures that your board printing matches the autotest exactly for a given board.
- An
init_board()
function:- This stores a default value in each of the tiles in the provided board.
- A
struct tile
struct:- Each square of the board (i.e. the 2D array) holds a
struct tile
, containing the information about what that tile contains. - The player's row and col values are stored seperately to the contents of the board
- Each square of the board (i.e. the 2D array) holds a
- An
enum entity
enum:- This is used in the
struct tile
struct to represent what is on each tile.
- This is used in the
Let us look at an example output from the print_board()
function.
+---+---+---+---+---+---+---+---+---+---+ | C S M O O N L A N D E R | +---+---+---+---+---+---+---+---+---+---+ | | | | | | | | | | | +---+---+---+---+---+---+---+---+---+---+ | | | | | | | | | | | +---+---+---+---+---+---+---+---+---+---+ | | |/|\| |^^^| |<(]| | | | +---+---+---+---+---+---+---+---+---+---+ | | | | | | | | | | | +---+---+---+---+---+---+---+---+---+---+ | | | | | | |0.0| | | | +---+---+---+---+---+---+---+---+---+---+ | | | | | | | | | | | +---+---+---+---+---+---+---+---+---+---+ | | |\O/| |~~~| |~~~| | | | +---+---+---+---+---+---+---+---+---+---+ | | | | | | | | | | | +---+---+---+---+---+---+---+---+---+---+ | | | | | | | | | | | +---+---+---+---+---+---+---+---+---+---+ | | | | | | | | | | | +---+---+---+---+---+---+---+---+---+---+
Here, we have tiles containing:
- the lander
/|\
- a rock
^^^
- a cheese
<(]
- a hole down
\O/
- two portals
~~~
- the player
0.0
Where do we store the player?
The player is not stored in the board
, instead the print_board()
function takes the player's row and column as arguments whenever we print the board.
- for the above example:
print_board(board, 4, 6);
.
So you can store the player however you like! (e.g. variables for the row/col, or perhaps a struct that contains both the row and the col!)
Reference Implementation
To help you understand how the assignment works, we have written a reference implementation for you to run. You can run it via the command 1511 cs_moonlander
.
1511 cs_moonlander ...
FAQ
Stages
We have broken the assignment spec down into incremental stages:
- Stage 1: Place the lander, add cheese & rocks to the board.
- Stage 2: Setup the player, add player movement, pick up and drop off cheese, keep oxygen levels correctly updated, refill oxygen at the lander.
- Stage 3: Check for a win or lose condition, add a command to quit the program early, add moonquake mechanics.
- Stage 4: Make the board 3D, add commands to create holes and jump between levels, add portals, implement travelling through portals.
- Extension (no marks): Add a graphical user interface.
Your Tasks
This assignment consists of four stages. Each stage builds on the work of the previous stage, and each stage has a higher complexity than its predecessor. You should complete the stages in order.
A video explanation to help you get started with the assignment can here found here:
Stage 1
In stage 1, you will scan and store values to set up the map, including the lander, rock obstacles, and collectible cheese.
There is a reference implementation that you can play by running the command 1511 cs_moonlander
in the terminal.
Here is an example of input for a finished stage 1 that you can try within the reference implementation.
1511 cs_moonlander 1 5 c 1 2 c 3 1 r 3 5 r 3 7 R 5 4 8 6 [ctrl+d]
Stage 1.1: Placing the Lander
We will begin by scanning in and storing some values from the terminal. We will also need to assert that the values are valid.
In this substage, you will need to do the following:
- Print the prompt
Please enter the [row] [col] of the lander:
. - Scan in the lander's position as
row
andcol
. - Check that the row and col values correspond to a valid tile:
- If the requested tile is not on the board, place the lander at
board[4][4]
. - Otherwise, add the lander to the board at the requested tile.
- If the requested tile is not on the board, place the lander at
- Call the provided
print_board()
function with these arguments:INVALID_INDEX
as the arguments forplayer_row
andplayer_col
.BASE_OXY_RATE
as the argument foroxy_rate
.0
or0.0
for all other arguments.
Clarifications
- The lander row and col will always be ints.
Examples:
Autotest
Stage 1.2: Add cheese and rocks
So far we have only added the lander to the board, that is pretty boring so let us add some moon cheese collectibles and rock obstacles to spice it up!
To do this we will create a setup loop that scans in commands to let the user add CHEESE
and ROCK
s to the board. Allow the user to add CHEESE
using the command in the form c int int
and add a ROCK
using the command in the form r int int
until [ctrl+d]
is pressed.
In this substage, you will need to do the following:
- Print the prompt
Please enter cheese and rock locations:\n
. - Allow the user to input commands in a loop until
[ctrl+d]
is pressed. - Given the command:
c [row] [col]
, add aCHEESE
to that tile. - Given the command:
r [row] [col]
, add aROCK
to that tile. - After the user enters
[ctrl+d]
, call the providedprint_board()
function with these arguments:- INVALID_INDEX as the arguments for
player_row
andplayer_col
. - BASE_OXY_RATE as the argument for
oxy_rate
. 0
or0.0
for all other arguments.
- INVALID_INDEX as the arguments for
Clarifications
- Each command provided will be of the form
char int int
. - You can not assume that only the
c
orr
commands will be entered.
Examples
Autotest
Stage 1.3: Add Large Rocks and Check Scan Positioning
Adding rocks one by one can get quite repetitive, so here we will introduce the new R
command to our handy setup loop from stage 1.2. This will allow us to add large rectangular rocks to the board. We will also print an error message if the cheese and rocks we scan in would be placed on a square that already contains something.
In this substage, you will need to do the following:
- For our cheese input from stage 1.2, if the requested tile is occupied or not on the board, instead of adding the cheese to the board print
That is not a valid cheese placement!\n
. - For our single rock input from stage 1.2, if the requested tile is occupied or not on the board, instead of adding the rock to the board print
That is not a valid rock placement!\n
. - Given the command
R [start_row] [start_col] [end_row] [end_col]
, place a large rock with top left corner at[start_row] [start_col]
and bottom right corner at[end_row] [end_col]
. A large rock is represented by placing aROCK
on every tile in it's area.- If any of the following error conditons are true, print
That is not a valid rock placement!\n
and do not add the large rock to the board.- Any tile enclosed in the requested rectangle does not lie on the board.
- Any tile enclosed in the requested rectangle is occupied.
start_row
is greater thanend_row
, orstart_col
is greater thanend_col
.
- If any of the following error conditons are true, print
Clarifications
- A tile is occupied if its
entity
field is notEMPTY
.
Examples:
Autotest
Testing and Submission
Are you finished with this stage? If so, you should make sure to do the following:
- Run
1511 style
, and clean up any issues a human may have reading your code. Don't forget -- 20% of your mark in the assignment is based on style! - Autotest for this stage of the assignment by running the
autotest-stage
command as shown below. - Remember -- give early, and give often. Only your last submission counts, but why not be safe and submit right now?
1511 style cs_moonlander.c 1511 autotest-stage 01 cs_moonlander give cs1511 ass1_cs_moonlander cs_moonlander.c