Crossfire Server, Trunk
check_1727944.c
Go to the documentation of this file.
1 /*
2  * CrossFire, A Multiplayer game for X-windows
3  *
4  * Copyright (C) 2007 Crossfire Development Team
5  * Copyright (C) 1992 Frank Tore Johansen
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  *
21  * The authors can be reached via e-mail at crossfire-devel@real-time.com
22  */
23 
34 #include <stdlib.h>
35 #include <check.h>
36 #include <global.h>
37 #include <sproto.h>
38 #include <toolkit_common.h>
39 
40 static void setup(void) {
41  /* put any initialisation steps here, they will be run before each testcase */
42 }
43 
44 static void teardown(void) {
45  /* put any cleanup steps here, they will be run after each testcase */
46 }
47 
48 #if 0
49 static mapstruct *get_random_map(mapstruct *map) {
50  object *exit_ob;
51  mapstruct *random;
52  RMParms rp;
53  char newmap_name[HUGE_BUF], *cp;
54  static int reference_number = 0;
55  int x, y;
56 
57  exit_ob = NULL;
58  for (x = 0; x < MAP_WIDTH(map) && exit_ob == NULL; x++) {
59  for (y = 0; y < MAP_HEIGHT(map) && exit_ob == NULL; y++) {
60  for (exit_ob = GET_MAP_OB(map, x, y); exit_ob != NULL; exit_ob = exit_ob->above)
61  if (exit_ob->type == EXIT && exit_ob->msg != NULL)
62  break;
63  }
64  }
65 
66  if (!exit_ob)
67  /* this means we reached the end of the random part. */
68  return NULL;
69 
70  /* copied from server/server.c:enter_random_map(). */
71  memset(&rp, 0, sizeof(RMParms));
72  rp.Xsize = -1;
73  rp.Ysize = -1;
74  rp.region = get_region_by_map(exit_ob->map);
75  if (exit_ob->msg)
76  set_random_map_variable(&rp, exit_ob->msg);
77  rp.origin_x = exit_ob->x;
78  rp.origin_y = exit_ob->y;
79  strcpy(rp.origin_map, map->path);
80 
81  /* If we have a final_map, use it as a base name to give some clue
82  * as where the player is. Otherwise, use the origin map.
83  * Take the last component (after the last slash) to give
84  * shorter names without bogus slashes.
85  */
86  if (rp.final_map[0]) {
87  cp = strrchr(rp.final_map, '/');
88  if (!cp)
89  cp = rp.final_map;
90  } else {
91  char buf[HUGE_BUF];
92 
93  cp = strrchr(rp.origin_map, '/');
94  if (!cp)
95  cp = rp.origin_map;
96  /* Need to strip of any trailing digits, if it has them */
97  snprintf(buf, sizeof(buf), "%s", cp);
98  while (isdigit(buf[strlen(buf)-1]))
99  buf[strlen(buf)-1] = 0;
100  cp = buf;
101  }
102  snprintf(newmap_name, sizeof(newmap_name), "/random/%s%04d", cp+1, reference_number++);
103  /* now to generate the actual map. */
104  return generate_random_map(newmap_name, &rp, NULL);
105 }
106 
107 static void do_run(void) {
108  mapstruct *worldmap;
109  mapstruct *random;
110  mapstruct *old;
111  int iteration, x, y, map;
112  object *check;
113  char path[150];
114 
115  for (map = 1; map <= 3; map++) {
116  snprintf(path, sizeof(path), "/whalingoutpost/underwaterdungeon/level%d", map);
117  worldmap = ready_map_name(path, 0);
118  fail_unless(worldmap != NULL, "Can't load %s", path);
119 
120  random = worldmap;
121  old = NULL;
122  iteration = 0;
123  while (random != NULL) {
124  random = get_random_map(random);
125  if (!random)
126  break;
127  if (old)
128  delete_map(old);
129  old = random;
130  iteration++;
131  for (x = 0; x < MAP_WIDTH(random); x++) {
132  for (y = 0; y < MAP_HEIGHT(random); y++) {
133  for (check = GET_MAP_OB(random, x, y); check; check = check->above) {
134  if (check->type == ROD && check->title && strcmp(check->title, "of Plenty") == 0)
135  fail_unless(check->inv != NULL, "Horn has empty inventory!");
136  }
137  }
138  }
139  }
140  fail_unless(iteration != 0, "did %d iterations", iteration);
141  if (old)
142  delete_map(old);
143  }
144 }
145 #endif
146 
147 #if 0
148 static void do_run(void) {
149  mapstruct *map, *overlay;
150  int x, y, found = 0, test = 0;
151  object *check;
152 
153  overlay = ready_map_name("../../rsc/bug_1727944_unique", MAP_PLAYER_UNIQUE);
154  fail_unless(overlay != NULL, "Couldn't load unique map ../../rsc/bug_1727944_unique");
155 
156  while (found == 0 && test < 10) {
157  map = ready_map_name("../../rsc/bug_1727944", MAP_PLAYER_UNIQUE);
158  fail_unless(map != NULL, "couldn't load map ../../rsc/bug_1727944");
159 
160  for (x = 0; x < MAP_WIDTH(map); x++) {
161  for (y = 0; y < MAP_HEIGHT(map); y++) {
162  for (check = GET_MAP_OB(map, x, y); check; check = check->above) {
163  if (check->type == ROD) {
164  fail_unless(check->inv != NULL, "Horn has empty inventory!");
165  fail_unless(check->inv->below == NULL, "Horn has 2 items in inventory!");
166  if (check->title && strcmp(check->title, "of Plenty") == 0) {
168  object_insert_in_map_at(check, overlay, NULL, 0, 2, 3);
169  found++;
170  break;
171  }
172  }
173  }
174  }
175  }
176  delete_map(map);
177  test++;
178  }
179  save_map(overlay, SAVE_MODE_OVERLAY);
180  delete_map(overlay);
181 }
182 #endif
183 
184 extern int artifact_init;
185 extern int arch_init;
186 
187 static void local_check_loaded_object(object *op) {
188  int ip;
189 
190  if (artifact_init)
191  /* Artifacts are special beasts, let's not check them. */
192  return;
193 
194  /* We do some specialized handling to handle legacy cases of name_pl.
195  * If the object doesn't have a name_pl, we just use the object name -
196  * this isn't perfect (things won't be properly pluralized), but works to
197  * that degree (5 heart is still quite understandable). But the case we
198  * also have to catch is if this object is not using the normal name for
199  * the object. In that case, we also want to use the loaded name.
200  * Otherwise, what happens is that the the plural name will lose
201  * information (appear as just 'hearts' and not 'goblins heart')
202  */
203  if (op->arch && op->name != op->arch->clone.name && op->name_pl == op->arch->clone.name_pl) {
204  if (op->name_pl)
205  free_string(op->name_pl);
206  op->name_pl = NULL;
207  }
208  if (!op->name_pl && op->name)
209  op->name_pl = add_string(op->name);
210 
211  /* objects now have a materialname. try to patch it in */
212  if (!(IS_WEAPON(op) && op->level > 0)) {
214  }
215  /* only do these when program is first run - a bit
216  * excessive to do this at every run - most of this is
217  * really just to catch any errors - program will still run, but
218  * not in the ideal fashion.
219  */
220  if ((op->type == WEAPON || op->type == BOW) && arch_init) {
221  if (!op->skill) {
222  LOG(llevError, "Weapon %s lacks a skill.\n", op->name);
223  } else if ((!strcmp(op->skill, "one handed weapons") && op->body_info[1] != -1)
224  || (!strcmp(op->skill, "two handed weapons") && op->body_info[1] != -2)) {
225  LOG(llevError, "weapon %s arm usage does not match skill: %d, %s\n",
226  op->name, op->body_info[1], op->skill);
227  }
228  }
229 
230  /* We changed last_heal to gen_sp_armour, which is what it
231  * really does for many objects. Need to catch any in maps
232  * that may have an old value.
233  */
234  if ((op->type == WEAPON)
235  || (op->type == ARMOUR)
236  || (op->type == HELMET)
237  || (op->type == SHIELD)
238  || (op->type == RING)
239  || (op->type == BOOTS)
240  || (op->type == GLOVES)
241  || (op->type == AMULET)
242  || (op->type == GIRDLE)
243  || (op->type == BRACERS)
244  || (op->type == CLOAK)) {
245  if (op->last_heal) {
246  LOG(llevDebug, "Object %s still has last_heal set, not gen_sp_armour\n", op->name ? op->name : "NULL");
247  op->gen_sp_armour = op->last_heal;
248  op->last_heal = 0;
249  }
250  ip = calc_item_power(op);
251  /* Legacy objects from before item power was in the game */
252  if (!op->item_power && ip) {
253  if (ip > 3) {
254  LOG(llevDebug, "Object %s had no item power, using %d\n", op->name ? op->name : "NULL", ip);
255  }
256  op->item_power = ip;
257  }
258  /* Check for possibly bogus values. Has to meet both these criteria -
259  * something that has item_power 1 is probably just fine if our calculated
260  * value is 1 or 2 - these values are small enough that hard to be precise.
261  * similarly, it item_power is 0, the first check will always pass,
262  * but not the second one.
263  */
264  if (ip > 2*op->item_power && ip > (op->item_power+3)) {
265  LOG(llevDebug, "Object %s seems to have too low item power? %d > %d\n", op->name ? op->name : "NULL", ip, op->item_power);
266  }
267  }
268  /* Old spellcasting object - need to load in the appropiate object */
269  if ((op->type == ROD || op->type == WAND || op->type == SCROLL || op->type == FIREWALL || /* POTIONS and ALTARS don't always cast spells, but if they do, update them */ ((op->type == POTION || op->type == ALTAR) && op->stats.sp))
270  && !op->inv
271  && !arch_init) {
272  object *tmp;
273 
274  /* Fireall is bizarre in that spell type was stored in dam. Rest are 'normal'
275  * in that spell was stored in sp.
276  */
277  tmp = create_archetype(spell_mapping[op->type == FIREWALL ? op->stats.dam : op->stats.sp]);
279  op->randomitems = NULL; /* So another spell isn't created for this object */
280  }
281 
282  /* spellbooks & runes use slaying. But not to arch name, but to spell name */
283  if ((op->type == SPELLBOOK || op->type == RUNE) && op->slaying && !op->inv && !arch_init) {
284  object *tmp;
285 
288  op->randomitems = NULL; /* So another spell isn't created for this object */
289  /* without this, value is all screwed up */
290  op->value = op->arch->clone.value*op->inv->value;
291  }
292 
293  if (QUERY_FLAG(op, FLAG_MONSTER)) {
294  if (op->stats.hp > op->stats.maxhp)
295  LOG(llevDebug, "Monster %s has hp set higher than maxhp (%d>%d)\n", op->name, op->stats.hp, op->stats.maxhp);
296  }
298  || op->type == CREATOR
299  || op->type == CONVERTER) {
300  /* Object will duplicate it's content as part of the
301  * generation process. To do this, we must flag inventory
302  * so it remains unevaluated concerning the randomitems and
303  * the living (a demonlord shouldn't cast from inside generator!)
304  */
306  }
307 
308  /* Here we'll handle custom monsters. In order to handle them correctly, especially in the fix_object
309  * method, we'll create a new temporary archetype containing defined values.
310  * Of course this doesn't apply when loading archetypes or artifacts.
311  */
312  if (arch_init == 0 && artifact_init == 0 && QUERY_FLAG(op, FLAG_MONSTER) && op->arch && !object_can_merge(op, &op->arch->clone)) {
314 
315  temp->reference_count++;
316  temp->name = add_string(op->arch->name);
317  temp->tail_x = op->arch->tail_x;
318  temp->tail_y = op->arch->tail_y;
319  object_copy(op, &temp->clone);
320  temp->clone.inv = NULL;
321  temp->clone.env = NULL;
322  temp->clone.x = 0;
323  temp->clone.y = 0;
324  temp->clone.map = NULL;
325  if (FABS(temp->clone.speed) > MIN_ACTIVE_SPEED) {
326  /* Clone has a speed, so need to clear that because it isn't on a map.
327  * But we need to keep the value, because otherwise the customized object
328  * will have no speed (fix_player() will use the 0 value). So set it
329  * to zero, call object_update_speed() to remove it from active list, then
330  * set its speed back to the original.
331  */
332  temp->clone.speed = 0;
333  object_update_speed(&temp->clone);
334  temp->clone.speed = op->speed;
335  }
336 
337  temp->more = op->arch->more;
338  op->arch = temp;
339  /* LOG(llevDebug, "created temporary archetype for %s at %d,%d\n", op->name, op->x, op->y); */
340  }
341 }
342 
343 START_TEST(test_randommaps) {
344 #if 0
345  int test;
346  mapstruct *overlay;
347  object *check;
348 
349  for (test = 0; test < 50; test++)
350  do_run();
351 
352  for (test = 0; test < 50; test++) {
353  overlay = ready_map_name("../../rsc/bug_1727944_unique", MAP_PLAYER_UNIQUE);
354  fail_unless(overlay != NULL, "Couldn't load unique map ../../rsc/bug_1727944_unique");
355  fail_unless(GET_MAP_OB(overlay, 2, 3) != NULL, "No item on spot 2,3?");
356 
357  for (check = GET_MAP_OB(overlay, 2, 3)->above; check != NULL; check = check->above) {
358  fail_unless(check->type == ROD, "Found a non horn?");
359  fail_unless(check->inv != NULL, "Horn without a spell!");
360  fail_unless(check->inv->below == NULL, "Horn with 2 items in inventory.");
361  }
362  save_map(overlay, SAVE_MODE_OVERLAY);
363  delete_map(overlay);
364  }
365 #endif
366 
367 #if 0
368  int test;
369  archetype *horn = find_archetype("horn");
370  fail_unless(horn != NULL, "couldn't find archetype horn.");
371  archetype *horn2 = find_archetype("horn2");
372  fail_unless(horn2 != NULL, "couldn't find archetype horn2.");
373 
374  for (test = 0; test < 100000; test++) {
375  object *check = arch_to_object(RANDOM()%2 ? horn : horn2);
376 
378  fail_unless(check->inv != NULL, "horn without inventory!");
379  }
380 #endif
381 
382  int test, level, found = 0;
383  object *the_chest, *check;
384  mapstruct *map;
385  treasurelist *tlist = find_treasurelist("uncommon_items");
386  fail_unless(tlist != NULL, "couldn't find treasure list uncommon_items");
387 
388  for (test = 0; test < 10; test++) {
389  for (level = 1; level < 120; level++) {
390  map = get_empty_map(1, 1);
391  fail_unless(map != NULL, "failed to get empty map");
392  map->difficulty = level;
393 
394  the_chest = create_archetype("chest"); /* was "chest_2" */
395  fail_unless(the_chest != NULL, "failed to get chest");
396  the_chest->randomitems = tlist;
397  the_chest->stats.hp = RANDOM()%100;
398  object_insert_in_map_at(the_chest, map, NULL, 0, 0, 0);
400  the_chest = GET_MAP_OB(map, 0, 0);
401  fail_unless(the_chest != NULL, "failed to recover chest?");
402  for (check = the_chest->inv; check; check = check->below) {
403  if (check->type != ROD)
404  continue;
406  fail_unless(check->inv != NULL, "horn without inventory");
407  fail_unless(check->inv->below == NULL, "horn with 2 items");
408  fail_unless(check->randomitems == NULL, "horn with randomitems set");
409  found++;
410  }
411  delete_map(map);
412  }
413  }
414  fail_unless(found > 100, "didn't find 100 horn but %d??", found);
415 
416 }
417 END_TEST
418 
419 static Suite *bug_suite(void) {
420  Suite *s = suite_create("bug");
421  TCase *tc_core = tcase_create("Core");
422 
423  /*setup and teardown will be called before each test in testcase 'tc_core' */
424  tcase_add_checked_fixture(tc_core, setup, teardown);
425 
426  suite_add_tcase(s, tc_core);
427  tcase_add_test(tc_core, test_randommaps);
428  tcase_set_timeout(tc_core, 0);
429 
430  return s;
431 }
432 
433 int main(void) {
434  int nf;
435  Suite *s = bug_suite();
436  SRunner *sr = srunner_create(s);
437 
438  srunner_set_fork_status(sr, CK_NOFORK);
439  cctk_setdatadir(SOURCE_ROOT "lib");
440  init(0, NULL);
441 
442  srunner_set_xml(sr, LOGDIR "/bugs/bugtrack/1727944.xml");
443  srunner_set_log(sr, LOGDIR "/bugs/bugtrack/1727944.out");
444  srunner_run_all(sr, CK_ENV); /*verbosity from env variable*/
445  nf = srunner_ntests_failed(sr);
446  srunner_free(sr);
447  return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
448 }
bug_suite
static END_TEST Suite * bug_suite(void)
Definition: check_1727944.c:419
GET_MAP_OB
#define GET_MAP_OB(M, X, Y)
Definition: map.h:173
ready_map_name
mapstruct * ready_map_name(const char *name, int flags)
Definition: map.c:1778
global.h
add_string
sstring add_string(const char *str)
Definition: shstr.c:124
object_remove
void object_remove(object *op)
Definition: object.c:1806
BOW
@ BOW
Definition: object.h:118
BRACERS
@ BRACERS
Definition: object.h:217
llevError
@ llevError
Definition: logger.h:11
RMParms::origin_map
char origin_map[RM_SIZE]
Definition: random_map.h:55
FABS
#define FABS(x)
Definition: define.h:22
WAND
@ WAND
Definition: object.h:220
FLAG_GENERATOR
#define FLAG_GENERATOR
Definition: define.h:248
GLOVES
@ GLOVES
Definition: object.h:213
GIRDLE
@ GIRDLE
Definition: object.h:223
diamondslots.x
x
Definition: diamondslots.py:15
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
get_archetype_struct
archetype * get_archetype_struct(void)
Definition: arch.cpp:198
FLAG_CONTENT_ON_GEN
#define FLAG_CONTENT_ON_GEN
Definition: define.h:365
cctk_setdatadir
void cctk_setdatadir(const char *datadir)
Definition: toolkit_common.c:69
teardown
static void teardown(void)
Definition: check_1727944.c:44
calc_item_power
int calc_item_power(const object *op)
Definition: item.c:238
main
int main(void)
Definition: check_1727944.c:433
RMParms::Ysize
int Ysize
Definition: random_map.h:75
ARMOUR
@ ARMOUR
Definition: object.h:120
set_materialname
void set_materialname(object *op)
Definition: utils.c:301
WEAPON
@ WEAPON
Definition: object.h:119
set_random_map_variable
int set_random_map_variable(RMParms *rp, const char *buf)
Definition: reader.c:2579
object_set_flag_inv
void object_set_flag_inv(object *op, int flag)
Definition: object.c:3189
python_event.path
path
Definition: python_event.py:11
liv::hp
int16_t hp
Definition: living.h:40
AMULET
@ AMULET
Definition: object.h:139
object_can_merge
int object_can_merge(object *ob1, object *ob2)
Definition: object.c:422
RUNE
@ RUNE
Definition: object.h:240
MAP_PLAYER_UNIQUE
#define MAP_PLAYER_UNIQUE
Definition: map.h:97
find_treasurelist
treasurelist * find_treasurelist(const char *name)
Definition: assets.cpp:257
RMParms::origin_y
int origin_y
Definition: random_map.h:88
Ice.tmp
int tmp
Definition: Ice.py:207
CREATOR
@ CREATOR
Definition: object.h:142
obj::randomitems
struct treasureliststruct * randomitems
Definition: object.h:389
RMParms
Definition: random_map.h:14
HUGE_BUF
#define HUGE_BUF
Definition: define.h:37
reputation_trigger_connect.check
def check()
Definition: reputation_trigger_connect.py:18
SAVE_MODE_OVERLAY
#define SAVE_MODE_OVERLAY
Definition: map.h:123
archt
Definition: object.h:468
FLAG_IS_A_TEMPLATE
#define FLAG_IS_A_TEMPLATE
Definition: define.h:366
free_string
void free_string(sstring str)
Definition: shstr.c:280
RMParms::origin_x
int origin_x
Definition: random_map.h:89
CLOAK
@ CLOAK
Definition: object.h:204
apply_auto_fix
void apply_auto_fix(mapstruct *m)
Definition: main.c:259
toolkit_common.h
HELMET
@ HELMET
Definition: object.h:136
disinfect.map
map
Definition: disinfect.py:4
object_copy
void object_copy(const object *src_ob, object *dest_ob)
Definition: object.c:1053
POTION
@ POTION
Definition: object.h:111
RMParms::final_map
char final_map[RM_SIZE]
Definition: random_map.h:57
ROD
@ ROD
Definition: object.h:109
arch_init
int arch_init
Definition: ArchetypeLoader.cpp:22
generate_artifact
void generate_artifact(object *op, int difficulty)
Definition: artifact.c:143
CONVERTER
@ CONVERTER
Definition: object.h:216
RMParms::region
struct regiondef * region
Definition: random_map.h:96
sproto.h
mapdef
Definition: map.h:324
RING
@ RING
Definition: object.h:185
delete_map
void delete_map(mapstruct *m)
Definition: map.c:1716
FLAG_MONSTER
#define FLAG_MONSTER
Definition: define.h:245
MAP_WIDTH
#define MAP_WIDTH(m)
Definition: map.h:78
log_login.ip
ip
Definition: log_login.py:6
create_archetype
object * create_archetype(const char *name)
Definition: arch.cpp:281
IS_WEAPON
#define IS_WEAPON(op)
Definition: define.h:163
RANDOM
#define RANDOM()
Definition: define.h:642
save_map
int save_map(mapstruct *m, int flag)
Definition: map.c:1416
is_valid_types_gen.found
found
Definition: is_valid_types_gen.py:39
EXIT
@ EXIT
Definition: object.h:181
get_region_by_map
region * get_region_by_map(mapstruct *m)
Definition: region.c:74
obj::stats
living stats
Definition: object.h:371
generate_random_map
mapstruct * generate_random_map(const char *OutFileName, RMParms *RP, char **use_layout)
Definition: random_map.c:74
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:51
create_archetype_by_object_name
object * create_archetype_by_object_name(const char *name)
Definition: arch.cpp:118
FIREWALL
@ FIREWALL
Definition: object.h:168
local_check_loaded_object
static void local_check_loaded_object(object *op)
Definition: check_1727944.c:187
give.op
op
Definition: give.py:33
find_archetype
archetype * find_archetype(const char *name)
Definition: assets.cpp:278
init
void init(int argc, char **argv)
Definition: init.c:1108
diamondslots.y
y
Definition: diamondslots.py:16
buf
StringBuffer * buf
Definition: readable.c:1606
MAP_HEIGHT
#define MAP_HEIGHT(m)
Definition: map.h:80
object_insert_in_ob
object * object_insert_in_ob(object *op, object *where)
Definition: object.c:2820
object_update_speed
void object_update_speed(object *op)
Definition: object.c:1317
arch_to_object
object * arch_to_object(archetype *at)
Definition: arch.cpp:232
MIN_ACTIVE_SPEED
#define MIN_ACTIVE_SPEED
Definition: define.h:637
object_insert_in_map_at
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Definition: object.c:2067
ALTAR
@ ALTAR
Definition: object.h:122
level
int level
Definition: readable.c:1604
SCROLL
@ SCROLL
Definition: object.h:221
BOOTS
@ BOOTS
Definition: object.h:212
setup
static void setup(void)
Definition: check_1727944.c:40
guildbuy.temp
def temp
Definition: guildbuy.py:26
SHIELD
@ SHIELD
Definition: object.h:135
spell_mapping
const char *const spell_mapping[SPELL_MAPPINGS]
Definition: object.c:63
get_empty_map
mapstruct * get_empty_map(int sizex, int sizey)
Definition: map.c:867
SPELLBOOK
@ SPELLBOOK
Definition: object.h:203
RMParms::Xsize
int Xsize
Definition: random_map.h:74
START_TEST
START_TEST(test_randommaps)
Definition: check_1727944.c:343
llevDebug
@ llevDebug
Definition: logger.h:13
treasureliststruct
Definition: treasure.h:82
artifact_init
int artifact_init
Definition: artifact.c:28
obj::inv
struct obj * inv
Definition: object.h:291
level
Definition: level.py:1