Skip to content

Instantly share code, notes, and snippets.

@Joelbyte
Created April 3, 2011 14:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Joelbyte/900462 to your computer and use it in GitHub Desktop.
Save Joelbyte/900462 to your computer and use it in GitHub Desktop.
Bacchus-Bosch - Part 4
:- object(property).
:- info([
version is 1.0,
author is 'Victor Lagerkvist',
date is 2011/03/19,
comment is 'A property constitutes the basic behaviours of the objects in Bacchus-Bosch.']).
:- public(update/2).
:- mode(update(+entity, -entity), zero_or_more).
:- info(update/2, [
comment is 'Update the entity to which the property belong.',
argnames is ['Entity', 'Entity1']]).
:- public(action/6).
:- mode(action(+atom, +list, +entity, +state, -state, -entity), zero_or_more).
:- info(action/6, [
comment is 'Execute the action Name with respects to Args, State and Entity, and store the resulting new state and entity in State1 and Entity1.',
argnames is ['Name', 'Args', 'Entity', 'State', 'Entity1', 'State1']]).
:- public(new/1).
:- mode(new(-term), zero_or_more).
:- info(new/1, [
comment is 'Unify State with the initial state of the property.',
argnames is ['State']]).
%% Basic definition: do nothing!
update(E, E).
%% Basic definition, overloaded in almost every descendant
%% prototype.
new(void).
:- end_object.
:- object(identity_property,
extends(property)).
new(_).
:- end_object.
:- object(player_property,
extends(property)).
:- end_object.
:- object(container_property,
extends(property)).
new([]).
update(E0, E) :-
entity::select_property(container_property-Items, E0, E1),
update_children(Items, Items1),
E = [container_property-Items1|E1].
update_children([], []).
update_children([E|Es], [E1|E1s]) :-
entity::update(E, E1),
update_children(Es, E1s).
action(add_item, [E], Owner, Items, Owner, [E|Items]).
action(select_item, [P, E], Owner, Items, Owner, Items1) :-
list::select(E, Items, Items1),
entity::get_property(E, P).
action(update_item, [P, Old, New], Owner, Items, Owner, [New|Items1]) :-
list::select(Old, Items, Items1),
entity::get_property(Old, P).
action(select_items, [P, Es], Owner, Items, Owner, Items1) :-
meta::partition([E] >> (entity::get_property(E, P)), Items, Es, Items1).
action(get_item, [P, E], Owner, Items, Owner, Items) :-
list::member(E, Items),
entity::get_property(E, P).
action(print_children, Args, Owner, Items, Owner, Items) :-
meta::include([E] >>
(entity::action(print, Args, E, _)),
Items,
_).
:- end_object.
:- object(inventory_property,
extends(container_property)).
update(E0, E) :-
entity::select_property(inventory_property-Items, E0, E1),
update_children(Items, Items1),
E = [inventory_property-Items1|E1].
update_children([], []).
update_children([E|Es], [E1|E1s]) :-
entity::update(E, E1),
update_children(Es, E1s).
valid_item(E) :-
entity::get_property(E, carriable_property-_).
action(add_item, [E], Owner, Items, Owner, [E|Items]) :-
valid_item(E).
action(select_item, [P, I], Owner, Items, Owner, Items1) :-
list::select(I, Items, Items1).
action(get_item, [P, E], Owner, Items, Owner, Items) :-
list::member(E, Items),
entity::get_property(E, P).
action(print_children, Args, Owner, Items, Owner, Items) :-
meta::include([E] >>
(entity::action(print, Args, E, _)),
Items,
_).
:- end_object.
:- object(carriable_property,
extends(property)).
%% Perhaps not the most interesting property in the game.
:- end_object.
:- object(health_property,
extends(property)).
new(10).
action(decrease_health, [], Owner, H0, Owner, H) :-
H is H0 - 1.
action(increase_health, [], Owner, H0, Owner, H) :-
H is H0 + 1.
:- end_object.
:- object(key_property,
extends(property)).
%% The default key.
new(key).
:- end_object.
:- object(lock_property,
extends(property)).
%% The (default) key that opens the lock.
new(key-locked).
valid_key(E, Key) :-
entity::get_property(E, key_property-Key).
action(lock, [Entity], Owner, Key-_, Owner, Key-locked) :-
valid_key(Entity, Key).
action(unlock, [Entity], Owner, Key-_, Owner, Key-unlocked) :-
valid_key(Entity, Key).
action(unlocked, [], Owner, Key-unlocked, Owner, Key-unlocked).
:- end_object.
:- object(openable_property,
extends(property)).
new(closed-[lock_property- Lock]) :- lock_property::new(Lock).
action(open, [], Owner, _-Lock, Owner, open-Lock) :-
entity::action(unlocked, [], Lock, Lock).
action(close, [], Owner, _-Lock, Owner, closed-Lock) :-
entity::action(unlocked, [], Lock, Lock).
action(unlock, Key, Owner, State-Lock, Owner, State-Lock1) :-
entity::action(unlock, Key, Lock, Lock1).
action(lock, Key, Owner, State-Lock, Owner, State-Lock1) :-
entity::action(lock, Key, Lock, Lock1).
:- end_object.
:- object(entrance_property,
extends(property)).
new(identity_property-_).
action(get_location, [Location], Owner, Location, Owner, Location).
:- end_object.
:- object(on_fire_property,
extends(property)).
update(E0, E) :-
entity::action(decrease_health, [], E0, E).
:- end_object.
:- object(printable_property,
extends(property)).
new(Description) :-
list::valid(Description).
action(print, [], Owner, Description, Owner, Description) :-
format(Description).
:- end_object.
:- object(eat_property,
extends(property)).
action(eat, [E, E1], Owner, void, Owner1, void) :-
entity::action(dissolve, [Owner, Owner1], E, E1).
:- end_object.
:- object(fruit_property,
extends(property)).
action(dissolve, [E0, E], Owner, State, Owner, State) :-
entity::action(move, [identity_property-final_state], E0, E).
:- end_object.
:- object(map_property,
extends(property)).
new([]-[]).
update(E0, E) :-
entity::update_property(map_property, E0, Rooms0-P0, Rooms-P, E),
entity::update(P0, P),
update_rooms(Rooms0, Rooms).
update_rooms([], []).
update_rooms([R0|R0s], [R|Rs]) :-
entity::update(R0, R),
update_rooms(R0s, Rs).
action(add_rooms, [Rooms1], Owner, Rooms2-P, Owner, Rooms-P) :-
list::append(Rooms1, Rooms2, Rooms).
action(get_room, [Property, R], Owner, Rooms-P, Owner, Rooms-P) :-
list::member(R, Rooms),
entity::get_property(R, Property).
action(select_room, [Property, R], Owner, Rooms-P, Owner, Rooms1-P) :-
list::select(R, Rooms, Rooms1),
entity::get_property(R, Property).
action(update_room, [Old, New], Owner, Rooms-P, Owner, [New|Rooms1]-P) :-
list::select(Old, Rooms, Rooms1).
action(print, [], Owner, Rooms-P, Owner, Rooms-P) :-
action(current_room, [Room], Owner, Rooms-P, _, _),
entity::action(print, [], Room, _).
action(current_room, [Current], Owner, Rooms-P, Owner, Rooms-P) :-
entity::action(get_location, [Id], P, _),
list::member(Current, Rooms),
entity::get_property(Current, Id).
action(update_current_room, [Current0, Current],
Owner, Rooms-P, Owner, [Current|Rooms1]-P) :-
entity::action(get_location, [Id], P, _),
list::select(Current0, Rooms, Rooms1),
entity::get_property(Current0, Id).
action(update_player, [P0, P], Owner, Rooms-P0, Owner, Rooms-P).
action(get_player, [P], Owner, Rooms-P, Owner, Rooms-P).
:- end_object.
:- object(movable_property,
extends(property)).
new(identity_property-_).
action(move, [New], Owner, _, Owner, New).
action(get_location, [Room], Owner, Room, Owner, Room).
:- end_object.
:- object(entity).
:- info([
version is 1.0,
author is 'Victor Lagerkvist',
date is 2011/03/18,
comment is 'The entity operations of Bacchus-Bosch.']).
:- public(update/2).
:- public(action/4).
:- public(get_property/2).
:- public(select_property/3).
:- public(add_property/3).
:- public(update_property/5).
update(E0, E) :-
update(E0, E0, E).
update(E, [], E).
update(E0, [P|Ps], E) :-
P = Name - _,
Name::update(E0, E1),
update(E1, Ps, E).
action(A, Args, E0, E) :-
%% Select a property from the list such that the action A can
%% be performed with the arguments Args.
list::select(P, E0, E1),
P = PropertyName - State,
PropertyName::action(A, Args, E1, State, E2, State1),
%% Add the property with the updated state to E2.
P1 = PropertyName - State1,
E = [P1|E2].
get_property(E, P) :-
list::member(P, E).
select_property(P, E, E1) :-
list::select(P, E, E1).
add_property(P, E, [P|E]).
update_property(Name, E0, S0, S, [Name-S|E]) :-
list::select(Name-S0, E0, E).
:- end_object.
:- object(game).
:- info([
version is 1.0,
author is 'Victor Lagerkvist',
date is 2011/03/20,
comment is 'The core functionality of Bacchus-Bosch.']).
:- public(init/0).
room_description("A rather unremarkable room.\n").
door_description("A wooden door with a small and rusty lock.\n").
key_description("A slightly bent key.\n").
banana_description("A yellow banana. Hot diggity dog!\n").
build_test_door1(Door) :-
Door = [openable_property-State1, printable_property-State2,
identity_property-door, entrance_property-State3],
openable_property::new(State1),
door_description(State2),
entrance_property::new(State3),
State3 = identity_property-r2.
build_test_door2(Door) :-
Door = [openable_property-State1, printable_property-State2,
identity_property-door, entrance_property-State3],
openable_property::new(State1),
door_description(State2),
entrance_property::new(State3),
State3 = identity_property-r1.
build_win_screen(Screen) :-
Screen = [printable_property - State, identity_property-final_state],
State = "Congratulations! A winner is you!\n (No, you can't quit. Stop trying.)\n".
build_test_key(Key) :-
Key = [key_property-State1, printable_property-State2,
identity_property-key, carriable_property-State3],
key_property::new(State1),
key_description(State2),
carriable_property::new(State3).
build_test_banana(Banana) :-
Banana = [fruit_property - State1, printable_property-State2,
identity_property-banana, carriable_property-State3],
fruit_property::new(State1),
banana_description(State2),
carriable_property::new(State3).
build_test_player(Player) :-
Player = [player_property - State1, inventory_property-State2,
health_property-State3, movable_property-(identity_property-r1)],
player_property::new(State1),
inventory_property::new(State2),
health_property::new(State3).
build_test_room1(Room) :-
build_test_door1(Door),
build_test_key(Key),
Room0 = [container_property - State1, printable_property - State2,
identity_property-r1],
container_property::new(State1),
room_description(State2),
entity::action(add_item, [Door], Room0, Room1),
entity::action(add_item, [Key], Room1, Room).
build_test_room2(Room) :-
build_test_door2(Door),
build_test_banana(Banana),
Room0 = [container_property - State1, printable_property - State2,
identity_property-r2],
container_property::new(State1),
State2 = "A room almost identical to the previous one. What on earth is going on!?\n",
entity::action(add_item, [Door], Room0, Room1),
entity::action(add_item, [Banana], Room1, Room).
build_test_world(World) :-
build_test_player(Player),
build_test_room1(R1),
build_test_room2(R2),
build_win_screen(W),
World = [map_property-State],
State = [R1, R2, W]-Player.
init :-
write('Welcome to Bacchus-Bosch!'), nl,
current_input(S),
build_test_world(World),
repl(S, [], World).
repl(S, History, World0) :-
entity::update(World0, World1),
entity::action(print, [], World1, _),
write('> '),
nlp::parse_line(S, Atoms),
write('The input is: '),
meta::map([X] >> (write(X), write(' ')), Atoms), nl,
nlp::tag_atoms(Atoms, AtomTags),
write('The tagged input is: '),
meta::map([X] >> (write(X), write(' ')), AtomTags), nl,
( eval(History, AtomTags, World1, World) ->
true
; write('no.'),
nl,
World = World1
),
write('-------------------'), nl,
repl(S, AtomTags, World).
eval(History, AtomTags, World, World1) :-
nlp::resolve_pronouns(History, AtomTags, AtomTags1),
nlp::parse_atoms(AtomTags1, _, Commands),
eval_commands(Commands, World, World1).
eval_commands([], World, World).
eval_commands([C|Cs], World0, World) :-
write('The command is: '), write(C), nl,
eval_command(C, World0, World1),
eval_commands(Cs, World1, World).
eval_command(take-[Id], World0, World) :-
entity::action(update_current_room, [R0, R], World0, World1),
entity::action(update_player, [P0, P], World1, World),
entity::action(select_item, [identity_property-Id, Item], R0, R),
entity::action(add_item, [Item], P0, P).
eval_command(look-[], World, World) :-
entity::action(current_room, [Room], World, _),
write('You see: '), nl,
entity::action(print_children, [], Room, _).
eval_command(look-[inventory], World, World) :-
entity::action(get_player, [P], World, _),
write('Your inventory consists of: '), nl,
entity::action(print_children, [], P, _).
eval_command(open-[Id], World0, World) :-
entity::action(update_current_room, [Room0, Room], World0, World),
entity::action(update_item, [identity_property-Id, Door0, Door],
Room0, Room),
entity::action(open, [], Door0, Door).
eval_command(close-[Id], World0, World) :-
entity::action(update_current_room, [Room0, Room], World0, World),
entity::action(update_item, [identity_property-Id, Door0, Door],
Room0, Room),
entity::action(close, [], Door0, Door).
eval_command(C-[Id1, Id2], World0, World) :-
( C = lock
; C = unlock
),
entity::action(update_current_room, [Room0, Room], World0, World),
entity::action(get_player, [P], World, _),
entity::action(update_item, [identity_property-Id1, Door0, Door],
Room0, Room),
entity::action(get_item, [identity_property-Id2, Key], P, _),
entity::action(C, [Key], Door0, Door).
eval_command(move-[Id], World0, World) :-
entity::action(current_room, [Room], World0, _),
entity::action(update_player, [P0, P], World0, World),
entity::action(get_item, [identity_property-Id, Entrance],
Room, _),
entity::action(open, [], Entrance, _),
entity::action(get_location, [Location], Entrance, _),
entity::action(move, [Location], P0, P).
eval_command(eat-[Id], World0, World) :-
entity::action(update_player, [P0, P], World0, World),
entity::action(select_item, [identity_property-Id, Item], P0, P1),
entity::action(dissolve, [P1, P], Item, _).
:- end_object.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment