HELP AWM                                     Jocelyn Paine November 1992


This module defines some routines and structures for Bugs to use when
storing information about their world in analogical form as a 2-D map of
the surroundings. I call the structures AWMs, for "array world-model".
To load the module, do
    lib awm;


Introduction
------------

AWMs are useful for tasks like finding paths between points, and
dividing the world into regions. Many of these are best done
analogically; for example, you can easily find regions by picking a
blank, flooding with some character until you hit obstructions on all
sides, and repeating until there are no blanks left.

Externally, an AWM looks like a 2-D array. Create one by calling
    new_awm( undefchar )
where 'undefchar' is the character to be stored in otherwise undefined
array elements.

Access it by subscripting:
    awm(3,4) =>
    `#` -> awm(x,y);
AWMs are mapped onto strings, so you'll get an error if you try to
store anything other than a character in them.

Their class_print is set to a line-by-line display routine, so the
print-arrow will automatically print the contents.

AWMs are flexible arrays. They are created with initial bounds running
from -10 to 10 in both dimensions. If you try to put a character outside
the present bounds, the array will be expanded automatically. If you try
to read outside the current bounds, or to read a location that hasn't
been set, you'll get the character indicating "undefined": this is the
undefchar argument to new_awm.

You can find out how much of an AWM is known using the routines
    awm_x_known_min awm_x_known_max
and
    awm_y_known_min awm_y_known_max
These delimit a rectangle for which at least one character in each line
and column is not undefined. Outside this rectangle, all the characters
are undefined. When an AWM is created, all characters are undefined.

You can discover the total size of an AWM by calling
    awm_x_actual_min awm_x_actual_max
    awm_y_actual_min awm_y_actual_max
These indicate the actual space allocated to the array. They are
completely irrelevant as far as finding out what information is in the
AWM, because an AWM is virtually infinite. However, you can use them to
calculate the amount of memory used - once your AWM gets too big, you
may want to discard some regions and begin again.

You can also use AWMs to keep track of the Bug's position. An AWM
contains internal coordinates and direction vectors corresponding for a
notional bug. You can change these with various routines, such as
awm_left and awm_forward, and can read out the resulting values. This
enables your Bug's world-model to keep track of the Bug itself. The
internal bug's coordinate system is as you would expect: north lies along
the Y axis, and corresponds to the forwardvector (0,1).

As already mentioned, there are routines for replacing characters
within an AWM, and for examining the neighbours of a point, and
applying various routines to them.

Finally, there is a routine for merging the contents of a bug's retina
into an AWM.


Exported routines
-----------------

PUBLIC new_awm( undefchar ):

Returns a new AWM whose undefined-character is undefchar. The x_known
and y_known bounds initially run from +1 to -1, and all characters are
undefined. The internal bug is created at (0,0), facing internal north:
forwardvector and rightvector are (0,1) and (1,0).


PUBLIC awm_undefchar( awm ):

Returns awm's undefined-character.


PUBLIC awm_x_known_min( awm ):
PUBLIC awm_x_known_max( awm ):
PUBLIC awm_y_known_min( awm ):
PUBLIC awm_y_known_max( awm ):

Return the lower and upper x-bounds, and the lower and upper y-bounds,
on the known area of awm. Within this rectangle, there is at least one
known location in every line and column. Outside it, all locations are
undefined.


PUBLIC awm_x_actual_min( awm ):
PUBLIC awm_x_actual_max( awm ):
PUBLIC awm_y_actual_min( awm ):
PUBLIC awm_y_actual_max( awm ):

Return the lower and upper x-bounds, and the lower and upper y-bounds,
on the actual storage used by AWM.


PUBLIC ved_awm():

Defines the Ved command 'awm', which copies the contents of the current
Ved buffer into an AWM.

The command can have the following forms:
    awm
    awm name
    awm name undefchar

These commands create a new awm and assign it to valof(name). If
undefchar is omitted, it defaults to ? . If name is omitted, it defaults
to "awm". The x-bounds of the AWM run from the leftmost non-blank column
(indexed at 1) to the rightmost non-blank column; its y-bounds run from
the top non-blank Ved line to the bottom (indexed at 1). If the buffer
contains a B, this will be taken to give the position of the internal
bug, and the square will be assumed blank.


PUBLIC app_awm( awm, p ):

Applies procedure p to every non-undefined location in awm. p must take
three arguments: p(awm,i,j), where the latter two give the location's
coordinates.


PUBLIC awm_replace( awm, c, newc ):

Replaces specified characters in awm by character newc. If c is a
character, all occurrences of it will be replaced by newc. If it is a
procedure, it must take a character as argument and return true or
false; all characters c for which p(c) is true will be replaced by newc.


PUBLIC awm_app_neighbours( awm, x, y, p ):

This applies p to every neighbour of awm(x,y). p must be a procedure of
three arguments, p(awm,i,j), as for app_awm.


PUBLIC awm_app_vh_neighbours( awm, x, y, p ):

This is like awm_app_neighbours, but only applies p to vertical and
horizontal neighbours. awm_app_neighbours also applies it to diagonal
ones. Both procedures avoid applying p to any undefined cells, i.e.
those which contain awm.awm_undefchar.


PUBLIC awm_neighbour( awm, x, y, p ):

This is used for finding a neighbour with specified properties. p must
be a procedure of three arguments, p(awm,i,j), returning true or false.
awm_neighbour applies p to each neighbour (including diagonal ones)
until it finds one for which p is true. If it finds one, it returns
true, otherwise false.


PUBLIC awm_move_bug_to( awm, x, y ):

Moves awm's internal bug to (x,y), without changing its bearing.


PUBLIC awm_set_direction( awm, direction ):

Sets awm's internal bug's direction to direction. This must be one of
"north", "east", "south", "west".


PUBLIC awm_move( awm, action ):

action must be one of "left", "right", "forward", "back". This procedure
changes awm's internal bug's location or bearing accordingly.


PUBLIC awm_right( awm ):
PUBLIC awm_left( awm ):
PUBLIC awm_forward( awm ):
PUBLIC awm_back( awm ):

Equivalent to awm_move( awm, "right" ) ... awm_move( awm, "back" ).


PUBLIC awm_direction( awm ):
PUBLIC awm_forwardvector( awm ):
PUBLIC awm_rightvector( awm ):

These return the bearing of awm's internal bug. The direction is one of
"north", "east", "south", "west". The forwardvector and rightvector are
unit vectors along the bug's Y and X axis, and are returned as a 'vec':
see lib vec.


PUBLIC awm_x( awm ):
PUBLIC awm_y( awm ):
PUBLIC awm_position( awm ):

These return the x and y coordinates of awm's internal bug, and the
bug's position as a 'vec'.


PUBLIC awm_merge_retina( awm, retina ):

This routine copies retinal contents into an AWM. 'retina' is a retina,
which must be as described in HELP EDEN, e.g. a 7*5 array whose bug is
at location (3,2). awm_merge_retina copies each retinal element into the
corresponding position of awm, assuming that the bug whose retina it is
has its location and bearing given by awm's internal bug.
