/*  AWM_TO_OBJECTS.PL  */


/*
SPECIFICATION
-------------

This file is used by PLANNING_BUG.PL. It converts an AWM into a list
of objects, regions, and coordinates. You should read the specification
at the top of AWM_TO_OBJECTS.P before going any further.


The predicate exported is
    awm_to_objects( AWM+, State-, StateAbs-, Map-, D- )

This takes an AWM as its first argument, and passes it to the Pop-11
routine awm_to_objects. From that's result, it generates a state
specifying what objects are found in which squares, an "abstract state"
specifying what objects are in what regions, a map specifying which
regions are adjacent, and a bug-direction.

State will become a list of elements, each of the form
    square( Obj, [X,Y] )
where Obj is either the atom 'me', or a structure such as hammer(1) or
key(3), and X,Y are the co-ordinates within AWM.

StateAbs will become a list of elements, each of the form
    in( R, Obj )
or
    blocked( R1, R2, Obj )
where R1 and R2 are integers identifying regions. The first form
indicates that Obj is entirely within R; the second, that it is a door
or rock set in a wall between them. The idea of the abstract state is
that it be used in an abstraction-based planner such as ABSTRIPS.

Map will become a list of elements
    joins( R1, R2 )
indicating that R1 is separated from R2 by a wall. Map contains both
joins(R1,R2) and joins(R2,R1). This is because it is to be used by a
planner, and I haven't worked out how to interface planning with
inference over states.

D is
    dir( [X,Y] )
where [X,Y] is Bug's forwardvector.


Note the caution in AWM_TO_OBJECTS.P about the limited range of worlds
this works on.
*/


/*
IMPLEMENTATION
--------------
*/


:- prolog_language(pop11).
needs awm_to_objects;
:- prolog_language(prolog).


awm_to_objects( AWM, State, StateAbs, Map, D ) :-
    prolog_eval( awm_to_objects(AWM), ObjectList ),
    stateify_objects( ObjectList, State, StateAbs, Map, D ).


/*  stateify_objects( ObjectList+, State-, StateAbs-, Map-, D- ):
        ObjectList is a list of objects, in the form specified by
        AWM_TO_OBJECTS.P. stateify_objects converts this to the other
        arguments.
*/
stateify_objects( [], [], [], [], [] ) :- !.

stateify_objects( [O1|On], S, SA, M, D ) :-
    stateify_object( O1, S1, SA1, M1, D1 ),
    stateify_objects( On, Sn, SAn, Mn, Dn ),
    append( S1, Sn, S ),
    append( SA1, SAn, SA ),
    append( M1, Mn, M ),
    append( D1, Dn, D ).


/*  stateify_object( Object+, State-, StateAbs-, Map-, D- ):
        Object is one element of an object list, in the form specified
        by AWM_TO_OBJECTS.P. stateify_object converts this to the other
        arguments, these each receive a list.
*/
stateify_object( [ X, Y, Type, Id, [ R1, R2 ] ], State, StateAbs, Map, D ) :-
    !,
    Obj =.. [ Type, Id ],
    ObjPred =.. [ Type, Obj ],
    State = [ square(Obj,[X,Y] ) ],
    StateAbs = [ blocked(R1,R2,Obj) ],
    Map = [ joins(R1,R2), joins(R2,R1) ],
    D = [].

stateify_object( [ X, Y, me, R ], State, StateAbs, Map, D ) :-
    !,
    State = [ square(me,[X,Y] ) ],
    StateAbs = [ in(me,R) ],
    Map = [],
    D = [].

stateify_object( [ dir, X, Y ], State, StateAbs, Map, D ) :-
    !,
    State = [],
    StateAbs = [],
    Map = [],
    D = [ dir([X,Y]) ].

stateify_object( [ X, Y, Type, Id, R ], State, StateAbs, Map, D ) :-
    Obj =.. [ Type, Id ],
    State = [ square(Obj,[X,Y] ) ],
    StateAbs = [ in(Obj,R) ],
    Map = [],
    D = [].
