% Virtual World (Vworld.pl) % % Author: Donald Nute % Date: 12/1/1996 % Last modified: 11/13/1999 % % This program contains the driver for operating an artificial environment into % which an artificial agent may inserted. To complete the environment, a world % file must be loaded after this program is initiated using the vmain command. :- dynamic [vagent_data/6,vmap/3,vobject_icon/2,veff/3,vact/3,vreact/3, vcurrent/2,vstop/0,vstep/1,vrelocate_agent/0,vgame_over/0, movable/1,collectable/1,consumable/1,animate/1,key/7, agent/1,agent_predicates/1,agent_icon/1]. % Information about some common entities. :- multifile vobject_icon/2, veff/3, consumable/1, collectable/1. :- ensure_loaded(vworld2). '?ERROR?'(Number,Goal) :- vstring_struct(GString,Goal), error_message(Number,EMessage), atom_string(EMessage,EString), cat([`A call to the goal `,GString,` caused the following error: `,EString,`.`],Message,_), message_box(ok,Message,_), abort. % vstartup is the initial query when the executable version of % Virtual World is created. vstartup :- vmain, halt. % vmain call the initialization routines, starts the Virtual World % window handler, and closes the window and menus when the dialog ends. vmain :- prolog_flag(unknown,_,fail), vcreate_screen, vload_icons, vmake_menus, show_dialog(vworld), repeat, wait(0), wshow(vworld,Status), Status = 0, vtidy. vtidy :- wmclose(vfile), wmclose(vactions), wmclose(voptions), wmclose(vhelp), wclose(vworld), help('vworld.hlp',2,0). vmain. % vrun starts the action in Virtual World and keeps it going until % the agent dies or an error is encountered in the agent code. vrun :- vwell_and_able(_,_,_,_,_), assert(vcurrent(state,running)), wmnunbl(vactions,0,0), wmnunbl(vactions,1,0), wmnunbl(vactions,2,0), wmnunbl(vactions,3,1), repeat, wait(0), one((vtest(Goal), Goal, veverybody_act, vlast(Goal))), vhalt, retractall(vcurrent(state,_)), retractall(vstop), retractall(vgame_over), wmnunbl(vactions,0,1), wmnunbl(vactions,1,1), wmnunbl(vactions,2,1), wmnunbl(vactions,3,0), wmnunbl(voptions,5,1). vtest(Move) :- agent(Move). % vhalt checks to see if one of the conditions for halting the % action in Virtual World is satisfied. vhalt :- vgame_over, wmnunbl(voptions,0,1), wmnunbl(voptions,1,0), wmnunbl(voptions,2,1), wmnunbl(voptions,3,1), wmnunbl(voptions,5,1). vhalt :- ( vstop ; vstep(N), vnumber_of_moves(M), M >= N ), wmnunbl(voptions,0,1), wmnunbl(voptions,1,1), wmnunbl(voptions,2,1), wmnunbl(voptions,3,1), wmnunbl(voptions,5,1). % look(-S,-D,-I,-L,-R1,-R2,-R3,-R4,-R5) returns the strength, damage, and % inventory of the agent plus the 5X5 grid of objects occupying % the locations in the current level of the world map centered on the % agents current location. look(Strength,Damage,Inventory,Last,R1,R2,R3,R4,R5) :- vagent_data(XX,YY,Strength,Damage,Inventory,Last), vlook(XX,YY,R1,R2,R3,R4,R5). % vlook(+X,+Y,-R1,-R2,-R3,-R4,-R5) returns the 5X5 grid of objects % occupying the locations in the current level of the world map % centered on the location X,Y. vlook(XX,YY, [A,B,C,D,E], [F,G,H,I,J], [K,L,M,N,O], [P,Q,R,S,T], [U,V,W,X,Y]) :- Y1 is YY - 2, Y2 is YY - 1, Y4 is YY + 1, Y5 is YY + 2, IX is XX - 2, vcurrent(level,Lev), vscan(Lev,Y1,IX,[A,B,C,D,E]), vscan(Lev,Y2,IX,[F,G,H,I,J]), vscan(Lev,YY,IX,[K,L,M,N,O]), vscan(Lev,Y4,IX,[P,Q,R,S,T]), vscan(Lev,Y5,IX,[U,V,W,X,Y]). sit :- !, retract(vagent_data(X,Y,S,D,I,_)), SS is S - 1, assert(vagent_data(X,Y,SS,D,I,same)). % move(+Dir) tries to move the agent in the direction Dir. What % happens depends on what is in direction Dir. move(Dir) :- vwell_and_able(X,Y,Str,Dmg,Inv), !, vtransform(X,Y,Dir,XX,YY), vinspect(current,XX,YY,Obj), vpush(a,X,Y,Obj,XX,YY,Dir,NuX,NuY,AdjStr,AdjDmg,Item,Move), NuStr is Str + AdjStr, NuDmg is Dmg + AdjDmg, vadd_to_inventory(Item,Inv,NuInv), retract(vagent_data(_,_,_,_,_,_)), ( Move = 1, member(Dir,[n,s,e,w,ne,nw,se,sw],N), member(Last,[s,n,w,e,sw,se,nw,ne],N) ; Last = same ), assert(vagent_data(NuX,NuY,NuStr,NuDmg,NuInv,Last)). move(_). % vmove(+Actor,+X,+Y,+XX,+YY) moves an Actor from location X,Y to % location XX,YY in the current level, leaving location X,Y empty. vmove(Actor,X,Y,XX,YY) :- vdraw(X,Y,o), vdraw(XX,YY,Actor). % vactor(+L,[-Actor,-X,-Y]) returns a list containing an actor other than % the agent in level L and its location X,Y. vactor(current,[Actor,X,Y]) :- vcurrent(level,L), vactor(L,[Actor,X,Y]). vactor(L,[Actor,X,Y]) :- integer_bound(0,X,18), integer_bound(0,Y,12), vinspect(L,X,Y,Actor), animate(Actor). % veverybody_act calls upon every actor in the current level other than the % agent to act in a random order. After all actors have acted, nature acts % and the status display is updated. (nature is defined in the world file.) veverybody_act :- !, vcurrent(level,L), findall(X,vactor(L,X),List), vrandom_permutation(List,ActorList), vtake_turns(ActorList), vnature, vstatus_report. vnature :- nature, !. vnature. % vtake_turns(ActorList) calls upon the actors in the current level other % than the agent to take turns acting in random order. vtake_turns([]). vtake_turns([[Actor,X,Y]|Rest]) :- vact(Actor,X,Y), !, vtake_turns(Rest). % vaction(+Actor,+X,+Y) calls upon vact/3, which must be defined in the % world file. If there is no information in the world file about how % Actor is supposed to act, vaction/3 succeeds without doing anything. vaction(Actor,X,Y) :- vact(Actor,X,Y). vaction(_,_,_). % vpush(+Actor,+X,+Y,+Obj,+XX,+YY,+Dir,-NuX,-NuY,-AdjStr,-AdjDmg,-Item,-Last) % updates the world map and display that results when an Actor at % location X,Y in the current level tries to move into the space occupied % by an Obj at location XX,YY. push/12 also returns the new location % NuX,NuY of the Actor after the action, then changes AdjStr and AdjDmg % to the Actor's strength and damage resulting from the action, and % any Item that is to be added to the Actor's inventory as a result of % the action. Last = 1 if the agent changed position. % When an actor moves into the space of a consumable object, the % object disappears and the actor enjoys/suffers the effects. vpush(Actor,X,Y,Obj,XX,YY,_,XX,YY,AdjStr,AdjDmg,[],1) :- consumable(Obj), veffect(Obj,AdjStr,AdjDmg), vmove(Actor,X,Y,XX,YY). % When an actor moves into the space of a collectable object, the % object is added to the actor's inventory, and the actor % enjoys/suffers the effects. vpush(Actor,X,Y,Obj,XX,YY,_,XX,YY,AdjStr,AdjDmg,[Obj],1) :- collectable(Obj), veffect(Obj,AdjStr,AdjDmg), vmove(Actor,X,Y,XX,YY). % When an actor tries to move into the space of a movable object, % that object moves out of the way unless this would require it % to move into the space occupied by another object. In that case, % the second object must also move. Several objects may be % moved unless some immovable object stands in the way. The effects % of moving several objects with one push are accumulated and passed % back to the actor. This particular clause is recursive since a % movable object becomes an actor which may move another object. vpush(Actor,X,Y,Obj,XX,YY,Dir,XX,YY,AdjStr,AdjDmg,[],1) :- movable(Obj), vtransform(XX,YY,Dir,XXX,YYY), vinspect(current,XXX,YYY,NuObj), vpush(Obj,XX,YY,NuObj,XXX,YYY,Dir,XXX,YYY,AdjStr1,AdjDmg1,_,1), veffect(Obj,AdjStr2,AdjDmg2), AdjStr is AdjStr1 + AdjStr2, AdjDmg is AdjDmg1 + AdjDmg2, vmove(Actor,X,Y,XX,YY). % To enter a portal, an agent must have any key required by the % portal in its inventory. If an agent lacks a key for a portal, the % portal becomes an immovable object. Some portals may not require % keys. Others may be locked, but require some other action to open % them rather than possession of a key. Actors other than the agent % cannot use portals. vpush(a,X,Y,p,XX,YY,_,NuX,NuY,-1,0,[],1) :- vcurrent(level,L), vkey(K,L,XX,YY,L2,NuX,NuY), vagent_data(_,_,_,_,Inv,_), ( K = none ; member(K,Inv) ), vinspect(L2,NuX,NuY,o), !, vdraw(X,Y,o), retract(vcurrent(level,_)), assert(vcurrent(level,L2)), vdraw(NuX,NuY,a), vcolor_world. % If none of the above apply, the agent is pushing against an % immovable object. The agent does not change position, but % the action may have far-ranging effects. vpush(Agent,X,Y,Obj,XX,YY,_,X,Y,AdjStr,AdjDmg,[],0) :- vreaction(Obj,XX,YY), veffect(Obj,AdjStr,AdjDmg). % vadd_to_inventory(+NewItem,+OldInventory,-NewInventory) appends % whatever item an agent has just picked up (which may be none - % then NewItem = []) to the agent's inventory. vadd_to_inventory([X],I,[X|I]). vadd_to_inventory(_,I,I). % vscan(+L,+Y,+X,-View) returns a list of the object at level L % and position X,Y, plus the four objects occupying positions % to the right of the first object. vscan(L,Y,X,View) :- vmap(L,Y,List), vscan_aux(X,List,View). vscan_aux(0,[A,B,C,D,E|_],[A,B,C,D,E]). vscan_aux(X,[_|List],View) :- XX is X - 1, vscan_aux(XX,List,View). % vinspect(+L,+X,+Y,-Obj) returns the object Obj located at % X,Y in level L of the currently loaded world map. L may % be the atom current, in which case the current level is used, or it % may be an integer representing an explicit level in the world map. vinspect(current,X,Y,Obj) :- vcurrent(level,L), !, vmap(L,Y,List), vinspect_aux(X,List,Obj). vinspect(L,X,Y,Obj) :- vmap(L,Y,List), vinspect_aux(X,List,Obj). vinspect_aux(0,[Obj|_],Obj). vinspect_aux(X,[_|List],Obj) :- X > 0, XX is X - 1, vinspect_aux(XX,List,Obj). % vdraw(+X,+Y,+Obj) places the symbol for Obj in the world map at % location X,Y in the current level and draws the icon for Obj % on the screen at the X,Y location. vdraw(X,Y,Obj) :- ( vcurrent(view,agent), vagent_data(XA,YA,_,_,_,_), ( X < XA - 2 ; XA + 2 < X ; Y < YA - 2 ; YA + 2 < Y ), Icon = dark ; vobject_icon(Obj,Icon) ), vcurrent(level,Lev), vdraw(Lev,X,Y,Obj), XX is X * 32, YY is Y * 32, gfx_begin((vworld,1)), gfx(icon(XX,YY,Icon)), gfx_end((vworld,1)), retractall(vrelocate_agent). vdraw(X,Y,obj(_,Obj,_)) :- ( vcurrent(view,agent), vagent_data(XA,YA,_,_,_,_), ( X < XA - 2 ; XA + 2 < X ; Y < YA - 2 ; YA + 2 < Y ), Icon = dark ; vobject_icon(Obj,Icon) ), vcurrent(level,Lev), vdraw(Lev,X,Y,Obj), XX is X * 32, YY is Y * 32, gfx_begin((vworld,1)), gfx(icon(XX,YY,Icon)), gfx_end((vworld,1)), retractall(vrelocate_agent). % vdraw(+Lev,+X,+Y,+Obj) places Obj in the world map % at location X,Y on level Lev. It does not draw any icons. vdraw(Lev,N,Y,Obj) :- retract(vmap(Lev,Y,List)), vreplace(Obj,N,List,NewList), assert(vmap(Lev,Y,NewList)). vreplace(Obj,0,[_|X],[Obj|X]). vreplace(Obj,N,[X|Y],[X|Z]) :- N > 0, M is N - 1, vreplace(Obj,M,Y,Z). % vtransform(+X,+Y,+Dir,-XX,-YY) determines the XX,YY coordinates of the % location one square away from the location X,Y in direction DIR. vtransform(X,Y,n,X,YY) :- YY is Y - 1. vtransform(X,Y,s,X,YY) :- YY is Y + 1. vtransform(X,Y,e,XX,Y) :- XX is X + 1. vtransform(X,Y,w,XX,Y) :- XX is X - 1. vtransform(X,Y,ne,XX,YY) :- XX is X + 1, YY is Y - 1. vtransform(X,Y,nw,XX,YY) :- XX is X - 1, YY is Y - 1. vtransform(X,Y,se,XX,YY) :- XX is X + 1, YY is Y + 1. vtransform(X,Y,sw,XX,YY) :- XX is X - 1, YY is Y + 1. % vstatus_report displays the current strength, % damage, and inventory for the agent at the top % of the screen. Strength will never exceed % a maximum value of 300, and damage will never % drop below a minimum of 0. vstatus_report also % increments the move counter and displays it, and % it repaints the world if the program is in agent % view mode. vstatus_report :- retract(vagent_data(X,Y,S,D,I,Last)), ( S > 300 -> SS = 300 ; SS = S ), ( D < 0 -> DD = 0 ; DD = D ), assert(vagent_data(X,Y,SS,DD,I,Last)), number_string(SS,SStr), wtext((vworld,200),SStr), number_string(DD,DStr), wtext((vworld,300),DStr), ( (I = [] -> II = ``) ; ( vcat(I,'',Atom), atom_string(Atom,II) ) ), wtext((vworld,400),II), retract(vnumber_of_moves(M)), MM is M + 1, assert(vnumber_of_moves(MM)), number_string(MM,MStr), wtext((vworld,500),MStr), ( \+ vcurrent(view,agent) ; vcolor_world ), vdie, !. % vwell_and_able(-X,-Y,-S,-D,-I) returns the location, strength, % damage, and inventory for the agent provided the agent has % strength greater than 0 and damage less than 100. Otherwise, % well_and_able/5 fails. vwell_and_able(X,Y,S,D,I) :- vagent_data(X,Y,S,D,I,_), S > 0, D < 100. % vdie will replace the agent's icon on the screen with a tombstone % if the agent "starves" (strength is below 0) or is "killed" (damage % is above 100). vdie :- \+ vwell_and_able(_,_,_,_,_), wmnusel(voptions,4,0), vcolor_world, !, vagent_data(X,Y,_,_,_,_), XX is X * 32, YY is Y * 32, gfx_begin((vworld,1)), gfx(icon(XX,YY,rip)), gfx_end((vworld,1)), % Disable Actions and Options menu items. wmnunbl(vactions,0,0), wmnunbl(vactions,1,0), wmnunbl(vactions,2,0), wmnunbl(vactions,3,0), wmnunbl(voptions,0,0), wmnunbl(voptions,1,0), wmnunbl(voptions,5,0), wmnusel(voptions,4,0), assert(vstop). vdie. % vlast(+Action) displays the last action taken by the agent. vlast(Action) :- vlast_string(Action,String), wtext((vworld,600),String), !. vlast_string(sit,`sit`). vlast_string(move(Dir),String) :- member(Dir,[n,s,e,w,ne,nw,se,sw]), !, atom_string(Dir,DirStr), cat([`move(`,DirStr,`)`],String,_). vlast_string(_,`error`). % vcolor_world reads the world map for the current level % and displays it. vcolor_world :- vcurrent(level,Lev), vcolor_row(Lev,0). vcolor_row(_,13). vcolor_row(Lev,N) :- vmap(Lev,N,List), vcolor_cells(N,0,List), M is N + 1, vcolor_row(Lev,M). vcolor_cells(_,19,_). vcolor_cells(N,K,[Obj|Rest]) :- ( Obj == a, \+ vwell_and_able(_,_,_,_,_), Icon = rip ; vcurrent(view,agent), vagent_data(XX,YY,_,_,_,_), ( K < XX - 2 ; XX + 2 < K ; N < YY - 2 ; YY + 2 < N ), Icon = dark ; vobject_icon(Obj,Icon) ), !, X is 32 * K, Y is 32 * N, gfx_begin((vworld,1)), gfx(icon(X,Y,Icon)), gfx_end((vworld,1)), J is K + 1, vcolor_cells(N,J,Rest). vcolor_cells(N,K,[obj(_,Obj,_)|Rest]) :- ( vcurrent(view,agent), vagent_data(XX,YY,_,_,_,_), ( K < XX - 2 ; XX + 2 < K ; N < YY - 2 ; YY + 2 < N ), Icon = dark ; vobject_icon(Obj,Icon) ), !, X is 32 * K, Y is 32 * N, gfx_begin((vworld,1)), gfx(icon(X,Y,Icon)), gfx_end((vworld,1)), J is K + 1, vcolor_cells(N,J,Rest). vcolor_cells(N,K,[_|Rest]) :- M is K + 1, vcolor_cells(N,M,Rest). % veffect(+Obj,-S,-D) returns the change in strength and damage that will % result if the agent pushes, picks up, or consumes Obj. This predicate % uses the eff/3 predicate from the world file that is loaded. veffect(Obj,S,D) :- veff(Obj,S,D), !. veffect(_,0,0). % vreaction(+Obj,+X,+Y) accomplishes the reaction of any immovable % object when the agent "pushes" on it (tries to move into the space % it occupies.) vreaction/3 calls the predicate vreact/3 which must be % defined within the world file. If vreact/3 is not defined for the % object and location, then there is no reaction. vreaction(Obj,X,Y) :- vreact(Obj,X,Y), !. vreaction(_,_,_). % Randomization routines. vrandom(N,M,K) :- J is M - N + 1, K is rand(J)//1 + N. vrandom_member(X,List) :- len(List,L), vrandom(1,L,K), member(X,List,K). vrandom_permutation(Old,New) :- vrandom_permutation(Old,[],New), !. vrandom_permutation([],X,X). vrandom_permutation(Old,SoFar,New) :- vrandom_member(Y,Old), remove(Y,Old,Next), !, vrandom_permutation(Next,[Y|SoFar],New). random_direction(Dir) :- vrandom_member(Dir,[n,s,e,w,ne,se,nw,sw]). % v_hndl/4 is the window handler for Virtual World. v_hndl(vworld,msg_close,_,R) :- vexit(R). v_hndl(vworld,msg_menu,N,R) :- clause(vmake_menus,Body), voccurs(wmnuadd(_,_,Menu,N),Body), vmenu(Menu,R). voccurs(X,X). voccurs(X,(X,_)). voccurs(X,(_,Y)) :- voccurs(X,Y). v_hndl((vworld,1),msg_leftup,(X,Y),_) :- retract(vrelocate_agent), XX is X//32, YY is Y //32, vinspect(current,XX,YY,o), retract(vagent_data(XXX,YYY,S,D,I,_)), assert(vagent_data(XX,YY,S,D,I,same)), vdraw(XXX,YYY,o), vdraw(XX,YY,a). v_hndl((vworld,1),msg_char,Key,_) :- vwell_and_able(_,_,_,_,_), wmnusel(voptions,5,Test), Test = 1, ( member(Key,[up,prior,right,next,down,end,left,home],N), member(Move,[n,ne,e,se,s,sw,w,nw],N), Last = move(Move) ; member(Key,[delete,insert]), Last = sit ), !, Last, veverybody_act, vlast(Last). v_hndl((vworld,1),msg_paint,_,_) :- vcolor_world. % Any message not handled by the above clauses are % passed to the standard LPA window handler. v_hndl(Window,Message,Data,Result) :- window_handler(Window,Message,Data,Result). vmenu(`Load &World`,_) :- agent_predicates(_), msgbox(`Save Agent?`, `Do you want to save your agent?`,36,B), B = 6, vsave_agent, fail. vmenu(`Load &World`,_) :- opnbox(`Load World`,[(`Virtual World files: *.vw`,`*.vw`)],``,'vw',[NewWorld|_]), ( retract(vcurrent(world,World)), abolish_files([World]), vload_icons ; true ), consult(NewWorld), assert(vcurrent(world,NewWorld)), verify_world_loaded. verify_world_loaded :- \+ vmap(_,_,_), !, msgbox(`Incorrect File`, `Your world file did not contain a world map.`,16,_). verify_world_loaded :- retractall(vgame_over), retractall(vcurrent(level,_)), assert(vcurrent(level,1)), retractall(vnumber_of_moves(_)), assert(vnumber_of_moves(-1)), forall(v_icon(X,Y),assert(vobject_icon(X,Y))), vcolor_world, vstatus_report, % Disable Actions and Options menu items until agent is loaded. wmnunbl(vactions,0,0), wmnunbl(vactions,1,0), wmnunbl(vactions,2,0), wmnunbl(vactions,3,0), wmnunbl(voptions,0,0), wmnunbl(voptions,1,0), wmnunbl(voptions,2,0), wmnunbl(voptions,3,0), wmnunbl(voptions,5,0), % Enable Load Agent and disable Save Agent options on Files menu. wmnunbl(vfile,1,1), wmnunbl(vfile,2,0). vmenu(`&Load Agent`,_) :- opnbox(`Load Agent`,[(`Agent files: *.agt`,`*.agt`)],``,'agt',[NewAgent|_]), ( retract(vcurrent(agent,Agent)), abolish_files([Agent]) ; true ), consult(NewAgent), assert(vcurrent(agent,NewAgent)), verify_agent_loaded. verify_agent_loaded :- \+ clause(agent(_),_), msgbox(`Improper agent file.`, `The file you loaded did not contain any agent/1 clauses.`, 16,_), !. verify_agent_loaded :- % Enable Actions and Options menu items. wmnunbl(vactions,0,1), wmnunbl(vactions,1,1), wmnunbl(vactions,2,1), wmnunbl(vactions,3,0), wmnunbl(voptions,0,1), wmnunbl(voptions,1,1), wmnunbl(voptions,2,1), wmnunbl(voptions,3,1), wmnunbl(voptions,5,1), % Enable Save Agent and disable Load Agent options in File menu. wmnunbl(vfile,1,0), wmnunbl(vfile,2,1), % Make the agent visible. vagent_data(X,Y,_,_,_,_), retractall(vobject_icon(a,_)), vagent_icons([First|Others]), ( agent_icon(Icon), member(Icon,[First|Others]) ; agent_icon(IconFile,N), catch(Error,gfx_icon_load(agent,IconFile,N)), Error = 0, Icon = agent ; Icon = First ), assert(vobject_icon(a,Icon)), vdraw(X,Y,a). vmenu(`&Save Agent`,_) :- \+ agent_predicates(_), !, msgbox(`Can't save agent.`, `There is no list of agent predicates to be saved.`, 16,_). vmenu(`&Save Agent`,_) :- savbox(`Save Agent`,[(`Agent files: *.agt`,`*.agt`)],``,'agt',[File|_]), agent_predicates(List), tell(File), forall(member(Predicate,List),listing(Predicate)), told. vmenu(`&Save Agent`,_). vmenu(`e&Xit`,R) :- vexit(R). vexit(R) :- agent_predicates(_), msgbox(`Exit V-World`, `Do you want to save your agent?`,35,B), ( B = 6, vsave_agent, R = ok ; B = 7, retractall(agent_predicates(_)), retractall(vmap(_,_,_)), R = ok ; true ). vexit(R) :- msgbox(`Exit V-World`, `Do you want to exit V-World?`,36,B), ( B = 6, R = ok ; true ). vmenu(`&Run Agent`,_) :- vrun. vmenu(`Set Run &Limit`,_) :- wdcreate(stop_dialog,`Set stop point`,155,150,300,120, [ws_popup,ws_caption,ws_border]), wccreate((stop_dialog,1),static, `Number of moves at which action should stop: `, 10,20,220,20, [ws_child,ws_visible,ss_right]), ( ( vstep(N), number_string(N,NStr) ) ; NStr = `0` ), wccreate((stop_dialog,2),edit,NStr,240,20,40,20, [ws_child,ws_visible,ws_border]), wccreate((stop_dialog,3),button,`Set`,90,60,50,20, [ws_child,ws_visible,bs_pushbutton]), wccreate((stop_dialog,4),button,`Cancel`,160,60,50,20, [ws_child,ws_visible,bs_pushbutton]), window_handler(stop_dialog,vstop_hndl), call_dialog(stop_dialog,ok). vmenu(`s&Tep Agent`,_) :- assert(vstop), vrun. vmenu(`&Stop Agent`,_) :- ( \+ vcurrent(state,running) ; assert(vstop) ). vmenu(`Change Agent &Icon`,_) :- retract(vobject_icon(a,Old)), vagent_icons(List), vnext_agent_icon(Old,List,New), assert(vobject_icon(a,New)), vagent_data(X,Y,_,_,_,_), vdraw(X,Y,a). vnext_agent_icon(_,[],New) :- vagent_icons([New|_]). vnext_agent_icon(Old,[Old,New|_],New). vnext_agent_icon(Old,[_|Rest],New) :- vnext_agent_icon(Old,Rest,New). vmenu(`Change Agent &Location`,_) :- assert(vrelocate_agent). vmenu(`Reset Agent &Strength`,_) :- retract(vagent_data(X,Y,_,D,I,L)), assert(vagent_data(X,Y,100,D,I,L)), vdraw(X,Y,a), vstatus_report, !, vwell_and_able(_,_,_,_,_), % Enable Actions and Options menu items. wmnunbl(vactions,0,1), wmnunbl(vactions,1,1), wmnunbl(vactions,2,1), wmnunbl(vactions,3,0), wmnunbl(voptions,0,1), wmnunbl(voptions,1,1), wmnunbl(voptions,5,1). vmenu(`Reset Agent &Damage`,_) :- retract(vagent_data(X,Y,S,D,I,L)), assert(vagent_data(X,Y,S,0,I,L)), vdraw(X,Y,a), vstatus_report, !, vwell_and_able(_,_,_,_,_), % Enable Actions and Options menu items. wmnunbl(vactions,0,1), wmnunbl(vactions,1,1), wmnunbl(vactions,2,1), wmnunbl(vactions,3,0), wmnunbl(voptions,0,1), wmnunbl(voptions,1,1), wmnunbl(voptions,5,1). vmenu(`Agent &View Mode`,_) :- wmnusel(voptions,4,Test), Test = 1, wmnusel(voptions,4,0), retractall(vcurrent(view,_)), vcolor_world. vmenu(`Agent &View Mode`,_) :- wmnusel(voptions,4,1), retractall(vcurrent(view,_)), assert(vcurrent(view,agent)), vcolor_world. vmenu(`&Manual Testing Mode`,_) :- wmnusel(voptions,5,Test), Test = 1, wmnusel(voptions,5,0). vmenu(`&Manual Testing Mode`,_) :- wmnusel(voptions,5,1), wfocus((vworld,1)). vmenu(`&Contents`,_) :- help('vworld.hlp',3,0). vmenu(`&About`,_) :- msgbox(`About Virtual World`, `Virtual World~J~MCopyright 1999 Donald Nute~J~MArtificial Intelligence Center~J~MThe University of Georgia`, 0,_). % Window handler for the Actions/Stop dialog. vstop_hndl((stop_dialog,3),msg_button,_,ok) :- wtext((stop_dialog,2),S), number_string(N,S), integer(N), N > 0, retractall(vstep(_)), assert(vstep(N)), wmnusel(vactions,3,1). vstop_hndl((stop_dialog,3),msg_button,_,_) :- msgbox(`Error`, `You should enter an integer greater than 0 as your stop value.`, 16,_), wfocus((stop_dialog,2)). vstop_hndl((stop_dialog,4),msg_button,_,ok) :- msgbox(`Run till you die!`, `No maximum number of moves has been set and the action will continue until the agent dies.`, 64,_), retractall(vstep(_)), wmnusel(vactions,3,0). vmnuadd(Dlg,Pos,Name,MenuToAdd) :- wndhdl(Dlg,Handle), winapi((user32,'GetMenu'),[Handle],Menu), wmnuadd(menu(Menu),Pos,Name,MenuToAdd), winapi((user32,'DrawMenuBar'),[Handle],_). vmnudel(Dlg,Pos) :- wndhdl(Dlg,Handle), winapi((user32,'GetMenu'),[Handle],Menu), wmnudel(menu(Menu),Pos), winapi((user32,'DrawMenuBar'),[Handle],_). vmnunbl(Dlg,Pos,Status) :- wndhdl(Dlg,Handle), winapi((user32,'GetMenu'),[Handle],Menu), wmnunbl(menu(Menu),Pos,Status), winapi((user32,'DrawMenuBar'),[Handle],_). % vcat(+List,'',-Atom) concatenates a List of atoms into Atom, placing % an underscore between each atom in List. vcat([],SoFar,SoFar). vcat([A|Rest],'',Atom) :- !, vcat(Rest,A,Atom). vcat([A|Rest],SoFar,Atom) :- cat([SoFar,'_',A],Next,_), !, vcat(Rest,Next,Atom). % vlocate(+X,+Y,+Object,-XX,-YY) locates coordinates XX,YY adjacent to % coordinates X,Y at which an Object is located. vlocate(X,Y,Object,XX,YY) :- vlook(X,Y, _, [_,G,H,I,_], [_,L,_,M,_], [_,P,Q,R,_], _), member(Object,[G,H,I,L,M,P,Q,R],Pos), member(Dir,[nw,n,ne,w,e,sw,s,se],Pos), vtransform(X,Y,Dir,XX,YY). % vdetect(+X,+Y,+Object) succeeds if an Object is visible from % coordinates X,Y. vdetect(X,Y,Object) :- vlook(X,Y, [A,B,C,D,E], [F,G,H,I,J], [K,L,_,M,N], [O,P,Q,R,S], [T,U,V,W,Z]), member(Object,[A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,Z]). % moves(-N) returns the number of moves the agent has made. moves(N) :- wtext((vworld,500),Str), number_string(N,Str). % vnature/0 performs any actions defined in a vworld file for the_world. vnature :- the_world, !. vnature. % The abort handler vabort/0 vabort :- vtidy, exit(0).