Zum Inhalt springen
Sitzung: Jeden Freitag in der Vorlesungszeit ab 16 Uhr c. t. im MAR 0.005. In der vorlesungsfreien Zeit unregelmäßig (Jemensch da?). Macht mit!

Forth

Aus FreitagsrundenWiki
Version vom 7. Oktober 2004, 22:41 Uhr von Thomas (Diskussion | Beiträge)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)

\ \ http://members.aol.com/plforth/ofpong/20020313/ofpong.txt \ \ \ \ Wednesday, March 13, 2002 \ \ See also http://members.aol.com/plforth/ofpong/index.html \ \ \ \ \ \ Hello, this is the game of Pong. \ \ \ \ To play, store this file in the root folder of your Macintosh \ \ HD, boot with Command+Option+O+F held down, and then enter \ \ the command `boot hd:\ofpong.txt` but without the quotes. \ \ \ \ While playing, hold down the A and Z keys to move the left \ \ paddle up and down, hold down the ' and / keys to move the \ \ right paddle up and down, press Esc to start a new game, \ \ press Delete to quit. \ \ \ \ After playing, enter the command `pong` to play some more, \ \ or enter the command `bye` to get back to MacOS. \ \ \ \ \ \ This code has been seen to work on a classic iMac, on an iBook, \ \ and on a flat-planel iMac. Please write to tell us if it \ \ doesn't work on your Mac. (Our web pages suggest addresses.) \ \ \ \ Before modifying this code, you probably want to comment \ \ out (or delete) the line at the end that says `pong`. That \ \ way when you `boot` this code you can look at it and modify \ \ it before running it. \ \ \ \ \ \ To construct this file, we modified a copy of the \ \ 1.0d1 MacHack '98 release of OFPong.of found in OFPONG.SIT. \ \ \ \ 1) We copied the text into a SimpleText file, so that `boot` \ \ knows it can read the text. (The original was a BBEdit file.) \ \ To let us edit this in Mac OS X, we had to tell TextEdit to \ \ make this a plain text file, not an Rtf text file. \ \ \ \ 2) We commented out the source code below that begins with \. \ \ \ \ 3) We added the source below that ends with \. \ \ \ \ 4) We added the comments you see here that begin with \ \. \ \ \ \ \ \ Technically speaking, our modifications included: \ \ \ \ 1) Begin with a \ comment, like `boot` wants. \ \ \ \ 2) Comment out the `dl` command, guessing that has something \ \ to do with running this game over a serial or Usb connection, \ \ as opposed to using `boot` to run this from a file system. \ \ \ \ 3) End with a `pong` command so that `boot` runs the game. \ \ \ \ 4) Use `dev keyboard` where `dev kbd` is unavailable, and \ \ accordingly adjust which bits of the key-map to poll to see \ \ the keys A Z ' / Esc Delete held down. \ \ \ \ 5) Use [ s" dev keyboard get-key-map 0 to active-package" \ \ evaluate ] in place of [ " get-key-map" ... $call-method ] \ \ because [ s" keyboard" open-dev ] crashes a classic iMac hard. \ \ \ \ 6) Draw with the background-color and erase with the \ \ foreground-color, rather than with colors -1 and 0, because \ \ on a flat-panel iMac the color -1 is black or transparent, not \ \ visibly different from the black background color 0. \ \ \ \ \ \ If you display this source code in a fixed width font like \ \ Courier or Monaco, then the column ruler here might help you \ \ keep your lines of source code short: \ \ \ \ 0000011111111111222222222223333333333344444444444555555555556666 \ \ 56789_0123456789_0123456789_0123456789_0123456789_0123456789_123 \ dl decimal 0 value gscreen " screen" open-dev to gscreen 0 value gkbd " kbd" open-dev to gkbd \ 0 value gkeyboard \ \ " keyboard" open-dev to gkeyboard \ 0 value erasecol -1 value drawcol foreground-color to erasecol \ background-color to drawcol \ 0 value key_left_up 0 value key_left_down 0 value key_right_up 0 value key_right_down 0 value key_esc 0 value key_off get-msecs value grandseed 0 value glastupdate 0 value loopcount 0 value totalupdate 0 value ballstop 0 value ballx 0 value bally 0 value balldx 0 value balldy 0 value leftbaty 0 value rightbaty 0 value batdy 0 value leftscore 0 value rightscore 640 value screenx 480 value screeny

