Complete.Org: Mailing Lists: Archives: freeciv-dev: September 2004:
[Freeciv-Dev] (PR#10047) RFC: restructuring map code to not use cartesia
Home

[Freeciv-Dev] (PR#10047) RFC: restructuring map code to not use cartesia

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients: ;
Subject: [Freeciv-Dev] (PR#10047) RFC: restructuring map code to not use cartesian coordinates
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Sat, 11 Sep 2004 00:20:56 -0700
Reply-to: rt@xxxxxxxxxxx

<URL: http://rt.freeciv.org/Ticket/Display.html?id=10047 >

Currently the usual interface to the map code is through cartesian (aka 
map) coordinates.  See map_get_tile() and friends.  In fact almost every 
piece of code outside of the map uses cartesian coordinates: see 
whole_map_iterate, adjc_dir_iterate, etc.

Of course this has always been the case.  When Raimar asked why we used 
cartesian coordinates here instead of native coordinates (see 
doc/HACKING for an explanation of native coordinates) Ross and I had no 
particular answer.  There is no real reason why either cartesian or 
native coordinates would be superior.  However switching would take a 
lot of work.

Of course this is still true today...

However there are some reasons why cartesian coordinates are not ideal 
for accessing.

- They are two-dimensional.  This means you need two variables for them. 
  it also makes the interfaces for functions longer: see functions like 
city_map_to_map or find_closest_owned_city.
- They aren't particularly type-safe.  It's easy to mix the (x,y) values 
or get them out-of-order in function calls.
- They aren't entirely extensible.  Of course we can always use some 2d 
coordinate system to hold cartesian tile positions.  But even in hex 
topologies the cartesian coordinate system has little meaning.  In 
future even more general systems we could have arbitrary adjacency 
relations between tiles (like provinces in the Total War games) and they 
would have even less meaning.

-----

There are several other forms of data storage we could use.

Index coordinates correspond closely to native coordinates.  They have 
the advantage of being one-dimensional, which not only reduces the 
number of variables lying around but avoids the need for tuples in 
expressions.  For instance you can't say

   native_to_index_pos(map_to_native_pos(x, y))

in C, but you can say

   index_to_natural_pos(map_pos_to_index(x, y))

.  Using these exclusively would make the interfaces to many functions 
simpler since instead of whole_map_iterate(x, y) you have 
whole_map_iterate(idx).  However it's still a lot of work to switch. 
Using them may be faster or slower depending on the operation: cartesian 
coordinates are at one end of the conversion scale and index coordinates 
are at the other (cartesian <-> natural <-> native <-> index).


Using natural coordinates (see doc/HACKING) offers no advantage over 
cartesian or native coordinates.  No reason to do that.


We could just use a "struct map_position" for it.  This is 
one-dimensional, sort of.  The struct itself would just hold the 
cartesian(x,y) values.


The last solution is to use tile values directly.  Now instead of 
holding coordinate values everyone tracks "struct tile *" values.  This 
has several advantages:

   - It is typesafe.
   - It is potentially very fast, since the tile structure can hold the
     coordinates of the tile in any or all coordinate systems.
   - Like index coordinates, it is one-dimensional.
   - There is an implicit NULL value as a special-case.  Using NULL
     is a better method than the current (-1,-1) hacks we have in
     a few places.  Similarly there is an implicit CHECK_MAP_POS
     any time you work with a tile.  Either the tile is NULL or it is
     valid.  It's not likely to be garbage and there's no way
     it's non-normalized.

-----

My proposal for long-term restructuring of the map code is this:

- Code outside of the map tracks tiles.  Thus whole_map_iterate, 
map_get_terrain, and all friends operate on tiles.  In particular the 
unit and city structures will hold tile values rather than (x,y) pairs.

- Eventually we can separate the map code out entirely.  The map is not 
freeciv-centric.  The same map system we use could be used by just about 
any tile-based game.  And even in freeciv there are multiple maps.  The 
warmap is just like the map structure but with a different type.  Even 
city maps follow the same system!  (Of course struct tile * is 
freeciv-centric.  Most of the values in civ_map are freeciv-centric but 
only indirectly related to the map.  I'm really talking about map.tiles 
and all related accessor and iterator functions here.)  To enforce 
typesafety we could have a specmap or something like it.

I don't plan to begin on this soon.  But I'd like to get other people's 
thoughts on it.

-----

Side note:

In MoM or that CivII variant where you could play on alpha centauri and 
earth at the same time, there were "multiple maps".  The MoM map was 
really just one map, since certain tiles existed on both maps 
simultaneously.  I never played the civ2 variant, so I'm not sure about 
that.  I don't know if these would be done as an even more general 
system of the current map, or as a wrapper holding two maps.

-jason




[Prev in Thread] Current Thread [Next in Thread]