0 | 0 |
%%% BEGIN animals.erl %%%
|
1 | 1 |
%%%
|
2 | 2 |
%%% animals - Classic 'expert system' game of Animals, in Erlang
|
3 | |
%%% Copyright (c)2002 Cat's Eye Technologies. All rights reserved.
|
|
3 |
%%% Copyright (c)2002-2010 Cat's Eye Technologies. All rights reserved.
|
4 | 4 |
%%%
|
5 | 5 |
%%% Redistribution and use in source and binary forms, with or without
|
6 | 6 |
%%% modification, are permitted provided that the following conditions
|
|
18 | 18 |
%%% contributors may be used to endorse or promote products derived
|
19 | 19 |
%%% from this software without specific prior written permission.
|
20 | 20 |
%%%
|
21 | |
%%% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
22 | |
%%% CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
23 | |
%%% INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
24 | |
%%% MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
25 | |
%%% DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
|
26 | |
%%% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
27 | |
%%% OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
28 | |
%%% PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
29 | |
%%% OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
30 | |
%%% ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
31 | |
%%% OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
32 | |
%%% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
33 | |
%%% POSSIBILITY OF SUCH DAMAGE.
|
|
21 |
%%% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
22 |
%%% ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
23 |
%%% LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
24 |
%%% FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
25 |
%%% COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
|
26 |
%%% INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
27 |
%%% (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
28 |
%%% SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
29 |
%%% HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
30 |
%%% STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
31 |
%%% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
|
32 |
%%% OF THE POSSIBILITY OF SUCH DAMAGE.
|
34 | 33 |
|
35 | 34 |
%% @doc The classic 'expert system' demonstration game of Animals.
|
36 | 35 |
%%
|
|
43 | 42 |
%% @end
|
44 | 43 |
|
45 | 44 |
-module(animals).
|
46 | |
-vsn('$Id: animals.erl 5 2004-09-20 02:22:25Z catseye $').
|
47 | |
-author('cpressey@catseye.mine.nu').
|
48 | |
-copyright('Copyright (c)2002-2004 Cat`s Eye Technologies. All rights reserved.').
|
|
45 |
-vsn('$Id: animals.erl 531 2010-04-29 20:05:21Z cpressey $').
|
|
46 |
-author('cpressey@catseye.tc').
|
|
47 |
-copyright('Copyright (c)2002-2010 Cat`s Eye Technologies. All rights reserved.').
|
49 | 48 |
|
50 | 49 |
-export([start/0]).
|
51 | 50 |
|
|
114 | 113 |
end
|
115 | 114 |
end.
|
116 | 115 |
|
117 | |
%%% Utilities
|
|
116 |
%%% High-level Utilities
|
118 | 117 |
|
119 | 118 |
%% @spec load() -> tree()
|
120 | 119 |
%% @doc Loads the animal knowledge tree from <code>animals.dat</code>.
|
|
132 | 131 |
%% @doc Saves the animal knowledge tree to <code>animals.dat</code>.
|
133 | 132 |
|
134 | 133 |
save(Animals) ->
|
135 | |
case ce_file:dump(filename:join([code:priv_dir(animals), "animals.dat"]),
|
|
134 |
case file_dump(filename:join([code:priv_dir(animals), "animals.dat"]),
|
136 | 135 |
[Animals]) of
|
137 | 136 |
{ok, [Animals]} ->
|
138 | 137 |
ok;
|
|
166 | 165 |
%% to the given noun.
|
167 | 166 |
|
168 | 167 |
indefart(Noun) ->
|
169 | |
case hd(ce_string:uc(Noun)) of
|
|
168 |
case hd(uc(Noun)) of
|
170 | 169 |
N when N == $A; N == $E; N == $I; N == $O; N == $U ->
|
171 | 170 |
"an " ++ Noun;
|
172 | 171 |
_ ->
|
|
179 | 178 |
get_y_or_n(Prompt) ->
|
180 | 179 |
io:fwrite("~s", [Prompt]),
|
181 | 180 |
Response = io:get_line(''),
|
182 | |
case string:strip(ce_string:uc(Response)) of
|
|
181 |
case string:strip(uc(Response)) of
|
183 | 182 |
"Y" ++ _Remainder ->
|
184 | 183 |
true;
|
185 | 184 |
"N" ++ _Remainder ->
|
|
194 | 193 |
|
195 | 194 |
get_animal_name() ->
|
196 | 195 |
io:fwrite("What was the name of the animal you were thinking of? "),
|
197 | |
case ce_string:chomp(io:get_line('')) of
|
|
196 |
case chomp(io:get_line('')) of
|
198 | 197 |
"" ->
|
199 | 198 |
io:fwrite("Sorry, I didn't quite catch that.~n"),
|
200 | 199 |
get_animal_name();
|
201 | 200 |
AnimalName ->
|
202 | |
ce_string:lc(AnimalName)
|
|
201 |
lc(AnimalName)
|
203 | 202 |
end.
|
204 | 203 |
|
205 | 204 |
get_question() ->
|
206 | |
case ce_string:chomp(io:get_line('> ')) of
|
|
205 |
case chomp(io:get_line('> ')) of
|
207 | 206 |
"" ->
|
208 | 207 |
io:fwrite("Sorry, I didn't quite catch that.~n"),
|
209 | 208 |
get_question();
|
|
211 | 210 |
strip_question_marks([to_upper(hd(Question)) | tl(Question)])
|
212 | 211 |
end.
|
213 | 212 |
|
|
213 |
%%% Low-level Utilities
|
|
214 |
|
214 | 215 |
strip_question_marks(String) ->
|
215 | 216 |
lists:reverse(strip_question_marks0(lists:reverse(String))).
|
216 | 217 |
|
|
219 | 220 |
strip_question_marks0(Else) ->
|
220 | 221 |
Else.
|
221 | 222 |
|
|
223 |
%% @spec chomp(string()) -> string()
|
|
224 |
%% @doc Removes all newlines from the end of a string.
|
|
225 |
%% Should work on both Unix and MS-DOS newlines.
|
|
226 |
|
|
227 |
chomp([]) -> [];
|
|
228 |
chomp(List) when is_list(List) ->
|
|
229 |
lists:reverse(chomp0(lists:reverse(List))).
|
|
230 |
chomp0([]) -> [];
|
|
231 |
chomp0([H | T]) when H == 10; H == 13 -> chomp0(T);
|
|
232 |
chomp0([_ | _]=L) -> L.
|
|
233 |
|
|
234 |
%% @spec uc(string()) -> string()
|
|
235 |
%% @doc Translates a string to uppercase. Also flattens the list.
|
|
236 |
|
|
237 |
uc(L) -> uc(L, []).
|
|
238 |
uc([], A) -> A;
|
|
239 |
uc([H|T], A) -> uc(T, A ++ [uc(H)]);
|
|
240 |
uc(L, _) -> to_upper(L).
|
|
241 |
|
222 | 242 |
to_upper(X) when X >= $a, X =< $z -> X + ($A - $a);
|
223 | 243 |
to_upper(X) -> X.
|
224 | 244 |
|
|
245 |
%% @spec lc(string()) -> string()
|
|
246 |
%% @doc Translates a string to lowercase. Also flattens the list.
|
|
247 |
|
|
248 |
lc(L) -> lc(L, []).
|
|
249 |
lc([], A) -> A;
|
|
250 |
lc([H|T], A) -> lc(T, A ++ [lc(H)]);
|
|
251 |
lc(L, _) -> to_lower(L).
|
|
252 |
|
|
253 |
to_lower(X) when X >= $A, X =< $Z -> X + ($a - $A);
|
|
254 |
to_lower(X) -> X.
|
|
255 |
|
|
256 |
%% @spec file_dump(filename(), [term()]) -> {ok, [term()]} | {error, Reason}
|
|
257 |
%% @doc Writes all terms to a file. Complements file:consult/1.
|
|
258 |
|
|
259 |
file_dump(Filename, List) ->
|
|
260 |
case file:open(Filename, [write]) of
|
|
261 |
{ok, Device} ->
|
|
262 |
lists:foreach(fun(Term) ->
|
|
263 |
io:fwrite(Device, "~p.~n", [Term])
|
|
264 |
end, List),
|
|
265 |
file:close(Device),
|
|
266 |
{ok, List};
|
|
267 |
Other ->
|
|
268 |
Other
|
|
269 |
end.
|
|
270 |
|
225 | 271 |
%%% END of animals.erl %%%
|