Assignment 1

Exercise:
AdventureRS

Change Log

  • Assignment Released
  • Added some clarification about the Quests system (2pm, 4th Oct)
  • Added hint about how to do Coloured Blocks (2pm, 4th Oct)
  • Clarified that using our maps is mandatory, and where to find them (11am, 5th Oct)
  • Fixed tar download (4pm, 5th Oct)
  • Clarified that the idea for starting is to copy the code in the termgame library (10am, 7th Oct)
  • Fixed the HTML for Part 2 -- the Quest trait we provided should have had a generic Event parameter, but HTML thought event was an HTML tag so it didn't render it. (10am, 7th Oct)
  • Clarified the size of the viewport. (10am, 7th Oct)
  • Clarified that you don't need to understand CharChunkMap (12pm, 14th Oct)
  • Added some more clarifications around the reset function, and Quest trait (12pm, 14th Oct)
  • Added more info about how error handling will be marked (00:09am, 20th Oct)

In this assignment, we will be calling back to the inspiration for many an introductory programming assignment, 2D explorer games.

This assignment is in two parts. You will first implement an "adventure" style 2D game in the terminal. You will then implement a "quests" system for the game, which will be designed to be re-usable. The goals of this assignment are:

  1. To get you to practice designing and structuring a larger rust program.
  2. To focus as much as possible on skills and design patterns that would actually be used when solving modern programming problems (i.e. writing a pull request, writing re-usable code, etc.)
  3. To have fun making an aesthetic and interesting application.

We want to also be explicit about what the goals aren’t:

  1. To assess your game design (or game-playing) skills - mechanics you implement in the game will be assessed solely on the technical skill they demonstrate.
  2. To assess your ability to write large amounts of useless cruft solely for us to mark you on. Where you're writing code, we have a reason for it. Where you're writing text, it's because we want to genuinely understand your thinking.

What you will submit

At the end of this assignment, you will submit:
  • One crate, containing your game.
  • One crate, containing your quests system (if you made one).
  • A completed copy of mark_request.txt containing a list of features that you've completed; how to run your code; and good/bad things about your code. This is basically a pull-request on GitHub; but in a text file.

Part 0: Getting Started

Starter Code

We have provided a small amount of starter code for this assignment; which you can access by downloading this tar file.

You can also run the following command to fetch the starter code:

  6991 fetch assignment 01

Reference Solution

To help you make stylistic decisions and see what we are looking for, you can use the command shown below to try our version of Adventurers.

  6991 adventurers [map_file] [quest_name]

Where [map_file] is the path to one of the ron files in maps/ (in your starter code); and [quest_name] is one of q1, q2 or q3.

While playing, use the arrow keys to move. The q key is used to show your progress in the quest; r will reset the quest; and Ctrl+C will quit.

Part 1: Adventure Game Features

These features are the basic mechanics of the game.

While you must make sure that you implement these features, you do not need to implement tests, or write significant documentation. You can feel free to write any tests or documenation that helps you; or helps us understand your code. You can feel free to implement extra features if you so wish!

1. Implement a termgame controller, and display it. (0%)

As a first step, we have to show a picture of the map. To get this working, you just need to show something on the screen using termgame. You should start by copying in the code from the example code on the main page of termgame's documentation.

To do this, we suggest that you make the key t (for test) display an 'a' in the top-left of the viewport; and a 'z' in the bottom-right of the viewport. You do not need to do this, but it may help familiarise yourself with the termgame library.

Getting termgame working is made easy by consulting the termgame docs

No marks are awarded for this section (if it's not complete, you won't have started the assignment).

2. Implement Player Navigation (5%)

When your program starts, you should implement the ability to “walk around” with a player. There should be a player character (We use U+265F, but any obvious character is fine). The player character should be able to move up, down, left and right. The player character should start in the third row, third column.

A naive implementation of this feature would just have the viewport move every time the player does. To minimise the movement of other objects on screen, full marks in this section require that the viewport only moves when the player is close to going off screen.

For marks in this section, you will need to ensure three things:

  • A player icon is visible
  • The player always starts on the third row, in the third column of the map.
  • The player icon moves around the viewport, but is always on screen.

3. Implement Different Coloured Block Types (5%)

It’s boring to walk around a world that’s all the same. You should add in different coloured “block types”, which look different to the default block. You must have at least five. We suggest:

  • Grass (a green block)
  • Sand (a yellow block)
  • Rocks (a grey block)
  • Cinderblock (a light red block)
  • Flowers (a pink or magenta block)

