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)->nop(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),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
  312put_in_world(Obj):- mudAtLoc(Obj,_XYZFn),!.
  313put_in_world(Obj):- is_in_world(Obj),!.
  314put_in_world(Obj):- localityOfObject(Obj,Loc),  
  315  in_grid(Loc,XYZFn),unoccupied(Obj,XYZFn),!,
  316  ain(mudAtLoc(Obj,XYZFn)),
  317  ain(mudNeedsLook(Obj,vTrue)).
  318put_in_world(Obj):- random_xyzFn(LOC),ain(mudAtLoc(Obj,LOC)),
  319  ain(mudNeedsLook(Obj,vTrue)).
  320
  321
  322/*
  323% :-export decl_database_hook/2.  baseKB:action_info
  324:-export(deduce_facts/2).
  325:-export(create_random_fact/1).
  326:-export( hooked_random_instance/3).
  327%:-export fact_always_true/1.
  328:-export( fact_maybe_deduced/1).
  329:-export( fact_is_false/2).
  330:-dynamic fact_is_false/2.
  331*/
  332
  333prologHybrid(mudInsideOf(tObj,tObj)).
  334
  335% facts that cant be true
  336
  337%fact_is_false(mudAtLoc(Obj,_LOC),mudInsideOf(Obj,What)) :- nonvar(Obj),is_asserted(mudInsideOf(Obj,What)),not(isa(What,tRegion)).
  338%fact_is_false(mudAtLoc(Obj,LOC),mudInsideOf(Obj,What)) :- nonvar(Obj),(mudInsideOf(Obj,What)),not(mudAtLoc(What,LOC)).
  339%fact_is_false(localityOfObject(Obj,_LOC),mudInsideOf(Obj,What)) :- nonvar(Obj),(mudInsideOf(Obj,What)),!.
  340
  341% facts that must be true 
  342%  suggest a deducable fact that is always defiantely true but not maybe asserted
  343%TODO USE EVER? fact_always_true(localityOfObject(apathFn(Region,Dir),Region)):-is_asserted(pathDirLeadsTo(Region,Dir,_)).
  344fact_always_true(localityOfObject(Obj,Region)):- is_asserted(mudAtLoc(Obj,LOC)),locationToRegion(LOC,Region),!.
  345
  346(((localityOfObject(_,_),{localityOfObject(apathFn(Region,Dir),Region)},
  347    \+ pathDirLeadsTo(Region, Dir, _)  ) ==>
  348     \+ localityOfObject(apathFn(Region,Dir),Region))).
  349
  350%  suggest a deducable fact that is probably true but not already asserted
  351%TODO USE EVER? fact_maybe_deduced(localityOfObject(Obj,Region)):- is_asserted(mudAtLoc(Obj,LOC)),locationToRegion(LOC,Region),!.
  352%TODO USE EVER? fact_maybe_deduced(localityOfObject(apathFn(Region,Dir),Region)):-is_asserted(pathDirLeadsTo(Region,Dir,_)).
  353
  354% create_and_assert_random_fact(_):- t_l:noDBaseHOOKS(_),!.
  355create_and_assert_random_fact(Fact):- fail,must(create_random_fact(Fact)),aina(Fact).
  356
  357%  suggest a random fact that is probably is not already true
  358create_random_fact(G) :- into_functor_form(t,G,MPred),G\=@=MPred,!,create_random_fact(MPred).
  359create_random_fact(G) :- is_asserted(G),!,dmsg((create_random_fact(G) :- is_asserted(G))).
  360create_random_fact(t(mudAtLoc,Obj,LOC)) :- !,nonvar(Obj),is_asserted(localityOfObject(Obj,Region)),!,((in_grid(Region,LOC),unoccupied(Obj,LOC),
  361   \+ ( ~ mudAtLoc(Obj,LOC)))).
  362create_random_fact(t(localityOfObject,Obj,Region)) :- !, nonvar(Obj),not_asserted((localityOfObject(Obj,_))),
  363  if_defined(asserted_or_deduced(localityOfObject(Obj,Region))).
  364create_random_fact(t(Other,Obj,Default)) :- nonvar(Obj),argIsa(Other,2,Type),random_instance_no_throw(Type,Default,ground(Default)),!.
  365
  366
  367my_rnd_member(ELE,[LOC]):-nonvar(LOC),!,ELE=LOC.
  368my_rnd_member(LOC,LOCS):- length(LOCS,Len),Len>0,random_permutation(LOCS,LOCS2),!,member(LOC,LOCS2).
  369
  370
  371%  suggest random values
  372hooked_random_instance(vtDirection,Dir,Test) :- my_rnd_member(Dir,[vNorth,vSouth,vEast,vWest,vNE,vNW,vSE,vSW]),Test,!.
  373hooked_random_instance(ftInt,3,Test):-call(Test),dmsg(random_instance(ftInt,3,Test)),dmsg(hooked_random_instance(ftInt,3,Test)),!,fail.
  374
  375random_region(LOC):- nonvar(LOC),!.
  376random_region(LOC):- var(LOC),findall(O,isa(O,tRegion),LOCS),list_to_set(LOCS,Set),my_rnd_member(LOC,Set).
  377
  378
  379random_xyzFn(LOC):-
  380   must_det(random_instance(tRegion,Region,true)),
  381   in_grid_rnd(Region,LOC),!.
  382random_xyzFn(xyzFn('Area1000',1,1,1)):- fail, dmsg(trace_or_throw(mpred_not_loaded)).
  383
  384unoccupied(_,Loc):- not_asserted((mudAtLoc(_,Loc))),!.
  385unoccupied(_,_):-!.
  386unoccupied(Obj,Loc):- loop_check(unoccupied_ilc(Obj,Loc),not_asserted((mudAtLoc(_,Loc)))),!.
  387
  388unoccupied_ilc(Obj,Loc):- is_occupied(Loc,What),!,What=Obj.
  389unoccupied_ilc(_,_).
  390
  391is_occupied(Loc,What):- is_asserted(mudAtLoc(What,Loc)),!.
  392is_occupied(Loc,What):- locationToRegion(Loc,Region),localityOfObject(What,Region),put_in_world(What),mudAtLoc(What,Loc),!.
  393
  394% Used all over the place
  395% Transforms location based on cardinal direction given
  396
  397calc_xyz(Region1,Dir,force(X1,Y1,Z1),X2,Y2,Z2):-
  398   to_3d(Region1,xyzFn(_,X,Y,Z)),
  399   get_dir_offset(Dir,1,OX,OY,OZ),
  400   X2 is X+ (OX*X1),Y2 is Y+OY*Y1,Z2 is Z+OZ*Z1.
  401
  402calc_from_center_xyz(Region1,Dir,R,X2,Y2,Z2):-
  403   room_center(Region1,X,Y,Z),
  404   get_dir_offset(Dir,R,OX,OY,_),
  405   X2 is X+ OX ,Y2 is Y+ OY, Z2 is Z.
  406
  407prologBuiltin(random_path_dir/1).
  408
  409system:sys_random_path_dir(Dir):- random_path_dir(Dir).
  410% random_path_dir(Dir):- nonvar(Dir),random_path_dir(Dir0),Dir=Dir0,!.
  411random_path_dir(Dir):- no_repeats(random_path_dir0(Dir)).
  412random_travel_dir(Dir):- no_repeats(random_path_dir1(Dir)).
  413
  414random_path_dir0(Dir):- call(call,random_instance(vtBasicDir,Dir,true)).
  415random_path_dir1(Dir):- call(call,random_instance(vtBasicDirPlusUpDown,Dir,true)).
  416random_path_dir1(Dir):- call(call,random_instance(vtDirection,Dir,true)).
  417
  418
  419from_dir_target(LOC,Dir,XXYY):- is_3d(LOC),!,
  420  move_dir_target(LOC,Dir,XXYY).
  421from_dir_target(Agent,Dir,XXYY):-
  422  mudAtLoc(Agent,RegionXYZ),
  423  move_dir_target(RegionXYZ,Dir,XXYY).
  424
  425move_dir_target(RegionXYZ,Dir,XXYY):-
  426   move_dir_target(RegionXYZ,Dir,1,XXYY).
  427
  428
  429move_dir_target(RegionXYZ,DirS,Force,XXYY):-
  430   any_to_atom(DirS,Dir),
  431   once(((calc_xyz(RegionXYZ,Dir,force(Force,Force,Force),X,Y,Z)),
  432   (locationToRegion(RegionXYZ,Region1)),
  433   (round_loc_target(Region1,X,Y,Z,Region2,X2,Y2,Z2)),
  434   XXYY = xyzFn(Region2,X2,Y2,Z2),
  435   sanity(ground(XXYY)))),
  436   check_ahead_for_ground(XXYY),!.
  437
  438move_dir_target(RegionXYZ,Dir,_Force,XXYY):-
  439   any_to_string(Dir,DirS),
  440   locationToRegion(RegionXYZ,Region1),!,
  441   pathBetween_call(Region1,DirS,Region2),
  442   in_grid_rnd(Region2,XXYY),
  443   XXYY = xyzFn(Region2,_X2,_Y2,_Z2),
  444   sanity(ground(XXYY)),!,
  445   check_ahead_for_ground(XXYY),!.
  446
  447
  448round_loc_target(Region1,X,Y,Z,Region3,X3,Y3,Z3):-
  449   round_loc(Region1,X,Y,Z,Region2,X2,Y2,Z2),!,
  450   Region2=Region3,X2=X3,Y2=Y3,Z2=Z3.
  451
  452round_loc(Region1,X,Y,Z,Region2,X2,Y2,Z2):-
  453   compute_dir(Region1,X,Y,Z,Dir),!,
  454   round_loc_dir(Region1,X,Y,Z,Dir,Region2,X2,Y2,Z2),!.
  455
  456round_loc_dir(Region1,X,Y,Z,'',Region2,X2,Y2,Z2):-!,
  457   X2=X,Y2=Y,Z2=Z,Region2=Region1.
  458
  459round_loc_dir(Region1,X,Y,Z,Dir,Region2,X2,Y2,Z2):- 
  460   any_to_dir(Dir,DirLong),
  461   pathBetween_call(Region1,DirLong,Region2),!,
  462   grid_size(Region1,X1,Y1,Z1),
  463   calc_xyz(xyzFn(Region2,X,Y,Z),Dir,force(-X1,-Y1,-Z1),X2,Y2,Z2),!.
  464
  465round_loc_dir(Region1,X,Y,Z,_Dir,Region2,X2,Y2,Z2):-Region2=Region1,X2=X,Y2=Y,Z2=Z.
  466
  467prologBuiltin(compute_dir/5).
  468compute_dir(Region1,X,Y,Z,Dir):-
  469  grid_size(Region1,MaxX,MaxY,MaxZ),
  470   ((X<1 -> EW=vWest ; X > MaxX -> EW=vEast ; EW= ''),
  471   (Y<1 -> NS=vNorth ; Y > MaxY -> NS=vSouth ; NS= ''),
  472   (Z<1 -> UD=vDown ; Z > MaxZ -> UD=vUp ; UD= '')),
  473   atomic_list_concat_catch([NS,EW,UD],'',Dir),!.
  474
  475prologBuiltin(get_dir_offset/5).
  476get_dir_offset(Dir,F,OX,OY,OZ):- sanity(nonvar(Dir)),
  477  dir_offset(Dir,F,OX,OY,OZ),!.
  478get_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.
  479get_dir_offset(Dir,F,OX,OY,OZ):- any_to_atom(Dir,DirA),
  480  dir_offset(DirA,F,OX,OY,OZ),!.
  481get_dir_offset(Dir,F,OX,OY,OZ):- any_to_string(Dir,DirS),
  482  dir_offset(DirS,F,OX,OY,OZ),!.
  483
  484
  485
  486p2c_dir2('s','vSouth').
  487p2c_dir2('w','vWest').
  488p2c_dir2('u','vUp').
  489p2c_dir2('d','vDown').
  490p2c_dir2('e','vEast').
  491p2c_dir2('n','vNorth').
  492
  493:-export(is_any_dir/1).  494is_any_dir(Dir):-var(Dir),!,fail.
  495is_any_dir(Dir):-any_to_dir(Dir,_).
  496:-export(any_to_dir/2).  497
  498any_to_dir(D,D):-var(D),!.
  499any_to_dir(S,D):-string(S),string_to_atom(S,A),any_to_dir(A,D),!.
  500any_to_dir(D,D):-dir_offset(D,_,_,_,_),!.
  501any_to_dir(A,D):-p2c_dir2(D,A),!.
  502any_to_dir(D,O):-atom(D),sub_atom(D, 0, 1, _, S),toLowercase(S,L),p2c_dir2(L,O),!.
  503any_to_dir(D,D):-pathDirLeadsTo(_,D,_),!.
  504
  505:-export(dir_offset/5).  506
  507% prologHybrid(dir_offset(term,int,int,int,int)).
  508
  509
  510% :-mpred_trace_all.
  511
  512prologBuiltin(dir_offset/5).
  513dir_offset(vUp,F,0,0,F).
  514dir_offset(vDown,F,0,0,-F).
  515dir_offset(vNorth,F,0,-F,0).
  516dir_offset(vSouth,F,0,F,0).
  517dir_offset(vEast,F,F,0,0).
  518dir_offset(vWest,F,-F,0,0).
  519dir_offset(vNE,F,F,-F,0).
  520dir_offset(vSW,F,-F,F,0).
  521dir_offset(vSE,F,F,F,0).
  522dir_offset(vNW,F,-F,-F,0).
  523dir_offset(vHere,_,0,0,0).
  524
  525% :-mpred_no_spy_all. with_pfa
  526
  527% MergedNess -1,0,1 = contacting_at,inside,outside_near_on
  528with_offset(detatched,F,X,Y,Z):-dir_offset(vHere,F,X,Y,Z).
  529with_offset(absolute_with,F,X,Y,Z):-dir_offset(vUp,F,X,Y,Z).
  530with_offset(relative_from,F,X,Y,Z):-dir_offset(vDown,F,X,Y,Z).
  531with_offset(surrounding,F,X,Y,Z):-dir_offset(vNorth,F,X,Y,Z).
  532with_offset(mudInsideOf,F,X,Y,Z):-dir_offset(vSouth,F,X,Y,Z).
  533with_offset(on,F,X,Y,Z):-dir_offset(vEast,F,X,Y,Z).
  534with_offset(tPartofObj,F,X,Y,Z):-dir_offset(vWest,F,X,Y,Z).
  535
  536facing_offset(at,F,X,Y,Z):-dir_offset(vHere,F,X,Y,Z).
  537facing_offset(above,F,X,Y,Z):-dir_offset(vUp,F,X,Y,Z).
  538facing_offset(below,F,X,Y,Z):-dir_offset(vDown,F,X,Y,Z).
  539facing_offset(left,F,X,Y,Z):-dir_offset(vWest,F,X,Y,Z).
  540facing_offset(right,F,X,Y,Z):-dir_offset(vEast,F,X,Y,Z).
  541facing_offset(behind,F,X,Y,Z):-dir_offset(vSouth,F,X,Y,Z).
  542facing_offset(front,F,X,Y,Z):-dir_offset(vNorth,F,X,Y,Z).
  543
  544
  545% baseKB:decl_database_hook(clause( retract,_),mudAtLoc(Agent,_)):-padd(Agent,mudNeedsLook(vTrue)).
  546
  547% mudAtLoc(Agent,_)==> mudNeedsLook(Agent,vTrue).
  548mudAtLoc(Agent,_)==>{padd(Agent,mudNeedsLook(vTrue))}.
  549
  550% dir_mult(X,Y,Z,X1,Y1,Z1,X2,Y2,Z2):- X2 is X * X1,Y2 is Y * Y1,Z2 is Z * Z1.
  551
  552
  553% Used in move.pl,push.pl and climb.pl
  554% Move agent (usually). Used to relocate agent'vSouth location.
  555in_world_move(LOC,Agent,DirS) :-
  556        string_to_atom(DirS,Dir),
  557        ignore(is_asserted(mudAtLoc(Agent,LOC))),
  558        must_det((locally(t_l:infAssertedOnly(mudAtLoc),in_world_move0(LOC,Agent,Dir)),       
  559         is_asserted(mudAtLoc(Agent,LOC2)),
  560         LOC2 \== LOC)),!.
  561
  562can_world_move(LOC,_Agent,Dir) :- check_behind_for_ground(LOC),move_dir_target(LOC,Dir,_).
  563
  564in_world_move0(LOC,Agent,Dir) :-
  565      any_to_dir(Dir,DirS),
  566        % rtrace(padd(Agent,mudFacing(DirS))),
  567       % must((
  568         ain(mudFacing(Agent,DirS)),
  569        % call_u(mudFacing(Agent,DirOther)),
  570         %DirOther==DirS)),
  571        sanity((is_asserted(mudAtLoc(Agent,LOC)))),
  572        check_behind_for_ground(LOC),
  573	move_dir_target(LOC,Dir,XXYY),!,
  574   must_det_l_pred(show_call,(
  575        dmsg(move_dir_target(LOC,DirS,XXYY)),
  576        locationToRegion(LOC,Region1),
  577        locationToRegion(XXYY,Region2),
  578        ((expire_dont_add, clr(mudAtLoc(Agent,LOC)))),
  579        %rtrace,
  580        call((expire_dont_add, ain_expanded(mudAtLoc(Agent,XXYY)),
  581        %nortrace,
  582        sanity((is_asserted(mudAtLoc(Agent,XXYY)))),
  583        sanity((clause_u(mudAtLoc(Agent,LOC2)),LOC2 \== LOC)))),         
  584   ifThen(( Region1\==Region2) ,raise_location_event(LOC,actNotice(reciever,actLeave(Agent,Region1,to(Dir))))),
  585        reverse_dir(Dir,Rev),
  586   ifThen(( Region1\==Region2) ,raise_location_event(XXYY,actNotice(reciever,actEnter(Agent,Region2,from(Rev))))),!,
  587	check_for_fall(LOC,XXYY,Agent))).
  588
  589check_behind_for_ground(LOC):-nonvar(LOC).
  590check_ahead_for_ground(XXYY):-nonvar(XXYY),
  591   to_3d(XXYY,xyzFn(L1,X,Y,Z)),
  592   grid_size(L1,MX,MY,MZ),
  593   inside_grid(L1,X,Y,Z,MX,MY,MZ).
  594
  595inside_grid(_L1,X,Y,Z,MX,MY,MZ):-is_between(1,MX,X),is_between(1,MY,Y),is_between(1,MZ,Z).
  596
  597is_between(L,H,V):- H >= V,L =< V.
  598
  599% Used for every move
  600% Does the agent take a header off a high object?
  601check_for_fall(LOC,XXYY,Agent) :-
  602	mudAtLoc(HighObj,LOC),
  603	props(HighObj,mudHeight(Hh)),
  604        % if nothing is there pretend it is 1
  605	(\+ (mudAtLoc(_,XXYY)) -> Hl = 1; mudAtLoc(LowObj,XXYY)),
  606	props(LowObj,mudHeight(Hl)),
  607	Hd is Hh - Hl,
  608	Hd > 1,
  609	call_update_stats(Agent,fall).
  610check_for_fall(_,_,_).
  611
  612
  613% Reverses the direction returned by number_to_direction
  614% Used for fleeing
  615:- export(reverse_dir/2).  616:- public(reverse_dir/2).  617reverse_dir(W,R):-string(W),atom_string(A,W),!,reverse_dir0(A,RA),atom_string(RA,R),!.
  618reverse_dir(A,R):-reverse_dir0(A,R)*->true;reverse_dir1(A,R).
  619
  620reverse_dir1(reverseOf(Was),RWas):-nonvar(Was),!,RWas=Was.
  621reverse_dir1(skPathFn(Direction,R2,R1),skPathFn(Direction,R1,R2)):-nonvar(Direction),!.
  622reverse_dir1(Was,reverseOf(Was)):-nonvar(Was),!.
  623
  624
  625reverse_dir0(vSouth,vNorth).
  626reverse_dir0(vEast,vWest).
  627reverse_dir0(vNorth,vSouth).
  628reverse_dir0(vWest,vEast).
  629reverse_dir0(vUp,vDown).
  630reverse_dir0(vDown,vUp).
  631reverse_dir0(vNW,vSE).
  632reverse_dir0(vNE,vSW).
  633reverse_dir0(vSW,vNE).
  634reverse_dir0(vSE,vNW).
  635
  636
  637% Yet another hash table to covert numbers into aDirectionsFn (or the reverse).
  638num_near_reverse(1,vNW,vHere).
  639num_near_reverse(2,vNorth,vHere).
  640num_near_reverse(3,vNE,vHere).
  641num_near_reverse(4,vWest,vHere).
  642num_near_reverse(6,vEast,vHere).
  643num_near_reverse(7,vSW,vHere).
  644num_near_reverse(8,vSouth,vHere).
  645num_near_reverse(9,vSE,vHere).
  646
  647num_near_reverse(0,vDown,vHere).
  648num_near_reverse(5,vUp,vHere).
  649
  650% Translates numbers returned from scan_lists_aux/3 (the number of the location)
  651% into thier relative aDirectionsFn.
  652number_to_dir(1,vNW,vNW).
  653number_to_dir(2,vNorth,vNW).
  654number_to_dir(3,vNorth,vNorth).
  655number_to_dir(4,vNorth,vNE).
  656number_to_dir(5,vNE,vNE).
  657number_to_dir(6,vWest,vNW).
  658number_to_dir(7,vNW,vHere).
  659number_to_dir(8,vNorth,vHere).
  660number_to_dir(9,vNE,vHere).
  661number_to_dir(10,vEast,vNE).
  662number_to_dir(11,vWest,vWest).
  663number_to_dir(12,vWest,vHere).
  664number_to_dir(14,vEast,vHere).
  665number_to_dir(15,vEast,vEast).
  666number_to_dir(16,vWest,vSW).
  667number_to_dir(17,vSW,vHere).
  668number_to_dir(18,vSouth,vHere).
  669number_to_dir(19,vSE,vHere).
  670number_to_dir(20,vEast,vSE).
  671number_to_dir(21,vSW,vSW).
  672number_to_dir(22,vSouth,vSW).
  673number_to_dir(23,vSouth,vSouth).
  674number_to_dir(24,vSouth,vSE).
  675number_to_dir(25,vSE,vSE).
  676
  677
  678% Scans through list of perceptions (as returned by look_percepts(Agent,L) or look_all(NearAgt,_,_,_,L,_))
  679% for an object,returns the direction in which the object lies.
  680list_object_dir_sensed(_,List,Type,Dir) :-
  681	!,
  682	scan_lists_aux(List,Type,1,N),
  683	number_to_dir(N,Dir,_).
  684
  685
  686list_object_dir_near(List,Type,Dir) :-
  687	!,
  688	scan_lists_aux(List,Type,1,N),
  689	num_near_reverse(N,Dir,_).
  690
  691scan_lists_aux([Loc|_],Type,N,N) :-
  692	member(Obj,Loc),
  693        isa(Obj,Type),
  694	!.
  695scan_lists_aux([_|Rest],Type,M,N) :-
  696	Mtemp is M + 1,
  697	!,
  698	scan_lists_aux(Rest,Type,Mtemp,N).
  699
  700
  701doorLocation(_Room,3,0,_Z,vNorth).
  702doorLocation(_Room,2,0,_Z,vNorth).
  703doorLocation(_Room,4,0,_Z,vNorth).
  704doorLocation(_Room,3,6,_Z,vSouth).
  705doorLocation(_Room,2,6,_Z,vSouth).
  706doorLocation(_Room,4,6,_Z,vSouth).
  707doorLocation(_Room,0,2,_Z,vWest).
  708doorLocation(_Room,0,3,_Z,vWest).
  709doorLocation(_Room,0,4,_Z,vWest).
  710doorLocation(_Room,6,2,_Z,vEast).
  711doorLocation(_Room,6,3,_Z,vEast).
  712doorLocation(_Room,6,4,_Z,vEast).
  713doorLocation(_Room,6,0,_Z,vNE).
  714doorLocation(_Room,6,6,_Z,vSE).
  715doorLocation(_Room,0,0,_Z,vNW).
  716doorLocation(_Room,0,6,_Z,vSW).
  717doorLocation(_Room,_X,_Y,_Z,_Dir):-!,fail