screen-prop@ ( prop-name prop-len -- value )

gscreen ihandle>phandle get-package-property 0= if decode-int -rot 2drop else 256 then

" width" screen-prop@ to screenx " height" screen-prop@ to screeny 20 value ballsize ballsize 2 / value scoresize ballsize 5 * value batsize 1000 value pscale screenx ballsize - pscale * value ball_limit_x ballsize pscale * value ball_limit_lo_y screeny ballsize 2 * - pscale * value ball_limit_hi_y ballsize pscale * value bat_limit_lo_y screeny ballsize batsize + - pscale * value bat_limit_hi_y 0 value hit_limit_left_lo_x ballsize 2 * pscale * value hit_limit_left_hi_x screenx ballsize 3 * - pscale * value hit_limit_right_lo_x screenx ballsize - pscale * value hit_limit_right_hi_x ballsize pscale * value reflect_left_x screenx ballsize 2 * - pscale * value reflect_right_x

random ( -- n ) grandseed 16807 * 17 + abs to grandseed grandseed 1000 mod ;
unscale ( n -- n ) pscale 2 / + pscale / ;
calcbatx ( n -- x ) screenx ballsize 3 * - * ballsize + ;
paintrect ( c pixx pixy pixw pixh -- ) " fill-rectangle" gscreen $call-method ;
rectcol ( startx starty x1 y1 x2 y2 c -- startx starty )

{ startx starty x1 y1 x2 y2 c } c x1 scoresize * startx + y1 scoresize * starty + x2 x1 - scoresize * y2 y1 - scoresize * paintrect startx starty

blackrect ( startx starty x1 y1 x2 y2 -- ) drawcol rectcol ;
whiterect ( startx starty x1 y1 x2 y2 -- ) erasecol rectcol ;
drawblank ( startx starty -- startx starty )

0 0 4 7 whiterect

drawzero ( startx starty -- startx starty )

0 0 1 7 blackrect 1 0 3 1 blackrect 1 6 3 7 blackrect 3 0 4 7 blackrect 1 3 3 4 whiterect

drawone ( startx starty -- startx starty )

3 0 4 7 blackrect 0 0 3 7 whiterect

drawtwo ( startx starty -- )

0 0 4 1 blackrect 3 1 4 3 blackrect 0 3 4 4 blackrect 0 4 1 6 blackrect 0 6 4 7 blackrect 0 1 1 3 whiterect 3 4 4 6 whiterect

drawthree ( startx starty -- startx starty )

0 0 4 1 blackrect 3 1 4 3 blackrect 0 3 4 4 blackrect 3 4 4 6 blackrect 0 6 4 7 blackrect 0 1 1 3 whiterect 0 4 1 6 whiterect

drawfour ( startx starty -- startx starty )

0 0 1 3 blackrect 0 3 3 4 blackrect 3 0 4 7 blackrect 1 0 3 1 whiterect 0 4 3 7 whiterect

drawfive ( startx starty -- startx starty )

0 0 4 1 blackrect 0 1 1 3 blackrect 0 3 4 4 blackrect 3 4 4 6 blackrect 0 6 4 7 blackrect 3 1 4 3 whiterect 0 4 1 6 whiterect

drawsix ( startx starty -- startx starty )

0 0 1 7 blackrect 1 3 3 4 blackrect 1 6 3 7 blackrect 3 3 4 7 blackrect 1 0 4 3 whiterect

drawseven ( startx starty -- startx starty )

0 0 3 1 blackrect 3 0 4 7 blackrect 0 1 3 7 whiterect

draweight ( startx starty -- startx starty )

0 0 4 1 blackrect 0 1 1 3 blackrect 3 1 4 3 blackrect 0 3 4 4 blackrect 0 4 1 6 blackrect 3 4 4 6 blackrect 0 6 4 7 blackrect

drawnine ( startx starty -- startx starty )

