1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372
|
\
\ tt.pfe 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.
\
only forth also definitions
[ifdef] forget-tt forget-tt [then] marker forget-tt
vocabulary tetris tetris also definitions
decimal
\ 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
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 time&date + + + + + seed ! ;
1 cells 4 = [IF]
$10450405 Constant generator
: rnd ( -- n ) seed @ generator um* drop 1+ dup seed ! ;
: random ( n -- 0..n-1 ) rnd um* nip ;
[ELSE]
: random \ max --- n ; return random number < max
seed @ 13 * [ hex ] 07FFF [ decimal ] and
dup seed ! swap mod ;
[THEN]
\ Access pairs of characters in memory:
: 2c@ dup 1+ c@ swap c@ ;
: 2c! dup >r c! r> 1+ c! ;
: d<> d= 0= ;
\ 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* + ;
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 pure dpANS 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* + ;
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 wiping off draw-brick ;
: hide-brick wiping on 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 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 [char] z 1+ within if
bl -
then ;
: interaction \ --- flag
case key 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 interaction 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
|