Annotation of gforth/arch/r8c/tt.fs, revision 1.6

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

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