0 0 1 4 blackrect 1 0 3 1 blackrect 1 3 3 4 blackrect 3 0 4 7 blackrect 0 4 3 7 whiterect

drawdigit ( startx starty n -- )

{ n } n 0 = if drawzero then n 1 = if drawone then n 2 = if drawtwo then n 3 = if drawthree then n 4 = if drawfour then n 5 = if drawfive then n 6 = if drawsix then n 7 = if drawseven then n 8 = if draweight then n 9 = if drawnine then 2drop

drawnumber ( startx starty num -- )

{ startx starty num } startx starty num abs 100 mod 10 / drawdigit startx scoresize 5 * + starty num abs 10 mod drawdigit

plotball ( x y -- ) { x y } drawcol x unscale y unscale ballsize ballsize paintrect ;
eraseball ( x y -- ) { x y } erasecol x unscale y unscale ballsize ballsize paintrect ;
plotbat ( n y -- ) { n y } drawcol n calcbatx y unscale ballsize batsize paintrect ;
erasebat ( n y -- ) { n y } erasecol n calcbatx y unscale ballsize batsize paintrect ;
redraw ( -- )

drawcol 0 0 screenx ballsize paintrect drawcol 0 screeny ballsize - screenx ballsize paintrect drawcol screenx scoresize - 2 / ballsize 2 * scoresize screeny ballsize 4 * - paintrect ballsize 7 * ballsize 2 * leftscore drawnumber screenx ballsize 7 * 9 scoresize * + - ballsize 2 * rightscore drawnumber 0 leftbaty plotbat 1 rightbaty plotbat ballx bally plotball

drawboard ( -- )

drawcol 0 0 screenx screeny paintrect erasecol 0 0 screenx screeny paintrect redraw

resetball ( -- )

500 to ballstop screenx ballsize - 2 / pscale * ballx pscale mod + random + to ballx screeny ballsize - 2 / pscale * bally pscale mod + random + to bally random screenx pscale * * 2000000 / to balldx random screeny pscale * * 2000000 / to balldy balldx screenx pscale * 3000 / + to balldx balldy screeny pscale * 6000 / + to balldy random 500 < if balldx negate to balldx then random 500 < if balldy negate to balldy then

initvalues ( -- )

ballsize 2 * pscale * to leftbaty screeny ballsize 2 * - batsize - pscale * to rightbaty screeny pscale * 1000 / to batdy

doreset ( -- )

resetball 0 to leftscore 0 to rightscore drawboard

testkey ( map index mask -- bool )

{ map index mask } map index ca+ c@ mask and 0<>

\ : scankeys ( -- )

gkbd-scankeys ( -- )

" get-key-map" gkbd $call-method drop dup 0 128 testkey to key_left_up dup 0 2 testkey to key_left_down dup 4 1 testkey to key_right_up dup 5 8 testkey to key_right_down dup 6 4 testkey to key_esc dup 6 16 testkey to key_off drop

gkeyboard-scankeys ( -- ) \

s" dev keyboard get-key-map 0 to active-package" evaluate \ dup 0 8 testkey to key_left_up \ the A key dup 3 4 testkey to key_left_down \ the Z key dup 6 8 testkey to key_right_up \ the ' key dup 7 128 testkey to key_right_down \ the / key dup 5 64 testkey to key_esc \ the Esc key dup 5 32 testkey to key_off \ the Delete key drop \

\
forth-scankeys \

0 to key_esc key? if \ key dup 64 or [char] a = to key_left_up \ dup 64 or [char] z = to key_left_down \ dup [char] ' = to key_right_up \ dup [char] / = to key_right_down \ dup 27 = to key_esc \ dup 8 = to key_off \ drop \ then \

\
roelf-scankeys \

key? if key case \ [char] a of true to key_left_up endof \ [char] z of true to key_left_down endof \ [char] ' of true to key_right_up endof \ [char] / of true to key_right_down endof \ [char] q of true to key_esc endof \ true to key_off endof \ endcase then \

\
scankeys ( -- ) \

\ forth-scankeys \ \ roelf-scankeys \ gkbd if gkbd-scankeys else gkeyboard-scankeys then \

