~ubuntu-branches/ubuntu/lucid/warzone2100/lucid

« back to all changes in this revision

Viewing changes to src/map.c

  • Committer: Bazaar Package Importer
  • Author(s): Christoph Egger, Paul Wise, Christoph Egger
  • Date: 2009-06-29 17:12:52 UTC
  • mfrom: (1.1.11 upstream) (2.1.7 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090629171252-5ddnlfg3zfchrega
Tags: 2.2.1+dfsg1-1
[ Paul Wise ]
* New upstream release (Closes: #534962)
* Adjust the flex build-depends to take account of the conflict
  with all the versions of flex 2.5.34 (LP: #372872)
* Make the -music Recommends more strict, 2.1 music doesn't work
  with 2.2.
* Upstream moved the downloads to sourceforge, update the watch file
* Bump Standards-Version, no changes needed
* Drop use of dh_desktop since it no longer does anything
* Recommend the new warzone2100-video package, version 2.2 or similar
* Mention the warzone2100 crash reports in the -dbg package description

[ Christoph Egger ]
* Replace CC-2.0 graphic from cybersphinx, create a new tarball
* Add myself to uploaders

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
        This file is part of Warzone 2100.
3
3
        Copyright (C) 1999-2004  Eidos Interactive
4
 
        Copyright (C) 2005-2007  Warzone Resurrection Project
 
4
        Copyright (C) 2005-2009  Warzone Resurrection Project
5
5
 
6
6
        Warzone 2100 is free software; you can redistribute it and/or modify
7
7
        it under the terms of the GNU General Public License as published by
26
26
#include <time.h>
27
27
 
28
28
#include "lib/framework/frame.h"
29
 
#include "lib/framework/tagfile.h"
 
29
#include "lib/framework/endian_hack.h"
30
30
#include "lib/framework/file.h"
31
31
#include "lib/framework/physfs_ext.h"
 
32
#include "lib/framework/tagfile.h"
32
33
#include "lib/ivis_common/tex.h"
33
34
 
34
35
#include "map.h"
62
63
        UDWORD          height;
63
64
} MAP_SAVEHEADER;
64
65
 
65
 
 
66
 
#define SAVE_MAP_V2 \
67
 
        UWORD           texture; \
68
 
        UBYTE           height
69
 
 
70
66
typedef struct _map_save_tilev2
71
67
{
72
 
        SAVE_MAP_V2;
73
 
} MAP_SAVETILEV2;
74
 
 
75
 
typedef struct _map_save_tile
76
 
{
77
 
        SAVE_MAP_V2;
 
68
        UWORD           texture;
 
69
        UBYTE           height;
78
70
} MAP_SAVETILE;
79
71
 
80
72
typedef struct _gateway_save_header
88
80
        UBYTE   x0,y0,x1,y1;
89
81
} GATEWAY_SAVE;
90
82
 
91
 
typedef struct _zonemap_save_header_v1 {
92
 
        UWORD version;
93
 
        UWORD numZones;
94
 
} ZONEMAP_SAVEHEADER_V1;
95
 
 
96
83
typedef struct _zonemap_save_header {
97
84
        UWORD version;
98
85
        UWORD numZones;
112
99
/* Number of entries in the sqrt(1/(1+x*x)) table for aaLine */
113
100
#define ROOT_TABLE_SIZE         1024
114
101
 
115
 
/* aaLine direction bits and tables */
116
 
#define DIR_STEEP                       1  /* set when abs(dy) > abs(dx) */
117
 
#define DIR_NEGY                        2  /* set whey dy < 0 */
118
 
 
119
102
/* The size and contents of the map */
120
103
UDWORD  mapWidth = 0, mapHeight = 0;
121
104
MAPTILE *psMapTiles = NULL;
147
130
 
148
131
        if (width*height > MAP_MAXAREA)
149
132
        {
150
 
                debug( LOG_ERROR, "mapNew: map too large : %d %d\n", width, height );
 
133
                debug(LOG_ERROR, "map too large : %u %u", width, height);
 
134
 
 
135
                return false;
 
136
        }
 
137
 
 
138
        psMapTiles = calloc(width * height, sizeof(MAPTILE));
 
139
        if (psMapTiles == NULL)
 
140
        {
 
141
                debug(LOG_ERROR, "Out of memory");
151
142
                abort();
152
143
                return false;
153
144
        }
154
145
 
155
 
        psMapTiles = calloc(width * height, sizeof(MAPTILE));
156
 
        ASSERT(psMapTiles != NULL, "mapNew: Out of memory")
157
 
 
158
146
        psTile = psMapTiles;
159
147
        for (i = 0; i < width * height; i++)
160
148
        {
187
175
static BOOL mapLoadV3(char *pFileData, UDWORD fileSize)
188
176
{
189
177
        UDWORD                          i,j;
190
 
        MAP_SAVETILEV2          *psTileData;
 
178
        MAP_SAVETILE            *psTileData;
191
179
        GATEWAY_SAVEHEADER      *psGateHeader;
192
180
        GATEWAY_SAVE            *psGate;
193
 
        ZONEMAP_SAVEHEADER      *psZoneHeader;
194
 
        UWORD ZoneSize;
195
 
        UBYTE *pZone;
196
 
        UBYTE *pDestZone;
197
181
 
198
182
        /* Load in the map data */
199
 
        psTileData = (MAP_SAVETILEV2 *)(pFileData + SAVE_HEADER_SIZE);
 
183
        psTileData = (MAP_SAVETILE *)(pFileData + SAVE_HEADER_SIZE);
200
184
        for(i=0; i< mapWidth * mapHeight; i++)
201
185
        {
202
 
                /* MAP_SAVETILEV2 */
 
186
                /* MAP_SAVETILE */
203
187
                endian_uword(&psTileData->texture);
204
188
 
205
189
                psMapTiles[i].texture = psTileData->texture;
208
192
                {
209
193
                        psMapTiles[i].tileVisBits =(UBYTE)(( (psMapTiles[i].tileVisBits) &~ (UBYTE)(1<<j) ));
210
194
                }
211
 
                psTileData = (MAP_SAVETILEV2 *)(((UBYTE *)psTileData) + SAVE_TILE_SIZE);
 
195
                psTileData = (MAP_SAVETILE *)(((UBYTE *)psTileData) + SAVE_TILE_SIZE);
212
196
        }
213
197
 
214
198
        psGateHeader = (GATEWAY_SAVEHEADER*)psTileData;
223
207
        for(i=0; i<psGateHeader->numGateways; i++) {
224
208
                if (!gwNewGateway(psGate->x0,psGate->y0, psGate->x1,psGate->y1)) {
225
209
                        debug( LOG_ERROR, "mapLoadV3: Unable to add gateway" );
226
 
                        abort();
 
210
 
227
211
                        return false;
228
212
                }
229
213
                psGate++;
230
214
        }
231
215
 
232
 
        psZoneHeader = (ZONEMAP_SAVEHEADER*)psGate;
233
 
 
234
 
        /* ZONEMAP_SAVEHEADER */
235
 
        endian_uword(&psZoneHeader->version);
236
 
        endian_uword(&psZoneHeader->numZones);
237
 
        endian_uword(&psZoneHeader->numEquivZones);
238
 
        endian_uword(&psZoneHeader->pad);
239
 
 
240
 
        ASSERT(psZoneHeader->version == 1
241
 
            || psZoneHeader->version == 2
242
 
            || psZoneHeader->version == 3, "Invalid zone map version: %u", psZoneHeader->version);
243
 
 
244
 
        /* Special case due to r4637: a version 2 with numZones and
245
 
         * numEquivZones set to zero is actually version 3.
246
 
         */
247
 
        if (psZoneHeader->version == 2
248
 
         && psZoneHeader->numZones == 0
249
 
         && psZoneHeader->numEquivZones == 0)
250
 
        {
251
 
                psZoneHeader->version = 3;
252
 
        }
253
 
 
254
 
        if(!gwNewZoneMap()) {
255
 
                return false;
256
 
        }
257
 
 
258
 
        // This is a bit nasty but should work fine.
259
 
        if      (psZoneHeader->version == 1)
260
 
        {
261
 
                // version 1 so add the size of a version 1 header.
262
 
                pZone = ((UBYTE*)psZoneHeader) + sizeof(ZONEMAP_SAVEHEADER_V1);
263
 
        }
264
 
        else if (psZoneHeader->version == 2)
265
 
        {
266
 
                // version 2 so add the size of a version 2 header.
267
 
                pZone = ((UBYTE*)psZoneHeader) + sizeof(ZONEMAP_SAVEHEADER);
268
 
        }
269
 
        /* Loading of savegames with ZONEMAP_SAVEHEADER structure versions of 3
270
 
         * or larger is not supported (and for version 3 cannot be supported as
271
 
         * long as we depend on zones).
272
 
         */
273
 
        else if (psZoneHeader->version == 3)
274
 
        {
275
 
                debug(LOG_ERROR, "Unsupported savegame (zone map version 3): this savegame cannot be loaded with this version of warzone because \"zone map\" version 3 fails to provide required data. NOTE: Warzone 2100 2.2 will most likely support this savegame anyway.");
276
 
                return false;
277
 
        }
278
 
        else
279
 
        {
280
 
                return false;
281
 
        }
282
 
 
283
 
        for(i=0; i<psZoneHeader->numZones; i++) {
284
 
                ZoneSize = *((UWORD*)(pZone));
285
 
                endian_uword(&ZoneSize);
286
 
 
287
 
                pDestZone = gwNewZoneLine(i,ZoneSize);
288
 
 
289
 
                if(pDestZone == NULL) {
290
 
                        return false;
291
 
                }
292
 
 
293
 
                for(j=0; j<ZoneSize; j++) {
294
 
                        pDestZone[j] = pZone[2+j];
295
 
                }
296
 
 
297
 
                pZone += ZoneSize+2;
298
 
        }
299
 
 
300
 
        // Version 2 has the zone equivelancy lists tacked on the end.
301
 
        if(psZoneHeader->version == 2) {
302
 
 
303
 
                if(psZoneHeader->numEquivZones > 0) {
304
 
                        // Load in the zone equivelance lists.
305
 
                        if(!gwNewEquivTable(psZoneHeader->numEquivZones)) {
306
 
                                debug( LOG_ERROR, "gwNewEquivTable failed" );
307
 
                                abort();
308
 
                                return false;
309
 
                        }
310
 
 
311
 
                        for(i=0; i<psZoneHeader->numEquivZones; i++) {
312
 
                                if(*pZone != 0) {
313
 
                                        if(!gwSetZoneEquiv(i, (SDWORD)*pZone, pZone+1)) {
314
 
                                                debug( LOG_ERROR, "gwSetZoneEquiv failed" );
315
 
                                                abort();
316
 
                                                return false;
317
 
                                        }
318
 
                                }
319
 
                                pZone += ((UDWORD)*pZone)+1;
320
 
                        }
321
 
                }
322
 
        }
323
 
 
324
 
        if ((char *)pZone - pFileData > fileSize)
325
 
        {
326
 
                debug( LOG_ERROR, "mapLoadV3: unexpected end of file" );
327
 
                abort();
328
 
                return false;
329
 
        }
330
 
 
331
 
        LOADBARCALLBACK();      //      loadingScreenCallback();
332
 
 
333
 
        if ((apEquivZones != NULL) &&
334
 
                !gwGenerateLinkGates())
335
 
        {
336
 
                return false;
337
 
        }
338
 
 
339
 
        LOADBARCALLBACK();      //      loadingScreenCallback();
340
 
 
341
 
        //add new map initialise
342
 
        if (!gwLinkGateways())
343
 
        {
344
 
                return false;
345
 
        }
346
 
 
347
 
        LOADBARCALLBACK();      //      loadingScreenCallback();
348
 
 
349
 
#if defined(DEBUG)
350
 
        gwCheckZoneSizes();
351
 
#endif
352
 
 
353
216
        return true;
354
217
}
355
218
 
365
228
        if (psHeader->aFileType[0] != 'm' || psHeader->aFileType[1] != 'a' ||
366
229
                psHeader->aFileType[2] != 'p' || psHeader->aFileType[3] != ' ')
367
230
        {
368
 
                debug( LOG_ERROR, "mapLoad: Incorrect file type" );
369
 
                abort();
 
231
                ASSERT(false, "Incorrect map type");
370
232
                free(pFileData);
371
233
                return false;
372
234
        }
379
241
        /* Check the file version */
380
242
        if (psHeader->version <= VERSION_9)
381
243
        {
382
 
                ASSERT(false, "MapLoad: unsupported save format version %d", psHeader->version);
 
244
                ASSERT(false, "Unsupported save format version %d", psHeader->version);
383
245
                free(pFileData);
384
246
                return false;
385
247
        }
386
248
        else if (psHeader->version > CURRENT_VERSION_NUM)
387
249
        {
388
 
                ASSERT(false, "MapLoad: undefined save format version %d", psHeader->version);
 
250
                ASSERT(false, "Undefined save format version %d", psHeader->version);
389
251
                free(pFileData);
390
252
                return false;
391
253
        }
396
258
 
397
259
        if (width*height > MAP_MAXAREA)
398
260
        {
399
 
                debug( LOG_ERROR, "mapLoad: map too large : %d %d\n", width, height );
400
 
                abort();
 
261
                debug( LOG_ERROR, "Map too large : %d %d\n", width, height );
 
262
                free(pFileData);
401
263
                return false;
402
264
        }
403
265
 
406
268
 
407
269
        /* Allocate the memory for the map */
408
270
        psMapTiles = calloc(width * height, sizeof(MAPTILE));
409
 
        ASSERT(psMapTiles != NULL, "mapLoad: Out of memory" );
 
271
        ASSERT(psMapTiles != NULL, "Out of memory" );
410
272
 
411
273
        mapWidth = width;
412
274
        mapHeight = height;
413
275
 
414
276
        //load in the map data itself
415
 
        if (!mapLoadV3(pFileData, fileSize))
416
 
                return false;
 
277
        mapLoadV3(pFileData, fileSize);
417
278
 
418
279
        environReset();
419
280
 
475
336
 
476
337
        tagWriteEnter(0x03, 1);
477
338
        tagWrite(0x01, body);
478
 
        tagWrite(0x02, NUM_WEAPON_CLASS);
 
339
        tagWrite(0x02, WC_NUM_WEAPON_CLASSES);
479
340
        tagWriteEnter(0x03, NUM_HIT_SIDES);
480
341
        for (i = 0; i < NUM_HIT_SIDES; i++)
481
342
        {
488
349
        tagWriteLeave(0x03);
489
350
}
490
351
 
491
 
static void objectWeaponTagged(int num, UWORD *rotation, UWORD *pitch, WEAPON *asWeaps, BASE_OBJECT **psTargets)
 
352
static void objectWeaponTagged(int num, WEAPON *asWeaps, BASE_OBJECT **psTargets)
492
353
{
493
354
        int i;
494
355
 
496
357
        for (i = 0; i < num; i++)
497
358
        {
498
359
                tagWrite(0x01, asWeaps[i].nStat);
499
 
                tagWrite(0x02, rotation[i]);
500
 
                tagWrite(0x03, pitch[i]);
501
 
                tagWrite(0x04, asWeaps[i].hitPoints);
 
360
                tagWrite(0x02, asWeaps[i].rotation);
 
361
                tagWrite(0x03, asWeaps[i].pitch);
502
362
                tagWrite(0x05, asWeaps[i].ammo);
503
363
                tagWrite(0x06, asWeaps[i].lastFired);
504
364
                tagWrite(0x07, asWeaps[i].recoilValue);
514
374
static void droidSaveTagged(DROID *psDroid)
515
375
{
516
376
        int plr = psDroid->player;
517
 
        uint16_t v[DROID_MAXCOMP], i, order[4], ammo[VTOL_MAXWEAPS];
 
377
        uint16_t v[ARRAY_SIZE(psDroid->asBits)], i, order[4], ammo[VTOL_MAXWEAPS];
518
378
        int32_t sv[2];
519
379
        float fv[3];
520
380
 
523
383
        objectSaveTagged((BASE_OBJECT *)psDroid); /* 0x01 */
524
384
        objectSensorTagged(psDroid->sensorRange, psDroid->sensorPower, 0, psDroid->ECMMod); /* 0x02 */
525
385
        objectStatTagged((BASE_OBJECT *)psDroid, psDroid->originalBody, psDroid->resistance); /* 0x03 */
526
 
        objectWeaponTagged(psDroid->numWeaps, psDroid->turretRotation, psDroid->turretPitch, psDroid->asWeaps, psDroid->psActionTarget);
 
386
        objectWeaponTagged(psDroid->numWeaps, psDroid->asWeaps, psDroid->psActionTarget);
527
387
 
528
388
        /* DROID GROUP */
529
389
 
530
390
        tagWriteEnter(0x0a, 1);
531
391
        tagWrite(0x01, psDroid->droidType);
532
 
        for (i = 0; i < DROID_MAXCOMP; i++)
 
392
        for (i = 0; i < ARRAY_SIZE(v); ++i)
533
393
        {
534
394
                v[i] = psDroid->asBits[i].nStat;
535
395
        }
536
 
        tagWrite16v(0x02, DROID_MAXCOMP, v);
 
396
        tagWrite16v(0x02, ARRAY_SIZE(v), v);
537
397
        // transporter droid in the mission list
538
398
        if (psDroid->droidType == DROID_TRANSPORTER && apsDroidLists[plr] == mission.apsDroidLists[plr])
539
399
        {
645
505
        objectSaveTagged((BASE_OBJECT *)psStruct); /* 0x01 */
646
506
        objectSensorTagged(psStruct->sensorRange, psStruct->sensorPower, 0, psStruct->ECMMod); /* 0x02 */
647
507
        objectStatTagged((BASE_OBJECT *)psStruct, psStruct->pStructureType->bodyPoints, psStruct->resistance); /* 0x03 */
648
 
        objectWeaponTagged(psStruct->numWeaps, psStruct->turretRotation, psStruct->turretPitch, psStruct->asWeaps, psStruct->psTarget);
 
508
        objectWeaponTagged(psStruct->numWeaps, psStruct->asWeaps, psStruct->psTarget);
649
509
 
650
510
        /* STRUCTURE GROUP */
651
511
 
865
725
                tagWrite(0x03, TRI_FLIPPED(psTile));
866
726
                tagWrite(0x04, psTile->texture & TILE_XFLIP);
867
727
                tagWrite(0x05, psTile->texture & TILE_YFLIP);
868
 
                tagWrite(0x06, TILE_IS_NOTBLOCKING(psTile));
 
728
                tagWrite(0x06, TileIsNotBlocking(psTile)); // Redundant, since already included in tileInfoBits
869
729
                tagWrite(0x08, psTile->height);
870
730
                tagWrite(0x09, psTile->tileVisBits);
871
731
                tagWrite(0x0a, psTile->tileInfoBits);
 
732
                tagWrite(0x0b, (psTile->texture & TILE_ROTMASK) >> TILE_ROTSHIFT);
872
733
 
873
734
                psTile++;
874
735
                x++;
1099
960
        }
1100
961
        tagWriteLeave(0x0f);
1101
962
 
1102
 
        tagWriteEnter(0x10, gwNumZoneLines()); // gateway zone lines
1103
 
        for (i = 0; i < gwNumZoneLines(); i++)
1104
 
        {
1105
 
                // binary blob for now... ugh, this is ugly, but no worse than it was
1106
 
                tagWrite(0x01, gwZoneLineSize(i));
1107
 
                tagWrite8v(0x02, gwZoneLineSize(i), apRLEZones[i]);
1108
 
                tagWriteNext();
1109
 
        }
1110
 
        tagWriteLeave(0x10);
1111
 
 
1112
 
        tagWriteEnter(0x11, gwNumZones); // gateway equivalency zones
1113
 
        for (i = 0; i < gwNumZones; i++)
1114
 
        {
1115
 
                tagWrite(0x01, aNumEquiv[i]);
1116
 
                if (aNumEquiv[i])
1117
 
                {
1118
 
                        // another ugly blob job
1119
 
                        tagWrite8v(0x02, aNumEquiv[i], apEquivZones[i]);
1120
 
                }
1121
 
                tagWriteNext();
1122
 
        }
1123
 
        tagWriteLeave(0x11);
1124
 
 
1125
963
        tagClose();
1126
964
        return true;
1127
965
}
1200
1038
        GATEWAY *psCurrGate = NULL;
1201
1039
        GATEWAY_SAVEHEADER *psGateHeader = NULL;
1202
1040
        GATEWAY_SAVE *psGate = NULL;
 
1041
        SDWORD  numGateways = 0;
1203
1042
        ZONEMAP_SAVEHEADER *psZoneHeader = NULL;
1204
 
        UBYTE *psZone = NULL;
1205
 
        UBYTE *psLastZone = NULL;
1206
 
        SDWORD  numGateways = 0;
1207
1043
 
1208
1044
        // find the number of non water gateways
1209
1045
        for(psCurrGate = gwGetGateways(); psCurrGate; psCurrGate = psCurrGate->psNext)
1218
1054
        *pFileSize = SAVE_HEADER_SIZE + mapWidth*mapHeight * SAVE_TILE_SIZE;
1219
1055
        // Add on the size of the gateway data.
1220
1056
        *pFileSize += sizeof(GATEWAY_SAVEHEADER) + sizeof(GATEWAY_SAVE)*numGateways;
1221
 
        // Add on the size of the zone data header.
 
1057
        // Add on the size of the zone data header. For backwards compatibility.
1222
1058
        *pFileSize += sizeof(ZONEMAP_SAVEHEADER);
1223
 
        // Add on the size of the zone data.
1224
 
        for(i=0; i<gwNumZoneLines(); i++) {
1225
 
                *pFileSize += 2+gwZoneLineSize(i);
1226
 
        }
1227
 
        // Add on the size of the equivalency lists.
1228
 
        for(i=0; i<(UDWORD)gwNumZones; i++) {
1229
 
                *pFileSize += 1+aNumEquiv[i];
1230
 
        }
1231
1059
 
1232
1060
        *ppFileData = (char*)malloc(*pFileSize);
1233
1061
        if (*ppFileData == NULL)
1257
1085
        psTile = psMapTiles;
1258
1086
        for(i=0; i<mapWidth*mapHeight; i++)
1259
1087
        {
1260
 
 
1261
 
                // don't save the noblock flag as it gets set again when the objects are loaded
1262
 
                psTileData->texture = (UWORD)(psTile->texture & (UWORD)~TILE_NOTBLOCKING);
1263
 
 
 
1088
                psTileData->texture = psTile->texture;
1264
1089
                psTileData->height = psTile->height;
1265
1090
 
1266
 
                /* MAP_SAVETILEV2 */
 
1091
                /* MAP_SAVETILE */
1267
1092
                endian_uword(&psTileData->texture);
1268
1093
 
1269
1094
                psTileData = (MAP_SAVETILE *)((UBYTE *)psTileData + SAVE_TILE_SIZE);
1298
1123
 
1299
1124
        // Put the zone header.
1300
1125
        psZoneHeader = (ZONEMAP_SAVEHEADER*)psGate;
1301
 
        psZoneHeader->version = 2;
1302
 
        psZoneHeader->numZones =(UWORD)gwNumZoneLines();
1303
 
        psZoneHeader->numEquivZones =(UWORD)gwNumZones;
 
1126
        psZoneHeader->version = 3;
 
1127
        psZoneHeader->numZones = 0;
 
1128
        psZoneHeader->numEquivZones = 0;
1304
1129
 
1305
1130
        /* ZONEMAP_SAVEHEADER */
1306
1131
        endian_uword(&psZoneHeader->version);
1308
1133
        endian_uword(&psZoneHeader->numEquivZones);
1309
1134
        endian_uword(&psZoneHeader->pad);
1310
1135
 
1311
 
        // Put the zone data.
1312
 
        psZone = (UBYTE*)(psZoneHeader+1);
1313
 
        for(i=0; i<gwNumZoneLines(); i++) {
1314
 
                psLastZone = psZone;
1315
 
                *((UWORD*)psZone) = (UWORD)gwZoneLineSize(i);
1316
 
                endian_uword(((UWORD *) psZone));
1317
 
 
1318
 
                psZone += sizeof(UWORD);
1319
 
                memcpy(psZone,apRLEZones[i],gwZoneLineSize(i));
1320
 
                psZone += gwZoneLineSize(i);
1321
 
        }
1322
 
 
1323
 
        // Put the equivalency lists.
1324
 
        if(gwNumZones > 0) {
1325
 
                for(i=0; i<(UDWORD)gwNumZones; i++) {
1326
 
                        psLastZone = psZone;
1327
 
                        *psZone = aNumEquiv[i];
1328
 
                        psZone ++;
1329
 
                        if(aNumEquiv[i]) {
1330
 
                                memcpy(psZone,apEquivZones[i],aNumEquiv[i]);
1331
 
                                psZone += aNumEquiv[i];
1332
 
                        }
1333
 
                }
1334
 
        }
1335
 
 
1336
 
        ASSERT( (intptr_t)psLastZone - (intptr_t)*ppFileData < (intptr_t)*pFileSize, "Buffer overflow saving map" );
1337
 
 
1338
1136
        return true;
1339
1137
}
1340
1138
 
1361
1159
        ASSERT(x >= 0, "map_Height: Negative x value");
1362
1160
        ASSERT(y >= 0, "map_Height: Negative y value");
1363
1161
 
1364
 
        x = x >= world_coord(mapWidth) ? world_coord(mapWidth - 1) : x;
1365
 
        y = y >= world_coord(mapHeight) ? world_coord(mapHeight - 1) : y;
 
1162
        x = (x >= world_coord(mapWidth) ? world_coord(mapWidth - 1) : x);
 
1163
        y = (y >= world_coord(mapHeight) ? world_coord(mapHeight - 1) : y);
1366
1164
 
1367
1165
        /* Turn into tile coordinates */
1368
1166
        tileX = map_coord(x);
1663
1461
        {
1664
1462
                PHYSFS_close(fileHandle);
1665
1463
                ASSERT(!"readVisibilityData: unexpected filesize", "readVisibilityData: unexpected filesize; should be %u, but is %u", expectedFileSize, fileSize);
1666
 
                abort();
 
1464
 
1667
1465
                return false;
1668
1466
        }
1669
1467
 
1689
1487
static void astarTest(const char *name, int x1, int y1, int x2, int y2)
1690
1488
{
1691
1489
        int             asret, i;
1692
 
        ASTAR_ROUTE     route;
 
1490
        MOVE_CONTROL    route;
1693
1491
        int             x = world_coord(x1);
1694
1492
        int             y = world_coord(y1);
1695
1493
        int             endx = world_coord(x2);
1696
1494
        int             endy = world_coord(y2);
1697
1495
        clock_t         stop;
1698
1496
        clock_t         start = clock();
1699
 
        int             iterations;
1700
1497
        bool            retval;
1701
1498
 
1702
1499
        retval = levLoadData(name, NULL, 0);
1703
1500
        ASSERT(retval, "Could not load %s", name);
1704
 
        fpathInitialise();
 
1501
        route.asPath = NULL;
1705
1502
        for (i = 0; i < 100; i++)
1706
1503
        {
1707
 
                iterations = 1;
 
1504
                PATHJOB job;
 
1505
 
1708
1506
                route.numPoints = 0;
1709
1507
                astarResetCounters();
1710
 
                ASSERT(astarInner == 0, "astarInner not reset");
1711
 
                asret = fpathAStarRoute(ASR_NEWROUTE, &route, x, y, endx, endy);
1712
 
                while (asret == ASR_PARTIAL)
1713
 
                {
1714
 
                        astarResetCounters();
1715
 
                        ASSERT(astarInner == 0, "astarInner not reset");
1716
 
                        asret = fpathAStarRoute(ASR_CONTINUE, &route, x, y, endx, endy);
1717
 
                        iterations++;
1718
 
                }
 
1508
                job.origX = x;
 
1509
                job.origY = y;
 
1510
                job.destX = endx;
 
1511
                job.destY = endy;
 
1512
                job.propulsion = PROPULSION_TYPE_WHEELED;
 
1513
                job.droidID = 1;
 
1514
                asret = fpathAStarRoute(&route, &job);
 
1515
                free(route.asPath);
 
1516
                route.asPath = NULL;
1719
1517
        }
1720
1518
        stop = clock();
1721
 
        fprintf(stdout, "\t\tPath-finding timing %s: %.02f (%d nodes, %d iterations)\n", name,
1722
 
                (double)(stop - start) / (double)CLOCKS_PER_SEC, route.numPoints, iterations);
1723
 
        levReleaseAll();
 
1519
        fprintf(stdout, "\t\tA* timing %s: %.02f (%d nodes)\n", name,
 
1520
                (double)(stop - start) / (double)CLOCKS_PER_SEC, route.numPoints);
 
1521
        start = clock();
 
1522
        fpathTest(x, y, endx, endy);
 
1523
        stop = clock();
 
1524
        fprintf(stdout, "\t\tfPath timing %s: %.02f (%d nodes)\n", name,
 
1525
                (double)(stop - start) / (double)CLOCKS_PER_SEC, route.numPoints);
 
1526
        retval = levReleaseAll();
 
1527
        assert(retval);
1724
1528
}
1725
1529
 
1726
1530
void mapTest()
1732
1536
 
1733
1537
        fprintf(stdout, "\tMap self-test: PASSED\n");
1734
1538
}
 
1539
 
 
1540
 
 
1541
/** Check if tile contained within the given world coordinates is burning. */
 
1542
bool fireOnLocation(unsigned int x, unsigned int y)
 
1543
{
 
1544
        const int posX = map_coord(x);
 
1545
        const int posY = map_coord(y);
 
1546
        const MAPTILE *psTile = mapTile(posX, posY);
 
1547
 
 
1548
        ASSERT(psTile, "Checking fire on tile outside the map (%d, %d)", posX, posY);
 
1549
        return psTile != NULL && TileIsBurning(psTile);
 
1550
}