8.14

Homework 8a🔗

home work!

Programming Language #lang htdp/isl+

MUST BE DONE WITH YOUR PARTNER

Due Date Fri at 9:00pm (Week 8)

Purpose Continue with QBert

You will submit several files in this assignment, zipped together. Make sure before you submit that you have all the pieces!

I recommend you read through the whole assignment, first, to make sure you have a todo-list of all the requirements.

Cleanup

In part 1 of the project, you developed your own data definitions for the game. You also were working with a different partner than you are now. Before continuing in this assignment, each of you should present your codebase to your new partner and explain your design choices, and then you should decide on which ideas from which codebase you’ll keep, and which ideas you’ll discard.

Exercise 1 Create a file called README.txt. In it, explain which design choices you’re keeping, which design choices you’re rejecting, and why.

For each game feature below, explain in your README what additional changes you had to make to your data definitions in order to support the new feature. (Note! There may well be additional helper functions and/or helper data definitions required for these features; the spec below simply states the requirements, and does not tell you how to implement them.)

Updating data definitions

At minimum, you needed several distinct data definitions:

; A Block is a (make-countdown Nat)
; INTERPRETATION: An individual block in a QBertLevel, whose number
; indicates how many more times QBert must stomp on this block
(define-struct countdown [stomps])
 
; A QBertBoard is a [List-of [List-of Block]]
; INTERPRETATION: the collection of Blocks in the current level.
; The 0th (i.e. first) item of the QBertBoard is the topmost row
; and the 0th (i.e. first) item of that is the leftmost Block,
; and indices count down and to the right.  Each row is centered on the row
; beneath it.
 
; A QBPosn is a (make-qbposn Num Num)
; INTERPRETATION: A QBPosn refers to a specific cell position on the board,
; using the coordinate system from QBertBoard
(define-struct qbposn [row col])
 
; A QBertLevel is a (make-level QBPosn QBertBoard Nat)
; INTERPRETATION: represents the current position of QBert (using the
; coordinate system described above in QBertBoard with x as column and
; y as row), the current board contents, and the current number of steps QBert
; has taken in the current level.
(define-struct qbert-level [qbert-pos board step-count])

Exercise 2 For each difference between your data definitions and these, explain. If your QBertBoard did not specify a coordinate system (or used Posns with x and y even though your board has rows and columns), or if the board was not a nested list-of-lists of blocks, or if you did not define what a Block was, or if your QBertLevel did not track the player’s position, explain explicitly in your README why your prior design did not include these details.

Exercise 3 Fix your data definitions to match these. If your data definitions contained more information than the minimal data here, keep those enhancements. But if you did not have at least this much information present, correct your definitions now.

Code quality

In all your existing code, and in all new code in this assignment, you should use list abstractions wherever possible, and lambdas wherever appropriate. In particular, you should not need—and must not use!—any manually-recursive list-processing functions.

Note: You may find yourself wanting to use some of the other functions defined in ISL+. Go ahead! You may also find yourself wanting to use map in its more general form: you can pass more than one list (as long as all lists have the same length!), and a function that expects more than one argument, and map will traverse both lists in tandem, calling your function on the corresponding elements of both lists. The lists do not have to have the same type, but the function needs to have a signature compatible with their actual element types. For instance:

(check-expect (map make-list '(1 2 3 4) '("a" "b" "c" "d"))
              '(("a") ("b" "b") ("c" "c" "c") ("d" "d" "d" "d")))

(Several other list abstractions also have more general forms than we’ve discussed in class so far, as well.)

Gameplay

Exercise 4 Enhance your key-handling logic to cause Blocks that QBert stomps on to decrease in value.

Exercise 5 Enhance your rendering of the game to ensure that QBert is drawn looking at the direction it most recently moved. E.g., if QBert just moved down and to the right, then you should render image; if QBert just moved up and to the left, you should render image; etc.

New game features

Implement the following new features:

Exercise 6 New blocks! In addition to the existing countdown blocks, design a new cycling block, which doesn’t stop once it reaches zero: instead it cycles back to its initial value if QBert stomps on it again and starts counting down again. You must also implement some distinctive rendering of these blocks, so the player knows that they’re cycling blocks rather than countdown blocks. (E.g., draw them with a highlighted border around the top diamond of the block, or something similar.)

Exercise 7 Enemies! Every E seconds (where E is new argument that you will add to your main function, and that will be used in your levels somehow), the game will randomly spawn an enemy. (The level should start with no enemies at all.) There are two kinds of enemies:

  • "Wanderers" appear at a random location on the level, and then randomly move around the level, choosing a direction at random. If QBert collides with a wanderer, the game is over.

  • "Fixers" start at the top of the level, randomly move downward through the level, and every block they step on increments its value by one.

Enemies move at a speed of one block per second. If an enemy falls off the level, so much the better for QBert!

You should pick distinct images for the two enemies, so that the player can tell which ones are which.

(Note: to test the behaviors of these enemies, you may want to use check-random.)

Exercise 8 Include in your submission a screenshot of your game in progress, showing a medium-large level, with both kinds of blocks and where some of the blocks have been stomped, with at least one enemy active on the board, and showing the current player score. (You may want to use the save-image function to accomplish this.) Name your screenshot gameplay.png.