For marks in this section, you should ensure two things:

  • All 5 coloured block types are implemented
  • When a player is standing on a block type, it is clear where in the viewport the player is standing, and the block type they are standing on.

4. Parsing from a file (5%)

So far, you may have hard-coded where the block types are shown on the screen. Now, we want to store them separately. You should implement a system so that the “map” is stored in a file; and loaded in at the beginning of the game.

We have provided two sample maps, which must work with your program, in the maps folder of your starter code.

For marks in this section, you just need to demonstrate that the files we have provided (in addition to others of your own design, if you wish) control what is displayed to the user, and to control where on the screen things are. Your file should ignore features you have not implemented yet.

5. Barriers (2%)

Games aren’t very interesting without obstacles! Let’s now implement a block type that the player cannot pass through.

For marks in this section, you just need to ensure there is a block-type that the player cannot pass through.

6. Water (3%)

Let’s add another obstacle – Water. Players can only hold their breath for 9 blocks in one go. In other words, after ten blocks of water, the player should die from drowning.

For marks in this section, you will need to ensure three things:

  • The player can walk through water.
  • When the player walks over 10 blocks without stepping on another block, they die.
  • A player dying should end the game, and display a message.

7. Signs (5%)

Games need a story too – to help with this, please implement Signs. When a player walks over a sign, a message should pop up for them. The message should disappear after the player moves again.

For marks in this section, you just need to ensure that when a player steps on a sign block, the appropriate message is displayed; and when they step off it, the message disappears.

8. Objects (5%)

The game should include objects (which could be any sensible unicode character) which appear on blocks. When a player walks over the block, the character should disappear.

You do not need to implement objects on top of coloured block types; each location will either be coloured or an object, never both.

For marks in this section, you just need to ensure that when a player steps on an object, the object disappears.

Part 2: Quest System Features

The second part of this assignment is designed to test your ability to write a piece of code that is high-quality, understandable and re-usable. You will be asked to implement a "quest" system, where the developer can set the user tasks to complete; and the system keeps track of their completion of those tasks. You will need to at least write one test for each quest (or write enough unit tests to prove that the three provided quests should work). You will also need to provide documentation where appropriate.

Importantly: we have provided a seperate crate to allow you to create a system which could be re-used, and be designed such that other students (or indeed other games) could re-use it. During design marking, we will consider how easy it would be for a future developer to specify new quests.

What should go in which crate is entirely up to you, and there are different approaches which could work well. You should consider which parts of the system are unique to your application; and which are "general" to any quest system. For example, the concept of "joining two quests together" might be general, but the exact list of events your quest system can handle, and the order parts of a quest need to be completed is specific to your application.

The minimal implementation of this system would be having the quest trait in one crate; and everything else in the other one. It's likely, however, that you'll find more functionality that can be abstracted away.

To help with re-usability (and to help as a starting point for the quests system), all quests must implement the following trait:

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum QuestStatus {
    Complete,
    Ongoing
}

/// This is what a "quest" should do.
/// Note that all `Quests` implement Debug and Display.
/// Traits' Debug implementation does not matter, but
/// they should implement [`std::fmt::Display`] to show
/// the current progress of the quest.
pub trait Quest<Event>: std::fmt::Display + std::fmt::Debug {
    /// Whenever something happens, you call "register_event" to tell the quest what's happened.
    fn register_event(&mut self, event: &Event) -> QuestStatus;

    /// Reset the quest, so that players can restart.
    fn reset(&mut self);
}

You should, at least, be able to play the following quests. For each, a key (preferably 'q') should show your progress in the quest, and when the quest is complete, the game should end.

UPDATE (14/10): in the sample implementation, the r key triggers a reset. We also use reset as part of our program, in addition to its debugging uses. However, if you do not implement the r key and leave the implementation of reset as todo!() we won't penalise you, because we weren't clear enough about the context we wanted it used in.

UPDATE (14/10): also to be clear, you are welcome to extend the above trait if you wish. An extension trait might look like pub trait ExtensionTrait<Event: Something>: Quest + SomethingElse { ... }. this trait is just a starting point.

  • (quest 1 - 4%) "The player wins the game if they walk over 5 sand blocks".
  • (quest 2 - 3%) "The player wins the game if they:"
    • "First, collect five objects called 'x'"
    • "After finishing that, collect three objects called 'y'"
  • (quest 3 - 3%) "The player wins the game if they do 2 of the following:"
    • "walk over 5 blocks of sand", then "collect an 'x' object".
    • "collect a 'y' object", then "walk on grass".
    • "walk over 9 blocks of water, 3 times".

