Files
sml-projects/game-sml/shell/parse-controls.sml

167 lines
4.2 KiB
Standard ML
Raw Permalink Normal View History

2025-02-17 03:13:45 +00:00
structure ParseControls =
struct
datatype action =
ACTION_LEFT
| ACTION_RIGHT
| ACTION_UP
| ACTION_DOWN
| ACTION_JUMP
| ACTION_ATTACK
fun actionFromString str =
case str of
"ACTION_LEFT" => SOME ACTION_LEFT
| "ACTION_RIGHT" => SOME ACTION_RIGHT
| "ACTION_UP" => SOME ACTION_UP
| "ACTION_DOWN" => SOME ACTION_DOWN
| "ACTION_JUMP" => SOME ACTION_JUMP
2025-02-17 03:13:45 +00:00
| "ACTION_ATTACK" => SOME ACTION_ATTACK
| _ => NONE
fun findColon (pos, str) =
if pos = String.size str then
~1
else
let val chr = String.sub (str, pos)
in if chr = #":" then pos else findColon (pos + 1, str)
end
type parsed_keys =
{ left: CoreKey.key_code option
, right: CoreKey.key_code option
, up: CoreKey.key_code option
, down: CoreKey.key_code option
, jump: CoreKey.key_code option
, attack: CoreKey.key_code option
}
fun updateControls (action, key, controls: parsed_keys) =
let
val {left, right, up, down, jump, attack} = controls
in
case action of
ACTION_LEFT =>
{ left = SOME key
, right = right
, up = up
, down = down
, jump = jump
, attack = attack
}
| ACTION_RIGHT =>
{ left = left
, right = SOME key
, up = up
, down = down
, jump = jump
, attack = attack
}
| ACTION_UP =>
{ left = left
, right = right
, up = SOME key
, down = down
, jump = jump
, attack = attack
}
| ACTION_DOWN =>
{ left = left
, right = right
, up = up
, down = SOME key
, jump = jump
, attack = attack
}
| ACTION_JUMP =>
{ left = left
, right = right
, up = up
, down = down
, jump = SOME key
, attack = attack
}
| ACTION_ATTACK =>
{ left = left
, right = right
, up = up
, down = down
, jump = jump
, attack = SOME key
}
end
fun returnControls controls =
let
val {left, right, up, down, jump, attack} = controls
in
case (left, right, up, down, jump, attack) of
(SOME left, SOME right, SOME up, SOME down, SOME jump, SOME attack) =>
SOME
{ left = left
, right = right
, up = up
, down = down
, jump = jump
, attack = attack
, escape = CoreKey.KEY_ESCAPE
2025-02-17 03:13:45 +00:00
}
| _ => NONE
end
(* We don't want to attempt to parse strings
* which have trailing spaces or newlines
* so get the length of the last non-space chr *)
fun getLastPos (pos, line) =
if pos = String.size line then
String.size line - 1
else
let val chr = String.sub (line, pos)
in if Char.isSpace chr then pos - 1 else getLastPos (pos + 1, line)
end
2025-02-17 03:13:45 +00:00
fun helpParse (controls, io) =
case TextIO.inputLine io of
SOME line =>
let
val colon = findColon (0, line)
in
if colon = ~1 then
helpParse (controls, io)
else
let
val actionString = String.substring (line, 0, colon)
2025-02-17 03:13:45 +00:00
val action = actionFromString actionString
val keyStart = colon + 1
val keyFinish = getLastPos (keyStart, line)
val keyLength = keyFinish - keyStart + 1
val keyString = String.substring (line, keyStart, keyLength)
2025-02-17 03:13:45 +00:00
val key = CoreKey.keyFromString keyString
val controls =
(case (action, key) of
(SOME action, SOME key) =>
updateControls (action, key, controls)
| (_, _) => controls)
in
helpParse (controls, io)
end
end
| NONE => let val () = TextIO.closeIn io in returnControls controls end
2025-02-17 03:13:45 +00:00
fun parse () =
let
val initial =
{ left = NONE
, right = NONE
, up = NONE
, down = NONE
, jump = NONE
, attack = NONE
}
val io = TextIO.openIn "controls.config"
in
helpParse (initial, io)
end
end