nieco trudniejsze zadanie małpy. klauzula canget pozwala lepiej zrozumieć pojęcie systemów produkcyjnych (rozdział drugi AI) i klaryfikuje nieco pojęcie rekurencji i zależności obiektów abstrakcyjnych. W Prologu, żeby nie musieć implementować wielu mechanizmów (np odcięcia) w C. Zadanie dla chętnych, ale warto na nie spojrzeć. Jeśli ktoś zrobi, to niech wrzuci mi na maila i wtedy przejrze.
h(X,Y). % położenie horyzontalne
v(Z). % położenie wertykalne
thing(Name, h(X,Y), v(Z)).
monkey( h(X,Y), v(Z), has(Thing) ).
state( M, L ) :-
M = monkey( h(X,Y), v(Z), has(Thing) ),
are_items( L ).
are_items( [] ).
are_items( [H|_] ) :- not( H=thing(Name, h(X,Y), v(Z)) ), !, fail.
are_items( [_|T] ) :- are_items( T ).
same_place( state(_,[]), _) :- !, fail.
same_place( state(M,[H|_]), T ) :-
M=monkey(MHor, MVert, _),
H=thing(Name, Hor, Vert),
Name=T,
Hor=MHor,
Vert=MVert.
same_place( state(M,[_|L]),T) :- same_place( state(M,L), T).
/* predykaty do zdefiniowania
walk(S1, X, Y, S2) :- ten predykat powinien zmieniać pozycję małpy w S1 wraz z pozycją przedmiotu który trzyma [has(Thing)] umieszczając wynik w S2, czyli np dla samej małpy
S1=state( monkey( _, v(A), B ), L ), A=0, S2=state( monkey( h(X,Y), v(A), B), L).
żeby zmienić położenie obiektu, trzeba znaleźć go na liście L ( thing(Name,_,_), Name=nazwa, ... przy czym nazwa jest wewnatrz predykatu has, czyli jesli mamy has(Thing) to Name=Thing.
grab(S1, T, S2) :- bierze przedmiot o nazwie T, jesli malpa jest w tym samym miejscu i wysokosci co przedmiot (wynik w S2) można użyć pomocniczego predykatu same_place
throw(S1, T, S2) :- wyrzuca przedmiot trzymany przez małpę (małpę ustalamy że has(nothing) )
use_item(S1, T, S2) :- małpa używa przedmiotu (niekoniecznie musi go mieć, np może się wspiąć na skrzynke nie mając jej, ale musi być w tym samym miejscu. use_item będzie definiowany przez użytkownika jak będzie dodawał nowy przedmiot (zachowanie predykatu), ale wspominam o nim, bo będzie potrzebny w mechanizmie uzgadniania w canget jako jedna z alternatyw. np use_item(S1, stick, S2) mogłoby strącić banan zawieszony z sufitu, a use_item(S1, box, S2) może powodować wejście małpy jeden poziom wyżej, lub zejście ze skrzynki
canget( Name, S ) - Czy małpa może w stanie S zdobyć przedmiot o nazwie Name, główny predykat, ważne żeby zachować porządek klauzul tak, aby się nie zapętlił. Jest to nasz system produkcyjny. przedmioty oraz to co można z nimi robić (oprócz przenoszenia , brania i wyrzucania ich ) będą zdefiniowane przez użytkownika, podobnie jak początkowy stan "gry". przykładowa definicja dla kija:
use_item(S1, stick, S2) :-
S1 = state( monkey(_,_,has(W) ), L),
stroke(S1,S2).
stroke( state(_,[]), _) :- !, fail.
stroke( state(M,[H|L]), S1 ) :-
M = monkey(Hor, vert(X), has(stick)),
H=thing(T,Hor,vert(Y)), ,
X is Y-1, !,
L1 = [thing( T, hor(4, 6), vert(X) )|L],
S1=state(M,L1).
stroke( state(M,[_|L], S1) ) :- stroke( state(M,L), S1 ).
*/