% $Id: wumpus.pl,v 1.3 2006/11/12 19:42:54 ioerger Exp $ :- dynamic now/1,state/1. dims(6,6). random_loc(X,Y) :- dims(A,B),X is random(A)+1,Y is random(B)+1. % initially, everything is in random (distinct?) rooms % agent: X, Y, facing % wumpus(X,Y), pit1(X,Y), pit2(X,Y), gold(X,Y), gun(X,Y) % holding gold, holding gun, alive agent, alive wumpus, % bump, scream, bullets, score random_state([A,B,north,C,D,E,F,G,H,I,J,K,L,0,0,1,1,0,0,1,0]) :- random_loc(A,B),random_loc(C,D),random_loc(E,F),random_loc(G,H), random_loc(I,J),random_loc(K,L). at(X,Y,[X,Y|_]). facing(F,[_,_,F|_]). wumpus(X,Y,S) :- nth(S,4,X),nth(S,5,Y). pit(X,Y,S) :- nth(S,6,X),nth(S,7,Y). pit(X,Y,S) :- nth(S,8,X),nth(S,9,Y). gold(X,Y,S) :- nth(S,10,X),nth(S,11,Y). gun(X,Y,S) :- nth(S,12,X),nth(S,13,Y). holding(gold,S) :- nth(S,14,1). holding(gun,S) :- nth(S,15,1). alive(agent,S) :- nth(S,16,1). alive(wumpus,S) :- nth(S,17,1). bump(S) :- nth(S,18,1). scream(S) :- nth(S,19,1). bullets(N,S) :- nth(S,20,N). score(N,S) :- nth(S,21,N). nth([A|_],1,A). nth([_|X],N,A) :- N>1,M is N-1,nth(X,M,A). %%%%%%%%%%%%%%%%%%%%%%%%%%%%% % does not show multiple-occupancies, pick one symbol show(S) :- dims(_,Y), show_rows(S,Y), show_senses(S), format("OK~n"). show_rows(S,Y) :- Y>0, show_cols(S,1,Y), Z is Y-1, show_rows(S,Z). show_rows(S,0). show_cols(_,X,Y) :- dims(A,B),X>A,format("~n"). show_cols(S,X,Y) :- contents(S,X,Y,C), format("~a ",[C]), Z is X+1, show_cols(S,Z,Y),!. contents(S,X,Y,'A') :- at(X,Y,S). contents(S,X,Y,'W') :- wumpus(X,Y,S). contents(S,X,Y,'P') :- pit(X,Y,S). contents(S,X,Y,'G') :- gold(X,Y,S). contents(S,X,Y,'U') :- gun(X,Y,S). contents(S,X,Y,'.'). show_senses(S) :- (breeze(S) -> format("breeze~n") ; true), (stench(S) -> format("stench~n") ; true), (glitter(S) -> format("glitter~n") ; true), (scream(S) -> format("scream~n") ; true), (bump(S) -> format("bump~n") ; true), (holding(gun,S) -> format("holding gun~n") ; true), (holding(gold,S) -> format("holding gold~n") ; true), (see_gun(S) -> format("see gun~n") ; true), % bullets? alive? facing(F,S),format("facing ~a~n",[F]), score(N,S),format("score ~a~n",[N]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%% adjacent(X,Y,P,Q) :- X is P+1, Y is Q. adjacent(X,Y,P,Q) :- X is P-1, Y is Q. adjacent(X,Y,P,Q) :- X is P, Y is Q+1. adjacent(X,Y,P,Q) :- X is P, Y is Q-1. glitter(S) :- at(X,Y,S),gold(X,Y,S). breeze(S) :- at(X,Y,S),pit(P,Q,S),adjacent(X,Y,P,Q). stench(S) :- at(X,Y,S),wumpus(P,Q,S),adjacent(X,Y,P,Q). see_gun(S) :- at(X,Y,S),gun(X,Y,S). result(State1,Action,State2) :- new_at(State1,Action,AgX,AgY), new_facing(State1,Action,Fac), wumpus(Wx,Wy,State1), nth(State1,6,Px),nth(State1,7,Py),nth(State1,8,Qx),nth(State1,9,Qy), new_gold(State1,Action,Gx,Gy), new_gun(State1,Action,Ux,Uy), new_holding(State1,Action,gold,Hg), new_holding(State1,Action,gun,Hu), new_alive(State1,Action,agent,Aa), new_alive(State1,Action,wumpus,Aw), new_bump(State1,Action,Bump), new_scream(State1,Action,Scream), new_bullets(State1,Action,Bullets), new_score(State1,Action,Score), State2 = [AgX,AgY,Fac, Wx,Wy,Px,Py,Qx,Qy,Gx,Gy,Ux,Uy, Hg,Hu,Aa,Aw, Bump,Scream,Bullets,Score]. %%%%%%%%%%%%%%%%%%%%%%%%%%% new_at(S,forward,A,E) :- at(A,B,S),facing(north,S),dims(X,Y),B1,E is B-1. new_at(S,forward,D,B) :- at(A,B,S),facing(east,S),dims(X,Y),A1,D is A-1. new_at(S,_,A,B) :- at(A,B,S). new_facing(S,turn(left),F2) :- facing(F1,S),left(F1,F2),!. new_facing(S,turn(right),F2) :- facing(F1,S),right(F1,F2),!. new_facing(S,_,F) :- facing(F,S). left(east,north). left(north,west). left(west,south). left(south,east). right(X,Y) :- left(Y,X). new_gold(S,forward,P,Q) :- holding(gold,S),new_at(S,forward,P,Q),!. new_gold(S,_,P,Q) :- gold(P,Q,S). new_gun(S,forward,P,Q) :- holding(gun,S),new_at(S,forward,P,Q),!. new_gun(S,_,P,Q) :- gun(P,Q,S). % never put down new_holding(S,pickup(gold),gold,1) :- at(X,Y,S),gold(X,Y,S),!. new_holding(S,pickup(gun),gun,1) :- at(X,Y,S),gun(X,Y,S),!. new_holding(S,_,Obj,1) :- holding(Obj,S),!. new_holding(S,_,Obj,0). % use new_at to determine if facing toward wumpus, hypothetical move forward new_alive(S,shoot,wumpus,0) :- new_at(S,forward,X,Y),wumpus(X,Y,S),holding(gun,S),bullets(N,S),N>0. new_alive(S,forward,agent,0) :- new_at(S,forward,X,Y),pit(X,Y,S). new_alive(S,forward,agent,0) :- new_at(S,forward,X,Y),wumpus(X,Y,S). new_alive(S,_,Obj,1) :- alive(Obj,S),!. new_alive(S,_,Obj,0). new_bump(S,forward,1) :- at(A,B,S),facing(north,S),dims(X,Y),B=Y. new_bump(S,forward,1) :- at(A,B,S),facing(south,S),dims(X,Y),B=1. new_bump(S,forward,1) :- at(A,B,S),facing(east,S),dims(X,Y),A=X. new_bump(S,forward,1) :- at(A,B,S),facing(west,S),dims(X,Y),A=1. new_bump(_,_,0). new_scream(S,shoot,1) :- alive(wumpus,S), new_at(S,forward,X,Y),wumpus(X,Y,S),holding(gun,S),bullets(N,S),N>0. new_scream(S,_,0). new_bullets(S,shoot,M) :- holding(gun,S),bullets(N,S),N>0,M is N-1. new_bullets(S,A,N) :- bullets(N,S). new_score(S,A,-1000) :- score(-1000,S). new_score(S,A,-1000) :- score(N,S),new_at(S,A,X,Y),pit(X,Y,S). new_score(S,A,-1000) :- score(N,S),new_at(S,A,X,Y),wumpus(X,Y,S),alive(wumpus,S). new_score(S,A,M) :- score(N,S),new_scream(S,A,1),M is N+100. new_score(S,A,M) :- score(N,S),\+ holding(gold,S),new_holding(S,A,gold,1),M is N+100. new_score(S,A,M) :- score(N,S),M is N-1. %%%%%%%%%%%%%%%%%%%%%%%%%%%% reset :- retractall(state(S)), random_state(S), assert(state(S)), retractall(now(X)), assert(now(1)). show :- state(S),show(S). do([]) :- !. do([X|Y]) :- do(X),do(Y),!. do(Action) :- state(S), result(S,Action,T), retract(state(S)), assert(state(T)), now(X), retract(now(X)), Y is X+1, assert(now(Y)), show(T). glitter :- state(S),glitter(S). breeze :- state(S),breeze(S). stench :- state(S),stench(S). bump :- state(S),bump(S). scream :- state(S),scream(S). see_gun :- state(S),see_gun(S). score(X) :- state(S),score(X,S).