\
moveball ( oldx oldy newx newy -- )

{ oldx oldy newx newy } oldx oldy eraseball newx newy plotball

doupdateball ( delta -- )

ballx swap bally swap dup balldx * ballx + to ballx balldy * bally + to bally ballx 0< if resetball balldx abs negate to balldx ballx ballsize 2 * pscale * + to ballx rightscore 1 + to rightscore rightscore 15 = if -1 to ballstop then then ballx ball_limit_x > if resetball balldx abs to balldx ballx ballsize 2 * pscale * - to ballx leftscore 1 + to leftscore leftscore 15 = if -1 to ballstop then then bally ball_limit_lo_y < if balldy negate to balldy ball_limit_lo_y 2 * bally - to bally then bally ball_limit_hi_y > if balldy negate to balldy ball_limit_hi_y 2 * bally - to bally then balldx 0< if ballx hit_limit_left_lo_x hit_limit_left_hi_x between if bally leftbaty ballsize pscale * - leftbaty batsize pscale * + between if bally leftbaty < if balldy abs negate to balldy then bally leftbaty batsize ballsize - pscale * + > if balldy abs to balldy then ballx reflect_left_x > if balldx abs random 50 / + to balldx leftbaty bally - unscale dup 0 batsize between if batsize 2 / - random * 2 / batsize / 25 / balldy + to balldy else drop then then then then then balldx 0> if ballx hit_limit_right_lo_x hit_limit_right_hi_x between if bally rightbaty ballsize pscale * - rightbaty batsize pscale * + between if bally rightbaty < if balldy abs negate to balldy then bally rightbaty batsize ballsize - pscale * + > if balldy abs to balldy then ballx reflect_right_x < if balldx abs random 50 / + negate to balldx rightbaty bally - unscale dup 0 batsize between if batsize 2 / - random * 2 / batsize / 25 / balldy + to balldy else drop then then then then then bally ball_limit_lo_y < if ball_limit_lo_y to bally then bally ball_limit_hi_y > if ball_limit_hi_y to bally then ballx bally moveball

updateball ( delta -- )

ballstop 0= if doupdateball else ballstop -1 = if drop else ballstop swap - to ballstop ballstop 0<= if 0 to ballstop then then then

movebatup ( n oldp delta -- )

{ n oldp delta } erasecol n calcbatx oldp batsize + delta + ballsize delta negate paintrect drawcol n calcbatx oldp delta + ballsize delta negate paintrect

movebatdown ( n oldp delta -- )

{ n oldp delta } erasecol n calcbatx oldp ballsize delta paintrect drawcol n calcbatx oldp batsize + ballsize delta paintrect

movebat ( n oldy newy -- )

{ n oldy newy } newy unscale oldy unscale - dup abs batsize < if dup 0<> if dup 0< if n swap oldy unscale swap movebatup else n swap oldy unscale swap movebatdown then else drop then else drop n oldy erasebat n newy plotbat then

updatebats ( delta -- )

{ delta } 0 leftbaty 0 over bat_limit_lo_y > if key_left_up 0<> if batdy - then then over bat_limit_hi_y < if key_left_down 0<> if batdy + then then delta * over + dup to leftbaty movebat 1 rightbaty 0 over bat_limit_lo_y > if key_right_up 0<> if batdy - then then over bat_limit_hi_y < if key_right_down 0<> if batdy + then then delta * over + dup to rightbaty movebat

initeverything ( -- )

cr 0 to loopcount 0 to totalupdate initvalues 10 0 do scankeys loop doreset get-msecs to glastupdate

doloop ( delta -- )

loopcount 1 + to loopcount dup totalupdate + to totalupdate dup updatebats dup updateball redraw glastupdate + to glastupdate

page 12 emit ; \
runpong ( -- )

initeverything begin get-msecs glastupdate - dup 0> if dup 250 > if drop get-msecs to glastupdate 250 then doloop else drop then scankeys key_esc 0<> if doreset then key_off 0<> until page base @ decimal \ " Count:" type loopcount s. cr " Avg millisec:" type totalupdate loopcount / s. cr base ! \

pong runpong ; \

hex \ pong \ \ \ (end of file) \ \