Mercurial > hg > Members > kono > os9 > sbc09
diff examples_forth/tetris.4 @ 57:2088fd998865
sbc09 directry clean up
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 23 Jul 2018 16:07:12 +0900 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples_forth/tetris.4 Mon Jul 23 16:07:12 2018 +0900 @@ -0,0 +1,374 @@ +\ +\ tetris.4th Tetris for terminals, redone in ANSI-Forth. +\ Written 05Apr94 by Dirk Uwe Zoller, e-mail: +\ duz@roxi.rz.fht-mannheim.de. +\ Look&feel stolen from Mike Taylor's "TETRIS FOR TERMINALS" +\ +\ Please copy and share this program, modify it for your system +\ and improve it as you like. But don't remove this notice. +\ +\ Thank you. +\ +\ Changes: +\ +\ + +ONLY FORTH DEFINITIONS +\ S" FORGET-TT" DROP 1 CHARS - FIND NIP [IF] FORGET-TT [THEN] +\ MARKER FORGET-TT + +DECIMAL + +WORDLIST CONSTANT TETRIS +GET-ORDER TETRIS DUP ROT 2 + SET-ORDER DEFINITIONS + + +\ Variables, constants + +BL BL 2CONSTANT EMPTY \ an empty position +VARIABLE WIPING \ if true: wipe brick, else draw brick +2 CONSTANT COL0 \ position of the pit on screen +0 CONSTANT ROW0 + +10 CONSTANT WIDE \ size of pit in brick positions +20 CONSTANT DEEP + +CHAR J VALUE LEFT-KEY \ customize if you don't like them +CHAR K VALUE ROT-KEY +CHAR L VALUE RIGHT-KEY +BL VALUE DROP-KEY +CHAR P VALUE PAUSE-KEY +12 VALUE REFRESH-KEY +CHAR Q VALUE QUIT-KEY + +VARIABLE SCORE +VARIABLE PIECES +VARIABLE LEVELS +VARIABLE DELAY + +VARIABLE BROW \ where the brick is +VARIABLE BCOL + + +\ stupid random number generator + +VARIABLE SEED + +: RANDOMIZE 0 ." Press any key." CR BEGIN 1+ KEY? UNTIL KEY DROP SEED ! ; + +: RANDOM \ max --- n ; return random number < max + SEED @ 1103515245 * 12345 + [ HEX ] 07FFF [ DECIMAL ] AND + DUP SEED ! SWAP MOD ; + + +\ Access pairs of characters in memory: + +: 2C@ DUP 1+ C@ SWAP C@ ; +: 2C! DUP >R C! R> 1+ C! ; + + +: <= > INVERT ; +: >= < INVERT ; +: D<> D= INVERT ; + + +\ Drawing primitives: + +: 2EMIT EMIT EMIT ; + +: POSITION \ row col --- ; cursor to the position in the pit + 2* COL0 + SWAP ROW0 + AT-XY ; + +: STONE \ c1 c2 --- ; draw or undraw these two characters + WIPING @ IF 2DROP 2 SPACES ELSE 2EMIT THEN ; + + +\ Define the pit where bricks fall into: + +: DEF-PIT CREATE WIDE DEEP * 2* ALLOT + DOES> ROT WIDE * ROT + 2* CHARS + ; + +DEF-PIT PIT + +: EMPTY-PIT DEEP 0 DO WIDE 0 DO EMPTY J I PIT 2C! + LOOP LOOP ; + + +\ Displaying: + +: DRAW-BOTTOM \ --- ; redraw the bottom of the pit + DEEP -1 POSITION + [CHAR] + DUP STONE + WIDE 0 DO [CHAR] = DUP STONE LOOP + [CHAR] + DUP STONE ; + +: DRAW-FRAME \ --- ; draw the border of the pit + DEEP 0 DO + I -1 POSITION [CHAR] | DUP STONE + I WIDE POSITION [CHAR] | DUP STONE + LOOP DRAW-BOTTOM ; + +: BOTTOM-MSG \ addr cnt --- ; output a message in the bottom of the pit + DEEP OVER 2/ WIDE SWAP - 2/ POSITION TYPE ; + +: DRAW-LINE \ line --- + DUP 0 POSITION WIDE 0 DO DUP I PIT 2C@ 2EMIT LOOP DROP ; + +: DRAW-PIT \ --- ; draw the contents of the pit + DEEP 0 DO I DRAW-LINE LOOP ; + +: SHOW-KEY \ char --- ; visualization of that character + DUP BL < + IF [CHAR] @ OR [CHAR] ^ EMIT EMIT SPACE + ELSE [CHAR] ` EMIT EMIT [CHAR] ' EMIT + THEN ; + +: SHOW-HELP \ --- ; display some explanations + 30 1 AT-XY ." ***** T E T R I S *****" + 30 2 AT-XY ." =======================" + 30 4 AT-XY ." Use keys:" + 32 5 AT-XY LEFT-KEY SHOW-KEY ." Move left" + 32 6 AT-XY ROT-KEY SHOW-KEY ." Rotate" + 32 7 AT-XY RIGHT-KEY SHOW-KEY ." Move right" + 32 8 AT-XY DROP-KEY SHOW-KEY ." Drop" + 32 9 AT-XY PAUSE-KEY SHOW-KEY ." Pause" + 32 10 AT-XY REFRESH-KEY SHOW-KEY ." Refresh" + 32 11 AT-XY QUIT-KEY SHOW-KEY ." Quit" + 32 13 AT-XY ." -> " + 30 16 AT-XY ." Score:" + 30 17 AT-XY ." Pieces:" + 30 18 AT-XY ." Levels:" + 0 22 AT-XY ." ======= This program was written 1994 in ANS Forth by Dirk Uwe Zoller ========" + 0 23 AT-XY ." =================== Copy it, port it, play it, enjoy it! =====================" ; + +: UPDATE-SCORE \ --- ; display current score + 38 16 AT-XY SCORE @ 3 .R + 38 17 AT-XY PIECES @ 3 .R + 38 18 AT-XY LEVELS @ 3 .R ; + +: REFRESH \ --- ; redraw everything on screen + PAGE DRAW-FRAME DRAW-PIT SHOW-HELP UPDATE-SCORE ; + + +\ Define shapes of bricks: + +: DEF-BRICK CREATE 4 0 DO + ' EXECUTE 0 DO DUP I CHARS + C@ C, LOOP DROP + REFILL DROP + LOOP + DOES> ROT 4 * ROT + 2* CHARS + ; + +DEF-BRICK BRICK1 S" " + S" ###### " + S" ## " + S" " + +DEF-BRICK BRICK2 S" " + S" <><><><>" + S" " + S" " + +DEF-BRICK BRICK3 S" " + S" {}{}{}" + S" {} " + S" " + +DEF-BRICK BRICK4 S" " + S" ()()() " + S" () " + S" " + +DEF-BRICK BRICK5 S" " + S" [][] " + S" [][] " + S" " + +DEF-BRICK BRICK6 S" " + S" @@@@ " + S" @@@@ " + S" " + +DEF-BRICK BRICK7 S" " + S" %%%% " + S" %%%% " + S" " + +\ this brick is actually in use: + +DEF-BRICK BRICK S" " + S" " + S" " + S" " + +DEF-BRICK SCRATCH S" " + S" " + S" " + S" " + +CREATE BRICKS ' BRICK1 , ' BRICK2 , ' BRICK3 , ' BRICK4 , + ' BRICK5 , ' BRICK6 , ' BRICK7 , + +CREATE BRICK-VAL 1 C, 2 C, 3 C, 3 C, 4 C, 5 C, 5 C, + + +: IS-BRICK \ brick --- ; activate a shape of brick + >BODY ['] BRICK >BODY 32 CMOVE ; + +: NEW-BRICK \ --- ; select a new brick by random, count it + 1 PIECES +! 7 RANDOM + BRICKS OVER CELLS + @ IS-BRICK + BRICK-VAL SWAP CHARS + C@ SCORE +! ; + +: ROTLEFT 4 0 DO 4 0 DO + J I BRICK 2C@ 3 I - J SCRATCH 2C! + LOOP LOOP + ['] SCRATCH IS-BRICK ; + +: ROTRIGHT 4 0 DO 4 0 DO + J I BRICK 2C@ I 3 J - SCRATCH 2C! + LOOP LOOP + ['] SCRATCH IS-BRICK ; + +: DRAW-BRICK \ row col --- + 4 0 DO 4 0 DO + J I BRICK 2C@ EMPTY D<> + IF OVER J + OVER I + POSITION + J I BRICK 2C@ STONE + THEN + LOOP LOOP 2DROP ; + +: SHOW-BRICK FALSE WIPING ! DRAW-BRICK ; +: HIDE-BRICK TRUE WIPING ! DRAW-BRICK ; + +: PUT-BRICK \ row col --- ; put the brick into the pit + 4 0 DO 4 0 DO + J I BRICK 2C@ EMPTY D<> + IF OVER J + OVER I + PIT + J I BRICK 2C@ ROT 2C! + THEN + LOOP LOOP 2DROP ; + +: REMOVE-BRICK \ row col --- ; remove the brick from that position + 4 0 DO 4 0 DO + J I BRICK 2C@ EMPTY D<> + IF OVER J + OVER I + PIT EMPTY ROT 2C! THEN + LOOP LOOP 2DROP ; + +: TEST-BRICK \ row col --- flag ; could the brick be there? + 4 0 DO 4 0 DO + J I BRICK 2C@ EMPTY D<> + IF OVER J + OVER I + + OVER DUP 0< SWAP DEEP >= OR + OVER DUP 0< SWAP WIDE >= OR + 2SWAP PIT 2C@ EMPTY D<> + OR OR IF UNLOOP UNLOOP 2DROP FALSE EXIT THEN + THEN + LOOP LOOP 2DROP TRUE ; + +: MOVE-BRICK \ rows cols --- flag ; try to move the brick + BROW @ BCOL @ REMOVE-BRICK + SWAP BROW @ + SWAP BCOL @ + 2DUP TEST-BRICK + IF BROW @ BCOL @ HIDE-BRICK + 2DUP BCOL ! BROW ! 2DUP SHOW-BRICK PUT-BRICK TRUE + ELSE 2DROP BROW @ BCOL @ PUT-BRICK FALSE + THEN ; + +: ROTATE-BRICK \ flag --- flag ; left/right, success + BROW @ BCOL @ REMOVE-BRICK + DUP IF ROTRIGHT ELSE ROTLEFT THEN + BROW @ BCOL @ TEST-BRICK + OVER IF ROTLEFT ELSE ROTRIGHT THEN + IF BROW @ BCOL @ HIDE-BRICK + IF ROTRIGHT ELSE ROTLEFT THEN + BROW @ BCOL @ PUT-BRICK + BROW @ BCOL @ SHOW-BRICK TRUE + ELSE DROP FALSE THEN ; + +: INSERT-BRICK \ row col --- flag ; introduce a new brick + 2DUP TEST-BRICK + IF 2DUP BCOL ! BROW ! + 2DUP PUT-BRICK DRAW-BRICK TRUE + ELSE 2DROP FALSE THEN ; + +: DROP-BRICK \ --- ; move brick down fast + BEGIN 1 0 MOVE-BRICK 0= UNTIL ; + +: MOVE-LINE \ from to --- + OVER 0 PIT OVER 0 PIT WIDE 2* CMOVE DRAW-LINE + DUP 0 PIT WIDE 2* BLANK DRAW-LINE ; + +: LINE-FULL \ line-no --- flag + TRUE WIDE 0 + DO OVER I PIT 2C@ EMPTY D= + IF DROP FALSE LEAVE THEN + LOOP NIP ; + +: REMOVE-LINES \ --- + DEEP DEEP + BEGIN + SWAP + BEGIN 1- DUP 0< IF 2DROP EXIT THEN DUP LINE-FULL + WHILE 1 LEVELS +! 10 SCORE +! REPEAT + SWAP 1- + 2DUP <> IF 2DUP MOVE-LINE THEN + AGAIN ; + +: TO-UPPER \ char --- char ; convert to upper case + DUP [CHAR] a >= OVER [CHAR] z <= AND + IF [ CHAR A CHAR a - ] LITERAL + THEN ; + +: DISPATCH \ key --- flag + CASE TO-UPPER + LEFT-KEY OF 0 -1 MOVE-BRICK DROP ENDOF + RIGHT-KEY OF 0 1 MOVE-BRICK DROP ENDOF + ROT-KEY OF 0 ROTATE-BRICK DROP ENDOF + DROP-KEY OF DROP-BRICK ENDOF + PAUSE-KEY OF S" Paused " BOTTOM-MSG KEY DROP + DRAW-BOTTOM ENDOF + REFRESH-KEY OF REFRESH ENDOF + QUIT-KEY OF FALSE EXIT ENDOF + ENDCASE TRUE ; + +: INITIALIZE \ --- ; prepare for playing + RANDOMIZE EMPTY-PIT REFRESH + 0 SCORE ! 0 PIECES ! 0 LEVELS ! 100 DELAY ! ; + +: ADJUST-DELAY \ --- ; make it faster with increasing score + LEVELS @ + DUP 50 < IF 100 OVER - ELSE + DUP 100 < IF 62 OVER 4 / - ELSE + DUP 500 < IF 31 OVER 16 / - ELSE 0 THEN THEN THEN + DELAY ! DROP ; + +: PLAY-GAME \ --- ; play one tetris game + BEGIN + NEW-BRICK + -1 3 INSERT-BRICK + WHILE + BEGIN 4 0 + DO 35 13 AT-XY + DELAY @ MS KEY? + IF BEGIN KEY KEY? WHILE DROP REPEAT + DISPATCH 0= + IF UNLOOP EXIT THEN + THEN + LOOP + 1 0 MOVE-BRICK 0= + UNTIL + REMOVE-LINES + UPDATE-SCORE + ADJUST-DELAY + REPEAT ; + +FORTH DEFINITIONS + +: TT \ --- ; play the tetris game + INITIALIZE + S" Press any key " BOTTOM-MSG KEY DROP DRAW-BOTTOM + BEGIN + PLAY-GAME + S" Again? " BOTTOM-MSG KEY TO-UPPER [CHAR] Y = + WHILE INITIALIZE REPEAT + 0 23 AT-XY CR ; + +ONLY FORTH ALSO DEFINITIONS