4 val main
: string * string list
-> OS
.Process
.status
9 val cursorhome
= "\^[[H"
10 val invisiblecursor
= "\^[[?25l"
11 val visiblecursor
= "\^[[?25h"
14 concat
["\^[[", Int.toString y
, ";", Int.toString x
, "H"]
18 fun helper (i
, x
, y
, acc
) =
19 if i
>= String.size str
then
22 case String.sub (str
, i
) of
23 #
"\n" => helper (i
+ 1, 0, y
+ 1, acc
)
24 (* map coordinates are
1-based
*)
25 | #
"#" => helper (i
+ 1, x
+ 1, y
, (x
+ 1, y
+ 1) :: acc
)
26 | _
=> helper (i
+ 1, x
+ 1, y
, acc
)
31 fun contains (_
, []) = false
32 |
contains (x
, y
::rest
) = (x
= y
) orelse contains (x
, rest
)
34 datatype direction
= LEFT | DOWN | UP | RIGHT | LEFTUP | RIGHTUP | LEFTDOWN | RIGHTDOWN
36 fun draw_move (p1
, p2
) =
37 cursorpos p1 ^
"." ^ cursorpos p2 ^
"@"
39 fun move (walls
, pawns
, point
as (x
, y
), direction
) =
41 val (dx
, dy
) = case direction
of
49 | RIGHTDOWN
=> ( 1, 1)
50 val newpoint
as (newx
, newy
) = (x
+ dx
, y
+ dy
)
52 if newx
>= 1 andalso newy
>= 1 andalso not(contains(newpoint
, walls
)) andalso
53 not(contains(newpoint
, pawns
)) then
54 (print (draw_move(point
, newpoint
));
55 {point
= newpoint
, quit
= false})
57 {point
= point
, quit
= false}
60 fun travel (walls
, pawns
, point
, direction
) =
62 val state
= move(walls
, pawns
, point
, direction
)
63 val {point
= newpoint
, ...} = state
65 if newpoint
= point
then state
else
66 (OS
.Process
.sleep(Time
.fromMilliseconds
15); travel (walls
, pawns
, newpoint
, direction
))
69 fun start_turns (walls
, pawns
) =
71 fun get_command (curpoint
) =
72 case TextIO.input1
TextIO.stdIn
of
75 val next
= case byte
of
76 | #
"h" => move(walls
, pawns
, curpoint
, LEFT
)
77 | #
"j" => move(walls
, pawns
, curpoint
, DOWN
)
78 | #
"k" => move(walls
, pawns
, curpoint
, UP
)
79 | #
"l" => move(walls
, pawns
, curpoint
, RIGHT
)
80 | #
"y" => move(walls
, pawns
, curpoint
, LEFTUP
)
81 | #
"u" => move(walls
, pawns
, curpoint
, RIGHTUP
)
82 | #
"b" => move(walls
, pawns
, curpoint
, LEFTDOWN
)
83 | #
"n" => move(walls
, pawns
, curpoint
, RIGHTDOWN
)
84 | #
"q" => {point
= curpoint
, quit
= true}
85 | _
=> {point
= curpoint
, quit
= false}
89 | NONE
=> {point
=curpoint
, quit
=true} (* EOF is not possible
in raw mode
*)
91 fun do_turn
{point
, quit
} =
93 val next
= case TextIO.canInput (TextIO.stdIn
, 1) of
94 | NONE
=> {point
=point
, quit
=true}
95 | SOME
0 => {point
=point
, quit
=false}
96 | SOME _
=> get_command (point
)
99 |
{quit
=true, ...} => ()
101 (OS
.Process
.sleep(Time
.fromMilliseconds
500);
106 do_turn
{point
= (9,4), quit
= false}
109 fun main (prgname
, argv
) =
111 val mapfile
= TextIO.openIn
"default.map"
112 val map
= TextIO.input mapfile
113 val _
= TextIO.closeIn mapfile
114 val pawns
= [(3, 5), (4, 4), (9, 2)]
115 val walls
= find_walls map
118 print (clrscr ^ cursorhome ^ invisiblecursor ^ map
);
119 print (concat(List.map(fn e
=> cursorpos e ^
"&") pawns
));
121 start_turns (walls
, pawns
);
122 print (clrscr ^ cursorhome ^ visiblecursor
);