home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-09-18 | 8.8 KB | 217 lines | [TEXT/ttxt] |
- /*
- This header file describes the format of a BOLO map file, and defines some
- (semi)useful structures to support reading and writing of that file format.
-
- Tabs are four spaces, and no lines exceed 80 characters.
-
- Format of BMAP file: (not to be confused with the old BMAP resource)
-
- 12 Byte preamble, consisting of an eight byte string "BMAPBOLO"
- and four data bytes:
- MAP_VERSION, to allow for future map files with different formats.
- p, the number of pillboxes on the map
- b, the number of refuelling bases on the map
- s, the number of tank starting square on the map
-
- This preamble is followed by:
- 5 bytes of pillbox info (see structure below), repeated p times
- 6 bytes of refuelling base info (see structure below), repeated b times
- 3 bytes of start square info (see structure below), repeated s times
-
- The remainder of the file -- the data which specifies the terrain of
- each map square -- follows after this header.
-
- The map is described by a series of horizontal 'runs' of non-deepsea squares.
- Any square of the map not included in any 'run' is deep sea. The data portion
- of each 'run' is subject to simple run-length encoding to save space.
-
- Each run is described by a run header followed by the run data.
- The run header structure is:
- BYTE datalen;// length of the data for this run INCLUDING this 4 byte header
- BYTE y; // y co-ordinate of this run.
- BYTE startx; // first square of the run
- BYTE endx; // last square of run + 1 (ie first deep sea square after run)
-
- The run data takes the form of a series of NIBBLEs, where NIBBLE means
- half a byte, most significant half first, least significant second.
-
- x = startx;
- while (x < endx)
- {
- The first nibble encodes the length of this portion of the run,
- and whether this portion is a sequence of different squares,
- or a sequence of identical squares.
-
- If length is 0-7 then this is a sequence of different squares.
- The next (len+1) nibbles give the terrain for the next (len+1) squares.
-
- If length is 8-15 then this is a sequence of identical squares repeated.
- The next single nibble gives the terrain for the next (len-6) squares.
- } (repeat until run is complete)
-
- If a run ends on an odd nibble, then it is padded out to a whole number
- of bytes with an extra zero nibble.
-
- The terrain types are:
- 0 Building 1 River 2 Swamp 3 Crater 4 Road 5 Forest 6 Rubble 7 Grass
- 8 Shot building 9 River with boat, and 10-15 are 2-7 with mines on them.
-
- The intention is to have one 'run' per map row, but it is allowable (though
- less efficient) to have more than one run per row if you wish, and if (god
- forbid) you feel the need to have deep sea in the middle of your map, then
- the only way to encode this is to have a run, then a gap, then another run.
-
- The end of the map is marked by a run { 4, 0xFF, 0xFF, 0xFF };
- This MUST be present or BOLO will reject the map as invalid.
-
- Notes:
-
- ** I use these types:
- typedef unsigned char BYTE;
- typedef unsigned short WORD;
- typedef BYTE MAP_X, MAP_Y;
-
- ** Coordinates start at (0,0) in the top left, and extend rightwards and
- downwards. No terrain may enter a twenty square border around the edge
- of the map -- ie nothing except deep sea at coordinates less than 20 or
- greater than 236. This imposes an absolute maximum map size of 216x216.
- Start squares may go slightly further out, but not within ten squares
- of the edges. In order to stop players from "wrapping around" the game
- area, Bolo generates a ten square wide border of mines in the deep sea
- all around the edge of the 'world'. This is why you must not place start
- squares into this border.
-
- ** Start squares indicate where new tanks may appear, and which direction
- the tank will face when it appears (so that players don't have trouble
- finding the land). Start squares must be on deep sea, or they will be
- ignored. The direction has the value in the range 0-15, and, following
- the usual mathematical convention, 0 points to the right, and values
- increase in the anticlockwise direction. The units are 22.5 degree
- increments, ie 0 is East, 4 is North, 8 is West and 12 is South.
-
- ** Many old BMAP resource maps don't conform to the 20 square border
- requirement. Bolo copes with this by automatically centring the BMAP
- within the 256x256 game area when it loads it. You should do the same,
- if you wish to support loading of old BMAPs (not really necessary,
- since all maps should be converted to the new format soon).
-
- ** Please try to make your editor encourage the users to draw their maps
- centred in the game play area. I'd like to discourage people from cramming
- maps up into the top left corner of the game area. My intention is that
- the major land mass should exist in the middle, circled evenly on all
- sides by the distant sea mines. The sea mines should not play a strong
- role in the game -- they are only there to catch strays who wander too
- far from the island.
-
- ** You should check the MAP_VERSION field to ensure that you are reading
- a map file format that you understand. This header file describes file
- format version 1.
-
- ** The terrain specified in the file for any square containing a pillbox
- or refuelling base IS SIGNIFICANT. That terrain is what will remain when
- the pillbox (or base, in the future perhaps) is removed.
-
- ** No square may contain more than one base or pillbox.
-
- ** The run-length encoding of the map data is done to keep the size of map
- files small, so that (after encoding with BinHex) they can be directly posted
- to news groups, or sent by e-mail, without requiring any further compression.
- Everard Island (the built-in map) encodes to under 2KB using this scheme.
-
- ** You can use Bolo to convert old BMAP resources to the new file format in
- the following way: Create a file, type BMAP, creator BOLO, and put the BMAP
- resource in it with id 128. Double click it, or drag and drop onto Bolo, and
- it will load the map. Now Quit and save the map, and it will be saved in the
- new format.
-
- ** IMPORTANT:
- The structures below describe the LOGICAL structure of the file. However,
- most C compilers (including Think C) will insert invisible padding fields
- to the structures to word-align fields as they deem necessary. For example,
- sizeof(BMAP_pill_info) is 6 in Think C, may be 8 in other compilers, but in
- the actual map file, just five bytes are used as you would expect.
-
- Therefore, while it might appear that you could simply load the map file
- into memory and cast its type to BMAP_file_header to access it, this
- won't work, because of the invisible fields the compiler adds.
-
- In addition C arrays have to be defined as a fixed size, but the actual
- number of pillboxes, bases and starts in the file is variable.
-
- That accompanying sample C code should show you how to read and write map
- files without problem.
- */
-
- #define CURRENT_MAP_VERSION 1
-
- typedef struct
- {
- char id[8]; // "BMAPBOLO"
- BYTE version; // currently 1
- BYTE num_pills; // maximum 16 (at the moment)
- BYTE num_bases; // maximum 16 (at the moment)
- BYTE num_starts; // maximum 16 (at the moment)
- } BMAP_preamble;
-
- typedef struct
- {
- MAP_X x;
- MAP_Y y;
- BYTE owner; // should be 0xFF except in speciality maps
- BYTE armour; // range 0-15 (dead pillbox = 0, full strength = 15)
- BYTE speed; // typically 50. Time between shots, in 20ms units
- // Lower values makes the pillbox start off 'angry'
- } BMAP_pill_info;
- #define sizeofBMAP_pill_info 5
-
- typedef struct
- {
- MAP_X x;
- MAP_Y y;
- BYTE owner; // should be 0xFF except in speciality maps
- BYTE armour; // initial stocks of base. Maximum value 90
- BYTE shells; // initial stocks of base. Maximum value 90
- BYTE mines; // initial stocks of base. Maximum value 90
- } BMAP_base_info;
- #define sizeofBMAP_base_info 6
-
- typedef struct
- {
- MAP_X x;
- MAP_Y y;
- BYTE dir; // Direction towards land from this start. Range 0-15
- } BMAP_start_info;
- #define sizeofBMAP_start_info 3
-
- typedef struct
- {
- BMAP_preamble preamble;
- BMAP_pill_info pills [MAX_PILLS ]; // Remember that the map file does
- BMAP_base_info bases [MAX_BASES ]; // not necessarily contain these
- BMAP_start_info starts[MAX_STARTS]; // numbers of elements in each array
- } BMAP_file_header;
-
- typedef struct
- {
- BYTE datalen; // length of the data for this run
- // INCLUDING this 4 byte header
- MAP_Y y; // y co-ordinate of this run.
- MAP_X startx; // first square of the run
- MAP_X endx; // last square of run + 1
- // (ie first deep sea square after run)
- BYTE data[0xFF];// actual length of data is always much less than 0xFF
- } BMAP_run;
-
- import BYTE *make_pillinfo (BYTE *number, BYTE *data);
- import void read_pillinfo (BYTE number, BYTE *data);
- import BYTE *make_baseinfo (BYTE *number, BYTE *data);
- import void read_baseinfo (BYTE number, BYTE *data);
- import BYTE *make_startinfo(BYTE *number, BYTE *data);
- import void read_startinfo(BYTE number, BYTE *data);
-
- import long make_run(BMAP_run *run_ptr, MAP_X *xp, MAP_Y *yp);
- import OSErr read_run(BMAP_run *run);
-
- import OSErr writemapfile(short refnum);
- import OSErr readmapfile(short refnum);
-