0

I need to make a program in Prolog where a guy gets to the gas station, gets a soda and a newspaper and back to his car, the outcome should look something like this:

?- go. 
>> goto(gas_station). 

You are in the gas_station.
>> goto(car). 

You can't get there from here. 

>> open(car_door). 

>> open(gas_station_door). 

>> take(soda). 

You now have a soda. 

>> goto(car). 

You are in the car 

Thanks for getting the newspaper.

This is what i did so far:

place(car).
place(gas_station).
item(player , soda).
item(player , newspaper).
at(soda , gas_station).
at(newspaper , gas_station).

at(player , gas_station) :- door(car_door , open),
                door(gas_station_door, open), nl.

at(player , gas_station) :-
    write('Can't get there'), nl.


open(X) :-
    assert(door(X , open).

goto(X) :-
    at(player , X),
    retract(at(player , X),
    write('You are in the gas station.'),
    nl.

take(X) :-
    item(player , X),
    write('You now have a soda and a newspaper'),
    nl.

I am new to Prolog, i just want to know if what i did so far is somewhat correct, if i am on the right track, and how to continue from here because i am stack, i am not sure if it works how it is supposed to or how to get the guy back to the car, i would appreciate any help, thanks.

David Tonhofer
  • 14,559
  • 5
  • 55
  • 51
kypgh
  • 11
  • 2
  • Is that for the course of [David Matuszek](https://www.cis.upenn.edu/~matuszek/cis554-2013/Assignments/prolog-2-adventure-game.html)? Is it fair to take a look at an [Example on Github](https://gist.github.com/JosephLenton/3191695)? That example doesn't use a read loop, it just modifies the fact database and the user inputs the action directly as a query `n`, `e`, `w`, `s` etc. Very nonomotonic logic, that. That's one way of doing it. – David Tonhofer Jan 05 '20 at 20:29
  • There are definitely some parentheses missing for the `assert` and `retract` statements. – David Tonhofer Jan 05 '20 at 20:36
  • Perhaps you are looking for a [planner](https://stackoverflow.com/a/55515519/1243762) solution. – Guy Coder Jan 06 '20 at 15:27

2 Answers2

0

Looks good so far. The general form of every "command" (really, Prolog query issued on the command line) being:

% precondition-dependent action:

commandX(Arg) :- check_precondition_for_commandX, !,
                 % past the "!" we are committed to the action
                 update_database_with_assert_and_retract_to_reflect_new_state,
                 print_out_some_message.

% maybe the effects of the action depend on another set of preconditions
% for example, going "north" may have different effects depending on
% current position

commandX(Arg) :- check_other_precondition_for_commandX, !,
                 % past the "!" we are committed to the action
                 update_database_with_assert_and_retract_to_reflect_new_state,
                 print_out_some_other_message.

% catch the case where preconditions are not fulfilled:

commandX(Arg) :- print_out_something_about_you_cant_do_that.

Maybe run this example found on GitHub: "spider.pl" to get a feel for what's going on.

Switch on the tracer tracer to see what is being called.

[debug]  ?- n.
Go into that dark cave without a light?  Are you crazy?
You can't go that way.
true.

[debug]  ?- trace.
true.

[trace]  ?- n.
   Call: (10) n ? creep
   Call: (11) go(n) ? creep
   Call: (12) i_am_at(_7492) ? creep
   Exit: (12) i_am_at(meadow) ? creep
   Call: (12) path(meadow, n, _7496) ? creep
   Call: (13) at(flashlight, in_hand) ? creep
   Fail: (13) at(flashlight, in_hand) ? creep
   Redo: (12) path(meadow, n, _7496) ? creep
   Call: (13) write('Go into that dark cave without a light?  Are you crazy?') ? creep
Go into that dark cave without a light?  Are you crazy?
   Exit: (13) write('Go into that dark cave without a light?  Are you crazy?') ? creep
   Call: (13) nl ? creep

   Exit: (13) nl ? creep
   Call: (13) fail ? creep
   Fail: (13) fail ? creep
   Fail: (12) path(meadow, n, _7496) ? creep
   Redo: (11) go(n) ? creep
   Call: (12) write('You can\'t go that way.') ? creep
You can't go that way.
   Exit: (12) write('You can\'t go that way.') ? creep
   Exit: (11) go(n) ? creep
   Exit: (10) n ? creep
true.

Not sure how that works? Here is a description of tracing for ALS Prolog: Using the Four Port Debugger

David Tonhofer
  • 14,559
  • 5
  • 55
  • 51
0

i figured it out thanks to the spider program that was posted and this is what i did:

:- dynamic at/2, i_am_at/1.
:- retractall(at(_, _)), retractall(i_am_at(_)).


i_am_at(car).

go_to_gas_station :- goto(gas_station).
go_to_car :- goto(car).
open_car_door :- open(car_door).
open_gas_station_door :- open(gas_station_door).
take_soda :- take(soda).
take_newspaper :- take(newspaper).

path(car, gas_station, gas_station) :- at(car_door, open),
                       at(gas_station_door, open).

path(car, gas_station, gas_station) :-
    write('Cant get there! Open the doors first.'), nl,
    !, fail.

path(gas_station, car, car) :- at(soda, in_hand),
                   at(newspaper, in_hand),
                   i_am_at(gas_station),
                   write('Thanks for playing.').

path(gas_station, car, car) :- 
    write('Did you forget something?'), nl,
    !, fail.


open(X) :-
    at(X, open),
    write('Door is already open!'),
    nl, !.

open(X) :-
    assert(at(X, open)),
    write('Door is now open.'),
    nl, !.

goto(Direction) :-
    i_am_at(Here),
    path(Here, Direction, There),
    write('You are now at '), write(Direction),
    retract(i_am_at(Here)),
    assert(i_am_at(There)), !.

take(X) :-
    at(X, in_hand),
    write('You already have it!'),
    nl, !.

take(X) :-
    assert(at(X, in_hand)),
    write('You now have '), write(X),
    nl, !.

my only problem is that as it is now, you can take the soda and the newspaper no matter where you are, you should be able to take those only when you are in the gas_station, if someone can help me with that it would be nice, other than that thanks for the help.

kypgh
  • 11
  • 2