[plt-scheme] HTDP Extended Exercise: Interactive Games

From: Matthias Felleisen (matthias at ccs.neu.edu)
Date: Tue Mar 9 23:36:37 EST 2004

Everyone, this is an instructive example. Please read!

Connor, the essential bug is that you didn't follow the design recipe.

Here is your function move-shot:

;; move-shot : shot -> shot
(define (move-shot a-shot)
   (make-shot (make-posn (posn-x (shot-posn a-shot))
                         (- 5 (posn-y (shot-posn a-shot))))
              (shot-l a-shot)
              (shot-w a-shot)
              (shot-col a-shot)))

You had no test for this function. Indeed, you didn't have a single 
test for any of the functions in a 400 line file. So I added a test 
like this:

(equal? (move-shot (make-shot (make-posn 200 100) 2 5 'red))
         (make-shot (make-posn 200 95) 2 5 'red))

This test/example says that if you move a shot, it reduces its y 
coordinate on the screen (which means it's closer to the top next time 
it's drawn). Naturally the test failed.

You want the function to look like this:

;; move-shot : shot -> shot
(define (move-shot a-shot)
   (make-shot (make-posn (posn-x (shot-posn a-shot))
                         (- (posn-y (shot-posn a-shot)) 5))
              (shot-l a-shot)
              (shot-w a-shot)
              (shot-col a-shot)))

Now my test succeeds and your program works like a charm. You had a few 
other mistakes:

1:
;; move-aup : AUP KeyEvent -> AUP
(define (move-aup aup ke)
   (cond
     [ (symbol? ke)
       (cond
         [ (symbol=? 'left ke) (make-aup
                                (make-posn (- (posn-x (aup-nw aup)) 10)
                                           (posn-y (aup-nw aup)))
                                (aup-len aup)
                                (aup-wid aup)
                                (aup-col aup))]
         [ (symbol=? 'right ke) (make-aup
                                 (make-posn (+ (posn-x (aup-nw aup)) 10)
                                            (posn-y (aup-nw aup)))
                                 (aup-len aup)
                                 (aup-wid aup)
                                 (aup-col aup))]
         [ (or (symbol=? 'up ke)
               (symbol=? 'down ke)) aup]
         ;; MF: there was no else clause here, but there are many more
         ;; symbols than these four. A test would have discovered this.
         [ else aup ])]
     [ else aup]))

Again there was no test, but there was this line:

(move-aup (create-aup 139) 'left)

You need to know that this is neither an example nor a test. It's 
*nothing*.
An example (or a test) consists of
  (1) an expression
  (2) its *expected* value, which *you* must supply.

2:

;; main : string symbol -> string
(define (main name level)
   (cond
     [ (symbol=? level 'wimpy) (print "You lazy idiot! You're better 
than that!")]
     [ (symbol=? level 'easy)
       (announcement
        (fly-until-down (create-ufo 140) (create-aup 139) 10 false) 
name)]
     [ (symbol=? level 'medium)
       (announcement
        (fly-until-down (create-ufo 140) (create-aup 139) 15 false) 
name)]
     [ (symbol=? level 'hard)
       (announcement
        (fly-until-down (create-ufo 140) (create-aup 139) 20 false) 
name)]
     [ (symbol=? level 'ridiculous)
       (announcement
        (fly-until-down (create-ufo 140) (create-aup 139) 30 false) 
name)]
     [ (symbol=? level 'deathmatch)
       (announcement
        ;; MF fixed: (fly-until-down (create-ufo 140) (create-aup 139) 
40 false)
        (fly-until-down (create-ufo 140) (create-aup 139) 40 false)
        name)]))


3: You had used the function print, which I assume you got from moving 
up in the language hierarchy. Bad mistake. That won't help, plus the 
Read-Eval-Print loop already prints strings for you. Why bother?

How did I find the bugs? First, I went to Beginner. That showed me two 
of them because the program failed on me twice in a row. Then I 
disabled Connor's beautiful background picture (great job!!) and 
stepped thru. Stepping let me add a key event in a very visible manner. 
Once I saw that the shot was added and carried around, I knew the 
mistake had to be in move shot. The stepper showed me how move-shot 
inserted negative coordinates. Then I went to the code and saw that it 
lacked tests. I added the test and confirmed the mistake. I switched 
the subtraction and confirmed the fix (with additional tests).

Enjoy the game now, and oh, don't forget to supplement the functions 
with tests. The 206p1 version of drscheme has a nice test menu. You can 
add visual test boxes that make it absolutely, totally clear what tests 
are. And once you don't want them anymore, you can turn them off in one 
click. All built in.

-- Matthias



On Mar 9, 2004, at 9:39 PM, Connor Ferguson wrote:

> Matthias and mathematica,
>
> Thank you both for your advice. I am having problems with getting the 
> AUP to
> fire one shot. Attached is my code. If you could look at it when you 
> get a
> chance and give me some pointers. When I execute the new version of 
> the game
> that should allow the UFO to fire one shot, it just acts like the one 
> where
> you just catch it. Whenever I press the up arrow it does nothing.
>
> Please help,
> -Connor
>
>
> on 3/8/04 7:09 PM, Matthias Felleisen at matthias at ccs.neu.edu wrote:
>
>> For list-related administrative tasks:
>> http://list.cs.brown.edu/mailman/listinfo/plt-scheme
>>
>>
>> On Mar 8, 2004, at 9:52 PM, mathematica wrote:
>>
>>> For list-related administrative tasks:
>>> http://list.cs.brown.edu/mailman/listinfo/plt-scheme
>>>
>>> Please don't mind that I reply.
>>
>> Never. I love it when "students" help each other.
>>
>>>
>>> ;; SHOT is a Posn
>>> ;; SHOT/f is SHOT of false, false indicate that now there is no shot
>>>
>>> draw-scene only draw the AUP, UFO and SHOT. It is clear-scene which
>>> clear AUP, UFO and SHOT
>>>
>>
>> Yes.
>>
>> -- Matthias
>>
>>
>>>
>>> --  mathematica
>>>
>>>>
>>>> Matthias-
>>>>
>>>> Sorry to take so long to get back to you. If draw-scene draws the 
>>>> AUP
>>>> and
>>>> UFO and draws and clears the shot, what would clear-scene do? Would
>>>> it need
>>>> to do anything with the shot, since draw-scene has already cleared 
>>>> it
>>>> from
>>>> the canvas?
>>>>
>>>> -Connor
>>>>
>>>> on 3/7/04 10:19 AM, Matthias Felleisen at matthias at ccs.neu.edu 
>>>> wrote:
>>>>
>>>>>
>>>>>
>>>>> On Mar 6, 2004, at 6:55 PM, Connor Ferguson wrote:
>>>>>
>>>>>> For list-related administrative tasks:
>>>>>> http://list.cs.brown.edu/mailman/listinfo/plt-scheme
>>>>>>
>>>>>> I am working on the extended exercise for HTDP: Interactive Games
>>>>>> (http://www.ccs.neu.edu/home/matthias/HtDP/Extended/igames.html). 
>>>>>> In
>>>>>> Exercise 2.4.5, it says to modify draw-scene and clear-scene to 
>>>>>> also
>>>>>> consume
>>>>>> a Shot/f. What do they do with this shot (draw it, move it?)?
>>>>>
>>>>> What did draw-scene and clear-scene do before? According to 2.3.2
>>>>> (the
>>>>> pointer in 2.4.5),
>>>>>
>>>>>> Design the function draw-scene. It consumes an AUP and a UFO and
>>>>>> draws
>>>>>> them on the canvas.
>>>>>> Also design clear-scene, which consumes a AUP and a UFO and clears
>>>>>> them from the canvas.
>>>>>
>>>>> So I'd say that draw-scene now draws and clears the shot, if it has
>>>>> been fired.
>>>>>
>>>>> Hint: If the shot/f argument is false, no shot has been fired. 
>>>>> Later
>>>>> you will see that it is -- as often -- easier to deal with the
>>>>> generalization of the problem, when you draw an entire list of 
>>>>> shots
>>>>> per scene. Then, when no shot has been fired, you just get empty.
>>>>>
>>>>> -- Matthias
>>>>>
>>>
>>
>>
>
> <ufos-1shot.scm>



Posted on the users mailing list.