sourcegames/guess/NumberGuess.xtl
1⍝# Guess the number's rules, a library: guess.xtl (scripted games),
2⍝# play.xtl (at the terminal) and the web page all use these. The
3⍝# computer thinks of a number from 1 to 100; each guess is answered
4⍝# higher, lower or correct.
5
6⍝ :: Int
7⍝# The largest number the player may pick.
8ˡtop ← 100
9⍝ :: Int -> Int
10⍝# A new game: the secret, 1 to n.
11ˡn̲ew ← { n → r̲oll! n }
12⍝ :: (Ord a, Num b, Truthy b) => a -> a -> b
13⍝# The answer to guess g for secret t: -1 the secret is higher, 1 lower,
14⍝# 0 right; the sign of the difference as a fork, (t < g) - (t > g).
15⍝# Item by item, so it answers many guesses (or games) at once.
16ˡm̲ove ← { t g → t [< − >] g }
17⍝ :: (Eq a, Truthy b) => a -> a -> b
18⍝# 1 once the guess is right.
19ˡs̲tatus ← { t g → t = g }
20⍝ :: Int -> Char
21⍝# The answer as the BASIC printed it.
22ˡr̲eply ← { r → d̲isclose (2 + r) s̲elect "HIGHER!" "CORRECT! YOU GUESSED IT." "LOWER!" }
23
24⍝ :: Int -> Int
25⍝# The halving player: the range still possible, low and high, as a
26⍝# 2-row matrix with a column per game; its guess is the middle.
27ˡg̲uess ← { b → ('+ r̲/ b) d̲iv 2 }
28⍝ :: Num a => Int -> a -> Int
29⍝# Narrow every range by the answers to its guess: a higher answer
30⍝# raises the low end past the guess, a lower one drops the high end
31⍝# below it (a max and a min that leave the other answers alone).
32ˡn̲arrow ← { b r →
33 g ← ˡg̲uess b
34 lo ← (1 s̲elect b) m̲ax (g + 1) × r = -1
35 hi ← (2 s̲elect b) m̲in (g − 1) + ˡtop × r ≠ 1
36 (2 c̲at s̲hape lo) r̲eshape lo c̲at hi
37}
38
39⍝ :: Truthy a => Int -> Int -> a
40⍝# The secrets still possible after guesses gs were answered for secret
41⍝# t: every candidate 1 to 100 against every guess at once (a table of
42⍝# answers, candidates by guesses), kept where its whole row agrees with
43⍝# the answers t got: a 0/1 vector of 100.
44ˡp̲ossible ← { t gs →
45 m ← (r̲ange ˡtop) 'ˡm̲ove t̲able gs
46 '∧ r̲/₂ m = (s̲hape m) r̲eshape ˡtop 'r̲ight t̲able t ˡm̲ove gs
47}