anchor.diff:  describe_room(#{location := Location, rooms := Rooms}) ->
       maps:get(Location, Rooms).
   
  -describe_objects(_State) ->
  -    undefined.
  +describe_directions(#{location_edges := Edges}) ->
  +    list_to_binary(
  +      string:join(
  +        [ io_lib:format("There is a ~s going to ~s from there", [Direction, Room])
  +          || {Direction, Room} <- maps:to_list(Edges)
  +        ], "\n")).
  +
  +describe_objects(#{location := Location, objects := Objects}) ->
  +    ObjectsInCurrentLocation =
  +        [ atom_to_list(Object) || {Object, ObjLocation} <- maps:to_list(Objects), ObjLocation == Location ],
  +    case ObjectsInCurrentLocation of
  +        [] ->
  +            undefined;
  +        ObjectNames ->
  +            unlines(["I can also see the following:" | ObjectNames])
  +    end.
   
   make_game_state() ->
       #{ location => ?INITIAL_ROOM
  +     , location_edges => maps:get(?INITIAL_ROOM, ?EDGES)
        , rooms => ?ROOMS
        , edges => ?EDGES
  +     , objects => ?OBJECTS
        , commands => ?KNOWN_COMMANDS
        , status => playing
        }.
  +
  +move_to(NewLocation, #{edges := Edges} = State) ->
  +    State#{location := NewLocation, location_edges := maps:get(NewLocation, Edges)}.
  +
  +unlines(ListOfStrings) ->
  +    list_to_binary(string:join(ListOfStrings, "\n")).
   
   %%%===================================================================
   %%% Simple text interface for testing
  
positive.code: make_empty_reply() ->
      #{ errors => [], messages => [], game_end => false}.
  
  add_reply_error(FormatStr, Data, Reply) ->
      Reply#{ errors := [ list_to_binary(io_lib:format(FormatStr, Data)) | maps:get(errors, Reply) ]}.
  
  add_reply_text(FormatStr, Data, Reply) ->
      Reply#{ messages := [ list_to_binary(io_lib:format(FormatStr, Data)) | maps:get(messages, Reply) ]}.
  
  
negative.code: 
  %% @doc Try to move in the direction specified by the player.
  -spec cmd_go(Cmd :: binary(), Args :: [binary()], State :: state(), Reply :: reply()) -> {state(), reply()}.
  cmd_go(_Cmd, [<<"n">>], #{location := a, objects := #{key := KeyLocation} } = State, Reply)
    when KeyLocation =/= body ->
      {State, add_reply_text("A strong iron door is blocking the way in that direction", Reply)};
  cmd_go(_Cmd, [Direction], #{location_edges := LocationEdges} = State, Reply) ->
      case maps:find(Direction, LocationEdges) of
          {ok, NewLocation} ->
              State1 = move_to(NewLocation, State),
              cmd_look(<<"look">>, [], State1, Reply);
          error ->
              {State, add_reply_error("Unknown direction: ~s", [Direction], Reply)}
      end;
  cmd_go(_Cmd, _Direction, State, Reply) ->
      {State, add_reply_error("Usage: go <direction>", Reply)}.
  
  %% @doc Try to move the named object from the world to the player's inventory.
  -spec cmd_get(Cmd :: binary(), Args :: [binary()], State :: state(), Reply :: reply()) -> {state(), reply()}.
  