Annotation of gforth/arch/misc/tt.fs, revision 1.1

1.1     ! pazsan      1: \
        !             2: \ tt.pfe       Tetris for terminals, redone in ANSI-Forth.
        !             3: \              Written 05Apr94 by Dirk Uwe Zoller,
        !             4: \                      e-mail duz@roxi.rz.fht-mannheim.de.
        !             5: \              Look&feel stolen from Mike Taylor's "TETRIS FOR TERMINALS"
        !             6: \ 
        !             7: \              Please copy and share this program, modify it for your system
        !             8: \              and improve it as you like. But don't remove this notice.
        !             9: \ 
        !            10: \              Thank you.
        !            11: \
        !            12: 
        !            13: decimal
        !            14: 
        !            15: : ms  0 ?DO ( $3000 0 DO LOOP ) LOOP ;
        !            16: : blank  bl fill ;
        !            17: 
        !            18: Create pn-tab ," 000102030405060708091011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980"
        !            19: 
        !            20: : pn    ( n -- )  2* pn-tab 1+ + 2 type ;
        !            21: : ;pn   [char] ; emit pn ;
        !            22: : ESC[  27 emit [char] [ emit ;
        !            23: : at-xy 1+ swap 1+ swap ESC[ pn ;pn [char] H emit ;
        !            24: : page  ESC[ ." 2J" 0 0 at-xy ;
        !            25: : d= rot = >r = r> and ;
        !            26: 
        !            27: \ Variables, constants
        !            28: 
        !            29: bl bl 2constant empty          \ an empty position
        !            30: variable wiping                        \ if true: wipe brick, else draw brick
        !            31:  2 constant col0               \ position of the pit
        !            32:  0 constant row0
        !            33: 
        !            34: 10 constant wide               \ size of pit in brick positions
        !            35: 20 constant deep
        !            36: 
        !            37: 'J     value left-key          \ customize if you don't like them
        !            38: 'K     value rot-key
        !            39: 'L     value right-key
        !            40: bl     value drop-key
        !            41: 'P     value pause-key
        !            42: 12     value refresh-key
        !            43: 'Q     value quit-key
        !            44: 
        !            45: : wide* dup 2* 2* + 2* ;
        !            46: 
        !            47: variable score
        !            48: variable pieces
        !            49: variable levels
        !            50: variable delay
        !            51: 
        !            52: variable brow                  \ where the brick is
        !            53: variable bcol
        !            54: 
        !            55: 
        !            56: \ stupid random number generator
        !            57: 
        !            58: variable seed
        !            59: 
        !            60: : randomize    1234 seed ! ( time&date + + + + + seed ! ) ;
        !            61: 
        !            62: 1 cells 4 = [IF]
        !            63: $10450405 Constant generator
        !            64: 
        !            65: : rnd  ( -- n )  seed @ generator um* drop 1+ dup seed ! ;
        !            66: 
        !            67: : random ( n -- 0..n-1 )  rnd um* nip ;
        !            68: [ELSE]
        !            69: : random       \ max --- n ; return random number < max
        !            70:                seed @ 13 * 1+ [ hex ] 07FFF [ decimal ] and
        !            71:                dup seed !  swap mod ;
        !            72: [THEN]
        !            73: 
        !            74: \ Access pairs of characters in memory:
        !            75: 
        !            76: : 2c@          dup 1+ c@ swap c@ ;
        !            77: : 2c!          dup >r c! r> 1+ c! ;
        !            78: 
        !            79: : d<>          d= 0= ;
        !            80: 
        !            81: 
        !            82: \ Drawing primitives:
        !            83: 
        !            84: : 2emit                emit emit ;
        !            85: 
        !            86: : position     \ row col --- ; cursor to the position in the pit
        !            87:                2* col0 + swap row0 + at-xy ;
        !            88: 
        !            89: : stone                \ c1 c2 --- ; draw or undraw these two characters
        !            90:                wiping @ if  2drop 2 spaces  else  2emit  then ;
        !            91: 
        !            92: 
        !            93: \ Define the pit where bricks fall into:
        !            94: 
        !            95: Create pit     wide deep * 2* allot
        !            96: DOES>  rot wide* rot + 2* + ;
        !            97: 
        !            98: : empty-pit    deep 0 do wide 0 do  empty j i pit 2c!
        !            99:                loop loop ;
        !           100: 
        !           101: 
        !           102: \ Displaying:
        !           103: 
        !           104: : draw-bottom  \ --- ; redraw the bottom of the pit
        !           105:                deep -1 position
        !           106:                [char] + dup stone
        !           107:                wide 0 do  [char] = dup stone  loop
        !           108:                [char] + dup stone ;
        !           109: 
        !           110: : draw-frame   \ --- ; draw the border of the pit
        !           111:                deep 0 do
        !           112:                    i -1   position [char] | dup stone
        !           113:                    i wide position [char] | dup stone
        !           114:                loop  draw-bottom ;
        !           115: 
        !           116: : bottom-msg   \ addr cnt --- ; output a message in the bottom of the pit
        !           117:                deep over 2/ wide swap - 2/ position type ;
        !           118: 
        !           119: : draw-line    \ line ---
        !           120:                dup 0 position  wide 0 do  dup i pit 2c@ 2emit  loop  drop ;
        !           121: 
        !           122: : draw-pit     \ --- ; draw the contents of the pit
        !           123:                deep 0 do  i draw-line  loop ;
        !           124: 
        !           125: : show-key     \ char --- ; visualization of that character
        !           126:                dup bl <
        !           127:                if  [char] @ or  [char] ^ emit  emit  space
        !           128:                else  [char] ` emit  emit  [char] ' emit
        !           129:                then ;
        !           130: 
        !           131: : show-help    \ --- ; display some explanations
        !           132:                30  1 at-xy ." ***** T E T R I S *****"
        !           133:                30  2 at-xy ." ======================="
        !           134:                30  4 at-xy ." Use keys:"
        !           135:                32  5 at-xy left-key    show-key ."  Move left"
        !           136:                32  6 at-xy rot-key     show-key ."  Rotate"
        !           137:                32  7 at-xy right-key   show-key ."  Move right"
        !           138:                32  8 at-xy drop-key    show-key ."  Drop"
        !           139:                32  9 at-xy pause-key   show-key ."  Pause"
        !           140:                32 10 at-xy refresh-key show-key ."  Refresh"
        !           141:                32 11 at-xy quit-key    show-key ."  Quit"
        !           142:                32 13 at-xy ." -> "
        !           143:                30 16 at-xy ." Score:"
        !           144:                30 17 at-xy ." Pieces:"
        !           145:                30 18 at-xy ." Levels:"
        !           146:                 0 22 at-xy ."  ==== This program was written 1994 in pure dpANS Forth by Dirk Uwe Zoller ===="
        !           147:                 0 23 at-xy ."  =================== Copy it, port it, play it, enjoy it! =====================" ;
        !           148: 
        !           149: : update-score \ --- ; display current score
        !           150:                38 16 at-xy score @ 3 .r
        !           151:                38 17 at-xy pieces @ 3 .r
        !           152:                38 18 at-xy levels @ 3 .r ;
        !           153: 
        !           154: : refresh      \ --- ; redraw everything on screen
        !           155:                page draw-frame draw-pit show-help update-score ;
        !           156: 
        !           157: 
        !           158: \ Define shapes of bricks:
        !           159: 
        !           160: Create brick1  ,"         ######    ##            "
        !           161: Create brick2  ,"         <><><><>                "
        !           162: Create brick3  ,"           {}{}{}  {}            "
        !           163: Create brick4  ,"         ()()()      ()          "
        !           164: Create brick5  ,"           [][]    [][]          "
        !           165: Create brick6  ,"         @@@@      @@@@          "
        !           166: Create brick7  ,"           %%%%  %%%%            "
        !           167: 
        !           168: \ this brick is actually in use:
        !           169: 
        !           170: Create brick   ,"                                 "
        !           171: DOES>  1+ rot 2* 2* rot + 2* + ;
        !           172: Create scratch ,"                                 "
        !           173: DOES>  1+ rot 2* 2* rot + 2* + ;
        !           174: 
        !           175: create bricks  brick1 1 + ,  brick2 1 + ,  brick3 1 + ,  brick4 1 + ,
        !           176:                brick5 1 + ,  brick6 1 + ,  brick7 1 + ,
        !           177: 
        !           178: create brick-val 1 c, 2 c, 3 c, 3 c, 4 c, 5 c, 5 c,
        !           179: 
        !           180: : is-brick     \ brick --- ; activate a shape of brick
        !           181:                ['] brick >body 1+ 32 cmove ;
        !           182: 
        !           183: : new-brick    \ --- ; select a new brick by random, count it
        !           184:                1 pieces +!  7 random
        !           185:                bricks over cells + @ is-brick
        !           186:                brick-val swap chars + c@ score +! ;
        !           187: 
        !           188: : rotleft      4 0 do 4 0 do
        !           189:                    j i brick 2c@  3 i - j scratch 2c!
        !           190:                loop loop
        !           191:                0 0 scratch is-brick ;
        !           192: 
        !           193: : rotright     4 0 do 4 0 do
        !           194:                    j i brick 2c@  i 3 j - scratch 2c!
        !           195:                loop loop
        !           196:                0 0 scratch is-brick ;
        !           197: 
        !           198: : draw-brick   \ row col ---
        !           199:                4 0 do 4 0 do
        !           200:                    j i brick 2c@  empty d<>
        !           201:                    if  over j + over i +  position
        !           202:                        j i brick 2c@  stone
        !           203:                    then
        !           204:                loop loop  2drop ;
        !           205: 
        !           206: : show-brick   wiping off draw-brick ;
        !           207: : hide-brick   wiping on  draw-brick ;
        !           208: 
        !           209: : put-brick    \ row col --- ; put the brick into the pit
        !           210:                4 0 do 4 0 do
        !           211:                    j i brick 2c@  empty d<>
        !           212:                    if  over j +  over i +  pit
        !           213:                        j i brick 2c@  rot 2c!
        !           214:                    then
        !           215:                loop loop  2drop ;
        !           216: 
        !           217: : remove-brick \ row col --- ; remove the brick from that position
        !           218:                4 0 do 4 0 do
        !           219:                    j i brick 2c@  empty d<>
        !           220:                    if  over j + over i + pit empty rot 2c!  then
        !           221:                loop loop  2drop ;
        !           222: 
        !           223: : test-brick   \ row col --- flag ; could the brick be there?
        !           224:                4 0 do 4 0 do
        !           225:                    j i brick 2c@ empty d<>
        !           226:                    if  over j +  over i +
        !           227:                        over dup 0< swap deep >= or
        !           228:                        over dup 0< swap wide >= or
        !           229:                        2swap pit 2c@  empty d<>
        !           230:                        or or if  unloop unloop 2drop false  exit  then
        !           231:                    then
        !           232:                loop loop  2drop true ;
        !           233: 
        !           234: : move-brick   \ rows cols --- flag ; try to move the brick
        !           235:                brow @ bcol @ remove-brick
        !           236:                swap brow @ + swap bcol @ + 2dup test-brick
        !           237:                if  brow @ bcol @ hide-brick
        !           238:                    2dup bcol ! brow !  2dup show-brick put-brick  true
        !           239:                else  2drop brow @ bcol @ put-brick  false
        !           240:                then ;
        !           241: 
        !           242: : rotate-brick \ flag --- flag ; left/right, success
        !           243:                brow @ bcol @ remove-brick
        !           244:                dup if  rotright  else  rotleft  then
        !           245:                brow @ bcol @ test-brick
        !           246:                over if  rotleft  else  rotright  then
        !           247:                if  brow @ bcol @ hide-brick
        !           248:                    if  rotright  else  rotleft  then
        !           249:                    brow @ bcol @ put-brick
        !           250:                    brow @ bcol @ show-brick  true
        !           251:                else  drop false  then ;
        !           252: 
        !           253: : insert-brick \ row col --- flag ; introduce a new brick
        !           254:                2dup test-brick
        !           255:                if  2dup bcol ! brow !
        !           256:                    2dup put-brick  draw-brick  true
        !           257:                else  false  then ;
        !           258: 
        !           259: : drop-brick   \ --- ; move brick down fast
        !           260:                begin  1 0 move-brick 0=  until ;
        !           261: 
        !           262: : move-line    \ from to ---
        !           263:                over 0 pit  over 0 pit  wide 2*  cmove  draw-line
        !           264:                dup 0 pit  wide 2*  blank  draw-line ;
        !           265: 
        !           266: : line-full    \ line-no --- flag
        !           267:                true  wide 0
        !           268:                do  over i pit 2c@ empty d=
        !           269:                    if  drop false  leave  then
        !           270:                loop nip ;
        !           271: 
        !           272: : remove-lines \ ---
        !           273:                deep deep
        !           274:                begin
        !           275:                    swap
        !           276:                    begin  1- dup 0< if  2drop exit  then  dup line-full
        !           277:                    while  1 levels +!  10 score +!  repeat
        !           278:                    swap 1-
        !           279:                    2dup <> if  2dup move-line  then
        !           280:                again ;
        !           281: 
        !           282: : to-upper     \ char --- char ; convert to upper case
        !           283:                dup [char] a >= over [char] z <= and if  bl -  then ;
        !           284: 
        !           285: : interaction  \ --- flag
        !           286:                case  key to-upper
        !           287:                    left-key    of  0 -1 move-brick drop  endof
        !           288:                    right-key   of  0  1 move-brick drop  endof
        !           289:                    rot-key     of  0 rotate-brick drop  endof
        !           290:                    drop-key    of  drop-brick  endof
        !           291:                    pause-key   of  S"  paused " bottom-msg  key drop
        !           292:                                    draw-bottom  endof
        !           293:                    refresh-key of  refresh  endof
        !           294:                    quit-key    of  false exit  endof
        !           295:                endcase  true ;
        !           296: 
        !           297: : initialize   \ --- ; prepare for playing
        !           298:                randomize empty-pit refresh
        !           299:                0 score !  0 pieces !  0 levels !  100 delay ! ;
        !           300: 
        !           301: : adjust-delay \ --- ; make it faster with increasing score
        !           302:                levels @
        !           303:                dup  50 < if  100 over -  else
        !           304:                dup 100 < if   62 over 4 / -  else
        !           305:                dup 500 < if   31 over 16 / -  else  0  then then then
        !           306:                delay !  drop ;
        !           307: 
        !           308: : play-game    \ --- ; play one tetris game
        !           309:                begin
        !           310:                    new-brick
        !           311:                    -1 3 insert-brick
        !           312:                while
        !           313:                    begin  4 0
        !           314:                        do  35 13 at-xy
        !           315:                            delay @ ms key?
        !           316:                            if  interaction 0=
        !           317:                                if  unloop exit  then
        !           318:                            then
        !           319:                        loop
        !           320:                        1 0 move-brick  0=
        !           321:                    until
        !           322:                    remove-lines
        !           323:                    update-score
        !           324:                    adjust-delay
        !           325:                repeat ;
        !           326: 
        !           327: : tt           \ --- ; play the tetris game
        !           328:                initialize
        !           329:                s"  Press any key " bottom-msg key drop draw-bottom
        !           330:                begin
        !           331:                    play-game
        !           332:                    s"  Again? " bottom-msg key to-upper [char] Y =
        !           333:                while  initialize  repeat
        !           334:                0 23 at-xy cr ;
        !           335: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>