quote:
Flarelocke
Personally, I'd use a tree. In other words, you're the commander-in-chief, so you have pointers to all the top groups(battalions?) underneath you (not necessary for them to know who their peers are because they can just link to you. Perhaps they have a pointer to the commander-in-chief, perhaps not). Those groups underneath the player have pointers to their members, and so on, until they have as members individual units.
Running with this, we first observe that the military is a hierarchical structure. Unless peers are explicitly grouped together, their instructions come only from "above".
Since each commanding unit may have a variable number of subordinate units under it, you want to have an N-ary tree of hierarchy, where N varies at each node. Solution? (Linked) list.
class CommandingUnit : public Unit{public: ... private: std::list< Unit * > subordinates; ...};
This eliminates the need to program explicit "unit holder" and "unit holder-holder" classes, as well as allows for infinite hierarchy with variable with (leaf count) at the nodes, meaning completely configurable organizational structure.
quote:
Dauntless
As for [coderx75's] suggestions, on question #3, I was sort of thinking of your idea of containing all the units into one container class, but I had two problems. One was that I wasn't quite sure how to group together units that belonged to the same Organizational Unit (actually I borrowed this term from M$ terminology for creating active directory objects...you have forests, trees, organizational units, etc in which to group units based on a common theme). I didn't really think of the Unit ID thing though. But I like your idea of linked lists better....like you say, it should cut down on search time. The only trouble there is....can you make linked lists grow? I know arrays are of fixed size, and I couldn't remember if you could insert nodes into linked lists...the reason that would be necessary is in case you decide to reinforce an Organized Unit, and of course by adding units during the game.
Choice of data structures is normally predicated by access and insert times.
Access time is how long it takes you to get to a particular element. For a (singly- or doubly-) linked list, the access time is a function of the offset of the desired node from the current location (usually assumed to be the top or head of the list), and is therefore a function of the number of objects in the list, n. We therefore classify list access as being of O(n) (Big-O is an upper bound on running time in terms of number of discrete operations). Access time for an array is constant, since all you need is the array element index. We denote constant time operations as O(1).
Insert time is how long it takes to add a new element to the data structure at an arbitrary but known location. For a linked list, insertion is O(1) (set the exisiting "next" node as the "next" node of the node to be inserted, and the "previous" node of the "next" node - if doubly-linked - to be the new node as well; then set the "previous" node of the new node to be the current node, and the "next" node of the current node to be the new node) as the same number of steps are always performed irrespective of node position. For an array, insertion requires the allocation of new memory large enough to hold the grown array (in practice this cost is mitigated for dynamic array structures by maintaining some "growing room"), copying over of data up to the location of the element to be inserted, insertion of the new element, and then the copying over of elements from the insertion position in the original array on to the end of the original array. It is clear that the number of operations required is a function of the number of elements in the array, thus making array insertion a O(n) operation.
The C++ STL provides std::list and std::vector among many other facilities, and both are dynamic structures that can be grown and shrunk at runtime (meaning you can insert data into vectors as well as lists, but be aware of the costs and factor them into your algorithms). Basically, all this background is to reinforce the position that linked lists are ideal for your Organizational Units because you can rapidly insert and remove nodes (units) while maintaining decent search times. If search happens very frequently, you can set up a vector of pointers to specific nodes that is refreshed whenever the list changes (so list element access becomes O(1) rather than O(n), but that's an optimzation topic.
quote:
Dauntless
As for question #2, why would a scripting engine be diffucult?
A true scripting engine isn't trivial. However, a solution that you can use immediately is custom initialization files. Essentially, your users/designers can specify and tweak unit attributes in simple text files (as coderx75 mentioned earlier) and those values are loaded into the game to define all objects. You could also allow them to define organizational structure and object aliases in these configuration files, sorta like so:
# interpret lines starting with hashes as comments, skip over them in code #example type definition; Platoon is type label# syntax is "object count id_0, id_1, ... id_count" where count is optional (default count is 1)[type Platoon]Tank RockerInfantry 20 TroopsRadio 2 Comms1, Comms2[end type] [type Company]Platoon 2 A, B[end type] [type Brigade]Company 4 Alpha Company, Beta Company, Charlie Company, Delta Company[end type]
My military teminology is obviously shot, but suffices to illustrate the point. This way you can tweak and play balance without having to recompile the engine unless there are structural defects. I think this was exactly what coderx75 was espousing earlier on.
Pause for digestion, and to peruse other comments at even greater length.
[Edit: scripting syntax error]
[edited by - Oluseyi on September 25, 2002 4:12:09 PM]