int main(int argc, char **argv) { char filename[PATH_MAX]; char path[PATH_MAX], *delim; GAMEMAP *map; if (argc != 2) { printf("Usage: %s <map>\n", argv[0]); return -1; } strcpy(path, argv[1]); delim = strrchr(path, '/'); if (delim) { *delim = '\0'; delim++; strcpy(filename, delim); } else { path[1] = '.'; path[1] = '\0'; strcpy(filename, argv[1]); } PHYSFS_init(argv[0]); PHYSFS_addToSearchPath(path, 1); map = mapLoad(filename); if (map) { char tilesetName[PATH_MAX]; if (map->tileset == TILESET_ARIZONA) { strcpy(tilesetName, "Arizona"); } else if (map->tileset == TILESET_URBAN) { strcpy(tilesetName, "Urban"); } else if (map->tileset == TILESET_ROCKIES) { strcpy(tilesetName, "Rockies"); } else { strcpy(tilesetName, "(unknown)"); } printf("Loaded map: %s\n", filename); printf("\tMap version: %d\n", (int)map->mapVersion); printf("\tGame version: %d\n", (int)map->gameVersion); printf("\tWidth: %d\n", (int)map->width); printf("\tHeight: %d\n", (int)map->height); printf("\tGateways: %d\n", (int)map->numGateways); printf("\tPlayers: %d\n", (int)map->numPlayers); printf("\tFeatures: %d\n", (int)map->numFeatures); printf("\tDroids: %d\n", (int)map->numDroids); printf("\tStructures: %d\n", (int)map->numStructures); printf("\tScroll limits: (%d, %d, %d, %d)\n", (int)map->scrollMinX, (int)map->scrollMinY, (int)map->scrollMaxX, (int)map->scrollMaxY); printf("\tLevel name: %s\n", map->levelName); printf("\tTileset: %s\n", tilesetName); } mapFree(map); return 0; }
main() { void** gc; errno = 0; if (-1 == mkdir(RUN_PATH, 00700)) { ASSERT(errno != EEXIST); errno = 0; } //printf("Content-type: text/plain\n\n"); /* int i = 0; char** lstEnv = getEnv(); for (; lstEnv[i]; ++i) { TRACE("%s\n", lstEnv[i]); } */ const char* http_host = getenv("HTTP_HOST"); ASSERT(http_host == NULL); char** lstArgs = lstSplitStr('.', http_host); ASSERT(lstArgs == NULL); int arg_c = lstSize(lstArgs); ASSERT(arg_c < 2); if (arg_c == 2) { const char* request_uri = getenv("REQUEST_URI"); ASSERT(request_uri == NULL); char* t = strchr(request_uri + 1, '/'); if (t == NULL) { Connect(atol(request_uri + 1)); } else { *t = '\0'; Respond(atol(request_uri + 1), atol(t + 1)); } } else { Pier(atol(lstArgs[0])); } mapFree(lstArgs); return 0; }
int main() { map *p = NULL; size_t cap, tSize; int objType,keyType; int objTypeSize, keyTypeSize; void *data = malloc(sizeof(double)*10); void *data2 = malloc(sizeof(double)*10); double double_neg_inf = DOUBLE_NEG_INF; short short_neg_inf = SHORT_NEG_INF; mapit it = NULL, rit=NULL; while(1){ char cmd[10240] = {0}; int ret; if(p == NULL){ printf("The map needs to be initialized.\n"); printf("Init step 1. Key Type: d for double, others for short.\n"); scanf("%s", cmd); keyType = (cmd[0] == 'd')?__DS__DOUBLE__:__DS__SHORT__; printf("Init step 2. Value Type: d for double, others for short.\n"); scanf("%s", cmd); objType = (cmd[0] == 'd')?__DS__DOUBLE__:__DS__SHORT__; printf("Init step 3. Capacity: \n"); scanf("%zu", &cap); p = mapAlloc(); if(p == NULL) ret = __DS__MAP__OUT_OF_MEM__; else{ objTypeSize = (objType==__DS__DOUBLE__)? sizeof(double): sizeof(short); if(keyType == __DS__DOUBLE__) ret = mapInit(p, sizeof(double), objTypeSize, cap, doubleGT); else ret = mapInit(p, sizeof(short), objTypeSize, cap, shortGT); } if(ret != __DS__MAP__NORMAL__){ printf("Not enough memory.\n"); if(p != NULL) mapFree(p); p = NULL; } else{ printf("Initialization done.\n"); } }else{ int choice = 0; printf("size/capacity: %zu/%zu\n", mapSize(p), mapCap(p)); printf("Valid operation: 1)insert, 2)delete, 3)get iterator, 4)set\n"); printf(" 5)update by it, 6)get order, 7)next, 8)pre, 9)get by iterator\n"); printf(" 10)empty, 11)free, 12)quit\n"); while(choice <= 0 || choice > 12){ scanf("%s", cmd); sscanf(cmd, "%d", &choice); } if (choice == 1){//insert printf("input a %s-type key:", (keyType == __DS__DOUBLE__)?"double":"short"); getData(keyType, data); printf("input a %s-type value:", (objType == __DS__DOUBLE__)?"double":"short"); getData(objType, data2); ret = mapInsert(p, data, data2); if(ret==__DS__MAP__FULL__)printf("Map is full!\n"); else if(ret==__DS__MAP__OBJ_EXIST__)printf("Element already exists!\n"); else if(ret==__DS__MAP__OUT_OF_MEM__)printf("Run out of memory\n"); else if(ret==__DS__MAP__NORMAL__)printf("Insert OK\n"); } else if(choice == 2){//delete printf("input a %s value:", (keyType == __DS__DOUBLE__)?"double":"short"); getData(keyType, data); ret = mapDelete(p, data); if(ret==__DS__MAP__OBJ_NOT_EXIST__){ printf("Element is not in the set.\n"); } else printf("Delete OK\n"); } else if (choice == 3){//get it printf("input a %s value:", (keyType == __DS__DOUBLE__)?"double":"short"); getData(keyType, data); ret = mapGetIt(p, data, &it); if(ret == __DS__MAP__OBJ_EXIST__){ printf("Get iterator OK!"); printf(".\n"); } else{ printf("The key "); printData(keyType, data); printf(" is not in the map.\n"); } } else if(choice == 4){//set by it printf("input the value to set:"); getData( objType, data2); ret = mapSetByIt(it, data2); if(ret == __DS__MAP__NORMAL__){ printf("Set OK!\n"); } else printf("Invalid It\n"); } else if(choice == 5){//update by it printf("input the key to set:"); getData( objType, data); printf("input the value to set:"); getData( objType, data2); ret = mapUpdateByIt(it, data, data2); if(ret == __DS__MAP__NORMAL__) { printf("Update OK!\n"); }else { printf("Invalid It\n"); } } else if (choice == 6){//get order int order; printf("input the order:"); scanf("%zu", &order); ret = mapGetOrderIt(p, order, data, data2, &it); if(ret == __DS__MAP__NORMAL__){ printf("The result key is "); printData( keyType, data); printf(".\n"); printf("The result value is "); printData( objType, data2); printf(".\n"); } else printf("No element found\n"); } else if(choice == 7){//next rit = mapNextIt(it); if(rit!=NULL) printf("Get Next OK!\n"); else printf("Cannot get next\n"); mapFreeIt(it); it = rit; } else if(choice == 8){//pre rit = mapPrevIt(it); if(rit!=NULL) printf("Get Priv OK!\n"); else printf("Cannot get priv\n"); mapFreeIt(it); it = rit; } else if(choice == 9){//get element by it ret = mapGetByIt(it,data,data2); if(ret==__DS__MAP__NORMAL__) { printf("The key of curremt it :"); printData( keyType, data); printf("\nThe value of curremt it :"); printData( objType, data2); printf("\n"); }else { printf("Invalid Iterator\n"); } } else if(choice == 10){//empty if(mapEmpty(p)==__DS__MAP__EMPTY__) printf("The map is empty.\n"); else printf("The map is not empty.\n"); } else if(choice == 11){ mapFree(p); p = NULL; } else if(choice == 12) break; } } }
int initMap(int sy, int sx, int nr, int ft, int wt){ // logEntry("Begin initMap()"); if(MAP != NULL){ // logEntry("[WARNING] MAP not NULL."); MAP = mapFree(MAP); } // logEntry("Begin mapAllocate()"); MAP = mapAllocate(MAP, sy, sx); if(MAP == NULL) return ERR_MALLOC; // logEntry("mapAllocate() OK!"); int y, x; // logEntry("Begin bspNew()"); BSPROOT = bspNew(BSPROOT, sy, sx, 4); if(BSPROOT == NULL) return ERR_MALLOC; // logEntry("bspNew() OK!"); // logEntry("Begin bspRecursive()"); bspRecursive(BSPROOT, nr); // logEntry("bspRecursive() OK!"); // logEntry("Begin bspResize()"); bspDoResize(BSPROOT, nr); // logEntry("bspResize() OK!"); // logEntry("Begin fillMap()"); fillMap(MAP, sy, sx, TILE_BLANK); // logEntry("fillMap() OK!"); MAPTAIL = &MAP[(sy * sx) - 1]; // logEntry("Begin bspDrawRooms()"); bspDrawRooms(BSPROOT, MAP, nr, sy, sx, ft, wt); // logEntry("bspDrawRooms() OK!"); int r = nr - 1; // logEntry("Begin bspLinkRooms()"); for(r; r >= 0; r--){ bspLinkRooms(BSPROOT, MAP, r, sy, sx, ft); } // logEntry("bspLinkRooms() OK!"); int d; // logEntry("Begin bspAddDoors(()"); bspAddDoors(BSPROOT, MAP, nr, sx, ft, wt); // logEntry("bspAddDoors() OK!"); // logEntry("Begin fillWall()"); fillWall(MAP, sy, sx, ft, wt); // logEntry("fillWall() OK!"); // logEntry("Begin fillStairs()"); fillStairs(MAP, sy, sx, ft); // logEntry("fillStairs() OK!"); // logEntry("Seeking suitable position to start player."); do{ y = getRand_i(0, sy); x = getRand_i(0, sx); }while(MAP[CM(y,sx,x)].tT != ft); // logEntry("Suitable position found."); player->locY = y; player->locX = x; // logEntry("Recording map maximum values to ENGINE."); genesis->maxY = sy; genesis->maxX = sx; // logEntry("Begin bspDel()"); bspDel(BSPROOT); // logEntry("bspDel() OK!"); int i; // logEntry("begin seedCreature()"); for(i = 0; i < 25; i++){ seedCreature(genesis->floor, ft); // Keep this out until seedCreature is revised to use spawnCreatur() } // logEntry("seedCreature() OK!"); TEST_seedItem(); // logEntry("initMap() OK!"); return ERR_NONE; }
int main(int argc, char **argv) { char *filename, *p_filename; char *base, tmpFile[PATH_MAX]; GAMEMAP *map; if (argc != 2) { printf("Usage: %s <map>\n", argv[0]); return -1; } physfs_init(argv[0]); filename = physfs_addmappath(argv[1]); p_filename = strrchr(filename, '/'); if (p_filename) { p_filename++; base = strdup(p_filename); } else { base = strdup(filename); } if (!PHYSFS_exists(base)) { PHYSFS_mkdir(base); } map = mapLoad(filename); free(filename); if (!map) { return EXIT_FAILURE; } uint x, y; uint8_t *pixels = (uint8_t *)malloc(map->width * map->height); for (x = 0; x < map->width; x++) { for (y = 0; y < map->height; y++) { MAPTILE *psTile = mapTile(map, x, y); int pixpos = y * map->width + x; pixels[pixpos++] = psTile->height; } } strcpy(tmpFile, base); strcat(tmpFile, "/height.png"); savePngI8(tmpFile, pixels, map->width, map->height); free(pixels); mapFree(map); physfs_shutdown(); return 0; }
/* Initialise the map structure */ GAMEMAP *mapLoad(char *filename) { char path[PATH_MAX]; GAMEMAP *map = (GAMEMAP *)malloc(sizeof(*map)); uint32_t i, j, gwVersion; char aFileType[4]; bool littleEndian = true; PHYSFS_file *fp = NULL; bool counted[MAX_PLAYERS]; uint16_t pType; // this cries out for a class based design #define readU8(v) ( littleEndian ? PHYSFS_readULE8(fp, v) : PHYSFS_readUBE8(fp, v) ) #define readU16(v) ( littleEndian ? PHYSFS_readULE16(fp, v) : PHYSFS_readUBE16(fp, v) ) #define readU32(v) ( littleEndian ? PHYSFS_readULE32(fp, v) : PHYSFS_readUBE32(fp, v) ) #define readS8(v) ( littleEndian ? PHYSFS_readSLE8(fp, v) : PHYSFS_readSBE8(fp, v) ) #define readS16(v) ( littleEndian ? PHYSFS_readSLE16(fp, v) : PHYSFS_readSBE16(fp, v) ) #define readS32(v) ( littleEndian ? PHYSFS_readSLE32(fp, v) : PHYSFS_readSBE32(fp, v) ) /* === Load map data === */ strcpy(path, filename); strcat(path, "/game.map"); fp = PHYSFS_openRead(path); map->mGateways = NULL; map->mMapTiles = NULL; if (!fp) { debug(LOG_ERROR, "Could not open %s", path); map->mapVersion = 0; map->width = UINT32_MAX; map->height = UINT32_MAX; map->mMapTiles = NULL; goto mapfailure; } else if (PHYSFS_read(fp, aFileType, 4, 1) != 1 || !readU32(&map->mapVersion) || !readU32(&map->width) || !readU32(&map->height) || aFileType[0] != 'm' || aFileType[1] != 'a' || aFileType[2] != 'p') { debug(LOG_ERROR, "Bad header in %s", path); goto failure; } else if (map->mapVersion <= 9) { debug(LOG_ERROR, "%s: Unsupported save format version %u", path, map->mapVersion); goto failure; } else if (map->mapVersion > 36) { debug(LOG_ERROR, "%s: Undefined save format version %u", path, map->mapVersion); goto failure; } else if (map->width * map->height > MAP_MAXAREA) { debug(LOG_ERROR, "Map %s too large : %d %d", path, map->width, map->height); goto failure; } /* Allocate the memory for the map */ map->mMapTiles = (MAPTILE *)calloc(map->width * map->height, sizeof(*map->mMapTiles)); if (!map->mMapTiles) { debug(LOG_ERROR, "Out of memory"); goto failure; } /* Load in the map data */ for (i = 0; i < map->width * map->height; i++) { uint16_t texture; uint8_t height; if (!readU16(&texture) || !readU8(&height)) { debug(LOG_ERROR, "%s: Error during savegame load", path); goto failure; } map->mMapTiles[i].texture = static_cast<TerrainType>(texture); map->mMapTiles[i].height = height; for (j = 0; j < MAX_PLAYERS; j++) { map->mMapTiles[i].tileVisBits = (uint8_t)(map->mMapTiles[i].tileVisBits &~ (uint8_t)(1 << j)); } } if (!readU32(&gwVersion) || !readU32(&map->numGateways) || gwVersion != 1) { debug(LOG_ERROR, "Bad gateway in %s", path); goto failure; } map->mGateways = (GATEWAY *)calloc(map->numGateways, sizeof(*map->mGateways)); for (i = 0; i < map->numGateways; i++) { if (!readU8(&map->mGateways[i].x1) || !readU8(&map->mGateways[i].y1) || !readU8(&map->mGateways[i].x2) || !readU8(&map->mGateways[i].y2)) { debug(LOG_ERROR, "%s: Failed to read gateway info", path); goto failure; } } PHYSFS_close(fp); mapfailure: /* === Load game data === */ strcpy(path, filename); strcat(path, ".gam"); fp = PHYSFS_openRead(path); if (!fp) { debug(LOG_ERROR, "Game file %s not found", path); goto failure; } else if (PHYSFS_read(fp, aFileType, 4, 1) != 1 || aFileType[0] != 'g' || aFileType[1] != 'a' || aFileType[2] != 'm' || aFileType[3] != 'e' || !readU32(&map->gameVersion)) { debug(LOG_ERROR, "Bad header in %s", path); goto failure; } if (map->gameVersion > 35) // big-endian { littleEndian = false; } if (!readU32(&map->gameTime) || !readU32(&map->gameType) || !readS32(&map->scrollMinX) || !readS32(&map->scrollMinY) || !readU32(&map->scrollMaxX) || !readU32(&map->scrollMaxY) || PHYSFS_read(fp, map->levelName, 20, 1) != 1) { debug(LOG_ERROR, "Bad data in %s", filename); goto failure; } for (i = 0; i < 8; i++) { if (map->gameVersion >= 10) { uint32_t dummy; // extracted power, not used if (!readU32(&map->power[i]) || !readU32(&dummy)) { debug(LOG_ERROR, "Bad power data in %s", filename); goto failure; } } else { map->power[i] = 0; // TODO... is there a default? } } PHYSFS_close(fp); /* === Load feature data === */ littleEndian = true; strcpy(path, filename); strcat(path, "/feat.bjo"); fp = PHYSFS_openRead(path); if (!fp) { debug(LOG_ERROR, "Feature file %s not found", path); map->featVersion = 0; map->numFeatures = 0; map->mLndObjects[IMD_FEATURE] = NULL; goto featfailure; } else if (PHYSFS_read(fp, aFileType, 4, 1) != 1 || aFileType[0] != 'f' || aFileType[1] != 'e' || aFileType[2] != 'a' || aFileType[3] != 't' || !readU32(&map->featVersion) || !readU32(&map->numFeatures)) { debug(LOG_ERROR, "Bad features header in %s", path); goto failure; } map->mLndObjects[IMD_FEATURE] = (LND_OBJECT *)malloc(sizeof(*map->mLndObjects[IMD_FEATURE]) * map->numFeatures); for(i = 0; i < map->numFeatures; i++) { LND_OBJECT *psObj = &map->mLndObjects[IMD_FEATURE][i]; int nameLength = 60; uint32_t dummy; uint8_t visibility[8]; if (map->featVersion <= 19) { nameLength = 40; } if (PHYSFS_read(fp, psObj->name, nameLength, 1) != 1 || !readU32(&psObj->id) || !readU32(&psObj->x) || !readU32(&psObj->y) || !readU32(&psObj->z) || !readU32(&psObj->direction) || !readU32(&psObj->player) || !readU32(&dummy) // BOOL inFire || !readU32(&dummy) // burnStart || !readU32(&dummy)) // burnDamage { debug(LOG_ERROR, "Failed to read feature from %s", path); goto failure; } psObj->player = 0; // work around invalid feature owner if (map->featVersion >= 14 && PHYSFS_read(fp, &visibility, 1, 8) != 8) { debug(LOG_ERROR, "Failed to read feature visibility from %s", path); goto failure; } psObj->type = 0; // IMD LND type for feature // Sanity check data if (psObj->x >= map->width * TILE_WIDTH || psObj->y >= map->height * TILE_HEIGHT) { debug(LOG_ERROR, "Bad feature coordinate %u(%u, %u)", psObj->id, psObj->x, psObj->y); goto failure; } } PHYSFS_close(fp); featfailure: /* === Load terrain data === */ littleEndian = true; strcpy(path, filename); strcat(path, "/ttypes.ttp"); fp = PHYSFS_openRead(path); if (!fp) { map->terrainVersion = 0; goto terrainfailure; } else if (PHYSFS_read(fp, aFileType, 4, 1) != 1 || aFileType[0] != 't' || aFileType[1] != 't' || aFileType[2] != 'y' || aFileType[3] != 'p' || !readU32(&map->terrainVersion) || !readU32(&map->numTerrainTypes)) { debug(LOG_ERROR, "Bad features header in %s", path); goto failure; } if (map->numTerrainTypes >= MAX_TILE_TEXTURES) { // Workaround for fugly map editor bug, since we can't fix the map editor map->numTerrainTypes = MAX_TILE_TEXTURES - 1; } // reset the terrain table memset(terrainTypes, 0, sizeof(terrainTypes)); for (i = 0; i < map->numTerrainTypes; i++) { readU16(&pType); if (pType > TER_MAX) { debug(LOG_ERROR, "loadTerrainTypeMap: terrain type out of range"); goto terrainfailure; } terrainTypes[i] = (uint8_t)pType; } if (terrainTypes[0] == 1 && terrainTypes[1] == 0 && terrainTypes[2] == 2) { map->tileset = TILESET_ARIZONA; } else if (terrainTypes[0] == 2 && terrainTypes[1] == 2 && terrainTypes[2] == 2) { map->tileset = TILESET_URBAN; } else if (terrainTypes[0] == 0 && terrainTypes[1] == 0 && terrainTypes[2] == 2) { map->tileset = TILESET_ROCKIES; } else { debug(LOG_ERROR, "Unknown terrain signature in %s: %u %u %u", path, terrainTypes[0], terrainTypes[1], terrainTypes[2]); goto failure; } PHYSFS_close(fp); terrainfailure: /* === Load structure data === */ map->mLndObjects[IMD_STRUCTURE] = NULL; map->numStructures = 0; littleEndian = true; strcpy(path, filename); strcat(path, "/struct.bjo"); map->mLndObjects[IMD_STRUCTURE] = NULL; fp = PHYSFS_openRead(path); if (fp) { if (PHYSFS_read(fp, aFileType, 4, 1) != 1 || aFileType[0] != 's' || aFileType[1] != 't' || aFileType[2] != 'r' || aFileType[3] != 'u' || !readU32(&map->structVersion) || !readU32(&map->numStructures)) { debug(LOG_ERROR, "Bad structure header in %s", path); goto failure; } map->mLndObjects[IMD_STRUCTURE] = (LND_OBJECT *)malloc(sizeof(*map->mLndObjects[IMD_STRUCTURE]) * map->numStructures); for (i = 0; i < map->numStructures; i++) { LND_OBJECT *psObj = &map->mLndObjects[IMD_STRUCTURE][i]; int nameLength = 60; uint32_t dummy; uint8_t visibility[8], dummy8; int16_t dummyS16; int32_t dummyS32; char researchName[60]; if (map->structVersion <= 19) { nameLength = 40; } if (PHYSFS_read(fp, psObj->name, nameLength, 1) != 1 || !readU32(&psObj->id) || !readU32(&psObj->x) || !readU32(&psObj->y) || !readU32(&psObj->z) || !readU32(&psObj->direction) || !readU32(&psObj->player) || !readU32(&dummy) // BOOL inFire || !readU32(&dummy) // burnStart || !readU32(&dummy) // burnDamage || !readU8(&dummy8) // status - causes structure padding || !readU8(&dummy8) // structure padding || !readU8(&dummy8) // structure padding || !readU8(&dummy8) // structure padding || !readS32(&dummyS32) // currentBuildPts - aligned on 4 byte boundary || !readU32(&dummy) // body || !readU32(&dummy) // armour || !readU32(&dummy) // resistance || !readU32(&dummy) // dummy1 || !readU32(&dummy) // subjectInc || !readU32(&dummy) // timeStarted || !readU32(&dummy) // output || !readU32(&dummy) // capacity || !readU32(&dummy)) // quantity { debug(LOG_ERROR, "Failed to read structure from %s", path); goto failure; } if (map->structVersion >= 12 && (!readU32(&dummy) // factoryInc || !readU8(&dummy8) // loopsPerformed - causes structure padding || !readU8(&dummy8) // structure padding || !readU8(&dummy8) // structure padding || !readU8(&dummy8) // structure padding || !readU32(&dummy) // powerAccrued - aligned on 4 byte boundary || !readU32(&dummy) // dummy2 || !readU32(&dummy) // droidTimeStarted || !readU32(&dummy) // timeToBuild || !readU32(&dummy))) // timeStartHold { debug(LOG_ERROR, "Failed to read structure v12 part from %s", path); goto failure; } if (map->structVersion >= 14 && PHYSFS_read(fp, &visibility, 1, 8) != 8) { debug(LOG_ERROR, "Failed to read structure visibility from %s", path); goto failure; } if (map->structVersion >= 15 && PHYSFS_read(fp, researchName, nameLength, 1) != 1) { // If version < 20, then this causes no padding, but the short below // will still cause two bytes padding; however, if version >= 20, we // will cause 4 bytes padding, but the short below will eat 2 of them, // leaving us again with only two bytes padding before the next word. debug(LOG_ERROR, "Failed to read structure v15 part from %s", path); goto failure; } if (map->structVersion >= 17 && !readS16(&dummyS16)) { debug(LOG_ERROR, "Failed to read structure v17 part from %s", path); goto failure; } if (map->structVersion >= 15 && !readS16(&dummyS16)) // structure padding { debug(LOG_ERROR, "Failed to read 16 bits of structure padding from %s", path); goto failure; } if (map->structVersion >= 21 && !readU32(&dummy)) { debug(LOG_ERROR, "Failed to read structure v21 part from %s", path); goto failure; } psObj->type = IMD_STRUCTURE; // Sanity check data if (psObj->player > MAX_PLAYERS) { debug(LOG_ERROR, "Bad structure owner %u for structure %d id=%u", psObj->player, i, psObj->id); goto failure; } if (psObj->x >= map->width * TILE_WIDTH || psObj->y >= map->height * TILE_HEIGHT) { debug(LOG_ERROR, "Bad structure %d coordinate %u(%u, %u)", i, psObj->id, psObj->x, psObj->y); goto failure; } } PHYSFS_close(fp); } /* === Load droid data === */ map->mLndObjects[IMD_DROID] = NULL; map->numDroids = 0; littleEndian = true; strcpy(path, filename); strcat(path, "/dinit.bjo"); map->mLndObjects[IMD_DROID] = NULL; fp = PHYSFS_openRead(path); if (fp) { if (PHYSFS_read(fp, aFileType, 4, 1) != 1 || aFileType[0] != 'd' || aFileType[1] != 'i' || aFileType[2] != 'n' || aFileType[3] != 't' || !readU32(&map->droidVersion) || !readU32(&map->numDroids)) { debug(LOG_ERROR, "Bad droid header in %s", path); goto failure; } map->mLndObjects[IMD_DROID] = (LND_OBJECT *)malloc(sizeof(*map->mLndObjects[IMD_DROID]) * map->numDroids); for (i = 0; i < map->numDroids; i++) { LND_OBJECT *psObj = &map->mLndObjects[IMD_DROID][i]; int nameLength = 60; uint32_t dummy; if (map->droidVersion <= 19) { nameLength = 40; } if (PHYSFS_read(fp, psObj->name, nameLength, 1) != 1 || !readU32(&psObj->id) || !readU32(&psObj->x) || !readU32(&psObj->y) || !readU32(&psObj->z) || !readU32(&psObj->direction) || !readU32(&psObj->player) || !readU32(&dummy) // BOOL inFire || !readU32(&dummy) // burnStart || !readU32(&dummy)) // burnDamage { debug(LOG_ERROR, "Failed to read droid from %s", path); goto failure; } psObj->type = IMD_DROID; // Sanity check data if (psObj->x >= map->width * TILE_WIDTH || psObj->y >= map->height * TILE_HEIGHT) { debug(LOG_ERROR, "Bad droid coordinate %u(%u, %u)", psObj->id, psObj->x, psObj->y); goto failure; } } PHYSFS_close(fp); } // Count players by looking for the obligatory construction droids map->numPlayers = 0; memset(counted, 0, sizeof(counted)); for(i = 0; i < map->numDroids; i++) { LND_OBJECT *psObj = &map->mLndObjects[IMD_DROID][i]; if (counted[psObj->player] == false && (strcmp(psObj->name, "ConstructorDroid") == 0 || strcmp(psObj->name, "ConstructionDroid") == 0)) { counted[psObj->player] = true; map->numPlayers++; } } return map; failure: mapFree(map); if (fp) { PHYSFS_close(fp); } return NULL; }
int main(int argc, char **argv) { char *filename, *p_filename; char *base, tmpFile[PATH_MAX]; GAMEMAP *map; MAPTILE *psTile; if (argc != 2) { printf("Usage: %s <map>\n", argv[0]); return -1; } physfs_init(argv[0]); filename = physfs_addmappath(argv[1]); p_filename = strrchr(filename, '/'); if (p_filename) { p_filename++; base = strdup(p_filename); } else { base = strdup(filename); } map = mapLoad(filename); free(filename); if (!map) { return EXIT_FAILURE; } const PreviewColors* tileColors = NULL; switch (map->tileset) { case TILESET_ARIZONA: tileColors = &pArizonaColors; break; case TILESET_URBAN: tileColors = &pUrbanColors; break; case TILESET_ROCKIES: tileColors = &pRockiesColors; break; default: fprintf(stderr, "Unknown tileset: %d\n", (int)map->tileset); mapFree(map); physfs_shutdown(); return EXIT_FAILURE; } const int mapWidth = (int) map->width; const int mapHeight = (int) map->height; int col; // RGB888 pixels uint8_t *pixels = (uint8_t*) malloc(sizeof(uint8_t) * mapWidth * mapHeight * 3); for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { // We're placing the origin at the top for aesthetic reasons psTile = mapTile(map, x, mapHeight-1-y); col = psTile->height / 2; // 2 = ELEVATION_SCALE uint8_t * const p = &pixels[(y * map->width + x) * 3]; switch(terrainType(psTile)) { case TER_CLIFFFACE: p[0] = tileColors->cliffLow.x + (tileColors->cliffHigh.x - tileColors->cliffLow.x) * col / 256; p[1] = tileColors->cliffLow.y + (tileColors->cliffHigh.y - tileColors->cliffLow.y) * col / 256; p[2] = tileColors->cliffLow.z + (tileColors->cliffHigh.z - tileColors->cliffLow.z) * col / 256; break; case TER_WATER: p[0] = tileColors->water.x; p[1] = tileColors->water.y; p[2] = tileColors->water.z; break; case TER_ROAD: p[0] = tileColors->roadLow.x + (tileColors->roadHigh.x - tileColors->roadLow.x) * col / 256; p[1] = tileColors->roadLow.y + (tileColors->roadHigh.y - tileColors->roadLow.y) * col / 256; p[2] = tileColors->roadLow.z + (tileColors->roadHigh.z - tileColors->roadLow.z) * col / 256; break; default: p[0] = tileColors->groundLow.x + (tileColors->groundHigh.x - tileColors->groundLow.x) * col / 256; p[1] = tileColors->groundLow.y + (tileColors->groundHigh.y - tileColors->groundLow.y) * col / 256; p[2] = tileColors->groundLow.z + (tileColors->groundHigh.z - tileColors->groundLow.z) * col / 256; break; } } } paintStructureData(pixels, map); strcpy(tmpFile, base); strcat(tmpFile, ".png"); savePng(tmpFile, pixels, mapWidth, mapHeight); free(pixels); mapFree(map); physfs_shutdown(); return 0; }
int main(int argc, char **argv) { char filename[PATH_MAX]; char path[PATH_MAX], *delim; GAMEMAP *map; FILE *fp; int i, x, y; if (argc != 2) { printf("Usage: %s <map>\n", argv[0]); return -1; } strcpy(path, argv[1]); delim = strrchr(path, '/'); if (delim) { *delim = '\0'; delim++; strcpy(filename, delim); } else { path[0] = '.'; path[1] = '\0'; strcpy(filename, argv[1]); } PHYSFS_init(argv[0]); PHYSFS_addToSearchPath(path, 1); map = mapLoad(filename); if (!map) { fprintf(stderr, "Failed to load map\n"); return -1; } strcat(filename, ".lnd"); fp = fopen(filename, "w"); if (!fp) { fprintf(stderr, "Could not open target: %s", filename); return -1; } #define MADD(...) fprintf(fp, __VA_ARGS__); fprintf(fp, "\n"); MADD("DataSet %s", tilesetDataSet[map->tileset]); MADD("GrdLand {"); MADD(" Version %d", GRDLANDVERSION); MADD(" 3DPosition %f %f %f", 0.0, 0.0, 0.0); // FIXME MADD(" 3DRotation %f %f %f", 0.0, 0.0, 0.0); // FIXME MADD(" 2DPosition %d %d", 0, 0); // FIXME MADD(" CustomSnap %d %d", 0, 0); // FIXME MADD(" SnapMode %d", SNAP_MODE); MADD(" Gravity %d", GRAVITY); MADD(" HeightScale %d", ELEVATION_SCALE); MADD(" MapWidth %d", map->width); MADD(" MapHeight %d", map->height); MADD(" TileWidth %d", TILE_HEIGHT); MADD(" TileHeight %d", TILE_WIDTH); MADD(" SeaLevel %d", SEALEVEL); MADD(" TextureWidth %d", 64); // Hack for editworld MADD(" TextureHeight %d", 64); MADD(" NumTextures %d", 1); MADD(" Textures {"); MADD(" %s", tilesetTextures[map->tileset]); MADD(" }"); MADD(" NumTiles %d", map->width * map->height); MADD(" Tiles {"); for (i = 0, x = 0, y = 0; i < map->width * map->height; i++) { MAPTILE *psTile = mapTile(map, x, y); // Example: TID 1 VF 0 TF 0 F 0 VH 128 128 128 128 // TID is texture identification // VF is triangle (vertex) flip. If value of one, it is flipped. // TF is tile or texture flip. If value of one, it is flipped in the X direction. Otherwise Y direction. // F are bitflags, with these values: // 2 : Triangle flip // 4 : Texture flip X (yes, duplicate info) // 8 : Texture flip Y (ditto) // 16 : Rotate 90 degrees // 32 : Rotate 180 degrees (yes, a 270 degree is possible) // 64 : Gateway? // 128: TF_TEXTURESPARE0, whatever that was, unused even in Editworld // VH is vertex height, and gives height of all the four vertices that make up our tile int tid = psTile->texture & TILE_NUMMASK; int vf = TRI_FLIPPED(psTile); int tf = (psTile->texture & TILE_XFLIP) > 0 ? 1 : 0; int f = 0; int vh[4]; // Compose flag if (TRI_FLIPPED(psTile)) f += 2; if (psTile->texture & TILE_XFLIP) f += 4; if (psTile->texture & TILE_YFLIP) f += 8; switch ((psTile->texture & TILE_ROTMASK) >> TILE_ROTSHIFT) { case 0: break; case 1: f += 16; break; case 2: f += 32; break; case 3: f += 48; break; default: fprintf(stderr, "Bad rotation value: %d\n", (psTile->texture & TILE_ROTMASK) >> TILE_ROTSHIFT); return -1; } // Vertex positions set in clockwise order vh[0] = psTile->height; vh[1] = vh[2] = vh[3] = 0; if (x + 1 < map->width) { vh[1] = mapTile(map, x + 1, y)->height; } if (x + 1 < map->width && y + 1 < map->height) { vh[2] = mapTile(map, x + 1, y + 1)->height; } if (y + 1 < map->height) { vh[3] = mapTile(map, x, y + 1)->height; } // No idea why +1 to TID. In EditWorld source, it is a "hide" flag. MADD(" TID %d VF %d TF %d F %d VH %d %d %d %d", tid + 1, vf, tf, f, vh[0], vh[1], vh[2], vh[3]); x++; if (x == map->width) { x = 0; y++; } } MADD(" }"); MADD("}"); MADD("ObjectList {"); MADD(" Version 3"); MADD(" FeatureSet %s", tilesetDataSet[map->tileset]); MADD(" NumObjects %u", map->numFeatures + map->numStructures + map->numDroids); MADD(" Objects {"); for (x = IMD_FEATURE; x < IMD_OBJECT; x++) { int max = 0; switch (x) { case IMD_FEATURE: max = map->numFeatures; break; case IMD_STRUCTURE: max = map->numStructures; break; case IMD_DROID: max = map->numDroids; break; default: break; } for (i = 0; i < max; i++) { LND_OBJECT *psObj = &map->mLndObjects[x][i]; double x = (double)psObj->x - (double)map->width * TILE_WIDTH / 2.0; double y = ((double)psObj->y - (double)map->height * TILE_HEIGHT / 2.0) * -1.0; MADD(" %u %d \"%s\" %u \"NONAME\" %.02f %.02f %.02f 0.00 %.02f 0.00", psObj->id, psObj->type, psObj->name, psObj->player, x, (double)psObj->z, y, (double)psObj->direction); // %d UniqueID, %d TypeID, \"%s\" StructureName or description or \"NONAME\", %d PlayerID, \"%s\" ScriptName or \"NONAME\" MAY BE MISSING in v<3! // fprintf(Stream, "%.2f %.2f %.2f ", Position.x, Position.y, Position.z); // fprintf(Stream, "%.2f %.2f %.2f\n", curNode->Rotation.x, curNode->Rotation.y, curNode->Rotation.z); } } MADD(" }"); MADD("}"); MADD("ScrollLimits {"); MADD(" Version 1"); MADD(" NumLimits 1"); // FIXME: do scroll limits go here? MADD(" Limits {"); MADD(" \"Entire Map\" 0 0 0 %d %d", map->width, map->height); MADD(" }"); MADD("}"); MADD("Gateways {"); MADD(" Version 1"); MADD(" NumGateways %d", (int)map->numGateways); MADD(" Gates {"); for (i = 0; i < map->numGateways; i++) { GATEWAY *psGate = mapGateway(map, i); MADD(" %u %u %u %u", (unsigned)psGate->x1, (unsigned)psGate->y1, (unsigned)psGate->x2, (unsigned)psGate->y2); } MADD(" }"); MADD("}"); MADD("TileTypes {"); MADD(" NumTiles 128"); // ??? FIXME - read from ttypes file MADD(" Tiles {"); // The first value of 2 is not written into the Deliverance (Warzone binary) format for some reason. switch (map->tileset) { case TILESET_ARIZONA: MADD(" 2 1 0 2 2 0 2 2 2 2 1 1 1 0 7 7\n" " 7 7 7 8 6 4 4 6 3 3 3 2 4 1 4 7\n" " 7 7 7 4 4 2 2 2 2 1 4 0 4 4 8 8\n" " 2 4 4 4 4 4 4 4 9 9 6 9 6 4 4 9\n" " 9 9 9 9 9 9 9 9 8 4 4 4 8 5 6 2\n" " 2 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0\n" " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"); break; case TILESET_URBAN: MADD(" 2 2 2 2 2 1 2 2 1 1 1 1 1 1 7 7\n" " 7 7 7 1 8 4 4 0 7 7 7 7 4 4 2 4\n" " 0 2 0 0 2 4 4 0 4 6 2 6 6 6 6 6\n" " 6 4 6 3 4 4 2 2 9 9 9 2 4 2 4 9\n" " 9 9 9 9 8 8 8 8 4 2 0 4 4 2 2 2\n" " 3 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0\n" " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"); break; case TILESET_ROCKIES: MADD(" 2 0 0 2 2 2 2 2 2 1 8 11 2 11 6 7\n" " 7 7 7 8 6 1 2 6 11 11 0 11 1 1 8 8\n" " 7 7 7 0 0 1 8 0 4 5 11 8 5 8 8 8\n" " 11 11 1 1 1 1 1 8 9 9 5 2 6 6 8 9\n" " 8 10 10 11 11 8 8 10 8 2 10 0 10 8 8 8\n" " 3 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0\n" " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"); break; } MADD(" }"); MADD("}"); MADD("TileFlags {"); // ?? MADD(" NumTiles 128"); MADD(" Flags {"); MADD(" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"); MADD(" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"); MADD(" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"); MADD(" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"); MADD(" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"); MADD(" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"); MADD(" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"); MADD(" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"); MADD(" }"); MADD("}"); MADD("Brushes {"); MADD(" Version 2"); MADD(" NumEdgeBrushes 16"); MADD(" NumUserBrushes 0"); MADD(" EdgeBrushes {"); switch (map->tileset) { case TILESET_ARIZONA: MADD(" 0 128 0 -1 0 29 0 29 16 28 16 29 48 28 0 -1 0 30 0 29 32 -1 0 28 32 30 16 28 48 30 48 30 32 54 0"); MADD(" 0 128 0 -1 0 30 32 30 48 28 48 30 16 28 32 -1 0 29 32 30 0 -1 0 28 0 29 48 28 16 29 16 29 0 10 0"); MADD(" 0 128 0 -1 0 42 0 42 16 44 16 42 48 44 0 -1 0 43 0 42 32 -1 0 44 32 43 16 44 48 43 48 43 32 13 128"); MADD(" 0 128 0 -1 0 43 32 43 48 44 48 43 16 44 32 -1 0 42 32 43 0 -1 0 44 0 42 48 44 16 42 16 42 0 77 0"); MADD(" 0 128 0 -1 0 76 32 46 32 72 8 46 0 47 16 -1 0 76 0 76 0 -1 0 47 48 46 0 72 0 46 32 76 32 75 0"); MADD(" 0 128 0 -1 0 5 32 5 48 3 16 5 16 3 0 -1 0 4 32 5 0 -1 0 3 32 4 48 3 48 4 16 4 0 7 0"); MADD(" 0 128 0 -1 0 4 0 4 16 3 48 4 48 3 32 -1 0 5 0 4 32 -1 0 3 0 5 16 3 16 5 48 5 32 13 0"); MADD(" 0 128 0 -1 0 26 0 26 16 25 16 26 48 25 0 -1 0 27 0 26 32 -1 0 25 32 27 16 25 48 27 48 27 32 7 0"); MADD(" 0 128 0 -1 0 27 32 27 48 25 48 27 16 25 32 -1 0 26 32 27 0 -1 0 25 0 26 48 25 16 26 16 26 0 24 0"); MADD(" 0 128 0 -1 0 21 32 21 48 22 48 21 16 22 32 -1 0 20 32 21 0 -1 0 22 0 20 48 22 16 20 16 20 0 23 0"); MADD(" 0 128 0 -1 0 20 0 20 16 22 16 20 48 22 0 -1 0 21 0 20 32 -1 0 22 32 21 16 22 48 21 48 21 32 45 0"); MADD(" 0 128 0 -1 0 16 16 16 32 15 32 16 0 15 16 -1 0 17 16 16 48 -1 0 15 48 17 32 15 0 17 0 17 48 18 0"); MADD(" 0 128 0 -1 0 17 48 17 0 15 0 17 32 15 48 -1 0 16 48 17 16 -1 0 15 16 16 0 15 32 16 32 16 16 13 0"); MADD(" 0 128 0 -1 0 33 0 33 16 32 0 33 48 32 48 -1 0 34 0 33 32 -1 0 32 16 34 16 32 32 34 48 34 32 18 0"); MADD(" 0 128 0 -1 0 34 32 34 48 32 32 34 16 32 16 -1 0 33 32 34 0 -1 0 32 48 33 48 32 0 33 16 33 0 24 0"); MADD(" 0 128 0 -1 0 78 0 78 0 78 0 78 0 78 0 -1 0 78 0 78 0 -1 0 78 0 78 0 78 0 78 0 78 0 78 0"); break; case TILESET_URBAN: MADD(" 0 128 0 -1 0 73 0 73 16 61 48 73 48 61 32 -1 0 74 0 73 32 -1 0 61 0 74 16 61 16 74 48 74 32 39 128"); MADD(" 0 128 0 -1 0 74 32 74 48 61 16 74 16 61 0 -1 0 73 32 74 0 -1 0 61 32 73 48 61 48 73 16 73 0 79 0"); MADD(" 0 128 0 -1 0 5 0 5 16 7 48 5 48 7 32 -1 0 4 0 5 32 -1 0 7 0 4 16 7 16 4 48 4 32 1 128"); MADD(" 0 128 64 -1 0 4 32 4 48 7 16 4 16 7 0 -1 0 5 32 4 0 -1 0 7 32 5 48 7 48 5 16 5 0 79 0"); MADD(" 0 128 0 -1 0 27 0 27 16 24 16 27 48 24 0 -1 0 26 0 27 32 -1 0 24 32 26 16 24 48 26 48 26 32 18 0"); MADD(" 2 147 64 -1 0 26 32 26 48 24 48 26 16 24 32 -1 0 27 32 26 0 -1 0 24 0 27 48 24 16 27 16 27 0 8 0"); MADD(" 0 128 0 -1 0 16 16 16 32 14 16 16 0 14 0 -1 0 17 16 16 48 -1 0 14 32 17 32 14 48 17 0 17 48 18 0"); MADD(" 0 128 0 -1 0 69 16 69 32 70 32 69 0 70 48 -1 0 69 48 69 48 -1 0 70 16 69 0 70 0 69 32 69 16 79 0"); MADD(" 0 128 0 -1 0 77 0 77 16 72 16 77 48 72 0 -1 0 76 0 77 32 -1 0 72 32 76 16 72 48 76 48 76 32 52 0"); MADD(" 0 128 0 -1 0 76 32 76 48 72 48 76 16 72 32 -1 0 77 32 76 0 -1 0 72 0 77 48 72 16 77 16 77 0 23 0"); MADD(" 0 128 0 -1 0 35 0 35 16 34 16 35 48 34 0 -1 0 36 0 35 32 -1 0 34 32 36 16 34 48 36 48 36 32 1 0"); MADD(" 0 128 64 -1 0 36 32 36 48 34 48 36 16 34 32 -1 0 35 32 36 0 -1 0 34 0 35 48 34 16 35 16 35 0 23 0"); MADD(" 0 128 0 -1 0 38 0 38 16 40 48 38 48 40 32 -1 0 39 0 38 32 -1 0 40 0 39 16 40 16 39 48 39 32 23 0"); MADD(" 0 128 0 -1 0 39 32 39 48 40 16 39 16 40 0 -1 0 38 32 39 0 -1 0 40 32 38 48 40 48 38 16 38 0 51 0"); MADD(" 0 255 64 -1 0 12 48 12 0 13 48 12 32 13 32 -1 0 19 0 12 16 -1 0 13 0 19 0 13 16 19 0 19 0 19 0"); MADD(" 0 128 0 -1 0 19 0 19 0 13 16 19 0 13 0 -1 0 12 16 19 0 -1 0 13 32 12 32 13 48 12 0 12 48 52 0"); break; case TILESET_ROCKIES: MADD(" 0 128 0 -1 0 46 16 46 32 30 32 46 0 30 16 47 0 64 0 46 48 47 0 30 48 64 16 30 0 64 48 64 32 65 16"); MADD(" 0 128 0 -1 0 43 16 43 32 30 32 43 0 30 16 47 0 10 0 43 48 47 0 30 48 10 16 30 0 10 48 10 32 42 0"); MADD(" 0 128 0 -1 0 10 32 10 48 45 32 10 16 45 16 47 0 64 0 10 0 47 0 45 48 64 16 45 0 64 48 64 32 65 128"); MADD(" 0 128 0 -1 0 34 0 34 16 32 0 34 48 32 48 -1 0 33 0 34 32 -1 0 32 16 33 16 32 32 33 48 33 32 18 0"); MADD(" 0 128 0 -1 0 4 32 4 48 3 48 4 16 3 32 -1 0 5 32 4 0 -1 0 3 0 5 48 3 16 5 16 5 0 6 0"); MADD(" 0 128 0 -1 0 46 16 46 32 47 0 46 0 47 16 -1 0 19 0 46 48 -1 0 47 48 19 16 47 32 19 48 19 32 6 128"); MADD(" 0 128 0 -1 0 5 0 5 16 3 16 5 48 3 0 -1 0 4 0 5 32 -1 0 3 32 4 16 3 48 4 48 4 32 1 128"); MADD(" 0 128 0 -1 0 11 0 11 16 13 0 11 48 13 48 6 128 12 0 11 32 6 128 13 16 12 16 13 32 12 48 12 32 6 128"); MADD(" 0 128 0 -1 0 41 32 41 48 39 48 41 16 39 32 -1 0 40 32 41 0 -1 0 39 0 40 48 39 16 40 16 40 0 54 128"); MADD(" 0 128 0 -1 0 36 0 36 16 35 16 36 48 35 0 -1 0 37 0 36 32 -1 0 35 32 37 16 35 48 37 48 37 32 54 0"); MADD(" 0 128 0 -1 0 66 0 66 16 68 0 66 48 68 48 -1 0 67 0 66 32 -1 0 68 16 67 16 68 32 67 48 67 32 42 128"); MADD(" 0 128 0 -1 0 78 32 78 48 77 32 78 16 77 16 -1 0 55 32 78 0 -1 0 77 48 55 48 77 0 55 16 55 0 65 128"); MADD(" 0 128 0 -1 0 21 32 21 48 22 48 21 16 22 32 -1 0 20 32 21 0 -1 0 22 0 20 48 22 16 20 16 20 0 23 128"); MADD(" 0 128 0 -1 0 67 32 67 48 68 32 67 16 68 16 -1 0 66 32 67 0 -1 0 68 48 66 48 68 0 66 16 66 0 65 128"); MADD(" 0 128 0 -1 0 12 32 12 48 49 32 12 16 49 16 -1 0 11 32 12 0 -1 0 49 48 11 48 49 0 11 16 11 0 42 0"); MADD(" 0 128 0 -1 0 16 16 16 32 15 32 16 0 15 16 15 16 17 16 16 48 15 16 15 48 17 32 15 0 17 0 17 48 18 0"); break; } MADD(" }"); MADD("}"); fclose(fp); mapFree(map); return 0; }