00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00034 #include <stdlib.h>
00035 #include <check.h>
00036 #include <global.h>
00037
00038 void setup(void) {
00039
00040 }
00041
00042 void teardown(void) {
00043
00044 }
00045
00046 #if 0
00047 static mapstruct *get_random_map(mapstruct *map) {
00048 object *exit_ob;
00049 mapstruct *random;
00050 RMParms rp;
00051 char newmap_name[HUGE_BUF], *cp;
00052 static int reference_number = 0;
00053 int x, y;
00054
00055 exit_ob = NULL;
00056 for (x = 0; x < MAP_WIDTH(map) && exit_ob == NULL; x++) {
00057 for (y = 0; y < MAP_HEIGHT(map) && exit_ob == NULL; y++) {
00058 for (exit_ob = GET_MAP_OB(map, x, y); exit_ob != NULL; exit_ob = exit_ob->above)
00059 if (exit_ob->type == EXIT && exit_ob->msg != NULL)
00060 break;
00061 }
00062 }
00063
00064 if (!exit_ob)
00065
00066 return NULL;
00067
00068
00069 memset(&rp, 0, sizeof(RMParms));
00070 rp.Xsize = -1;
00071 rp.Ysize = -1;
00072 rp.region = get_region_by_map(exit_ob->map);
00073 if (exit_ob->msg)
00074 set_random_map_variable(&rp, exit_ob->msg);
00075 rp.origin_x = exit_ob->x;
00076 rp.origin_y = exit_ob->y;
00077 strcpy(rp.origin_map, map->path);
00078
00079
00080
00081
00082
00083
00084 if (rp.final_map[0]) {
00085 cp = strrchr(rp.final_map, '/');
00086 if (!cp)
00087 cp = rp.final_map;
00088 } else {
00089 char buf[HUGE_BUF];
00090
00091 cp = strrchr(rp.origin_map, '/');
00092 if (!cp)
00093 cp = rp.origin_map;
00094
00095 snprintf(buf, sizeof(buf), "%s", cp);
00096 while (isdigit(buf[strlen(buf)-1]))
00097 buf[strlen(buf)-1] = 0;
00098 cp = buf;
00099 }
00100 snprintf(newmap_name, sizeof(newmap_name), "/random/%s%04d", cp+1, reference_number++);
00101
00102 return generate_random_map(newmap_name, &rp, NULL);
00103 }
00104
00105 static void do_run() {
00106 mapstruct *worldmap;
00107 mapstruct *random;
00108 mapstruct *old;
00109 int iteration, x, y, map;
00110 object *check;
00111 char path[150];
00112
00113 for (map = 1; map <= 3; map++) {
00114 snprintf(path, sizeof(path), "/whalingoutpost/underwaterdungeon/level%d", map);
00115 worldmap = ready_map_name(path, 0);
00116 fail_unless(worldmap != NULL, "Can't load %s", path);
00117
00118 random = worldmap;
00119 old = NULL;
00120 iteration = 0;
00121 while (random != NULL) {
00122 random = get_random_map(random);
00123 if (!random)
00124 break;
00125 if (old)
00126 delete_map(old);
00127 old = random;
00128 iteration++;
00129 for (x = 0; x < MAP_WIDTH(random); x++) {
00130 for (y = 0; y < MAP_HEIGHT(random); y++) {
00131 for (check = GET_MAP_OB(random, x, y); check; check = check->above) {
00132 if (check->type == HORN && check->title && strcmp(check->title, "of Plenty") == 0)
00133 fail_unless(check->inv != NULL, "Horn has empty inventory!");
00134 }
00135 }
00136 }
00137 }
00138 fail_unless(iteration != 0, "did %d iterations", iteration);
00139 if (old)
00140 delete_map(old);
00141 }
00142 }
00143 #endif
00144
00145 #if 0
00146 static void do_run() {
00147 mapstruct *map, *overlay;
00148 int x, y, found = 0, test = 0;
00149 object *check;
00150
00151 overlay = ready_map_name("../../rsc/bug_1727944_unique", MAP_PLAYER_UNIQUE);
00152 fail_unless(overlay != NULL, "Couldn't load unique map ../../rsc/bug_1727944_unique");
00153
00154 while (found == 0 && test < 10) {
00155 map = ready_map_name("../../rsc/bug_1727944", MAP_PLAYER_UNIQUE);
00156 fail_unless(map != NULL, "couldn't load map ../../rsc/bug_1727944");
00157
00158 for (x = 0; x < MAP_WIDTH(map); x++) {
00159 for (y = 0; y < MAP_HEIGHT(map); y++) {
00160 for (check = GET_MAP_OB(map, x, y); check; check = check->above) {
00161 if (check->type == HORN) {
00162 fail_unless(check->inv != NULL, "Horn has empty inventory!");
00163 fail_unless(check->inv->below == NULL, "Horn has 2 items in inventory!");
00164 if (check->title && strcmp(check->title, "of Plenty") == 0) {
00165 remove_ob(check);
00166 insert_ob_in_map_at(check, overlay, NULL, 0, 2, 3);
00167 found++;
00168 break;
00169 }
00170 }
00171 }
00172 }
00173 }
00174 delete_map(map);
00175 test++;
00176 }
00177 save_map(overlay, SAVE_MODE_OVERLAY);
00178 delete_map(overlay);
00179 }
00180 #endif
00181
00182 extern int artifact_init;
00183 extern int arch_init;
00184
00185
00186 extern const char *const spell_mapping[];
00187
00188 static void local_check_loaded_object(object *op) {
00189 int ip;
00190
00191 if (artifact_init)
00192
00193 return;
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204 if (op->arch && op->name != op->arch->clone.name && op->name_pl == op->arch->clone.name_pl) {
00205 if (op->name_pl)
00206 free_string(op->name_pl);
00207 op->name_pl = NULL;
00208 }
00209 if (!op->name_pl && op->name)
00210 op->name_pl = add_string(op->name);
00211
00212
00213 if (!(IS_WEAPON(op) && op->level > 0)) {
00214 if (op->map != NULL)
00215 set_materialname(op, op->map->difficulty, NULL);
00216 else
00217 set_materialname(op, 5, NULL);
00218 }
00219
00220
00221
00222
00223
00224 if ((op->type == WEAPON || op->type == BOW) && arch_init) {
00225 if (!op->skill) {
00226 LOG(llevError, "Weapon %s lacks a skill.\n", op->name);
00227 } else if ((!strcmp(op->skill, "one handed weapons") && op->body_info[1] != -1)
00228 || (!strcmp(op->skill, "two handed weapons") && op->body_info[1] != -2)) {
00229 LOG(llevError, "weapon %s arm usage does not match skill: %d, %s\n",
00230 op->name, op->body_info[1], op->skill);
00231 }
00232 }
00233
00234
00235
00236
00237
00238 if ((op->type == WEAPON)
00239 || (op->type == ARMOUR)
00240 || (op->type == HELMET)
00241 || (op->type == SHIELD)
00242 || (op->type == RING)
00243 || (op->type == BOOTS)
00244 || (op->type == GLOVES)
00245 || (op->type == AMULET)
00246 || (op->type == GIRDLE)
00247 || (op->type == BRACERS)
00248 || (op->type == CLOAK)) {
00249 if (op->last_heal) {
00250 LOG(llevDebug, "Object %s still has last_heal set, not gen_sp_armour\n", op->name ? op->name : "NULL");
00251 op->gen_sp_armour = op->last_heal;
00252 op->last_heal = 0;
00253 }
00254 ip = calc_item_power(op, 0);
00255
00256 if (!op->item_power && ip) {
00257 if (ip > 3) {
00258 LOG(llevDebug, "Object %s had no item power, using %d\n", op->name ? op->name : "NULL", ip);
00259 }
00260 op->item_power = ip;
00261 }
00262
00263
00264
00265
00266
00267
00268 if (ip > 2*op->item_power && ip > (op->item_power+3)) {
00269 LOG(llevDebug, "Object %s seems to have too low item power? %d > %d\n", op->name ? op->name : "NULL", ip, op->item_power);
00270 }
00271 }
00272
00273 if ((op->type == ROD || op->type == WAND || op->type == SCROLL || op->type == HORN || op->type == FIREWALL || ((op->type == POTION || op->type == ALTAR) && op->stats.sp))
00274 && !op->inv
00275 && !arch_init) {
00276 object *tmp;
00277
00278
00279
00280
00281 tmp = create_archetype(spell_mapping[op->type == FIREWALL ? op->stats.dam : op->stats.sp]);
00282 insert_ob_in_ob(tmp, op);
00283 op->randomitems = NULL;
00284 }
00285
00286
00287 if ((op->type == SPELLBOOK || op->type == RUNE) && op->slaying && !op->inv && !arch_init) {
00288 object *tmp;
00289
00290 tmp = create_archetype_by_object_name(op->slaying);
00291 insert_ob_in_ob(tmp, op);
00292 op->randomitems = NULL;
00293
00294 op->value = op->arch->clone.value*op->inv->value;
00295 }
00296
00297 if (QUERY_FLAG(op, FLAG_MONSTER)) {
00298 if (op->stats.hp > op->stats.maxhp)
00299 LOG(llevDebug, "Monster %s has hp set higher than maxhp (%d>%d)\n", op->name, op->stats.hp, op->stats.maxhp);
00300 }
00301 if ((QUERY_FLAG(op, FLAG_GENERATOR) && QUERY_FLAG(op, FLAG_CONTENT_ON_GEN))
00302 || op->type == CREATOR
00303 || op->type == CONVERTER) {
00304
00305
00306
00307
00308
00309 flag_inv(op, FLAG_IS_A_TEMPLATE);
00310 }
00311
00312
00313
00314
00315
00316 if (arch_init == 0 && artifact_init == 0 && QUERY_FLAG(op, FLAG_MONSTER) && op->arch && !can_merge(op, &op->arch->clone)) {
00317 archetype *temp = get_archetype_struct();
00318
00319 temp->reference_count++;
00320 temp->name = add_string(op->arch->name);
00321 temp->tail_x = op->arch->tail_x;
00322 temp->tail_y = op->arch->tail_y;
00323 copy_object(op, &temp->clone);
00324 temp->clone.inv = NULL;
00325 temp->clone.env = NULL;
00326 temp->clone.x = 0;
00327 temp->clone.y = 0;
00328 temp->clone.map = NULL;
00329 if (FABS(temp->clone.speed) > MIN_ACTIVE_SPEED) {
00330
00331
00332
00333
00334
00335
00336 temp->clone.speed = 0;
00337 update_ob_speed(&temp->clone);
00338 temp->clone.speed = op->speed;
00339 }
00340
00341 temp->more = op->arch->more;
00342 op->arch = temp;
00343
00344 }
00345 }
00346
00347 START_TEST(test_randommaps) {
00348 #if 0
00349 int test;
00350 mapstruct *overlay;
00351 object *check;
00352
00353 for (test = 0; test < 50; test++)
00354 do_run();
00355
00356 for (test = 0; test < 50; test++) {
00357 overlay = ready_map_name("../../rsc/bug_1727944_unique", MAP_PLAYER_UNIQUE);
00358 fail_unless(overlay != NULL, "Couldn't load unique map ../../rsc/bug_1727944_unique");
00359 fail_unless(GET_MAP_OB(overlay, 2, 3) != NULL, "No item on spot 2,3?");
00360
00361 for (check = GET_MAP_OB(overlay, 2, 3)->above; check != NULL; check = check->above) {
00362 fail_unless(check->type == HORN, "Found a non horn?");
00363 fail_unless(check->inv != NULL, "Horn without a spell!");
00364 fail_unless(check->inv->below == NULL, "Horn with 2 items in inventory.");
00365 }
00366 save_map(overlay, SAVE_MODE_OVERLAY);
00367 delete_map(overlay);
00368 }
00369 #endif
00370
00371 #if 0
00372 int test;
00373 archetype *horn = find_archetype("horn");
00374 fail_unless(horn != NULL, "couldn't find archetype horn.");
00375 archetype *horn2 = find_archetype("horn2");
00376 fail_unless(horn2 != NULL, "couldn't find archetype horn2.");
00377
00378 for (test = 0; test < 100000; test++) {
00379 object *check = arch_to_object(RANDOM()%2 ? horn : horn2);
00380
00381 generate_artifact(check, RANDOM()%100);
00382 fail_unless(check->inv != NULL, "horn without inventory!");
00383 }
00384 #endif
00385
00386 int test, level, found = 0;
00387 object *the_chest, *check;
00388 mapstruct *map;
00389 treasurelist *tlist = find_treasurelist("uncommon_items");
00390 fail_unless(tlist != NULL, "couldn't find treasure list uncommon_items");
00391
00392 for (test = 0; test < 10; test++) {
00393 for (level = 1; level < 120; level++) {
00394 map = get_empty_map(1, 1);
00395 fail_unless(map != NULL, "failed to get empty map");
00396 map->difficulty = level;
00397
00398 the_chest = create_archetype("chest");
00399 fail_unless(the_chest != NULL, "failed to get chest");
00400 the_chest->randomitems = tlist;
00401 the_chest->stats.hp = RANDOM()%100;
00402 insert_ob_in_map_at(the_chest, map, NULL, 0, 0, 0);
00403 fix_auto_apply(map);
00404 the_chest = GET_MAP_OB(map, 0, 0);
00405 fail_unless(the_chest != NULL, "failed to recover chest?");
00406 for (check = the_chest->inv; check; check = check->below) {
00407 if (check->type != HORN)
00408 continue;
00409 local_check_loaded_object(check);
00410 fail_unless(check->inv != NULL, "horn without inventory");
00411 fail_unless(check->inv->below == NULL, "horn with 2 items");
00412 fail_unless(check->randomitems == NULL, "horn with randomitems set");
00413 found++;
00414 }
00415 delete_map(map);
00416 }
00417 }
00418 fail_unless(found > 100, "didn't find 100 horn but %d??", found);
00419
00420 }
00421 END_TEST
00422
00423 Suite *bug_suite(void) {
00424 Suite *s = suite_create("bug");
00425 TCase *tc_core = tcase_create("Core");
00426
00427
00428 tcase_add_checked_fixture(tc_core, setup, teardown);
00429
00430 suite_add_tcase(s, tc_core);
00431 tcase_add_test(tc_core, test_randommaps);
00432 tcase_set_timeout(tc_core, 0);
00433
00434 return s;
00435 }
00436
00437 int main(void) {
00438 int nf;
00439 Suite *s = bug_suite();
00440 SRunner *sr = srunner_create(s);
00441
00442 srunner_set_fork_status(sr, CK_NOFORK);
00443 init(0, NULL);
00444
00445 srunner_set_xml(sr, LOGDIR "/bugs/bugtrack/1727944.xml");
00446 srunner_set_log(sr, LOGDIR "/bugs/bugtrack/1727944.out");
00447 srunner_run_all(sr, CK_ENV);
00448 nf = srunner_ntests_failed(sr);
00449 srunner_free(sr);
00450 return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
00451 }