prolog

swi prolog game assignment . I want the player to unlock the door when the player has key but i can't seem to make the function work


This how my code looks like . I want the player to take the key from the room and then use it on the door from garden to hallway . the command used is "?use(door(garden,hallway))." . the problem is that when i use the door without the key in my inventory i can still used the door even though the door is locked

% Facts

% Define the rooms
room(garden, 'You are in a beautiful garden with colorful flowers and singing birds.', [key], [door(garden, hallway)]).
room(hallway, 'You are in a dimly lit hallway with portraits of ancient kings lining the walls.', [note], [door(hallway, garden), door(hallway, library), door(hallway, throne_room)]).

% Define objects
object(key, 'A shiny golden key that seems important.').
object(note, 'A crumpled note with strange symbols written on it.').

% Define locked doors and their corresponding keys
locked_door(door(garden, hallway), key).

% Define incomplete objects
incomplete_object(broken_shard).
incomplete_object(glowing_piece).

% Define limited resources
resource(coin, 10). % Player starts with 10 coins
resource(mana, 100). % Player starts with 100 mana

% Rules

% Predicate to start the game
start :-
    write('Welcome to the Fairy Tale Adventure Game!'),nl,nl,
    game_help,nl,nl,
    write('You have been tasked with rescuing the kingdom\'s beloved princess from the clutches of the nefarious Demon King Diablos.'),nl,nl,
    look.

% Predicate to print the description of the current room
look :-
    current_room(Room),
    describe_room(Room),
    list_objects(Room),
    list_paths(Room),
    !.

% Predicate to describe the current room
describe_room(Room) :-
    room(Room, Description, _, _),
    write(Description), nl.

% Predicate to list objects in the current room
list_objects(Room) :-
    room(Room, _, Objects, _),
    write('You see the following objects in the room:'), nl,
    print_objects(Objects).

% Helper predicate to print objects
print_objects([]).
print_objects([Object|Rest]) :-
    object(Object, Description),
    write('- '), write(Description), nl,
    print_objects(Rest).

% Predicate to list paths out of the current room
list_paths(Room) :-
    room(Room, _, _, Paths),
    write('Paths out of the room:'), nl,
    sort(Paths, UniquePaths), % Remove duplicates
    print_unique_paths(UniquePaths).

% Helper predicate to print unique paths
print_unique_paths([]).
print_unique_paths([Path|Rest]) :-
    once(print_path(Path)), % Use once/1 to ensure only one instance of each path is printed
    print_unique_paths(Rest).

% Helper predicate to print a single path
print_path(door(_, Destination)) :-
    write('- Door to '), write(Destination), nl.

% Helper predicate to print paths
print_paths([]).
print_paths([door(Room, _)|Rest]) :-
    write('- Door to '), write(Room), nl,
    print_paths(Rest).

% Predicate to pick up an object
take(Object) :-
    current_room(Room),
    room(Room, _, Objects, _),
    member(Object, Objects),
    retract(room(Room, Description, Objects, Paths)),
    delete(Objects, Object, NewObjects),
    asserta(room(Room, Description, NewObjects, Paths)),
    asserta(inventory(Object)),
    write('You took the '), write(Object), write('.'), nl,
    !.

% Define a predicate for using objects
use(Object) :-
    inventory(Object), % Check if the player has the object
    (   % Use different rules based on the object
        % Add rules for other objects here
        write('You can\'t use that object here.'), nl
    ).

% Define a predicate for using doors
use(door(Room1, Room2)) :-
    current_room(Room1),
    door(Room1, Room2), % Check if there's a door connecting the two rooms
    can_access(Room2), % Check if the player can access the destination
    retract(current_room(Room1)), % Move the player to the destination room
    asserta(current_room(Room2)),!.

% Define a predicate for using doors when access is not allowed
use(door(_, _)) :-
    write('You cannot unlock the door.'), nl,
    fail.

% Define Rules for accessing different rooms
can_access(hallway) :-
    % Check if there's a locked door to the destination
    locked_door(door(garden, hallway), Key),
    % Check if the player has the key in their inventory
    (   inventory(Key) -> % If the player has the key
        write('You unlocked the door and entered the hallway.'), nl
    ;   % If the player doesn't have the key
        write('The door is locked, you need a key to unlock it.'), nl,
        fail % Fail to prevent the player from moving to the destination
    ).

% Define doors connecting different rooms

door(garden,hallway).
door(hallway, library).
door(hallway, throne_room).
% Add more door connections as needed.



% Predicate to display inventory
inventory :-
    write('You are currently holding:'), nl,
    findall(Item, inventory(Item), Inventory),
    print_inventory(Inventory),
    !.

% Helper predicate to print inventory
print_inventory([]) :-
    write('Nothing.'), nl.
print_inventory([Item|Rest]) :-
    write('- '), write(Item), nl,
    print_inventory(Rest).

% Define game-specific help
game_help :-
    write('Instructions:'), nl,
    write('- Type "look" to see the description of the current room.'), nl,
    write('- Type "take(Object)" to pick up an object.'), nl,
    write('- Type "use(Object)" to use an object.'), nl,
    write('- Type "inventory" to see what you\'re currently holding.'), nl,
    write('- Type "quit" to exit the game.'), nl,
    write('- Type "game_help" to show this instruction agian.'),nl.

% Initialize the game
:- dynamic(current_room/1).
:- dynamic(inventory/1).
:- dynamic room/4.
current_room(garden). % Start the game in the garden

player still can access to the hallway without the key

I tried a redoing the predicates but no matter how i change it still not working


Solution

  • It gives false when I run the query,

    use(door(garden,hallway)).
    

    So I believe your code is correct. Maybe you have accidentally asserted inventory(key). before while you are testing things and now it gives you incorrect results? I think adding the following line at the start of your program will solve any potential issues like this.

    :- retractall(inventory(key))