Towers of Hanoi
by
Ricardo Fernandes Lopes
( Towers of Hanoi game ) ( by Ricardo F. Lopes - 2006 ) ( Use keys 1, 2 and 3 to play ) 0 VARIABLE MOV# ( Move count ) : MOV+1 ( Increment move count ) MOV# @ 1+ MOV# ! ; CREATE T 24 ALLOT ( Towers array: 3 poles, 8 lines ) : T> ( pole line -- c-adr ) 3 * + T + ; : RING@ ( pole line -- ring ) T> C@ ; : RING! ( ring pole line -- ) T> C! ; : INIT ( Initialize game ) 0 MOV# ! ( Reset move count) 8 0 ( Set rings) DO 7 I - ( ring size) 0 I RING! ( Put all rings in pole 1) 0 1 I RING! ( empty pole 2) 0 2 I RING! ( empty pole 3) LOOP ; : .FRAME ( draw poles ) 7 0 ( poles with 7 lines) DO 8 SPACES ( left margin) 3 0 ( 3 poles) DO ." | " LOOP LOOP 32 0 ( bottom line) DO ASCII _ EMIT LOOP ." 1 2 3" ( pole labels) ; : .RING ( ring line pole -- , Draw a ring) 1+ 16 * 3 PICK - ( x = pole+1 * 16 - ring) SWAP 2 * 32 + ( y = line*2 + 32 ) ROT 2 * 2+ 0 ( ringsize = ring*2 + 2 ) DO ( Plot ring) OVER I + OVER 1 PLOT LOOP DROP DROP ; : SHOW ( Draw everything) CLS .FRAME CR CR ." Moves: " MOV# @ . ( Show moves) 3 0 ( Three Poles) DO 7 0 ( Seven Lines) DO J I RING@ ?DUP IF ( Is there a ring?) I J .RING ( Draw the ring) THEN LOOP LOOP ; : TOP> ( pole -- pole line , Find free line over the rings in a pole) 0 ( dummy previous line) 8 0 ( check 8 lines ) DO DROP ( discard previous line) I OVER OVER RING@ ( Get ring in current line) 0= IF ( Free line? Done ) LEAVE THEN LOOP ; : END? ( -- flag , Check for end of game) 0 ( sum = 0) 7 0 ( 7 lines) DO 2 I RING@ + ( Sum all rings in pole 3) LOOP 28 = ( Game over if sum of rings = 28) ; : MOV ( from to -- , Move a ring from one pole to another) OVER TOP> ?DUP IF ( Is there a ring in the source?) 1- RING@ ( Get top ring from source ) OVER TOP> ?DUP IF ( Destination not empty?) 1- RING@ ( Yes, get top ring from destination) ELSE ( The destination is empty..) DROP 8 ( ..assume top destination ring = 8) THEN OVER > ( Smaller ring over bigger?) IF SWAP TOP> RING! ( Place ring in the destination pole) 0 SWAP TOP> 1- RING! ( Remove ring from source) MOV+1 ( Count move) ELSE ( Invalid move, do nothing) DROP DROP DROP THEN ELSE ( No rings in source, do nothing) DROP DROP DROP THEN ; : KEY? ( -- n , Get user input) BEGIN INKEY 0= UNTIL ( Wait for key release) BEGIN INKEY ?DUP UNTIL ( Wait for a keypress) ASCII 0 - 1 MAX 3 MIN ( convert key 1-3 to number 1-3) ; : HANOI ( Main word, execute it to play) INIT ( Init variables) SHOW ( Draw screen) BEGIN ( Main game loop) CR ." From? " KEY? DUP . 1- ( Get user "from" input) CR ." To? " KEY? DUP . 1- ( Get user "to" input) MOV ( Move ring as commanded) SHOW ( Update screen) END? ( Check for success) UNTIL ; |
|