home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / Games / Bolo 0.99.6 / More information / Sample Code / Map File Format / BoloMapFile.h < prev   
Encoding:
Text File  |  1993-09-18  |  8.8 KB  |  217 lines  |  [TEXT/ttxt]

  1. /*
  2. This header file describes the format of a BOLO map file, and defines some
  3. (semi)useful structures to support reading and writing of that file format.
  4.  
  5. Tabs are four spaces, and no lines exceed 80 characters.
  6.  
  7. Format of BMAP file: (not to be confused with the old BMAP resource)
  8.  
  9. 12 Byte preamble, consisting of an eight byte string "BMAPBOLO"
  10. and four data bytes:
  11. MAP_VERSION, to allow for future map files with different formats.
  12. p, the number of pillboxes on the map
  13. b, the number of refuelling bases on the map
  14. s, the number of tank starting square on the map
  15.  
  16. This preamble is followed by:
  17. 5 bytes of pillbox info (see structure below), repeated p times
  18. 6 bytes of refuelling base info (see structure below), repeated b times
  19. 3 bytes of start square info (see structure below), repeated s times
  20.  
  21. The remainder of the file -- the data which specifies the terrain of
  22. each map square -- follows after this header.
  23.  
  24. The map is described by a series of horizontal 'runs' of non-deepsea squares.
  25. Any square of the map not included in any 'run' is deep sea. The data portion
  26. of each 'run' is subject to simple run-length encoding to save space.
  27.  
  28. Each run is described by a run header followed by the run data.
  29. The run header structure is:
  30. BYTE datalen;// length of the data for this run INCLUDING this 4 byte header
  31. BYTE y;      // y co-ordinate of this run.
  32. BYTE startx; // first square of the run
  33. BYTE endx;   // last square of run + 1 (ie first deep sea square after run)
  34.  
  35. The run data takes the form of a series of NIBBLEs, where NIBBLE means
  36. half a byte, most significant half first, least significant second.
  37.  
  38. x = startx;
  39. while (x < endx)
  40.     {
  41.     The first nibble encodes the length of this portion of the run,
  42.     and whether this portion is a sequence of different squares,
  43.     or a sequence of identical squares.
  44.     
  45.     If length is 0-7 then this is a sequence of different squares.
  46.     The next (len+1) nibbles give the terrain for the next (len+1) squares.
  47.     
  48.     If length is 8-15 then this is a sequence of identical squares repeated.
  49.     The next single  nibble gives the terrain for the next (len-6) squares.
  50.     } (repeat until run is complete)
  51.  
  52. If a run ends on an odd nibble, then it is padded out to a whole number
  53. of bytes with an extra zero nibble.
  54.  
  55. The terrain types are:
  56. 0 Building 1 River 2 Swamp 3 Crater 4 Road 5 Forest 6 Rubble 7 Grass
  57. 8 Shot building 9 River with boat, and 10-15 are 2-7 with mines on them.
  58.  
  59. The intention is to have one 'run' per map row, but it is allowable (though
  60. less efficient) to have more than one run per row if you wish, and if (god
  61. forbid) you feel the need to have deep sea in the middle of your map, then
  62. the only way to encode this is to have a run, then a gap, then another run.
  63.  
  64. The end of the map is marked by a run { 4, 0xFF, 0xFF, 0xFF };
  65. This MUST be present or BOLO will reject the map as invalid.
  66.  
  67. Notes:
  68.  
  69. ** I use these types:
  70. typedef unsigned char  BYTE;
  71. typedef unsigned short WORD;
  72. typedef BYTE MAP_X, MAP_Y;
  73.  
  74. ** Coordinates start at (0,0) in the top left, and extend rightwards and
  75. downwards. No terrain may enter a twenty square border around the edge
  76. of the map -- ie nothing except deep sea at coordinates less than 20 or
  77. greater than 236. This imposes an absolute maximum map size of 216x216.
  78. Start squares may go slightly further out, but not within ten squares
  79. of the edges. In order to stop players from "wrapping around" the game
  80. area, Bolo generates a ten square wide border of mines in the deep sea
  81. all around the edge of the 'world'. This is why you must not place start
  82. squares into this border.
  83.  
  84. ** Start squares indicate where new tanks may appear, and which direction
  85. the tank will face when it appears (so that players don't have trouble
  86. finding the land). Start squares must be on deep sea, or they will be
  87. ignored. The direction has the value in the range 0-15, and, following
  88. the usual mathematical convention, 0 points to the right, and values
  89. increase in the anticlockwise direction. The units are 22.5 degree
  90. increments, ie 0 is East, 4 is North, 8 is West and 12 is South.
  91.  
  92. ** Many old BMAP resource maps don't conform to the 20 square border
  93. requirement. Bolo copes with this by automatically centring the BMAP
  94. within the 256x256 game area when it loads it. You should do the same,
  95. if you wish to support loading of old BMAPs (not really necessary,
  96. since all maps should be converted to the new format soon).
  97.  
  98. ** Please try to make your editor encourage the users to draw their maps
  99. centred in the game play area. I'd like to discourage people from cramming
  100. maps up into the top left corner of the game area. My intention is that
  101. the major land mass should exist in the middle, circled evenly on all
  102. sides by the distant sea mines. The sea mines should not play a strong
  103. role in the game -- they are only there to catch strays who wander too
  104. far from the island.
  105.  
  106. ** You should check the MAP_VERSION field to ensure that you are reading
  107. a map file format that you understand. This header file describes file
  108. format version 1.
  109.  
  110. ** The terrain specified in the file for any square containing a pillbox
  111. or refuelling base IS SIGNIFICANT. That terrain is what will remain when
  112. the pillbox (or base, in the future perhaps) is removed.
  113.  
  114. ** No square may contain more than one base or pillbox.
  115.  
  116. ** The run-length encoding of the map data is done to keep the size of map
  117. files small, so that (after encoding with BinHex) they can be directly posted
  118. to news groups, or sent by e-mail, without requiring any further compression.
  119. Everard Island (the built-in map) encodes to under 2KB using this scheme.
  120.  
  121. ** You can use Bolo to convert old BMAP resources to the new file format in
  122. the following way: Create a file, type BMAP, creator BOLO, and put the BMAP
  123. resource in it with id 128. Double click it, or drag and drop onto Bolo, and 
  124. it will load the map. Now Quit and save the map, and it will be saved in the
  125. new format.
  126.  
  127. ** IMPORTANT:
  128. The structures below describe the LOGICAL structure of the file. However,
  129. most C compilers (including Think C) will insert invisible padding fields
  130. to the structures to word-align fields as they deem necessary. For example,
  131. sizeof(BMAP_pill_info) is 6 in Think C, may be 8 in other compilers, but in
  132. the actual map file, just five bytes are used as you would expect.
  133.  
  134. Therefore, while it might appear that you could simply load the map file
  135. into memory and cast its type to BMAP_file_header to access it, this
  136. won't work, because of the invisible fields the compiler adds.
  137.  
  138. In addition C arrays have to be defined as a fixed size, but the actual
  139. number of pillboxes, bases and starts in the file is variable.
  140.  
  141. That accompanying sample C code should show you how to read and write map
  142. files without problem.
  143. */
  144.  
  145. #define CURRENT_MAP_VERSION 1
  146.  
  147. typedef struct
  148.     {
  149.     char id[8];            // "BMAPBOLO"
  150.     BYTE version;        // currently 1
  151.     BYTE num_pills;        // maximum 16 (at the moment)
  152.     BYTE num_bases;        // maximum 16 (at the moment)
  153.     BYTE num_starts;    // maximum 16 (at the moment)
  154.     } BMAP_preamble;
  155.  
  156. typedef struct
  157.     {
  158.     MAP_X x;
  159.     MAP_Y y;
  160.     BYTE owner;            // should be 0xFF except in speciality maps
  161.     BYTE armour;        // range 0-15 (dead pillbox = 0, full strength = 15)
  162.     BYTE speed;            // typically 50. Time between shots, in 20ms units
  163.                         // Lower values makes the pillbox start off 'angry'
  164.     } BMAP_pill_info;
  165. #define sizeofBMAP_pill_info 5
  166.  
  167. typedef struct
  168.     {
  169.     MAP_X x;
  170.     MAP_Y y;
  171.     BYTE owner;            // should be 0xFF except in speciality maps
  172.     BYTE armour;        // initial stocks of base. Maximum value 90
  173.     BYTE shells;        // initial stocks of base. Maximum value 90
  174.     BYTE mines;            // initial stocks of base. Maximum value 90
  175.     } BMAP_base_info;
  176. #define sizeofBMAP_base_info 6
  177.  
  178. typedef struct
  179.     {
  180.     MAP_X x;
  181.     MAP_Y y;
  182.     BYTE dir;            // Direction towards land from this start. Range 0-15
  183.     } BMAP_start_info;
  184. #define sizeofBMAP_start_info 3
  185.  
  186. typedef struct
  187.     {
  188.     BMAP_preamble   preamble;
  189.     BMAP_pill_info  pills [MAX_PILLS ];    // Remember that the map file does
  190.     BMAP_base_info  bases [MAX_BASES ];    // not necessarily contain these
  191.     BMAP_start_info starts[MAX_STARTS];    // numbers of elements in each array
  192.     } BMAP_file_header;
  193.  
  194. typedef struct
  195.     {
  196.     BYTE datalen;    // length of the data for this run
  197.                     // INCLUDING this 4 byte header
  198.     MAP_Y y;        // y co-ordinate of this run.
  199.     MAP_X startx;    // first square of the run
  200.     MAP_X endx;        // last square of run + 1
  201.                     // (ie first deep sea square after run)
  202.     BYTE data[0xFF];// actual length of data is always much less than 0xFF
  203.     } BMAP_run;
  204.  
  205. import BYTE *make_pillinfo (BYTE *number, BYTE *data);
  206. import void  read_pillinfo (BYTE  number, BYTE *data);
  207. import BYTE *make_baseinfo (BYTE *number, BYTE *data);
  208. import void  read_baseinfo (BYTE  number, BYTE *data);
  209. import BYTE *make_startinfo(BYTE *number, BYTE *data);
  210. import void  read_startinfo(BYTE  number, BYTE *data);
  211.  
  212. import long make_run(BMAP_run *run_ptr, MAP_X *xp, MAP_Y *yp);
  213. import OSErr read_run(BMAP_run *run);
  214.  
  215. import OSErr writemapfile(short refnum);
  216. import OSErr readmapfile(short refnum);
  217.