/** * @brief test the maps that have problems with certain seeds * this can also be used to produce new seedlists */ TEST_F(RandomMapAssemblyTest, NewSeedlists) { long time, timeSum = 0; char entityString[MAX_TOKEN_CHARS]; sv_rmadisplaythemap->integer = 1; /* print out the RMA analysis */ sv_threads->integer = 0; for (int i = 0; i < RMA_HIGHEST_SUPPORTED_SEED; i++) { srand(i); time = Sys_Milliseconds(); Com_Printf("Seed: %i\n", i); Cvar_Set("rm_drop", Com_GetRandomMapAssemblyNameForCraft("craft_drop_herakles")); Cvar_Set("rm_ufo", Com_GetRandomMapAssemblyNameForCraft("craft_ufo_fighter")); const char* mapTheme = "industrial"; const char* asmName = "medium"; #if 0 mapTheme = "tropic"; asmName = "river"; mapTheme = "village"; asmName = "large"; mapTheme = "desert"; asmName = "large"; #endif int numPlaced = SV_AssembleMap(mapTheme, asmName, mapStr, posStr, entityString, i, false); ASSERT_TRUE(numPlaced != 0); time = Sys_Milliseconds() - time; timeSum += time; ASSERT_TRUE(time < MAX_ALLOWED_TIME_TO_ASSEMBLE) << mapTheme << " fails to assemble in a reasonable time with seed " << i << "(time: " << time << " ms)"; if (time > 10000) Com_Printf("Seed %i: tiles: %i ms: %li\n", i, numPlaced, time); } Com_Printf("TotalTime: %li\n", timeSum); }
/* test the maps that have seedlists */ TEST_F(RandomMapAssemblyTest, Seedlists) { const char* assNames[][2] = { {"farm", "medium"}, {"farm", "large"}, {"forest", "large"}, {"forest", "large_crash"}, {"oriental", "large"}, {"village", "commercial"}, {"village", "small"} }; size_t length = sizeof(assNames) / (2 * sizeof(char*)); char entityString[MAX_TOKEN_CHARS]; sv_threads->integer = 0; long timeSum = 0; for (int n = 0; n < length; n++) { for (int i = 1; i < 20; i++) { srand(i); int time = Sys_Milliseconds(); Com_Printf("Seed: %i\n", i); int numPlaced = SV_AssembleMap(assNames[n][0], assNames[n][1], mapStr, posStr, entityString, i, true); ASSERT_TRUE(numPlaced != 0); time = Sys_Milliseconds() - time; timeSum += time; ASSERT_TRUE(time < MAX_ALLOWED_TIME_TO_ASSEMBLE) << assNames[n][0] << " fails to assemble in a reasonable time with seed " << i << "(time: " << time << " ms)"; if (time > 10000) Com_Printf("Seed %i: tiles: %i ms: %li\n", i, numPlaced, time); } } Com_Printf("TotalTime: %li\n", timeSum); }
TEST_F(RandomMapAssemblyTest, UMPExtends) { char entityString[MAX_TOKEN_CHARS]; srand(0); int numPlaced = SV_AssembleMap("test_extends", "default", mapStr, posStr, entityString, 0, true); ASSERT_TRUE(numPlaced != 0); }
TEST_F(RandomMapAssemblyTest, Assembly) { char entityString[MAX_TOKEN_CHARS]; srand(0); int numPlaced = SV_AssembleMap(TEST_THEME, TEST_ASSEMBLY, mapStr, posStr, entityString, 0, true); ASSERT_TRUE(numPlaced != 0); }
TEST_F(RandomMapAssemblyTest, Assembly) { char entityString[MAX_TOKEN_CHARS]; srand(0); int numPlaced = SV_AssembleMap("forest", "large", mapStr, posStr, entityString, 0, true); ASSERT_TRUE(numPlaced != 0); }
static void testAssembly (void) { mapInfo_t *randomMap; srand(0); randomMap = SV_AssembleMap("forest", "large", mapStr, posStr, 0); CU_ASSERT(randomMap != NULL); Mem_Free(randomMap); }
static void testUMPExtends (void) { mapInfo_t *randomMap; srand(0); randomMap = SV_AssembleMap("test_extends", "default", mapStr, posStr, 0); CU_ASSERT(randomMap != NULL); Mem_Free(randomMap); }
static void testAssembly (void) { MapInfo *randomMap; char entityString[MAX_TOKEN_CHARS]; srand(0); randomMap = SV_AssembleMap("forest", "large", mapStr, posStr, entityString, 0); CU_ASSERT(randomMap != NULL); Mem_Free(randomMap); }
static void testUMPExtends (void) { MapInfo *randomMap; char entityString[MAX_TOKEN_CHARS]; srand(0); randomMap = SV_AssembleMap("test_extends", "default", mapStr, posStr, entityString, 0); CU_ASSERT(randomMap != NULL); Mem_Free(randomMap); }
/* sequential version */ TEST_F(RandomMapAssemblyTest, MassAssemblySequential) { char entityString[MAX_TOKEN_CHARS]; sv_threads->integer = 0; for (int i = 0; i < 10; i++) { srand(i); long time = Sys_Milliseconds(); const char* mapTheme = "forest"; int numPlaced = SV_AssembleMap(mapTheme, "large", mapStr, posStr, entityString, i, true); ASSERT_TRUE(numPlaced != 0); time = Sys_Milliseconds() - time; ASSERT_TRUE(time < MAX_ALLOWED_TIME_TO_ASSEMBLE) << mapTheme << " fails to assemble in a reasonable time with seed " << i << "(time: " << time << " ms)"; Com_Printf("%i: %i %li\n", i, numPlaced, time); } }
/* sequential version */ static void testMassAssemblySequential (void) { int i; long time; mapInfo_t *randomMap; sv_threads->integer = 0; for (i = 0; i < 10; i++) { srand(i); time = Sys_Milliseconds(); randomMap = SV_AssembleMap("forest", "large", mapStr, posStr, i); CU_ASSERT_PTR_NOT_NULL(randomMap); time = Sys_Milliseconds() - time; UFO_CU_ASSERT_TRUE_MSG(time < MAX_ALLOWED_TIME_TO_ASSEMBLE, va("%s fails to assemble in a reasonable time with seed %i (time: %li ms)", randomMap->name, i, time)); Com_Printf("%i: %i %li\n", i, randomMap->numPlaced, time); Mem_Free(randomMap); } }
static void testMassAssemblyParallel (void) { int i; long time; mapInfo_t *randomMap; sv_threads->integer = 2; for (i = 0; i < 10; i++) { /** @todo the assemble thread sets a different seed */ srand(i); time = Sys_Milliseconds(); randomMap = SV_AssembleMap("forest", "large", mapStr, posStr, i); CU_ASSERT(randomMap != NULL); time = Sys_Milliseconds() - time; UFO_CU_ASSERT_TRUE_MSG(time < MAX_ALLOWED_TIME_TO_ASSEMBLE, va("%s fails to assemble in a reasonable time with seed %i (time: %li ms)", randomMap->name, i, time)); Com_Printf("%i: %i %li\n", i, randomMap->numPlaced, time); fflush(stdout); Mem_Free(randomMap); } }
/* test the maps that have seedlists */ static void testSeedlists (void) { int i, n; long time, timeSum = 0; MapInfo *randomMap; size_t length; const char* assNames[][2] = { {"farm", "medium"}, {"farm", "large"}, {"forest", "large"}, {"forest", "large_crash"}, {"oriental", "large"}, {"village", "commercial"}, {"village", "small"} }; length = sizeof(assNames) / (2 * sizeof(char *)); char entityString[MAX_TOKEN_CHARS]; sv_threads->integer = 0; for (n = 0; n < length; n++) { for (i = 1; i < 20; i++) { srand(i); time = Sys_Milliseconds(); Com_Printf("Seed: %i\n", i); randomMap = SV_AssembleMap(assNames[n][0], assNames[n][1], mapStr, posStr, entityString, i); CU_ASSERT(randomMap != NULL); time = Sys_Milliseconds() - time; timeSum += time; UFO_CU_ASSERT_TRUE_MSG(time < MAX_ALLOWED_TIME_TO_ASSEMBLE, va("%s fails to assemble in a reasonable time with seed %i (time: %li ms)", randomMap->name, i, time)); if (time > 10000) Com_Printf("Seed %i: tiles: %i ms: %li\n", i, randomMap->numPlaced, time); Mem_Free(randomMap); } } Com_Printf("TotalTime: %li\n", timeSum); }
/** * @brief Change the server to a new map, taking all connected clients along with it. * @note the full syntax is: @code map [day|night] [+]<map> [<assembly>] @endcode * @sa SV_AssembleMap * @sa CM_LoadMap * @sa Com_SetServerState */ void SV_Map (qboolean day, const char *levelstring, const char *assembly) { int i; unsigned checksum = 0; char * map = SV_GetConfigString(CS_TILES); char * pos = SV_GetConfigString(CS_POSITIONS); mapInfo_t *randomMap = NULL; client_t *cl; /* any partially connected client will be restarted */ Com_SetServerState(ss_restart); /* the game is just starting */ SV_InitGame(); if (!svs.initialized) { Com_Printf("Could not spawn the server\n"); return; } assert(levelstring[0] != '\0'); Com_DPrintf(DEBUG_SERVER, "SpawnServer: %s\n", levelstring); /* save name for levels that don't set message */ SV_SetConfigString(CS_NAME, levelstring); SV_SetConfigString(CS_LIGHTMAP, day); Q_strncpyz(sv->name, levelstring, sizeof(sv->name)); /* set serverinfo variable */ sv_mapname = Cvar_FullSet("sv_mapname", sv->name, CVAR_SERVERINFO | CVAR_NOSET); /* notify the client in case of a listening server */ SCR_BeginLoadingPlaque(); if (assembly) Q_strncpyz(sv->assembly, assembly, sizeof(sv->assembly)); else sv->assembly[0] = '\0'; /* leave slots at start for clients only */ cl = NULL; while ((cl = SV_GetNextClient(cl)) != NULL) { /* needs to reconnect */ if (cl->state >= cs_spawning) SV_SetClientState(cl, cs_connected); } /* assemble and load the map */ if (levelstring[0] == '+') { randomMap = SV_AssembleMap(levelstring + 1, assembly, map, pos, 0); if (!randomMap) { Com_Printf("Could not load assembly for map '%s'\n", levelstring); return; } } else { SV_SetConfigString(CS_TILES, levelstring); SV_SetConfigString(CS_POSITIONS, assembly ? assembly : ""); } CM_LoadMap(map, day, pos, &sv->mapData, &sv->mapTiles); Com_Printf("checksum for the map '%s': %u\n", levelstring, sv->mapData.mapChecksum); SV_SetConfigString(CS_MAPCHECKSUM, sv->mapData.mapChecksum); checksum = Com_GetScriptChecksum(); Com_Printf("ufo script checksum %u\n", checksum); SV_SetConfigString(CS_UFOCHECKSUM, checksum); SV_SetConfigString(CS_OBJECTAMOUNT, csi.numODs); SV_SetConfigString(CS_VERSION, UFO_VERSION); SV_SetConfigString(CS_MAPTITLE, SV_GetMapTitle(randomMap, levelstring)); if (Q_strstart(SV_GetConfigString(CS_MAPTITLE), "b/")) { /* For base attack, CS_MAPTITLE contains too many chars */ SV_SetConfigString(CS_MAPTITLE, "Base attack"); SV_SetConfigString(CS_NAME, ".baseattack"); } /* clear random-map assembly data */ Mem_Free(randomMap); randomMap = NULL; /* clear physics interaction links */ SV_ClearWorld(); /* fix this! */ for (i = 1; i <= sv->mapData.numInline; i++) sv->models[i] = CM_InlineModel(&sv->mapTiles, va("*%i", i)); /* precache and static commands can be issued during map initialization */ Com_SetServerState(ss_loading); TH_MutexLock(svs.serverMutex); /* load and spawn all other entities */ svs.ge->SpawnEntities(sv->name, SV_GetConfigStringInteger(CS_LIGHTMAP), sv->mapData.mapEntityString); TH_MutexUnlock(svs.serverMutex); /* all precaches are complete */ Com_SetServerState(ss_game); Com_Printf("-------------------------------------\n"); Cbuf_CopyToDefer(); }
/** * @brief This test cycles through the list of map definitions found in the maps.ufo script * and builds each map with each ufo and every assembly for all valid seeds. * In other words: this a FULL test to check if some seed causes problems in any of the * possible combinations, so it should not be run on the buildserver on a daily basis. */ TEST_F(MapDefMassRMATest, DISABLED_MapDefsMassRMA) { /** You can test a certain assembly by passing "-Dmapdef-id=assembly" to testall. */ const char* filterId = TEST_GetStringProperty("mapdef-id"); const mapDef_t* md; int mapCount = 0; ASSERT_TRUE(csi.numMDs > 0); MapDef_Foreach(md) { if (md->mapTheme[0] == '.') continue; if (filterId && !Q_streq(filterId, md->id)) continue; if (++mapCount <= 0) /* change 0 to n to skip the first n assemblies */ continue; { char* p = md->mapTheme; if (*p == '+') p++; else continue; const char* asmName = (const char*)LIST_GetByIdx(md->params, 0); Com_Printf("\nMap: %s Assembly: %s AssNr: %i\n", p, asmName, mapCount); sv_threads->integer = 0; /* This is tricky. Some maps don't have any ufo on them and thus in the mapdef. * That would cause a LIST_Foreach macro to never run it's body. That's why these * for-loops seem to have two termination conditions. In fact, we have to manually * exit the for-loops if we ran it just once (without ufos nor dropships). */ bool didItOnce = false; linkedList_t* iterDrop; for (iterDrop = md->aircraft; iterDrop || !didItOnce; iterDrop = iterDrop->next) { const char* craft = nullptr; if (iterDrop) craft = (const char*) (iterDrop->data); if (craft) Cvar_Set("rm_drop", "%s", Com_GetRandomMapAssemblyNameForCraft(craft)); else Cvar_Set("rm_drop", "+craft_drop_firebird"); linkedList_t* iterUfo; for (iterUfo = md->ufos; iterUfo || !didItOnce; iterUfo = iterUfo->next) { const char* ufo = nullptr; if (iterUfo) ufo = (const char*) (iterUfo->data); if (ufo) Cvar_Set("rm_ufo", "%s", Com_GetRandomMapAssemblyNameForCraft(ufo)); else Cvar_Set("rm_ufo", "+craft_ufo_scout"); Com_Printf("\nDrop: %s Ufo: %s", craft, ufo); Com_Printf("\nSeed:"); for (int i = 0; i < RMA_HIGHEST_SUPPORTED_SEED; i++) { asmName = nullptr; srand(i); long time = Sys_Milliseconds(); Com_Printf(" %i", i); #if 0 typedef struct skip_info { int seed; char const* map; char const* params; char const* craft; char const* ufo; } skip_info; /* if we have known problems with some combinations, we can skip them */ skip_info const skip_list[] = { /* examples: */ // { 20, "forest", "large", "craft_drop_raptor", 0 }, // { 12, "forest", "large" "craft_drop_herakles", "craft_ufo_harvester" }, { -1, "frozen", "nature_medium",0, 0 }, { 11, "village", "medium", 0, 0 }, { 19, "village", "medium", 0, 0 }, { -1, "village", "medium_noufo", 0, 0 }, { -1, "village", "small", 0, 0 }, }; bool skip = false; for (skip_info const* e = skip_list; e != endof(skip_list); ++e) { if (e->seed >= 0 && i != e->seed) continue; if (e->map && !Q_streq(p, e->map)) continue; if (e->params && !Q_streq(md->params, e->params)) continue; if (e->craft && !Q_streq(craft, e->craft)) continue; if (e->ufo && !Q_streq(ufo, e->ufo)) continue; skip = true; break; } if (skip) continue; #endif /* for ufocrash map, the ufoname is the assemblyame */ if (Q_streq(p, "ufocrash")) asmName = Com_GetRandomMapAssemblyNameForCraft(ufo) + 1; /* +1 = get rid of the '+' */ else asmName = (const char*)LIST_GetByIdx(md->params, 0); char* entityString = SV_GetConfigString(CS_ENTITYSTRING); const int numPlaced = SV_AssembleMap(p, asmName, mapStr, posStr, entityString, i, false); ASSERT_TRUE(numPlaced != 0); time = (Sys_Milliseconds() - time); ASSERT_TRUE(time < 30000); if (time > 10000) Com_Printf("\nMap: %s Assembly: %s Seed: %i tiles: %i ms: %li\n", p, asmName, i, numPlaced, time); } didItOnce = true; if (!iterUfo) break; } if (!iterDrop) break; } } } }