Remember, however, that you should also support a future developer who wants to extend this system -- it should be easy to add in tasks or compose new quests.

5 marks are reserved for the style of your quests system, 10 marks are reserved for the implementation of your quests system, and 15 marks are specifically reserved for the design of your quests system, so the maximum possible mark without completing quests is 70%.

Part 3: Submit a Mark Request

When building modern software, you are expected to send in a pull request, explaining what you've done. In COMP6991, you must submit a "mark request". This is contained in mark_request.txt.

The mark request helps us mark you -- we will use it to help us find out what to mark. It is not meant to take more than 10 minutes to write. No marks are awarded for the mark request specifically; but if it is very inaccurate, we reserve the right to either request you resubmit it with a penalty; or mark using it as a basis (and therefore not mark things you've done).

Other Information

Submission

See the instructions down the bottom of the page.

How to Debug Termgame

Because termgame uses curses to control the terminal, regular println! debugging is not possble.

On unix-like systems, there are a few ways to make your life easier when debugging. One is to use the eprint! and eprintln! macros, to print to standard error. You can then do stderr redirection into files, like so:

  6991 cargo run 2> /tmp/adv_log

Debugging output can then be found in /tmp/adv-log. If you open a different terminal window, tail -f /tmp/adv-log will show a live-updating view of that file, so you can correlate log messages with a particular action.

If you want to have more advanced debugging capabilities, you may find the -p argument to gdb useful.

Using Other Crates

We are happy for you to use any crate that has been published on crates.io under three conditions:

      The crate must not have been authored by anyone else in the course.
      The crate must have at least 1000 downloads, excluding the last 30 days.
      The crate must not impose license restrictions which require you to share your own code.

If you are in doubt (or think these restrictions unfairly constrain you from using a reasonable crate), ask on the course forum.

Marking Scheme

There are 3 things on which you will be marked:

  • Mechanical Style
  • Functional Correctness
  • Idiomatic Design

You can see how the marks break down here:

Mechanical Style Functional Correctness
Idiomatic Design
Adventure Game
10% 30% 30%
Quests System 5% 10% 15%

And a detailed analysis is shown below:

1. Mechanical Style (10% + 5%):

We will look at your crates, and make sure they:

  • Compile, with no warnings or errors.
  • Raise no issues with 6991 cargo clippy
  • Are formatted with rustfmt
  • Have any tests written for them pass
  • (for quests only) have tests which encompass the three quests.
  • (for quests only) have all public interfaces documented (i.e. no warnings generated with #[warn(missing_docs)]).
  • (for quests only) have implemented at least one quest (otherwise submitting an empty file would get you free marks).

If they do all of the above, you get full. Otherwise, we will award partial marks. This is meant to be the "easy marks" of programming.

2. Functional Correctness (30% + 10%):

Your code should do what we describe. We will run the code through some obvious tests to make sure it behaves as we expect. For example, we will likely do the following:

  • Trying to start your program.
  • Testing the behaviour we stated below.
  • Trying out walking around a bunch, and trying to go off the map.
  • Modifying your map slightly.

The marks available of each section of the assignment is shown next to the title of the section above.

You must complete the checklist and the "How to Run My Program" section of the mark_request faithfully. We will only test things which you say you have done. In other words, if you do not fill in the file, we will not be able to give you any marks. If you do fill in the mark_request and you clearly have not done the work, we may ask you to re-complete it at a penalty before we do marking.

30% of your final mark will come from functional correctness of your adventure game. 10% of your final mark will come from functional correctness of the quests system.

3. Idiomatic Design (30% + 15%):

Your code should be well designed. This is where we will spend most of our time when marking. To help you, we have provided "design excellence" suggestions, which are ideas to make your design really excellent. You don't have to do them, but they would be good ways of getting a great design.

The following list of properties will be marked in your program:

  • Code is abstracted appropriately.
  • Types are used appropriately to express data in the program.
  • The design does not impose unnecessary constraints on either the caller or callee through borrowing, lifetimes or ownership.
  • Uses traits sensibly to add expressiveness and avoid unnecessary code.
  • Data structures used are appropriate to store data.
  • Functions perform error handling; cases that are expected do not panic. (see the hint below as of 20/10)
  • Code is sensibly organised, and split into appropriate modules.
  • Documentation, where provided, is correct and readable.
  • (optional) Uses external crates effectively to achieve the above goals.
  • (optional) Where code is designed in a sub-optimal way, comments about how to improve it are made under "Design Limitations".

Your mark will be calculated based on the feedback you have received:

100% of available marks Very little negative feedback is given on the above criteria; and multiple design excellence suggestions are implemented (or your own ideas which we consider equivalently excellent).
85% of available marks Some minor comments are made about some of the above criteria. Above this mark, at least one design excellence feature was implemented (or your own idea is considered equivalently excellent).
75% of available marks Major comments are made about one or two criteria, with multiple small comments in different areas.
65% of available marks Major comments are made about three or more criteria.
50% of available marks Many areas have major comments made.
below 50% of available marks Assignments in this category are likely written as "translations from C", and ignore many Rust features and design patterns.

30% of your final mark will come from the design of your adventure game. 15% of your final mark will come from the design of the quests system.

Note that the following penalties apply to your total mark for plagiarism:

0 for the assignment Knowingly providing your work to anyone and it is subsequently submitted (by anyone).
0 for the assignment Submitting any other persons work. This includes joint work.
0 FL for COMP6991 Paying another person to complete work. Submitting another persons work without their consent.

Formal Stuff

Assignment Conditions

  • Joint work is not permitted on this assignment.

    This is an individual assignment.

    The work you submit must be entirely your own work. Submission of any work even partly written by any other person is not permitted.

    The only exception being if you use small amounts (< 10 lines) of general purpose code (not specific to the assignment) obtained from a site such as Stack Overflow or other publicly available resources. You should attribute the source of this code clearly in an accompanying comment.

    Assignment submissions will be examined, both automatically and manually for work written by others.

    Do not request help from anyone other than the teaching staff of COMP6991.

    Do not post your assignment code to the course forum.

    Rationale: this assignment is an individual piece of work. It is designed to develop the skills needed to produce an entire working program. Using code written by or taken from other people will stop you learning these skills.

  • The use of code-synthesis tools is permitted on this assignment, however beware -- the code it creates can be subtly broken or introduce design flaws. It is your job to figure out what code is good.

    Rationale: this assignment is intended to mimic the real world. These tools are available in the real world.

  • Sharing, publishing, distributing your assignment work is not permitted.

    Do not provide or show your assignment work to any other person, other than the teaching staff of COMP6991. For example, do not share your work with friends.

    Do not publish your assignment code via the internet. For example, do not place your assignment in a public GitHub repository. You can publish Workshops or Labs (after they are due), but assignments are large investments for the course and worth a significant amount; so publishing them makes it harder for us and tempts future students.

    Rationale: by publishing or sharing your work you are facilitating other students to use your work, which is not permitted. If they submit your work, you may become involved in an academic integrity investigation.

  • Sharing, publishing, distributing your assignment work after the completion of COMP6991 is not permitted.

    For example, do not place your assignment in a public GitHub repository after COMP6991 is over.

    Rationale:COMP6991 sometimes reuses assignment themes, using similar concepts and content. If students in future terms can find your code and use it, which is not permitted, you may become involved in an academic integrity investigation.

Violation of the above conditions may result in an academic integrity investigation with possible penalties, up to and including a mark of 0 in COMP6991 and exclusion from UNSW.

Relevant scholarship authorities will be informed if students holding scholarships are involved in an incident of plagiarism or other misconduct. If you knowingly provide or show your assignment work to another person for any reason, and work derived from it is submitted - you may be penalised, even if the work was submitted without your knowledge or consent. This may apply even if your work is submitted by a third party unknown to you.

If you have not shared your assignment, you will not be penalised if your work is taken without your consent or knowledge.

For more information, read the UNSW Student Code , or contact the course account.

When you are finished working on this exercise, you must submit your work by running give:

This exercise regrettably cannot be submitted with 6991 give. Instead, please package your crate(s) (along with all other files intended for submission) up into a tar file named crate.tar.

For example:
tar cvf crate.tar <path1> <path2> <path3> ...
e.g.:
tar cvf crate.tar ./my_crate1/ ./my_crate2/

Finally, submit with the following command:

give cs6991 assign01_adventurers crate.tar

You must run give before Week 7 Wednesday 17:00:00 to obtain the marks for this exercise. Note that this is an individual exercise; the work you submit with give must be entirely your own.