% Valid locations. locations/1
location(great_hall).
location(ophelia_bedroom).
location(polonius_bedroom).
location(courtyard).
location(chapel).
location(castle_wall).
% Valid characters. characters/1
character(ophelia).
character(polonius).
character(gertrude).
character(claudius).
character(hamlet).
% The current location of characters and objects. in_location/2
:- dynamic(in_location/2).
in_location(ophelia, great_hall).
in_location(polonius, great_hall).
in_location(hamlet, chapel).
% Valid story events. story_event/1.
story_event(polonius_scold_ophelia).
story_event(claudius_confesses_murder).
% Story events that have already occurred. event_occurred/1.
:- dynamic(event_occurred/1).
event_occurred(claudius_confesses_murder).
% Availability tests for story events (scenes). event_available/1.
event_available(polonius_scold_ophelia) :-
\+( event_occurred(polonius_scold_ophelia) ),
in_location(ophelia, Loc),
in_location(polonius, Loc),
\+( character_present(Loc, [ophelia, polonius]) ).
% load the lists module since we’re using the member/2 predicate
:- use_module(library(lists)).
% True if a character is present in a location who is not in the list of excluded characters.
character_present(Location, ExcludedChars) :-
in_location(Char, Location),
\+( member(Char, ExcludedChars) ).
% Moving a character to a location.
move(Char, NewLoc) :-
in_location(Char, CurrentLoc),
location(NewLoc),
CurrentLoc \= NewLoc,
retract( in_location(Char, CurrentLoc) ),
asserta( in_location(Char, NewLoc) ).