/* AWM_TO_OBJECTS.P */ /* SPECIFICATION ------------- This file is used by PLANNING_BUG.PL. It converts an AWM into a list of objects, regions, and coordinates. The routine exported is awm_to_objects( awm ) This takes an AWM and divides it into regions, as implemented in AWM_TO_REGIONS.P. It then runs over each object and produces a list of objects. This is of the form [ ] Each is a list of the form [% x, y, type, n, [r1, r2] %] or [% x, y, type, n, r %] where x and y are the location within the AWM; type is the object's type (a word such as "rock"); n is a unique integer: no two objects have the same number; r, r1, and r2 are region numbers. The region numbers are arbitrary, but are printable characters. The first type of list is used for doors and rocks, which join one region to another. The second type is used for hammers, keys, and food, which sit entirely within one region. A is like the first type of , but without the object number: [% x, y, "me", r %] A is a list: [% "dir", fx, fy %] where fx and fy are the components of Bug's forwardvector, as represented by its AWM. Warning: these routines only work for certain types of world. Hammers, keys, and food must not be embedded within a wall like this: ***T*** and doors and rocks must always be: ***@*** and must not be free-standing. */ /* IMPLEMENTATION -------------- See comments in awm_to_objects. This code depends on AWM_TO_REGIONS.P. */ needs awm_to_regions; needs fault; define awm_to_objects( awm ); lvars awm; lvars objects; reset_object_no(); /* Each object has its own unique number. Reset the first number to 0. */ awm_to_regions( awm, `1`, procedure(c);1+c;endprocedure, false ).erase; /* Mark regions within awm. */ [% app_awm( awm, classify ) %] -> objects; /* Return a list of object classifications, including details of their regions. */ [% awm.awm_x, awm.awm_y, "me", region_in(awm,awm.awm_x,awm.awm_y) %] :: objects -> objects; /* Add the Bug to this. It is not explicitly represented as a character within the AWM. */ [% "dir", awm.awm_forwardvector.vec_x, awm.awm_forwardvector.vec_y %] :: objects -> objects; /* Add details of its direction. */ awm_replace( awm, designates_region, ` ` ); /* Wipe out the region markers. */ objects enddefine; /* classify( awm, x, y ): awm is an AWM in which regions have been marked. classify returns details of the object at awm(x,y) as an : see specification comment. door, then it's represented as */ define classify( awm, x, y ); lvars awm, x, y; lvars type; classifier( awm(x,y) ) -> type; switchon type case = "rock" orcase = "door" then [% x, y, type, new_object_no(), regions_joined_by(awm,x,y) %] case = "hammer" orcase = "key" orcase = "food" then [% x, y, type, new_object_no(), region_in(awm,x,y) %]; endswitchon; enddefine; /* region_in( awm, x, y ): awm(x,y) is assumed to be something like a hammer, that lies entirely within one region. region_in returns the character for that region. */ define region_in( awm, x, y ); lvars awm, x, y; lvars found, r; awm_neighbour( awm, x, y, procedure(awm,x,y); lvars awm, x, y; if designates_region( awm(x,y) ) then awm(x,y)->r; true else false endif; endprocedure ) -> found; if not( found ) then FAULT( 'region_in: no region found', [%awm,x,y%] ) endif; r; enddefine; /* regions_joined_by( awm, x, y ): awm(x,y) is assumed to be something like a door, that separates one region from another. regions_joined_by returns the characters for those two regions as a list [% c1, c2 %], where c1 < c2. */ define regions_joined_by( awm, x, y ); lvars awm, x, y; lvars r1, r2, found; region_in( awm, x, y ) -> r1; awm_neighbour( awm, x, y, procedure(awm,x,y); lvars awm, x, y; lvars c=awm(x,y); if designates_region( c ) then if c=r1 then false else c->r2; true endif; else false endif; endprocedure ) -> found; if not( found ) then FAULT( 'regions_joined_by: no region found', [%awm,x,y%] ) endif; if r1 < r2 then [% r1, r2 %] else [% r2, r1 %] endif; enddefine; /* designates_region( c ): True if character c is used to mark a region in an AWM. */ define designates_region( c ); lvars c; c >= `1` and c <= `9`; enddefine; /* classifier( c ): Returns a word naming the object whose character is c. */ newproperty([% [% `*`, "boulder" %], [% `@`, "rock" %], [% `T`, "hammer" %], [% `#`, "door" %], [% `k`, "key" %], [% `:`, "narrows" %], [% `+`, "food" %], [% `Q`, "quicksand" %] %], 10, "unknown", true ) -> classifier; /* Object numbers -------------- */ vars object_no; /* new_object_no(): Return a new unique object number. */ define new_object_no(); 1 + object_no ->> object_no; enddefine; /* reset_object_no(): Reset the object number to 0. */ define reset_object_no(); 0 -> object_no; enddefine;