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
|
\ --- 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.
|