-
Notifications
You must be signed in to change notification settings - Fork 0
/
io.sml
76 lines (69 loc) · 2.38 KB
/
io.sml
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
signature MOVE_IO = sig
type player = string
structure Move : MOVE where type 'a Card.card = string
val printMove : player -> Move.t -> unit
val readMove : player -> Move.t
end
functor MoveIOFn(structure Move : MOVE where type 'a Card.card = string
val prompt : bool) : MOVE_IO where type Move.t = Move.t
=
struct
structure Move = Move
type player = string
structure M = Move
local
fun prompt s =
( app print [s, "\n"]
; TextIO.flushOut TextIO.stdOut
; case TextIO.inputLine TextIO.stdIn
of SOME s => s
| NONE => OS.Process.exit OS.Process.success
)
fun noprompt (_ : string) =
case TextIO.inputLine TextIO.stdIn
of SOME s => s
| NONE => let exception EOF in raise EOF end
fun strip_newline s =
let val n = size s
val last = if n > 0 then String.sub(s, n-1) else #"x"
in if last = #"\n" then
String.substring(s, 0, n-1)
else
s
end
in
val (p, np) = (strip_newline o prompt, strip_newline o noprompt)
end
val prompter = if prompt then p else np
structure Tx = TranslateStringFn(StringCard)
fun printMove player (M.CardToSlot (c, s)) =
app print [player, " applied card ", c, " to slot ", Int.toString s, "\n"]
| printMove player (M.SlotToCard (s, c)) =
app print [player, " applied slot ", Int.toString s, " to card ", c, "\n"]
fun quietMove player (M.CardToSlot (c, s)) =
app print ["1\n", c, "\n", Int.toString s, "\n"]
| quietMove player (M.SlotToCard (s, c)) =
app print ["2\n", Int.toString s, "\n", c, "\n"]
val printMove = if prompt then printMove else quietMove
fun readMove player =
case prompter "(1) apply card to slot, or (2) apply slot to card?"
of "1" => readCardToSlot ()
| "2" => readSlotToCard ()
| _ => readMove player
and readCardToSlot () =
let val card = readCard ()
val slot = readSlot ()
in M.CardToSlot (card, slot)
end
and readSlotToCard () =
let val slot = readSlot ()
val card = readCard ()
in M.SlotToCard (slot, card)
end
and readCard () =
Tx.translate (prompter "card name?") handle Tx.Failed _ => readCard ()
and readSlot () =
case Int.fromString (prompter "slot no?")
of SOME n => n
| NONE => readSlot ()
end