Open byorgey opened 3 years ago
As a first step, we should just refactor the existing game to work this way, but generate exactly the same world (with no robots or structures) that we currently do.
Maybe we should keep the old type WorldFun t e = Coords -> (t, Maybe e)
(since we will certainly still want that type) and define type TiledWorldFun t e = TileCoords -> (TerrainTile t, EntityTile e, [Robot])
. Then as a starting point we can define
simpleTiledWorldFun :: WorldFun t e -> TiledWorldFun t e
which just fills in everything according to the WorldFun
. Maybe we can also make TiledWorldFun
a Monoid
such that the lists of robots compose and entities and tiles on the right overwrite ones on the left. We would have to make a special distinguished "empty terrain" value to serve as the identity. EntityTile
s will already contain Maybe e
s so Nothing
can serve as the identity. Given this monoid, we can start with a base generated by a WorldFun
and then layer on things like structures etc.
Here is another idea which is hopefully both simpler and more flexible: let's just keep the WorldFun
type similar to how it is now, but to the output we can add [Robot]
(i.e. WorldFun t e = Coords -> (t, Maybe e, [Robot])
), describing robots which should spawn when the given cell is first loaded.
WorldFun
type which prevents this, and in fact it is probably better/more flexible than generating things by tiles:
WorldFun
a monoid is still a good idea and will help keep things more modular/separated.[Robot]
values. Otherwise, we simply ignore them.
- As for spawning robots, we know when a particular tile is first loaded, and at that time we can pay attention to all the
[Robot]
values. Otherwise, we simply ignore them.
I suppose this would happen in the loadRegion
function in Swarm.Game.World
, which would probably need to be modified to return any newly spawned robots as well?
[Note, I no longer think this original issue description is a good idea, but leaving it here for context. Read all the way through the comments below to see how my thinking has changed.]
Right now a
World
is specified by aWorldFun
, defined asThis is just a function that specifies a terrain value and possible entity for every cell. However, this has several limitations. For one thing, it is difficult to specify things that should be coherent across multiple cells (i.e. structures). For another, if we want the world to contain creatures that move around (implemented as system robots), there is no good way to specify when they should spawn.
The implementation of
World
s already uses a notion of tiles for efficiency, and we can build on this to solve the limitations above. Instead of specifying a world cell by cell, we specify it tile by tile. That is, aWorldFun
will now be something likewhich says that the world function takes as input the coordinates of a tile and generates an entire tile's worth of terrain and entities all at once, in addition to some robots which should spawn when this tile is loaded. When calling the function, it will build tiles first by filling in initial values based on a
Coords -> (t, Maybe e)
function as before, but then has the opportunity to further modify them, e.g. by deciding where to draw in certain structures.