- Declared in:
- MultiGrid2d.h
- Conforms to:
- GridData
This code is made available under the GPL (GNU general
public license) with the additional proviso that any
users notify the author of their use and share their
code with the original author. A copy of version 2 of
the GPL is included in this directory, but you can use a
newer GPL at your choice. The author assumes no
liability for any inconvenience or damage caused by
this software and offers no warranty of any kind. Class
MultiGrid2d.h, Paul Johnson, descended from
Class "MoGrid2d" by Sven Thommesen which had been
modified by Pietro Terna Introduction. This
replacement for Grid2d allows for Multiple
Occupancy! Each occupied position has a "cell"
object, and that cell holds objects a collection.
MultiGrid2d is not a sublclass of Grid2d, it is a
free standing combination space/container class. It is
free standing and separate from Grid2d partly to assure
that no IVARS or methods are unintentinally inherited in
this multi-agent-per-cell environment. To assure that
MultiGrid2d can act as a data provider by Swarm,
it adopts the GridData protocol of Swarm, which means that
it is fully qualified to act as a discrete2dToDisplay for
Raster displays. By default, the cell uses an ordinary
Swarm list as the collection, but the user can provide
for a new kind of container. Why this feature? Some
collections are faster for extracting particular
objects by name, while others are faster for finding
an object at a particular offset, while others are faster
for finding the oldest, biggest, fattest, and so forth.
If your objects are fixed at particular positions, a cell
that is based on a Swarm Array would work great. So I
generalize to allow any kind of collection the
user desires. I also allow user-defined methods to be
accessed for any particular position in the grid.
How is this done? Think of each "thing" in the grid as a
cell, which can accept and give back items, and it can
also carry out other actions you want. The "default"
cell class is MultiGridCell, which uses a swarm list
class as a container. The user can create a subclass of
MultiGridCell, or can create a class from
scratch, as long as it adopts the protocol AppCell,
which is defined in MultiGridCell.h. This protocol
requires that the cell container be able to add,
remove, and find objects, and also to pass through
messages to them. My AppCell (documented in) uses
Swarm collection style names for methods. All of this
seems pretty obvious to me, but only because i've been
looking at this for 3 years. When the grid is
created, the user must tell the grid what "cell
Class" to use. If none is specified before createEnd
is called, then the MultiGridCell is assumed. (The
setCellClass: method sets the cell class for
the grid.) The Cell object has a list instance variable.
That's the collection. It may also have other instance
variables and it can be used for any data-gathering
purpose, including display purposes (create
drawSelfOn method and so forth). Objects/agents
are added to or removed from such lists, rather than from
the underlying grid. Cells are created as needed,
dynamically, when agents are added at a point.
(The grid is created initially with no Cell objects.)
This version uses a recycler to grab MultiCells that are
no longer in use. They are initialized and reused. This
behavior saves on memory and it may even make a
model faster if cells need not be constantly recreated.
It depends on whether your grid is sparsely populated, I
think. You can turn off the automatic removal of empty
cells with a CPP flag, NO_AGGRESSIVE_RECYCLING. This
leaves the cells, so they eagerly await a chance to
insert an object for you. I have many methods in here
with names that start with "passThrough". These methods
take a selector argument (and possibly another
argument). The idea here is that if one wants each
cell object to carry out a certain method, then the pass
through object can pass through that selector's
method to all cells (see passThroughToAllCells:). Or,
in the case of passThroughToAllObjects, it causes each
object in the grid to be sent a message. Or, in the
cases of passThroughToCell:atX:Y:, or
passThroughToObjects:atX:Y:, a
message is passed to a particular cell or to all
objects in that cell. If you have ever looked at the
Objective-C root class Object, you will have seen
the "perform: (SEL) aSelector" method, and I use that
same idea in these pass through methods. Because of
these "passThrough" methods, users who create a custom
cell class have to be a little careful to implement or
at least create stubs for methods like "performForEach".
Or subclass from MultiGridCell. Since MultiGridCell
implements these, I believe that any subclass that
uses a Swarm compliant collection will be acceptable and
these methods need not be overridden. There is a
special passThrough method, though, which I would
point out: - passThroughToCellCreation: (SEL)
aSelector{This sets the values of features that
might be needed when cells are created inside the grid.
If your Cell class requires some customization, say a Cell
object needs to have a variable set or something like
that, then this passThrough makes sure the Grid knows
what it is supposed to do. It works so that every time
the Grid creates a cell, it performs this method, i.e.,
[cell perform: aSelector]; I have found some cases
where there is no other way to get the desired
functionality of the Cell and still work with a
general purpose grid like MultiGrid2d. Here is an
example of a sequence of commands that create a
MultiGrid2d with a user-customized cell class
called "AppSpecificCell". homeGrid = [MultiGrid2d
create: self setSizeX: worldXSize Y: worldYSize
Cells: [AppSpecificCell class]];
[homeGrid
passThroughToCellCreation:
M(setRasterList:) with: [observerSwarm
getRasterList: nhood]]; The grid is created,
told to use cells of class AppSpecificCell, and every
time a cell is created, it is told to setRasterList:
with a given input variable. So that whenever it spawns
a new cell, it passes on a particular message to that cell.
Sometimes I have found it handy to have a
"global_list" of all objects that have ever
been inserted. In MultiGrid2d.hm, one can see CPP flags
that turn on the creation of a global object list and
maintenance of it when items are inserted and
removed. This version uses an AVL Tree to keep track
of objects so that removal of specific objects is fast.
This big list can be used to tell all objects in the
grid to do something, or to get a count of all objects
in the grid. Of course, you need my AVLSet class to make
that work, but it is included in this tarball. The CPP
flag for that is KEEP_GLOBAL_LIST I'm also providing an
example of a cell subclass that I use in an
application. The original MoGrid2d was authored
by Sven Thommesen (c) Sven Thommesen 1997
(sthomme@humsci.auburn.edu).
Sven's grid held Swarm lists. It had some
functionality to copy and shuffle lists that I
don't maintain here. If you need to shuffle a list, get
the collection and shuffle it yourself. Sven is not
responsible for any errors in this new
(significantly revised and generalized)
multiple occupancy grid. My earlier effort
WrappedListGrid2d was not so generally
functional as this one.
Create a MultiGrid2d that is x wide and y high
Creates a MultiGrid2d that is x wide, y high, and uses the indicated class type for the cells
Warning the underscore at the start of the name of this method indicates that it is private, for internal use only, and you should not use the method in your code.
Adds an object into the cell at x,y
Copied from Swarm's Grid2d
In order to put items at x,y, a cell must exist there. This creates the cell.
Finalize creation of the object
Remove and destroy (drop!) all objects in the cell's collection at x,y.
Search through the cell's collection for the desired
object. If it is found, delete it from the
collection and return it. Otherwise return
nil
;
Returns a pointer to the cell object at ( x,y)
Return the collection in the cell at x,y
Ask the cell's collection for its first member and returns a pointer to it
Return a set full list of all objects throughout the grid. I don't really recommend this unless you compile with KEEP_GLOBAL_LIST. If no globalList has been kept, then this method will cause a cycling across all cells in the grid to collect up references to their members. That's slow.
Ask the cell's collection for its last member and returns a pointer to it.
Returns the underlying lattice that is used to organize data inside this grid. Only people who really understand the way Grid2d works should ever consider using this method.
This is the same as "[getCell:atX:Y:]". It is included here because we need to make sure that the getObjectAtX:Y: method from Grid2d is not called. That would obliterate the cell's collection and replace it with the single object.
Returns the offsets method that is used to "index into" the lattice.Only people who really understand the way Grid2d works should ever consider using this method.
Returns the integer width of the grid
Returns the integer height of the grid
Asks the cell for its "value" and returns it. The value returned depends on your implementation of the cell class.
Copied from Swarm's Grid2d
Creates a Swarm probe on the cell at x,y
Return the number of items in the collection in cell x,y
In case one wants all cells that exist in a MultiGrid2d to carry out some method, this is the way to get it done.
In case one wants all cells that exist in a MultiGrid2d to carry out some method, this is the way to get it done. This method allows a selector to be passed through along with one argument.
In case one wants a particular cells that exist in a MultiGrid2d to carry out some method, this is the way to get it done.
In case one wants a particular cells that exist in a MultiGrid2d to carry out some method, this is the way to get it done. This method allows a selector to be passed through along with one argument.
When a cell is created, and you want it to run some method to initialize itself, use this to "pass through" that initializing method to the cell.
When a cell is created, and you want it to run some method to initialize itself, use this to "pass through" that initializing method to the cell. This method allows the user to add one standard argument that is passed on to all cells.
In the case that one wants all of the objects that inhabit a MultiGrid2d to do something, this is the way to get it done. This will cause the MultiGrid2d to have each object in each cell execute the given selector.
In the case that one wants all of the objects that inhabit a particular cell in the MultiGrid2d to do something, this is the way to get it done. This will cause the MultiGrid2d to have each object in the cell execute the given selector
In the case that one wants all of the objects that inhabit a MultiGrid2d to do something, this is the way to get it done. This will cause the MultiGrid2d to have each object in each cell execute the given selector. This allows one argument to be passed along with the selector to each object.
In the case that one wants all of the objects that inhabit a particular cell in the MultiGrid2d to do something, this is the way to get it done. This will cause the MultiGrid2d to have each object in the cell execute the given selector. This allows one argument to be passed along with the selector to each object.
This is the same as "[add:atX:Y:]". It is included here because we need to make sure that the putObject method from Grid2d is not called. That would obliterate the cell's collection and replace it with the single object.
Remove all objects in the cell's collection at x,y. This does not destroy objects, it just removes references to them. So if other references to these objects exist, then they can still be used.
Tell the cell's collection to remove its first element and return it to the caller
Tell the cell's collection to remove its first element and return it to the caller
Note: this does not delete or remove the randomly chosen member. it simply gives back a pointer to it. Similar to getFirst or getLast in that respect.
Sets the Class that will be used to create the Cells in the Grid. Should be a subclass or replacement for MultiGridCell. If you don't specify a class here, it assumes you want ordinary Swarm lists as your containers in the cells. If you custom-design a cell class which has containers and implements the protocol "AppCell", then use your cell instead.
The size of the grid is x wide and y high
Description forthcoming.
Description forthcoming.
Description forthcoming.
Description forthcoming.
Description forthcoming.
Description forthcoming.
Description forthcoming.
Description forthcoming.