-
Notifications
You must be signed in to change notification settings - Fork 0
/
validate.ml
137 lines (116 loc) · 4.16 KB
/
validate.ml
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
open Convert
open Command
open State
(*****************************************************************************
* DIFFERENT INVALID COMMANDS TO BE RETURNED
*****************************************************************************)
let undefined_command = {
valid = false; err_message = "The command you typed in is undefined!";
action = ""; target = ""
}
let too_many_arguments = {
valid = false; err_message = "This command takes no argument!";
action = ""; target = ""
}
let missing_key = {
valid = false;
err_message =
"You can't enter that room because you are missing some required item(s)";
action = "";
target = ""
}
let no_such_exit = {
valid = false; err_message = "There is nothing in that direction!";
action = ""; target = ""
}
let already_in_inv = {
valid = false; err_message = "This item is already in your inventory!";
action = ""; target = ""
}
let no_such_item = {
valid = false; err_message = "There is no such item in this room!";
action = ""; target = ""
}
let not_in_inv = {
valid = false; err_message = "This item is not in your inventory!";
action = ""; target = ""
}
let unknown_error = {
valid = false;
err_message = "Some unknown error occurs. Please doublecheck the game file.";
action = ""; target = ""
}
(*****************************************************************************
* FUNCTIONS
*****************************************************************************)
(* [get_exits_list room] is the list of all exits of [room]. *)
let get_exits_list room =
List.map (fun e -> e.direction) room.exits
(* [item_is_in_room item state] returns true if [item] is in current room,
false otherwise.
*)
let item_is_in_room it st =
Pervasives.snd
(List.find (fun (k,v) -> it = String.lowercase_ascii k)
(LocationMap.bindings (locations_map st))) = current_room_id st
(* [validate_commands12 command] is [command] if target field is empty,
otherwise return an invalid command with appropriate error message.
requires: [command.action] is one of the command in [Command.commands1] or
[Command.commands2].
*)
let validate_commands12 c =
if c.target = "" then c
else too_many_arguments
(* [validate_go command state] changes [state] according to [command] if it
is valid (the exit exists and all required keys are present), or return
an invalid command with error message otherwise.
requires: [command.action = "go"]
*)
let validate_go c s =
let exits_id_list = get_exits_list (current_room s) in
let exits_list = (current_room s).exits in
if List.mem c.target exits_id_list then
if is_sublist
(List.find
(fun e -> e.direction = c.target) exits_list).keys
((inv s) @ items_in_room (current_room s) (locations_map s))
then c
else missing_key
else no_such_exit
(* [validate_take command state] changes [state] according to [command] if it
is valid (the item is in current room), or return an invalid command with
error message otherwise.
requires: [command.action = "take"]
*)
let validate_take c s =
if List.mem c.target (inv s) then
already_in_inv
else
try
if item_is_in_room c.target s then c
else no_such_item
with
| Not_found -> no_such_item
| _ -> unknown_error
(* [validate_drop command state] changes [state] according to [command] if it
is valid (the item is in inventory), or return an invalid command with
error message otherwise.
requires: [command.action = "drop"]
*)
let validate_drop c s =
if not (List.mem c.target
(List.map(fun s -> String.lowercase_ascii s) (inv s)))
then not_in_inv
else c
(* When [c.valid = true], [validate c s] tells whether command [c] is truly
valid given current state [s]. If [c] is valid, the command is returned to
Main unchanged, otherwise a command with error message will be returned.
When [c.valid = false], [validate c s] returns [c] unchanged.
*)
let validate c s =
if not c.valid then c
else if List.mem c.action (commands1 @ commands2) then validate_commands12 c
else if c.action = "go" then validate_go c s
else if c.action = "take" then validate_take c s
else if c.action = "drop" then validate_drop c s
else undefined_command