%%% %%% woa.erl - World of Alan. It's like World of Warcraft if it were Zork. %%% -module(woa). -author('Alan G. Labouseur'). -define(else, true). % -- This is to make the if statements (somewhat) readable. %%% %%% Public %%% -export([start/0]). start() -> % -- Spawn the server process. Server = spawn(fun serverLoop/0), % -- Display the initial location description. io:fwrite(locations(0), []), io:fwrite("~n~n", []), % -- Kick off the game loop. gameLoop(Server, 0). %%% %%% Private %%% gameLoop(Server, CurrentLocale) -> % -- Get input from the player. {ok, Input} = io:fread("Enter a compass direction or quit -] ", "~s"), % Input gets returned as a list from io:fread. [Command | _] = Input, % Because Input is a list. % % -- Process the player's input/command into a NewLocale and Description. {NewLocale, Description} = processCommand(CurrentLocale, Command, Server), % % -- Update the display. io:fwrite("~n", []), io:fwrite(Description, []), io:fwrite("~n~n", []), % % -- Quit or Recurse. if (NewLocale < 0) -> io:fwrite("Good day.~n",[]); ?else -> gameLoop(Server, NewLocale) % This is tail recursion, so it's really a jump to the top of gameLoop. end. % if processCommand(CurrentLocale, Command, Server) -> case Command of % -- Compass directions "north" -> makeMove(Server, {CurrentLocale, north}); "n" -> makeMove(Server, {CurrentLocale, north}); "south" -> makeMove(Server, {CurrentLocale, south}); "s" -> makeMove(Server, {CurrentLocale, south}); "east" -> makeMove(Server, {CurrentLocale, east}); "e" -> makeMove(Server, {CurrentLocale, east}); "west" -> makeMove(Server, {CurrentLocale, west}); "w" -> makeMove(Server, {CurrentLocale, west}); % -- Other commands "quit" -> {-1, "Thank you for playing."}; "look" -> {CurrentLocale, locations(CurrentLocale)}; "help" -> {CurrentLocale, helpText()}; "sing" -> {CurrentLocale, itsPitchDark()}; % -- Otherwise... _Else -> {CurrentLocale, "I don't understand."} % Starting _Else wiht "_" prevents the "unused" error. end. makeMove(ServerPid, MoveTuple) -> remote(ServerPid, MoveTuple). remote(ToPid, Request) -> ToPid ! {self(), Request}, receive {ToPid, Response} -> Response % -- This waits for a response from ToPid. end. serverLoop() -> receive {FromPid, {CurrentLocale, Direction}} -> {NewLocale, Description} = mapper(CurrentLocale, Direction), FromPid ! {self(), {NewLocale, Description}}, serverLoop(); {FromPid, _} -> FromPid ! {self(), "Internal error: You are lost. Nice going, Indiana."}, serverLoop() end. mapper(0, north) -> {1, locations(1)}; mapper(0, west) -> {4, locations(4)}; mapper(1, south) -> {0, locations(0)}; mapper(1, east) -> {2, locations(2)}; mapper(2, west) -> {1, locations(1)}; mapper(2, east) -> {3, locations(3)}; mapper(3, west) -> {2, locations(2)}; mapper(4, east) -> {0, locations(0)}; mapper(4, west) -> {5, locations(5)}; mapper(5, east) -> {4, locations(4)}; mapper(Current, _) -> {Current, "You cannot go that way."}. %% These location descriptions DO NOT end with ~n newlines. The newline is taken care of up in the display code. locations(0) -> "0. FIELD~nYou are standing in a field by a white house.~nThere are paths leading to the north and west."; locations(1) -> "1. WHITE HOUSE~nThis is the front of the white house.~nYou see a field to the south and a shed to the east."; locations(2) -> "2. SMELLY SHED~nYou are inside a smelly shed. It's really smelly;~nyour stomach begins to turn. You're getting so sick you're not sure which way to go."; locations(3) -> "3. BEHIND THE SMELLY SHED~nAs you wonder why the shed was so smelly~nyou notice a trap door in the ground and hear the faint sounds of lurking grues."; locations(4) -> "4. TREE~nIt's a tree. A fairly large one at that. You consider climbing it,~nbut think better of it. You see a field to the east and a path leading west."; locations(5) -> "5. WEST LAKE~nBefore you sits the beautiful and glorious West Lake.~nIt's very cool. There is a path leading east.". helpText() -> "You can enter compass directions: [n] or [north], [s] or [south], [e] or [east], " ++ "[w] or [west], as well as [look], [help], and [quit].". itsPitchDark() -> "You are likely to be eaten by a grue. ~n" ++ "If this predicament seems particularly cruel, ~n" ++ "consider whose fault it could be: ~n" ++ "not a torch or a match in your inventory. ~n" ++ " - MC Frontalot~n" ++ " https://www.youtube.com/watch?v=4nigRT2KmCE".