diff options
Diffstat (limited to 'forth/guesser.fth')
-rw-r--r-- | forth/guesser.fth | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/forth/guesser.fth b/forth/guesser.fth new file mode 100644 index 0000000..01d84a0 --- /dev/null +++ b/forth/guesser.fth @@ -0,0 +1,100 @@ +\ --- Number Guessing Game for pForth --- + +\ First, we need some helper words for reliable numeric input. +\ These are based on the pForth tutorial. +( -- $addr ) +: INPUT$ ( A word to get a line of text from the user ) + PAD 1+ ( addr --- , leave room on the scratchpad for a byte count ) + 80 ACCEPT ( addr maxbytes -- numbytes , get up to 80 chars ) + PAD C! ( numbytes --- , store the count in the first byte ) + PAD ( -- $addr , leave the address of the counted string ) +; + +( -- n true | false ) +: INPUT# ( Read a line and convert it to a number ) + INPUT$ ( -- $addr ) + NUMBER? ( $addr -- d_num true | false , convert string to double ) + IF + SWAP DROP TRUE ( d_num true -- n true , drop high part of double ) + ELSE + FALSE ( -- false ) + THEN +; + +\ --- Game Logic --- + +VARIABLE SECRET# \ A place to store the secret number. + +( -- ) +: INIT-SECRET# ( Generate and store a random number ) + 501 CHOOSE ( -- rand , CHOOSE gives a number from 0 to n-1 ) + SECRET# ! ( rand -- , store it in our variable ) +; + +( -- n ) +: GET-GUESS ( Loop until the user enters a valid number ) + BEGIN + CR ." Your guess (0-500)? " + INPUT# ( -- n true | false ) + UNTIL ( loops until flag is true ) +; + +( guess -- correct? ) +: CHECK-GUESS ( Compares guess to the secret number, gives a hint ) + SECRET# @ ( guess -- guess secret# ) + 2DUP = ( guess secret# -- guess secret# flag ) + IF ( guess is equal to secret# ) + ." You got it!" CR + 2DROP TRUE \ --> Make sure this 2DROP is here. + ELSE ( guess is not equal ) + 2DUP < ( guess secret# -- guess secret# flag ) + IF + ." Too low!" CR + 2DROP FALSE \ --> And this one. + ELSE + ." Too high!" CR + 2DROP FALSE \ --> And this one. + THEN + THEN +; + +( -- ) +: SEED-BY-WAITING ( Uses user's reaction time to seed the PRNG ) + CR ." Press any key to begin..." + BEGIN + 501 CHOOSE DROP \ "Burn" a random number from the sequence + ?TERMINAL \ Check if a key has been pressed + UNTIL + CR +; + +( -- ) +: GUESSING-GAME ( The main word to run the game ) + SEED-BY-WAITING \ Call our new interactive seeder + INIT-SECRET# + CR ." I'm thinking of a number between 0 and 500." + CR ." You have 5 chances to guess it." + + FALSE ( -- user-won? , place a 'false' flag on the stack ) + + 5 0 DO ( loop 5 times, from 0 to 4 ) + CR 5 I - . ." guesses left." + GET-GUESS + CHECK-GUESS ( guess -- correct? ) + IF ( a correct guess was made ) + DROP TRUE ( replace the 'user-won?' flag with 'true' ) + LEAVE ( and exit the loop immediately ) + THEN + LOOP + + ( The 'user-won?' flag is now on top of the stack ) + IF + CR ." Congratulations!" CR + ELSE + CR ." Sorry, you ran out of guesses." + CR ." The number was " SECRET# @ . CR + THEN +; + +GUESSING-GAME \ This line executes the game word we just defined. +BYE \ This tells pForth to exit when the game is over. |