1/* * <module> 
    2% This module defines the way we lay out 2-D grids into room
    3%
    4% Logicmoo Project PrologMUD: A MUD server written in Prolog
    5% Maintainer: Douglas Miles
    6% Dec 13,2035
    7%
    8*/
    9% :-swi_module(world_2d,[]).
   10
   11:-export(((
   12         check_for_fall/3,
   13         dir_offset/5,
   14         doorLocation/5,
   15         grid_size/4,
   16         in_grid/2,
   17         in_grid_rnd/2,
   18         in_world_move/3,
   19         is_3d/1,
   20         loc_to_xy/4,
   21         move_dir_target/3,
   22         number_to_dir/3, 
   23         reverse_dir/2,
   24         round_loc/8,
   25         round_loc_target/8,
   26         to_3d/2))).   27
   28:- include(prologmud(mud_header)).   29
   30:- do_gc.   31
   32grid_dist(L1,L2,Dist):- to_3d(L1,L13D),to_3d(L2,L23D),dist(L13D,L23D,Dist),!.
   33
   34dist(_,_,5).
   35
   36==> prologHybrid(pathBetween_call(tRegion,vtDirection,tRegion)).
   37
   38% pathBetween_call(From,DirS,To):-string(DirS),!,atom_string(Dir,DirS),!,any_to_dir(Dir,Dir2),pathDirLeadsTo(From,Dir2,To),same(Dir,Dir2).
   39pathBetween_call_0(From,Dir,To):-any_to_dir(Dir,Dir2),is_asserted(pathDirLeadsTo(From,Dir2,To)),same(Dir,Dir2).
   40pathBetween_call(From,Dir,To):-pathBetween_call_0(From,DirS,To),same(Dir,DirS).
   41   
   42% 5x5 rooms are average
   43%% to_3d(L1,L13D):-compound(L1)->L13D=L1; room_center(L1,X,Y,Z),L13D = xyz(L1,X,Y,Z).
   44to_3d(xyzFn(L1,X,Y,Z),xyzFn(L1,X,Y,Z)):- nonvar(L1),!.
   45to_3d(L1,xyzFn(L1,X,Y,Z)):-room_center(L1,X,Y,Z),!.
   46
   47
   48center_xyz(MaxX,MidX):- MidX is MaxX div 2 + MaxX mod 2.
   49
   50room_center(Region,X,Y,Z):-
   51      grid_size(Region,MaxX,MaxY,MaxZ),
   52      center_xyz(MaxX,X),
   53      center_xyz(MaxY,Y),
   54      center_xyz(MaxZ,Z),!,
   55      dmsg(todo("get room size and calc center ",Region)).
   56
   57loc_to_xy(LOC,X,Y,xyzFn(Region,X,Y,1)):- locationToRegion(LOC,Region),!.
   58loc_to_xy(Region,X,Y,xyzFn(Region,X,Y,1)).
   59
   60is_3d(LOC):- compound(LOC).
   61
   62% Quintus random(1,MaxX,X) and random(1,MaxY,Y)
   63grid_size(Room,MaxX,MaxY,MaxZ):- var(Room),!,tRegion(Room),grid_size(Room,MaxX,MaxY,MaxZ).
   64grid_size(Region,MaxX,MaxY,MaxZ):- fail,
   65   typeGrid(What,1,L),length(L,MaxX),isaOrEq(Region,What),!,
   66   maxZ(MaxZ),findall(1,typeGrid(What,_,_),LL),length(LL,MaxY),!.
   67grid_size(Room,MaxX,MaxY,MaxZ):- nonvar(Room), MaxX = 5 ,MaxY = 5 ,maxZ(MaxZ).
   68
   69maxZ(2).
   70
   71isaOrEq(Region,What):- isa(Region,What).
   72isaOrEq(Region,What):- =@=(Region,What).
   73
   74
   75in_grid(LocName,Var):-var(LocName),!,no_repeats_old([LocName,Var],(tRegion(LocName),in_grid_rnd(LocName,Var))).
   76in_grid(LocName,Var):-var(Var),!,(in_grid_rnd(LocName,Var);in_grid_rnd(LocName,Var);in_grid_rnd(LocName,Var)).
   77in_grid(LocName,Var):-in_grid_no_rnd(LocName,Var).
   78
   79in_grid_no_rnd(xyzFn(LocName,X,Y,Z),xyzFn(LocName,X,Y,Z)) :- nonvar(X),!.
   80in_grid_no_rnd(LocName,xyzFn(LocName,X,Y,Z)) :- !,
   81   grid_size(LocName,MaxX,MaxY,MaxZ),!,between(1,MaxX,X),between(1,MaxY,Y),between(1,MaxZ,Z).
   82in_grid_no_rnd(LocName,LocName).
   83
   84in_grid_rnd(LocName,xyzFn(LocName,X,Y,1)) :-
   85   grid_size(LocName,MaxX,MaxY,_MaxZ),
   86   between(1,100,_),
   87	X is (1 + random(MaxX-2)),
   88	Y is (1 + random(MaxY-2)).	
   89% in_grid_rnd(LocName,xyzFn(LocName,1,1,1)).
   90
   91% for now not useing grids
   92
   93
   94init_location_grid(LocName):-
   95        isa(LocName,LocType),
   96        init_location_grid(LocName,LocType),!.
   97
   98init_location_grid(LocName,LocType):-
   99        isa(LocName,LocType),
  100        init2(LocName,LocType,1,1).
  101
  102% process map file (world.map.pl)
  103init2(LocName,LocType,Y,1) :-
  104	call_u(gridValue(LocName,1,Y,L)),
  105	!,
  106	init3(LocName,LocType,xyzFn(LocName,1,Y,_),L).
  107init2(_LocName,_LocType,_,_).
  108
  109init3(LocName,LocType,xyzFn(LocName,_,Y,1),[]) :-
  110	!,
  111	X is Y + 1,
  112	init2(LocName,LocType,X,1).
  113
  114init3(LocName,LocType,xyzFn(LocName,X,Y,1),[O|T]) :-
  115	typeHasGlyph(Type, O),
  116           rez_loc_object(xyzFn(LocName,X,Y,1),Type),
  117	K is X + 1,
  118	init3(LocName,LocType,xyzFn(LocName,K,Y,1),T).
  119
  120
  121% rez_loc_object(_,0):-!.
  122rez_loc_object(XY,Type):-
  123           gensym(Type,Name2),
  124           Name = xyN(XY,Name2),          
  125           assert_isa(Name,Type),
  126           ain(mudAtLoc(Name,XY)),!,
  127           find_and_call(add_missing_instance_defaults(Name)).
  128
  129
  130%prologDynamic(mudNearbyObjs(tObj,tObj)).
  131%prologDynamic(mudNearbyObjs(tObj,tObj)).
  132%predicateConventionMt(mudNearbyObjs(tObj,tObj),user).
  133mudNearbyObjs(X,Y):-mudAtLoc(X,L1),mudAtLoc(Y,L2),mudNearbyLocs(L1,L2).
  134
  135is_location(Obj):-var(Obj),!,fail.
  136is_location(xyzFn(_,_,_,_)):-!.
  137is_location(Obj):-!,isa(Obj,tRegion),!.
  138
  139locationToRegion(Obj,RegionIn):-locationToRegion_0(Obj,Region)->sanity((nonvar(Region),tRegion(Region))),!,RegionIn=Region.
  140
  141locationToRegion_0(Obj,Obj):-var(Obj),dmsg(warn(var_locationToRegion(Obj,Obj))),!.
  142locationToRegion_0(xyzFn(Region,_,_,_),Region2):-nonvar(Region),!,locationToRegion_0(Region,Region2).
  143locationToRegion_0(Obj,Obj):-nonvar(Obj),!,isa(Obj,tRegion),!.
  144locationToRegion_0(Obj,Region):-nonvar(Obj),must(localityOfObject(Obj,Location)),!,
  145  locationToRegion_0(Location,Region).
  146locationToRegion_0(Obj,Obj):-dmsg(warn(locationToRegion(Obj,Obj))),!.
  147
  148:-export(mudNearbyLocs/2).  149mudNearbyLocs(L1,L2):- var(L1),nonvar(L2),!,mudNearbyLocs(L2,L1).
  150mudNearbyLocs(L1,L2):- nonvar(L1),nonvar(L2),L2=xyzFn(_,_,_,_),locationToRegion(L1,R),!,lc_tcall(locs_near_i(R,L2)).
  151mudNearbyLocs(L1,L2):- nonvar(L1),nonvar(L2),locationToRegion(L1,R1),locationToRegion(L2,R2),!,mudNearbyRegions(R1,R2).
  152mudNearbyLocs(L1,L2):- must((quietly(mudNearbyRegions(R1,R2)),in_grid_no_rnd(R1,L1),in_grid_no_rnd(R2,L2))).
  153
  154% :- decl_not_mpred(locs_near_i,2).
  155:-export(locs_near_i/2).  156locs_near_i(L1,L2):- locationToRegion(L1,R),in_grid_no_rnd(R,L2).
  157locs_near_i(L1,L2):- locationToRegion(L1,R),pathBetween_call(R,_,R2),in_grid_no_rnd(R2,L2).
  158
  159mudNearbyRegions(R1,R2):-pathBetween_call(R1,_,R2).
  160mudNearbyRegions(R1,R1).
  161
  162% 345345  instTypeProps(OfAgent,agent,[facing(F),atloc(L)]):-  dfsdfd ignore((nonvar(OfAgent),create_someval(facing,OfAgent,F),create_someval(atloc,OfAgent,L))).
  163
  164% CANT transitive_other(mudAtLoc,1,Obj,What):-mudInsideOf(Obj,What).
  165
  166is_at(Obj,Where):-localityOfObject(Obj,Where).
  167is_at(Obj,Where):-mudAtLoc(Obj,Where).
  168is_at(Obj,Where):-mudSubPart(What,Obj),is_at(What,Where).
  169
  170% ((tObj(Obj), ~(mudPossess(_,Obj)))==>spatialInRegion(Obj)).
  171tPathway(Obj)==>spatialInRegion(Obj).
  172
  173
  174
  175localityOfObject(Obj,Region),tRegion(Region)==> inRegion(Obj,Region).
  176mudAtLoc(Obj,LOC),{locationToRegion(LOC,Region)},tRegion(Region)==> inRegion(Obj,Region).
  177
  178
  179prologHybrid(mudInsideOf/2).
  180% :-sanity(( requires_storage((mudInsideOf(_G3775190, _G3775191):-is_asserted(mudStowing(_G3775191, _G3775190))))  )).
  181mudInsideOf(Inner,Outer):-loop_check(mudStowing(Outer,Inner)).
  182mudInsideOf(Inner,Outer):-loop_check(mudContains(Outer,Inner)).
  183
  184moves_with(Obj1,Obj2):-nonvar(Obj2),!,moves_with(Obj2,Where),localityOfObject(Where,Obj1).
  185moves_with(Obj1,Obj2):-moves_with_sym(Obj1,Obj2).
  186moves_with(Obj1,Obj2):-moves_with_sym(Obj2,Obj1).
  187moves_with_sym(Obj1,Obj2):-localityOfObject(Where,Obj1),moves_with(Obj2,Where).
  188
  189mudLocOnSurface(Clothes,Agent):-loop_check(wearsClothing(Agent,Clothes),fail).
  190
  191:-export(same_regions/2).  192same_regions(Agent,Obj):-inRegion(Agent,Where1),dif(Agent,Obj),inRegion(Obj,Where2),Where1=Where2.
  193
  194==>(prologHybrid(inRegion(tObj,tRegion))).
  195%prologPTTP(localityOfObject(tObj,tSpatialthing)).
  196
  197%:- ensure_universal_stub(prologPTTP,inRegion/2).
  198%:- ensure_universal_stub(prologPTTP,mudTestAgentWearing/2).
  199
  200==>(prologHybrid(mudAtLoc/2)).
  201==>(meta_argtypes(mudAtLoc(tObj,tSpatialThing))).
  202
  203
  204% compute the most specific location description
  205mostSpecificLocalityOfObject(Obj,Where):-
  206   one_must(is_asserted(mudAtLoc(Obj,Where)),one_must(is_asserted(localityOfObject(Obj,Where)),is_asserted(inRegion(Obj,Where)))).
  207
  208% :- (rtrace,trace).
  209
  210% objects can be two places x,y,z's at once
  211((spatialInRegion(Obj),mudAtLoc(Obj,NewLoc), 
  212 {(mudAtLoc(Obj,OldLoc), OldLoc\==NewLoc)})
  213   ==>
  214   ~mudAtLoc(Obj,OldLoc)).
  215
  216
  217% objects are placed by default in center of region
  218((spatialInRegion(Obj), inRegion(Obj,Region), {
  219 \+ tPathway(Obj), \+ lookup_u(mudAtLoc(Obj,xyzFn(Region,_,_,_)))},
  220  {in_grid_rnd(Region,LOC)})
  221  ==>
  222   mudAtLoc(Obj,LOC)).
  223
  224
  225% objects cannot be in two localities (Regions?) at once
  226((spatialInRegion(Obj),localityOfObject(Obj,NewLoc), 
  227 {(localityOfObject(Obj,OldLoc), OldLoc\==NewLoc)})
  228  ==> 
  229  ~localityOfObject(Obj,OldLoc)).
  230
  231% if something leaves a room get rid of old location 
  232((spatialInRegion(Obj),inRegion(Obj,NewRegion), 
  233 {(mudAtLoc(Obj,OldLoc), OldLoc\=xyzFn(NewRegion,_,_,_))})
  234  ==> 
  235  ~mudAtLoc(Obj,OldLoc)).
  236
  237% if something leaves a room get rid of old inRegion/2 
  238((spatialInRegion(Obj),inRegion(Obj,NewRegion), 
  239 {dif(NewRegion,OldLoc),(inRegion(Obj,OldLoc), OldLoc\=NewRegion)})
  240  ==> 
  241  ~inRegion(Obj,OldLoc)).
  242
  243:- ain((inRegion(Obj,Region)==> {ain((spatialInRegion(Obj),tRegion(Region)))})).
  244
  245
  246% create pathway objects and place them in world
  247/*
  248(pathDirLeadsTo(Region,Dir,R2)/ground(pathDirLeadsTo(Region,Dir,R2)),   
  249    { mudExitAtLoc(Region,Dir,LOC), Obj = apathFn_BAD1(Region,Dir) }) ==>  
  250                        (tPathway(Obj),localityOfObject(Obj,Region),mudAtLoc(Obj,LOC)).
  251*/
  252
  253:- ain(tPathway(apathFn(Region,Dir)) ==> mudDoorwayDir(Region,apathFnAA(Region,Dir),Dir)).
  254
  255
  256mudExitAtLoc(Region,Dir,xyzFn(Region,X,Y,Z)):- call_u(calc_from_center_xyz(Region,Dir,2,X,Y,Z)).
  257
  258% :-kif_tell(localityOfObject(A,B) &  localityOfObject(B,C) ==> localityOfObject(A,C)).
  259
  260:- kb_shared(mudSubPart/2).  261:- kb_shared(predInterArgIsa/1).  262:- kb_shared(relationAllExists/3).  263
  264==>singleValuedInArgDefault(localityOfObject, 2, isMissing).
  265
  266mudAtLoc(Who,xyzFn(Loc,_,_,_))==>localityOfObject(Who,Loc).
  267
  268genls(tHominid,tAgent).
  269genls(tHumanBody,tBodyPart).
  270
  271predInterArgIsa(mudSubPart(tBodyPart,tBodyPart)).
  272
  273/* TODO Re-Enable 
  274relationAllExists(mudSubPart,tHominid,tHumanBody).
  275relationAllExists(mudSubPart,tHumanBody,tBodyPart).
  276relationAllExists(mudSubPart,tHumanBody,isEach(tHumanHead,tHumanNeck,tHumanUpperTorso,tHumanLowerTorso,tHumanPelvis,tHumanArms,tHumanLegs)).
  277relationAllExists(mudSubPart,tHumanHead,isEach(tHumanFace,tHumanHair)).
  278*/
  279
  280predPredicateToFunction(Pred,SubjT,ObjT,FullNameFnO):- 
  281  is_asserted(predPredicateToFunction(Pred,SubjT,ObjT,FullNameFn)) *-> FullNameFnO=FullNameFn ; 
  282  (i_name('i',ObjT,Obj),i_name(Obj,Pred,ObjPred),i_name('Of',SubjT,OfSubj),concat_atom([ObjPred,OfSubj,'Fn'],FullNameFn)),simplifyFullName(FullNameFn,FullNameFnO).
  283
  284
  285simplifyFullName(FullNameFn,FullNameFn).
  286
  287find_instance_of(Pred,Subj,Obj):-
  288 relationAllExists(Pred,SubjT,ObjT), 
  289 isa(Subj,SubjT), 
  290 ((is_asserted(t(Pred,Subj,Obj)),isa(Obj,ObjT)) *-> true ; (predPredicateToFunction(Pred,SubjT,ObjT,PredFn), Obj =.. [PredFn,Subj])).
  291
  292mudInsideOf(Inner,Outer)==>mudSubPart(Outer,Inner).
  293wearsClothing(Agent,Clothes)==>mudSubPart(Agent,Clothes).
  294% mudSubPart(Subj,Obj):- (nonvar(Subj);nonvar(Obj)),!,test_tl(infThirdOrder), find_instance_of(mudSubPart,Subj,Obj).
  295% mudSubPart(face,isEach(eyes,nose,mouth)).
  296% mudSubPart([upper_torso,arms,left_arm,left_hand,left_digits]).
  297% mudSubPart([upper_torso,arms,right_arm,right_hand,right_digits]).
  298% mudSubPart([pelvis,legs,left_leg,left_foot,left_toes]).
  299% mudSubPart([pelvis,legs,right_leg,right_foot,right_toes]).
  300
  301
  302
  303
  304is_in_world(Var):- is_ftVar(Var),!,trace_or_throw(var_is_in_world(Var)).
  305is_in_world(apathFn(A,B)):- ground(apathFn(A,B)),!.
  306is_in_world(Obj):-isa_asserted(Obj,tRegion),!.
  307is_in_world(Obj):-lookup_u(mudAtLoc(Obj,_)),!.
  308is_in_world(Obj):-lookup_u(mudStowing(Who,Obj)),!,is_in_world(Who).
  309is_in_world(Obj):-lookup_u(mudSubPart(Who,Obj)),!,is_in_world(Who).
  310
  311
  312
  313put_in_world(Obj):- mudAtLoc(Obj,_XYZFn),!.
  314put_in_world(Obj):- is_in_world(Obj),!.
  315put_in_world(Obj):- localityOfObject(Obj,Loc),  
  316  in_grid(Loc,XYZFn),unoccupied(Obj,XYZFn),!,
  317  ain(mudAtLoc(Obj,XYZFn)),
  318  ain(mudNeedsLook(Obj,vTrue)).
  319put_in_world(Obj):- random_xyzFn(LOC),ain(mudAtLoc(Obj,LOC)),
  320  ain(mudNeedsLook(Obj,vTrue)).
  321
  322
  323/*
  324% :-export decl_database_hook/2.  action_info
  325:-export(deduce_facts/2).
  326:-export(create_random_fact/1).
  327:-export( hooked_random_instance/3).
  328%:-export fact_always_true/1.
  329:-export( fact_maybe_deduced/1).
  330:-export( fact_is_false/2).
  331:-dynamic fact_is_false/2.
  332*/
  333
  334prologHybrid(mudInsideOf(tObj,tObj)).
  335
  336% facts that cant be true
  337
  338%fact_is_false(mudAtLoc(Obj,_LOC),mudInsideOf(Obj,What)) :- nonvar(Obj),is_asserted(mudInsideOf(Obj,What)),not(isa(What,tRegion)).
  339%fact_is_false(mudAtLoc(Obj,LOC),mudInsideOf(Obj,What)) :- nonvar(Obj),(mudInsideOf(Obj,What)),not(mudAtLoc(What,LOC)).
  340%fact_is_false(localityOfObject(Obj,_LOC),mudInsideOf(Obj,What)) :- nonvar(Obj),(mudInsideOf(Obj,What)),!.
  341
  342% facts that must be true 
  343%  suggest a deducable fact that is always defiantely true but not maybe asserted
  344%TODO USE EVER? fact_always_true(localityOfObject(apathFn(Region,Dir),Region)):-is_asserted(pathDirLeadsTo(Region,Dir,_)).
  345fact_always_true(localityOfObject(Obj,Region)):- is_asserted(mudAtLoc(Obj,LOC)),locationToRegion(LOC,Region),!.
  346
  347(((localityOfObject(_,_),{localityOfObject(apathFn(Region,Dir),Region)},
  348    \+ pathDirLeadsTo(Region, Dir, _)  ) ==>
  349     \+ localityOfObject(apathFn(Region,Dir),Region))).
  350
  351%  suggest a deducable fact that is probably true but not already asserted
  352%TODO USE EVER? fact_maybe_deduced(localityOfObject(Obj,Region)):- is_asserted(mudAtLoc(Obj,LOC)),locationToRegion(LOC,Region),!.
  353%TODO USE EVER? fact_maybe_deduced(localityOfObject(apathFn(Region,Dir),Region)):-is_asserted(pathDirLeadsTo(Region,Dir,_)).
  354
  355% create_and_assert_random_fact(_):- t_l:noDBaseHOOKS(_),!.
  356create_and_assert_random_fact(Fact):- fail,must(create_random_fact(Fact)),aina(Fact).
  357
  358%  suggest a random fact that is probably is not already true
  359create_random_fact(G) :- into_functor_form(t,G,MPred),G\=@=MPred,!,create_random_fact(MPred).
  360create_random_fact(G) :- is_asserted(G),!,dmsg((create_random_fact(G) :- is_asserted(G))).
  361create_random_fact(t(mudAtLoc,Obj,LOC)) :- !,nonvar(Obj),is_asserted(localityOfObject(Obj,Region)),!,((in_grid(Region,LOC),unoccupied(Obj,LOC),
  362   \+ ( ~ mudAtLoc(Obj,LOC)))).
  363create_random_fact(t(localityOfObject,Obj,Region)) :- !, nonvar(Obj),not_asserted((localityOfObject(Obj,_))),
  364  if_defined(asserted_or_deduced(localityOfObject(Obj,Region))).
  365create_random_fact(t(Other,Obj,Default)) :- nonvar(Obj),argIsa(Other,2,Type),random_instance_no_throw(Type,Default,ground(Default)),!.
  366
  367
  368%  suggest random values
  369hooked_random_instance(vtDirection,Dir,Test) :- my_random_member(Dir,[vNorth,vSouth,vEast,vWest,vNE,vNW,vSE,vSW]),Test,!.
  370hooked_random_instance(ftInt,3,Test):-call(Test),dmsg(random_instance(ftInt,3,Test)),dmsg(hooked_random_instance(ftInt,3,Test)),!,fail.
  371
  372
  373random_region(LOC):- var(LOC),findall(O,isa(O,tRegion),LOCS),my_random_member(LOC,LOCS).
  374
  375
  376random_xyzFn(LOC):-
  377   must_det(random_instance(tRegion,Region,true)),
  378   in_grid_rnd(Region,LOC),!.
  379random_xyzFn(xyzFn('Area1000',1,1,1)):- fail, dmsg(trace_or_throw(mpred_not_loaded)).
  380
  381unoccupied(_,Loc):- not_asserted((mudAtLoc(_,Loc))),!.
  382unoccupied(_,_):-!.
  383unoccupied(Obj,Loc):- loop_check(unoccupied_ilc(Obj,Loc),not_asserted((mudAtLoc(_,Loc)))),!.
  384
  385unoccupied_ilc(Obj,Loc):- is_occupied(Loc,What),!,What=Obj.
  386unoccupied_ilc(_,_).
  387
  388is_occupied(Loc,What):- is_asserted(mudAtLoc(What,Loc)),!.
  389is_occupied(Loc,What):- locationToRegion(Loc,Region),localityOfObject(What,Region),put_in_world(What),mudAtLoc(What,Loc),!.
  390
  391% Used all over the place
  392% Transforms location based on cardinal direction given
  393
  394calc_xyz(Region1,Dir,force(X1,Y1,Z1),X2,Y2,Z2):-
  395   to_3d(Region1,xyzFn(_,X,Y,Z)),
  396   get_dir_offset(Dir,1,OX,OY,OZ),
  397   X2 is X+ (OX*X1),Y2 is Y+OY*Y1,Z2 is Z+OZ*Z1.
  398
  399calc_from_center_xyz(Region1,Dir,R,X2,Y2,Z2):-
  400   room_center(Region1,X,Y,Z),
  401   get_dir_offset(Dir,R,OX,OY,_),
  402   X2 is X+ OX ,Y2 is Y+ OY, Z2 is Z.
  403
  404prologBuiltin(random_path_dir/1).
  405
  406% random_path_dir(Dir):- nonvar(Dir),random_path_dir(Dir0),Dir=Dir0,!.
  407random_path_dir(Dir):- no_repeats(random_path_dir0(Dir)).
  408random_travel_dir(Dir):- no_repeats(random_path_dir1(Dir)).
  409
  410random_path_dir0(Dir):- call(call,random_instance(vtBasicDir,Dir,true)).
  411random_path_dir1(Dir):- call(call,random_instance(vtBasicDirPlusUpDown,Dir,true)).
  412random_path_dir1(Dir):- call(call,random_instance(vtDirection,Dir,true)).
  413
  414
  415from_dir_target(LOC,Dir,XXYY):- is_3d(LOC),!,
  416  move_dir_target(LOC,Dir,XXYY).
  417from_dir_target(Agent,Dir,XXYY):-
  418  mudAtLoc(Agent,RegionXYZ),
  419  move_dir_target(RegionXYZ,Dir,XXYY).
  420
  421move_dir_target(RegionXYZ,Dir,XXYY):-
  422   move_dir_target(RegionXYZ,Dir,1,XXYY).
  423
  424
  425move_dir_target(RegionXYZ,DirS,Force,XXYY):-
  426   any_to_atom(DirS,Dir),
  427   once(((calc_xyz(RegionXYZ,Dir,force(Force,Force,Force),X,Y,Z)),
  428   (locationToRegion(RegionXYZ,Region1)),
  429   (round_loc_target(Region1,X,Y,Z,Region2,X2,Y2,Z2)),
  430   XXYY = xyzFn(Region2,X2,Y2,Z2),
  431   sanity(ground(XXYY)))),
  432   check_ahead_for_ground(XXYY),!.
  433
  434move_dir_target(RegionXYZ,Dir,_Force,XXYY):-
  435   any_to_string(Dir,DirS),
  436   locationToRegion(RegionXYZ,Region1),!,
  437   pathBetween_call(Region1,DirS,Region2),
  438   in_grid_rnd(Region2,XXYY),
  439   XXYY = xyzFn(Region2,_X2,_Y2,_Z2),
  440   sanity(ground(XXYY)),!,
  441   check_ahead_for_ground(XXYY),!.
  442
  443
  444round_loc_target(Region1,X,Y,Z,Region3,X3,Y3,Z3):-
  445   round_loc(Region1,X,Y,Z,Region2,X2,Y2,Z2),!,
  446   Region2=Region3,X2=X3,Y2=Y3,Z2=Z3.
  447
  448round_loc(Region1,X,Y,Z,Region2,X2,Y2,Z2):-
  449   compute_dir(Region1,X,Y,Z,Dir),!,
  450   round_loc_dir(Region1,X,Y,Z,Dir,Region2,X2,Y2,Z2),!.
  451
  452round_loc_dir(Region1,X,Y,Z,'',Region2,X2,Y2,Z2):-!,
  453   X2=X,Y2=Y,Z2=Z,Region2=Region1.
  454
  455round_loc_dir(Region1,X,Y,Z,Dir,Region2,X2,Y2,Z2):- 
  456   any_to_dir(Dir,DirLong),
  457   pathBetween_call(Region1,DirLong,Region2),!,
  458   grid_size(Region1,X1,Y1,Z1),
  459   calc_xyz(xyzFn(Region2,X,Y,Z),Dir,force(-X1,-Y1,-Z1),X2,Y2,Z2),!.
  460
  461round_loc_dir(Region1,X,Y,Z,_Dir,Region2,X2,Y2,Z2):-Region2=Region1,X2=X,Y2=Y,Z2=Z.
  462
  463prologBuiltin(compute_dir/5).
  464compute_dir(Region1,X,Y,Z,Dir):-
  465  grid_size(Region1,MaxX,MaxY,MaxZ),
  466   ((X<1 -> EW=vWest ; X > MaxX -> EW=vEast ; EW= ''),
  467   (Y<1 -> NS=vNorth ; Y > MaxY -> NS=vSouth ; NS= ''),
  468   (Z<1 -> UD=vDown ; Z > MaxZ -> UD=vUp ; UD= '')),
  469   atomic_list_concat_catch([NS,EW,UD],'',Dir),!.
  470
  471prologBuiltin(get_dir_offset/5).
  472get_dir_offset(Dir,F,OX,OY,OZ):- sanity(nonvar(Dir)),
  473  dir_offset(Dir,F,OX,OY,OZ),!.
  474get_dir_offset(reverseOf(Dir),F,OX,OY,OZ):- !,get_dir_offset((Dir),F,X,Y,Z),!, OX is -X, OY is -Y, OZ is -Z.
  475get_dir_offset(Dir,F,OX,OY,OZ):- any_to_atom(Dir,DirA),
  476  dir_offset(DirA,F,OX,OY,OZ),!.
  477get_dir_offset(Dir,F,OX,OY,OZ):- any_to_string(Dir,DirS),
  478  dir_offset(DirS,F,OX,OY,OZ),!.
  479
  480
  481
  482p2c_dir2('s','vSouth').
  483p2c_dir2('w','vWest').
  484p2c_dir2('u','vUp').
  485p2c_dir2('d','vDown').
  486p2c_dir2('e','vEast').
  487p2c_dir2('n','vNorth').
  488
  489:-export(is_any_dir/1).  490is_any_dir(Dir):-var(Dir),!,fail.
  491is_any_dir(Dir):-any_to_dir(Dir,_).
  492:-export(any_to_dir/2).  493
  494any_to_dir(D,D):-var(D),!.
  495any_to_dir(S,D):-string(S),string_to_atom(S,A),any_to_dir(A,D),!.
  496any_to_dir(D,D):-dir_offset(D,_,_,_,_),!.
  497any_to_dir(A,D):-p2c_dir2(D,A),!.
  498any_to_dir(D,O):-atom(D),sub_atom(D, 0, 1, _, S),toLowercase(S,L),p2c_dir2(L,O),!.
  499any_to_dir(D,D):-pathDirLeadsTo(_,D,_),!.
  500
  501:-export(dir_offset/5).  502
  503% prologHybrid(dir_offset(term,int,int,int,int)).
  504
  505
  506% :-mpred_trace_all.
  507
  508prologBuiltin(dir_offset/5).
  509dir_offset(vUp,F,0,0,F).
  510dir_offset(vDown,F,0,0,-F).
  511dir_offset(vNorth,F,0,-F,0).
  512dir_offset(vSouth,F,0,F,0).
  513dir_offset(vEast,F,F,0,0).
  514dir_offset(vWest,F,-F,0,0).
  515dir_offset(vNE,F,F,-F,0).
  516dir_offset(vSW,F,-F,F,0).
  517dir_offset(vSE,F,F,F,0).
  518dir_offset(vNW,F,-F,-F,0).
  519dir_offset(vHere,_,0,0,0).
  520
  521% :-mpred_no_spy_all. with_pfa
  522
  523% MergedNess -1,0,1 = contacting_at,inside,outside_near_on
  524with_offset(detatched,F,X,Y,Z):-dir_offset(vHere,F,X,Y,Z).
  525with_offset(absolute_with,F,X,Y,Z):-dir_offset(vUp,F,X,Y,Z).
  526with_offset(relative_from,F,X,Y,Z):-dir_offset(vDown,F,X,Y,Z).
  527with_offset(surrounding,F,X,Y,Z):-dir_offset(vNorth,F,X,Y,Z).
  528with_offset(mudInsideOf,F,X,Y,Z):-dir_offset(vSouth,F,X,Y,Z).
  529with_offset(on,F,X,Y,Z):-dir_offset(vEast,F,X,Y,Z).
  530with_offset(tPartofObj,F,X,Y,Z):-dir_offset(vWest,F,X,Y,Z).
  531
  532facing_offset(at,F,X,Y,Z):-dir_offset(vHere,F,X,Y,Z).
  533facing_offset(above,F,X,Y,Z):-dir_offset(vUp,F,X,Y,Z).
  534facing_offset(below,F,X,Y,Z):-dir_offset(vDown,F,X,Y,Z).
  535facing_offset(left,F,X,Y,Z):-dir_offset(vWest,F,X,Y,Z).
  536facing_offset(right,F,X,Y,Z):-dir_offset(vEast,F,X,Y,Z).
  537facing_offset(behind,F,X,Y,Z):-dir_offset(vSouth,F,X,Y,Z).
  538facing_offset(front,F,X,Y,Z):-dir_offset(vNorth,F,X,Y,Z).
  539
  540
  541% baseKB:decl_database_hook(clause( retract,_),mudAtLoc(Agent,_)):-padd(Agent,mudNeedsLook(vTrue)).
  542
  543% mudAtLoc(Agent,_)==> mudNeedsLook(Agent,vTrue).
  544mudAtLoc(Agent,_)==>{padd(Agent,mudNeedsLook(vTrue))}.
  545
  546% dir_mult(X,Y,Z,X1,Y1,Z1,X2,Y2,Z2):- X2 is X * X1,Y2 is Y * Y1,Z2 is Z * Z1.
  547
  548
  549% Used in move.pl,push.pl and climb.pl
  550% Move agent (usually). Used to relocate agent'vSouth location.
  551in_world_move(LOC,Agent,DirS) :-
  552        string_to_atom(DirS,Dir),
  553        ignore(is_asserted(mudAtLoc(Agent,LOC))),
  554        must_det((locally(t_l:infAssertedOnly(mudAtLoc),in_world_move0(LOC,Agent,Dir)),       
  555         is_asserted(mudAtLoc(Agent,LOC2)),
  556         LOC2 \== LOC)),!.
  557
  558can_world_move(LOC,_Agent,Dir) :- check_behind_for_ground(LOC),move_dir_target(LOC,Dir,_).
  559
  560in_world_move0(LOC,Agent,Dir) :-
  561      any_to_dir(Dir,DirS),
  562        % rtrace(padd(Agent,mudFacing(DirS))),
  563       % must((
  564         ain(mudFacing(Agent,DirS)),
  565        % call_u(mudFacing(Agent,DirOther)),
  566         %DirOther==DirS)),
  567        sanity((is_asserted(mudAtLoc(Agent,LOC)))),
  568        check_behind_for_ground(LOC),
  569	move_dir_target(LOC,Dir,XXYY),!,
  570   must_det_l_pred(show_call,(
  571        dmsg(move_dir_target(LOC,DirS,XXYY)),
  572        locationToRegion(LOC,Region1),
  573        locationToRegion(XXYY,Region2),
  574        ((expire_dont_add, clr(mudAtLoc(Agent,LOC)))),
  575        %rtrace,
  576        call((expire_dont_add, ain_expanded(mudAtLoc(Agent,XXYY)),
  577        %nortrace,
  578        sanity((is_asserted(mudAtLoc(Agent,XXYY)))),
  579        sanity((clause_u(mudAtLoc(Agent,LOC2)),LOC2 \== LOC)))),         
  580   ifThen(( Region1\==Region2) ,raise_location_event(LOC,actNotice(reciever,actLeave(Agent,Region1,to(Dir))))),
  581        reverse_dir(Dir,Rev),
  582   ifThen(( Region1\==Region2) ,raise_location_event(XXYY,actNotice(reciever,actEnter(Agent,Region2,from(Rev))))),!,
  583	check_for_fall(LOC,XXYY,Agent))).
  584
  585check_behind_for_ground(LOC):-nonvar(LOC).
  586check_ahead_for_ground(XXYY):-nonvar(XXYY),
  587   to_3d(XXYY,xyzFn(L1,X,Y,Z)),
  588   grid_size(L1,MX,MY,MZ),
  589   inside_grid(L1,X,Y,Z,MX,MY,MZ).
  590
  591inside_grid(_L1,X,Y,Z,MX,MY,MZ):-is_between(1,MX,X),is_between(1,MY,Y),is_between(1,MZ,Z).
  592
  593is_between(L,H,V):- H >= V,L =< V.
  594
  595% Used for every move
  596% Does the agent take a header off a high object?
  597check_for_fall(LOC,XXYY,Agent) :-
  598	mudAtLoc(HighObj,LOC),
  599	props(HighObj,mudHeight(Hh)),
  600        % if nothing is there pretend it is 1
  601	(\+ (mudAtLoc(_,XXYY)) -> Hl = 1; mudAtLoc(LowObj,XXYY)),
  602	props(LowObj,mudHeight(Hl)),
  603	Hd is Hh - Hl,
  604	Hd > 1,
  605	call_update_stats(Agent,fall).
  606check_for_fall(_,_,_).
  607
  608
  609% Reverses the direction returned by number_to_direction
  610% Used for fleeing
  611:- export(reverse_dir/2).  612:- public(reverse_dir/2).  613reverse_dir(W,R):-string(W),atom_string(A,W),!,reverse_dir0(A,RA),atom_string(RA,R),!.
  614reverse_dir(A,R):-reverse_dir0(A,R)*->true;reverse_dir1(A,R).
  615
  616reverse_dir1(reverseOf(Was),RWas):-nonvar(Was),!,RWas=Was.
  617reverse_dir1(skPathFn(Direction,R2,R1),skPathFn(Direction,R1,R2)):-nonvar(Direction),!.
  618reverse_dir1(Was,reverseOf(Was)):-nonvar(Was),!.
  619
  620
  621reverse_dir0(vSouth,vNorth).
  622reverse_dir0(vEast,vWest).
  623reverse_dir0(vNorth,vSouth).
  624reverse_dir0(vWest,vEast).
  625reverse_dir0(vUp,vDown).
  626reverse_dir0(vDown,vUp).
  627reverse_dir0(vNW,vSE).
  628reverse_dir0(vNE,vSW).
  629reverse_dir0(vSW,vNE).
  630reverse_dir0(vSE,vNW).
  631
  632
  633% Yet another hash table to covert numbers into aDirectionsFn (or the reverse).
  634num_near_reverse(1,vNW,vHere).
  635num_near_reverse(2,vNorth,vHere).
  636num_near_reverse(3,vNE,vHere).
  637num_near_reverse(4,vWest,vHere).
  638num_near_reverse(6,vEast,vHere).
  639num_near_reverse(7,vSW,vHere).
  640num_near_reverse(8,vSouth,vHere).
  641num_near_reverse(9,vSE,vHere).
  642
  643num_near_reverse(0,vDown,vHere).
  644num_near_reverse(5,vUp,vHere).
  645
  646% Translates numbers returned from scan_lists_aux/3 (the number of the location)
  647% into thier relative aDirectionsFn.
  648number_to_dir(1,vNW,vNW).
  649number_to_dir(2,vNorth,vNW).
  650number_to_dir(3,vNorth,vNorth).
  651number_to_dir(4,vNorth,vNE).
  652number_to_dir(5,vNE,vNE).
  653number_to_dir(6,vWest,vNW).
  654number_to_dir(7,vNW,vHere).
  655number_to_dir(8,vNorth,vHere).
  656number_to_dir(9,vNE,vHere).
  657number_to_dir(10,vEast,vNE).
  658number_to_dir(11,vWest,vWest).
  659number_to_dir(12,vWest,vHere).
  660number_to_dir(14,vEast,vHere).
  661number_to_dir(15,vEast,vEast).
  662number_to_dir(16,vWest,vSW).
  663number_to_dir(17,vSW,vHere).
  664number_to_dir(18,vSouth,vHere).
  665number_to_dir(19,vSE,vHere).
  666number_to_dir(20,vEast,vSE).
  667number_to_dir(21,vSW,vSW).
  668number_to_dir(22,vSouth,vSW).
  669number_to_dir(23,vSouth,vSouth).
  670number_to_dir(24,vSouth,vSE).
  671number_to_dir(25,vSE,vSE).
  672
  673
  674% Scans through list of perceptions (as returned by look_percepts(Agent,L) or look_all(NearAgt,_,_,_,L,_))
  675% for an object,returns the direction in which the object lies.
  676list_object_dir_sensed(_,List,Type,Dir) :-
  677	!,
  678	scan_lists_aux(List,Type,1,N),
  679	number_to_dir(N,Dir,_).
  680
  681
  682list_object_dir_near(List,Type,Dir) :-
  683	!,
  684	scan_lists_aux(List,Type,1,N),
  685	num_near_reverse(N,Dir,_).
  686
  687scan_lists_aux([Loc|_],Type,N,N) :-
  688	member(Obj,Loc),
  689        isa(Obj,Type),
  690	!.
  691scan_lists_aux([_|Rest],Type,M,N) :-
  692	Mtemp is M + 1,
  693	!,
  694	scan_lists_aux(Rest,Type,Mtemp,N).
  695
  696
  697doorLocation(_Room,3,0,_Z,vNorth).
  698doorLocation(_Room,2,0,_Z,vNorth).
  699doorLocation(_Room,4,0,_Z,vNorth).
  700doorLocation(_Room,3,6,_Z,vSouth).
  701doorLocation(_Room,2,6,_Z,vSouth).
  702doorLocation(_Room,4,6,_Z,vSouth).
  703doorLocation(_Room,0,2,_Z,vWest).
  704doorLocation(_Room,0,3,_Z,vWest).
  705doorLocation(_Room,0,4,_Z,vWest).
  706doorLocation(_Room,6,2,_Z,vEast).
  707doorLocation(_Room,6,3,_Z,vEast).
  708doorLocation(_Room,6,4,_Z,vEast).
  709doorLocation(_Room,6,0,_Z,vNE).
  710doorLocation(_Room,6,6,_Z,vSE).
  711doorLocation(_Room,0,0,_Z,vNW).
  712doorLocation(_Room,0,6,_Z,vSW).
  713doorLocation(_Room,_X,_Y,_Z,_Dir):-!,fail