/* AWM_PATH.P */ section awm_path => awm_path; /* SPECIFICATION ------------- This module finds a path within an awm, using hill-climbing search. An ``awm'' is an ``array world-model'', for letting a bug represent a map of its world. For a description of AWMs and the operations on them, see HELP AWM. The module defines one routine, awm_path: PUBLIC awm_path( awm, start, goal, safe ): Searches for a path from start to goal within awm. The procedure safe determines which points can be traversed and which are treated as obstacles. The path is returned as a list of points whose first element is start and whose final element is goal. Each point is represented as a two-element list [%x,%y]. If there is no path, the procedure returns false. safe must be a procedure of three arguments, safe(awm,x,y) returning true or false. It returns true if awm(x,y) is passable, and false if it is an obstacle. You will usually want to define it as define safe(awm,x,y); lvars awm, x, y; awm(x,y) = ` ` enddefine; Because the search method will not always be the most suitable, I describe it below. It works as follows: 0) Initialise a queue of points to [% start %]. 1) Take the first element off the queue. If there is none, the search has failed: return false. Otherwise, this is the next point to be explored. 2) If this point is the goal, return true. 3) Find all the safe horizontal and vertical neighbours of this point, eliminating any which have already been explored. Add the others to the front of the queue, before all the points already there. We do this so that the points added are sorted by distance to goal: the nearer a point is to goal, the nearer it is to the front of the queue. 4) Go back to 1. If you are unfamiliar with search, you will find it helpful to read TEACH SEARCHING for an introduction, and then HELP SEARCH to see how I implement and use it. */ /* IMPLEMENTATION -------------- We use path_search from SEARCH.P, supplying an insert procedure that implements hill-climbing, using distance towards the goal as its evaluation function. This module has an associated HELP file, HELP AWM_PATH. Please keep the two in step. */ needs utils; needs vec; needs awm; needs search; define global awm_path( awm, start, goal, safe ); lvars awm, start, goal, safe; define next_from( point ); lvars point; lvars x0=point.vec_x, y0=point.vec_y; [% awm_app_vh_neighbours( awm, x0, y0, procedure(awm,x,y); lvars awm, x, y; if safe(awm,x,y) then [% x, y %] endif; endprocedure ) %] enddefine; define insert( newpoint, path, q ); lvars newpoint, q, path; lvars d, first, rest, f, first_path; define dist( p1, p2 ); lvars p1, p2; distance( p1.vec_x, p1.vec_y, p2.vec_x, p2.vec_y ); enddefine; dist( goal, newpoint ) -> d; if q /= [] then dest(q) -> rest -> f; f(1) -> first; f(2) -> first_path; if d <= dist( goal, first ) then [ [^newpoint ^path] ^^q ] else [ [^first ^first_path] ^^(insert( newpoint, path, rest )) ] endif else [ [^newpoint ^path] ] endif; enddefine; path_search( start, (nonop =)(% goal %), next_from, insert ); enddefine; endsection;