Space: The Initial Frontier Location and its Central role in wargaming [04-Location.txt] Ernest Prabhakar, 15 Oct 1993 [with Comments by Simon Marchat, 18 Oct 93, SM>] [and replies by me, 18 Oct 93, EP>] Now that we've set our parameters (nobody's complained, so I guess we're stuck with them) we can now start discussing an actual model for implementing the first version of WarKit. The first place I'd like to start is with - place! The taking of territory is in one sense the fundamental goal of warfare, and consequently one of the distinguishing features of wargames. It has been said that having a bad combat system makes a game uninteresting, but having a bad movement system makes it unplayable! Topology, Terrain, and Movement will be covered in separate essays. To start with, though, I just want to discuss Location - the identification of a point in space. I will make several assertions concerning them, and give my justifications. If people agree/ignore me, we will move on from there. As usual, just because I assert something to be true does not mean I am unwilling to change my opinion. 1) A location should be specified by three numbers. SM> Seems like a good idea. The simplest reason is that the real world consists of three dimensions. Well, technically four, but you only treat time as a coordinate when doing relativistic transformations. Very few wargames involve traveling near the speed of light, and almost none of those actually use relativity correctly, so we can ignore them for now. Conversely, even though most games are played on 2D maps, height is often an important aspect of location. And for those where they are not, the extra overhead of one more number is negligible. 2) Each number is a C "float" SM> Hmm. I reserve judgement until I see how terrain is to be done. Again, our locations should be real numbers because the real world is, well, real. This way we can model both gridded board games and miniatures. And it is important to remember that even games on hex maps can make use of continuous terrain features (e.g., Squad Leader). A 32-bit floating point number has plenty of precision, so we're not really constrained relative to integers. And because of word alignment issues, using smaller variables (short int) would greatly reduce flexibility without reducing space usage much. 3) Our location structure is actually a C++ class with inline members C++ classes using inline member functions have no additional space or time overhead (just compilation time!). Using C++ classes makes adding and subtracting very easy. Also, as objects, external code does not know about the internal representation of the objects, so it would be trivial for developers to substitute other things which conformed to those messages. It would be possible to use more of C++ (virtual functions, templates, etc.) but a) that would strain NeXT's compiler, and b) that's only needed if people need more than one kind of location. The standard, 3-float Location we will use should work for 99% of the games out there, so I don't want to bother with it for this release. I happen to have a C++ vector package I wrote for work already, so it would be trivial to simplify it for use with WarKit. 4) Differing boards are handled by different 'metrics' A 'metric' (for you non-mathematical people) is how you determine distances between vectors. This takes into account both the nature of space (for example, a sphere or a plane) and the way it parametrized - for example, by hexes or squares. SM> Well, technically speaking, the metric in the latter case ain't SM> one. If I recall correctly, the term is semimetric (the distance SM> between two distinct points can be zero). Both hex and square map surfaces can be described uniquely by two parameters. However, instead of x and y at 90 degree angles to each other, we have (for hexes) u and v at 60 degrees. In addition to the directions +-u, +-v, there is also the w=u+v, which is a direction but not an independent coordinate. SM> Somehow, I think you mean either (a) u and v are at 120 degrees SM> (and then u+v is the other "direction") or (b) u and v are at SM> 60 degrees, and u-v (or v-u) is the other "direction." SM> EP> Right. Note we are adding basis vectors, not coordinates. SM> [If u & v are at 60 degrees, then u+v is longer than u and v, SM> and isn't parallel to the side of a hex either. Bad.] SM> SM> For some reason, I'd prefer if we used u & v at 120 degrees. SM> SM> And it takes a little more than knowing what the basis vectors SM> are (or, alternatively, what the inner product is) - otherwise, SM> there's nothing to distinguish a triangular grid from a hex SM> one, or a skewed square one for that matter... EP> The basic idea is this: EP> V EP> / EP> / EP> x--U EP> \ EP> \ EP> W EP> EP> Thus, positive directions are "forward" (along U), and negative EP> directions are 180 degrees away from that. This seems to have EP> the greatest symmetry. Besides, working in oblique space, the EP> important question is actually not what the basis vectors are, EP> but where are the "equidistant" lines. The mathematics is a little tricky, but physicists like Dustin and I do this all the time, so trust us it will work. And wargamers are smart enough to be able to figure it out, I believer. The subtlety is that there are two different ways to measure distance. "true" distance, as you would measure with a ruler, and "counting" distance - the number of hexes or squares between them. And with squares you can either count diagonals as one or two squares away. This can be handled either by: a) creating separate subclasses for all these different types, and the developer picks one as the "standard" location. b) have different methods in the same base Location class for all these different measurements, and each class knows which one it calls. My personal preference is to have "xy" being the base class, and have "hex" as a subclass, and put all the relevant member functions in each class. Anybody else have a preference? SM> Don't forget to throw in "square" as well. SM> SM> Thinking about it, if we want to take height into account, SM> there are lots of combinations. For instance, we could have SM> a fully continuous plane, with discrete levels of height. And SM> there are several ways to compute the distance between two SM> points then - L^2 (Euclidean, square root of sum of squares of SM> planar distance and height difference), L^1 (sum of planar SM> distance & abs(height difference)), or L^\infty (maximum of SM> the two). SM> SM> Perhaps it would be as well to leave the two measurements SM> (planar distance, and height difference) orthogonal (pun not SM> quite intended), and leave it to some higher level to figure SM> out the true distance between points that are at different SM> heights? SM> SM> Or maybe not. SM> SM> Simon. EP> That's more or less what I had in mind. EP> EP> The important thing is that our 'generic' classes just pass EP> around this thing called a Location which consists of three EP> floats. Location is known to have (say) the methods: EP> - X, Y, and Z member access - xymag(), xydist(Location&) EP> - xyangle(), xyangleTo(Location &) [in degrees] [Height EP> is just Z distance] - addition, subtraction EP> EP> Then, each game designer is responsible for defining a location EP> class which gives the proper response for those. We provide EP> a set of classes (probably Continuous, SquareGrid, DiaganalGrid, EP> HexGrid) which the game developer can use or subclass. He can EP> also add additional methods, which only he and his pieces will EP> know about. EP> EP> Then, the developer should just be able to insert a: EP> EP> typedef MyLocation Location; EP> EP> and recompile everything, and our classes will just work fine. EP> We would have to recompile even if we used virtual classes, EP> since C++ can't do dynamic binding. :-( 5) Location belongs on the server More precisely, the server maintains a relationship between a location on a map and an object owned by the client. The reason I've decided this is appropriate is not so much for the reasons discussed earlier, but because of the way I think we will need to handle sensors. But that's another topic for another day... Does anybody have a good object for maintaining (and searching through) a paired list of C structures and ObjC classes?