Atrinik Server  4.0
treasure.c
Go to the documentation of this file.
1 /*************************************************************************
2  * Atrinik, a Multiplayer Online Role Playing Game *
3  * *
4  * Copyright (C) 2009-2014 Alex Tokar and Atrinik Development Team *
5  * *
6  * Fork from Crossfire (Multiplayer game for X-windows). *
7  * *
8  * This program is free software; you can redistribute it and/or modify *
9  * it under the terms of the GNU General Public License as published by *
10  * the Free Software Foundation; either version 2 of the License, or *
11  * (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License *
19  * along with this program; if not, write to the Free Software *
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
21  * *
22  * The author can be reached at admin@atrinik.org *
23  ************************************************************************/
24 
30 #include <global.h>
31 #include <loader.h>
32 #include <arch.h>
33 #include <artifact.h>
34 #include "object_methods.h"
35 #include <toolkit/string.h>
36 
38 const char *const coins[NUM_COINS + 1] = {
39  "ambercoin",
40  "mithrilcoin",
41  "jadecoin",
42  "goldcoin",
43  "silvercoin",
44  "coppercoin",
45  NULL
46 };
47 
51 static const int difftomagic_list[DIFFLEVELS][MAXMAGIC + 1] = {
52  /* Chance of magic Difficulty */
53  /* +0 +1 +2 +3 +4 */
54  {94, 3, 2, 1, 0}, /*1*/
55  {94, 3, 2, 1, 0}, /*2*/
56  {94, 3, 2, 1, 0}, /*3*/
57  {94, 3, 2, 1, 0}, /*4*/
58  {94, 3, 2, 1, 0}, /*5*/
59  {90, 4, 3, 2, 1}, /*6*/
60  {90, 4, 3, 2, 1}, /*7*/
61  {90, 4, 3, 2, 1}, /*8*/
62  {90, 4, 3, 2, 1}, /*9*/
63  {90, 4, 3, 2, 1}, /*10*/
64  {85, 6, 4, 3, 2}, /*11*/
65  {85, 6, 4, 3, 2}, /*12*/
66  {85, 6, 4, 3, 2}, /*13*/
67  {85, 6, 4, 3, 2}, /*14*/
68  {85, 6, 4, 3, 2}, /*15*/
69  {80, 8, 5, 4, 3}, /*16*/
70  {80, 8, 5, 4, 3}, /*17*/
71  {80, 8, 5, 4, 3}, /*18*/
72  {80, 8, 5, 4, 3}, /*19*/
73  {80, 8, 5, 4, 3}, /*20*/
74  {75, 10, 6, 5, 4}, /*21*/
75  {75, 10, 6, 5, 4}, /*22*/
76  {75, 10, 6, 5, 4}, /*23*/
77  {75, 10, 6, 5, 4}, /*24*/
78  {75, 10, 6, 5, 4}, /*25*/
79  {70, 12, 7, 6, 5}, /*26*/
80  {70, 12, 7, 6, 5}, /*27*/
81  {70, 12, 7, 6, 5}, /*28*/
82  {70, 12, 7, 6, 5}, /*29*/
83  {70, 12, 7, 6, 5}, /*30*/
84  {70, 9, 8, 7, 6}, /*31*/
85  {70, 9, 8, 7, 6}, /*32*/
86  {70, 9, 8, 7, 6}, /*33*/
87  {70, 9, 8, 7, 6}, /*34*/
88  {70, 9, 8, 7, 6}, /*35*/
89  {70, 6, 9, 8, 7}, /*36*/
90  {70, 6, 9, 8, 7}, /*37*/
91  {70, 6, 9, 8, 7}, /*38*/
92  {70, 6, 9, 8, 7}, /*39*/
93  {70, 6, 9, 8, 7}, /*40*/
94  {70, 3, 10, 9, 8}, /*41*/
95  {70, 3, 10, 9, 8}, /*42*/
96  {70, 3, 10, 9, 8}, /*43*/
97  {70, 3, 10, 9, 8}, /*44*/
98  {70, 3, 10, 9, 8}, /*45*/
99  {70, 2, 9, 10, 9}, /*46*/
100  {70, 2, 9, 10, 9}, /*47*/
101  {70, 2, 9, 10, 9}, /*48*/
102  {70, 2, 9, 10, 9}, /*49*/
103  {70, 2, 9, 10, 9}, /*50*/
104  {70, 2, 7, 11, 10}, /*51*/
105  {70, 2, 7, 11, 10}, /*52*/
106  {70, 2, 7, 11, 10}, /*53*/
107  {70, 2, 7, 11, 10}, /*54*/
108  {70, 2, 7, 11, 10}, /*55*/
109  {70, 2, 5, 12, 11}, /*56*/
110  {70, 2, 5, 12, 11}, /*57*/
111  {70, 2, 5, 12, 11}, /*58*/
112  {70, 2, 5, 12, 11}, /*59*/
113  {70, 2, 5, 12, 11}, /*60*/
114  {70, 2, 3, 13, 12}, /*61*/
115  {70, 2, 3, 13, 12}, /*62*/
116  {70, 2, 3, 13, 12}, /*63*/
117  {70, 2, 3, 13, 12}, /*64*/
118  {70, 2, 3, 13, 12}, /*65*/
119  {70, 2, 3, 12, 13}, /*66*/
120  {70, 2, 3, 12, 13}, /*67*/
121  {70, 2, 3, 12, 13}, /*68*/
122  {70, 2, 3, 12, 13}, /*69*/
123  {70, 2, 3, 12, 13}, /*70*/
124  {70, 2, 3, 11, 14}, /*71*/
125  {70, 2, 3, 11, 14}, /*72*/
126  {70, 2, 3, 11, 14}, /*73*/
127  {70, 2, 3, 11, 14}, /*74*/
128  {70, 2, 3, 11, 14}, /*75*/
129  {70, 2, 3, 10, 15}, /*76*/
130  {70, 2, 3, 10, 15}, /*77*/
131  {70, 2, 3, 10, 15}, /*78*/
132  {70, 2, 3, 10, 15}, /*79*/
133  {70, 2, 3, 10, 15}, /*80*/
134  {70, 2, 3, 9, 16}, /*81*/
135  {70, 2, 3, 9, 16}, /*82*/
136  {70, 2, 3, 9, 16}, /*83*/
137  {70, 2, 3, 9, 16}, /*84*/
138  {70, 2, 3, 9, 16}, /*85*/
139  {70, 2, 3, 8, 17}, /*86*/
140  {70, 2, 3, 8, 17}, /*87*/
141  {70, 2, 3, 8, 17}, /*88*/
142  {70, 2, 3, 8, 17}, /*89*/
143  {70, 2, 3, 8, 17}, /*90*/
144  {70, 2, 3, 7, 18}, /*91*/
145  {70, 2, 3, 7, 18}, /*92*/
146  {70, 2, 3, 7, 18}, /*93*/
147  {70, 2, 3, 7, 18}, /*94*/
148  {70, 2, 3, 7, 18}, /*95*/
149  {70, 2, 3, 6, 19}, /*96*/
150  {70, 2, 3, 6, 19}, /*97*/
151  {70, 2, 3, 6, 19}, /*98*/
152  {70, 2, 3, 6, 19}, /*99*/
153  {70, 2, 3, 6, 19}, /*100*/
154  {70, 2, 3, 6, 19}, /*101*/
155  {70, 2, 3, 6, 19}, /*101*/
156  {70, 2, 3, 6, 19}, /*102*/
157  {70, 2, 3, 6, 19}, /*103*/
158  {70, 2, 3, 6, 19}, /*104*/
159  {70, 2, 3, 6, 19}, /*105*/
160  {70, 2, 3, 6, 19}, /*106*/
161  {70, 2, 3, 6, 19}, /*107*/
162  {70, 2, 3, 6, 19}, /*108*/
163  {70, 2, 3, 6, 19}, /*109*/
164  {70, 2, 3, 6, 19}, /*110*/
165  {70, 2, 3, 6, 19}, /*111*/
166  {70, 2, 3, 6, 19}, /*112*/
167  {70, 2, 3, 6, 19}, /*113*/
168  {70, 2, 3, 6, 19}, /*114*/
169  {70, 2, 3, 6, 19}, /*115*/
170  {70, 2, 3, 6, 19}, /*116*/
171  {70, 2, 3, 6, 19}, /*117*/
172  {70, 2, 3, 6, 19}, /*118*/
173  {70, 2, 3, 6, 19}, /*119*/
174  {70, 2, 3, 6, 19}, /*120*/
175  {70, 2, 3, 6, 19}, /*121*/
176  {70, 2, 3, 6, 19}, /*122*/
177  {70, 2, 3, 6, 19}, /*123*/
178  {70, 2, 3, 6, 19}, /*124*/
179  {70, 2, 3, 6, 19}, /*125*/
180  {70, 2, 3, 6, 19}, /*126*/
181  {70, 2, 3, 6, 19}, /*127*/
182  {70, 2, 3, 6, 19}, /*128*/
183  {70, 2, 3, 6, 19}, /*129*/
184  {70, 2, 3, 6, 19}, /*130*/
185  {70, 2, 3, 6, 19}, /*131*/
186  {70, 2, 3, 6, 19}, /*132*/
187  {70, 2, 3, 6, 19}, /*133*/
188  {70, 2, 3, 6, 19}, /*134*/
189  {70, 2, 3, 6, 19}, /*135*/
190  {70, 2, 3, 6, 19}, /*136*/
191  {70, 2, 3, 6, 19}, /*137*/
192  {70, 2, 3, 6, 19}, /*138*/
193  {70, 2, 3, 6, 19}, /*139*/
194  {70, 2, 3, 6, 19}, /*140*/
195  {70, 2, 3, 6, 19}, /*141*/
196  {70, 2, 3, 6, 19}, /*142*/
197  {70, 2, 3, 6, 19}, /*143*/
198  {70, 2, 3, 6, 19}, /*144*/
199  {70, 2, 3, 6, 19}, /*145*/
200  {70, 2, 3, 6, 19}, /*146*/
201  {70, 2, 3, 6, 19}, /*147*/
202  {70, 2, 3, 6, 19}, /*148*/
203  {70, 2, 3, 6, 19}, /*149*/
204  {70, 2, 3, 6, 19}, /*150*/
205  {70, 2, 3, 6, 19}, /*151*/
206  {70, 2, 3, 6, 19}, /*152*/
207  {70, 2, 3, 6, 19}, /*153*/
208  {70, 2, 3, 6, 19}, /*154*/
209  {70, 2, 3, 6, 19}, /*155*/
210  {70, 2, 3, 6, 19}, /*156*/
211  {70, 2, 3, 6, 19}, /*157*/
212  {70, 2, 3, 6, 19}, /*158*/
213  {70, 2, 3, 6, 19}, /*159*/
214  {70, 2, 3, 6, 19}, /*160*/
215  {70, 2, 3, 6, 19}, /*161*/
216  {70, 2, 3, 6, 19}, /*162*/
217  {70, 2, 3, 6, 19}, /*163*/
218  {70, 2, 3, 6, 19}, /*164*/
219  {70, 2, 3, 6, 19}, /*165*/
220  {70, 2, 3, 6, 19}, /*166*/
221  {70, 2, 3, 6, 19}, /*167*/
222  {70, 2, 3, 6, 19}, /*168*/
223  {70, 2, 3, 6, 19}, /*169*/
224  {70, 2, 3, 6, 19}, /*170*/
225  {70, 2, 3, 6, 19}, /*171*/
226  {70, 2, 3, 6, 19}, /*172*/
227  {70, 2, 3, 6, 19}, /*173*/
228  {70, 2, 3, 6, 19}, /*174*/
229  {70, 2, 3, 6, 19}, /*175*/
230  {70, 2, 3, 6, 19}, /*176*/
231  {70, 2, 3, 6, 19}, /*177*/
232  {70, 2, 3, 6, 19}, /*178*/
233  {70, 2, 3, 6, 19}, /*179*/
234  {70, 2, 3, 6, 19}, /*180*/
235  {70, 2, 3, 6, 19}, /*181*/
236  {70, 2, 3, 6, 19}, /*182*/
237  {70, 2, 3, 6, 19}, /*183*/
238  {70, 2, 3, 6, 19}, /*184*/
239  {70, 2, 3, 6, 19}, /*185*/
240  {70, 2, 3, 6, 19}, /*186*/
241  {70, 2, 3, 6, 19}, /*187*/
242  {70, 2, 3, 6, 19}, /*188*/
243  {70, 2, 3, 6, 19}, /*189*/
244  {70, 2, 3, 6, 19}, /*190*/
245  {70, 2, 3, 6, 19}, /*191*/
246  {70, 2, 3, 6, 19}, /*192*/
247  {70, 2, 3, 6, 19}, /*193*/
248  {70, 2, 3, 6, 19}, /*194*/
249  {70, 2, 3, 6, 19}, /*195*/
250  {70, 2, 3, 6, 19}, /*196*/
251  {70, 2, 3, 6, 19}, /*197*/
252  {70, 2, 3, 6, 19}, /*198*/
253  {70, 2, 3, 6, 19}, /*199*/
254  {70, 2, 3, 6, 19}, /*200*/
255 };
256 
259 
261 #define CHANCE_FIX (-1)
262 
263 static void free_treasurestruct(treasure_t *t);
264 
265 /* Function prototypes */
266 static void
268  FILE *fp,
269  const char *filename,
270  uint64_t *linenum);
271 static void
273  object *op,
274  int difficulty,
275  int flags,
276  treasure_affinity_t *affinity,
277  int artifact_chance,
278  int tries,
279  treasure_attrs_t *attrs);
280 
287 static treasure_list_t *
289 {
290  treasure_list_t *treasure_list = ecalloc(1, sizeof(*treasure_list));
291 
292  treasure_list->artifact_chance = TREASURE_ARTIFACT_CHANCE;
293  treasure_list->chance_fix = CHANCE_FIX;
294  treasure_list->total_chance = 0;
295 
296  return treasure_list;
297 }
298 
305 static treasure_t *
307 {
308  treasure_t *treasure = ecalloc(1, sizeof(*treasure));
309 
310  treasure->magic_chance = 3;
312  treasure->chance_fix = CHANCE_FIX;
313  treasure->chance = 100;
314 
315  treasure->attrs.item_race = -1;
316  treasure->attrs.material = -1;
317  treasure->attrs.material_quality = -1;
318  treasure->attrs.material_range = -1;
319  treasure->attrs.quality = -1;
320  treasure->attrs.quality_range = -1;
321 
322  return treasure;
323 }
324 
342 static treasure_t *
344  const char *filename,
345  uint64_t *linenum,
346  treasure_affinity_t **affinity,
347  int *artifact_chance)
348 {
349  HARD_ASSERT(fp != NULL);
350  HARD_ASSERT(filename != NULL);
351  HARD_ASSERT(linenum != NULL);
352  HARD_ASSERT(affinity != NULL);
353  HARD_ASSERT(artifact_chance != NULL);
354 
355  bool start_marker = false;
357 
358  char buf[MAX_BUF];
359  while (fgets(VS(buf), fp) != NULL) {
360  (*linenum)++;
361 
362  char *cp = buf;
363  string_skip_whitespace(cp);
364  string_strip_newline(cp);
365 
366  char *cps[2];
367  if (string_split(cp, cps, arraysize(cps), ' ') < 1) {
368  continue;
369  }
370 
371  const char *key = cps[0], *value = cps[1], *error_str = NULL;
372 
373  if (value == NULL) {
374  if (strcmp(key, "yes") == 0) {
375  treasure_load_more(&treasure->next_yes, fp, filename, linenum);
376  } else if (strcmp(key, "no") == 0) {
377  treasure_load_more(&treasure->next_no, fp, filename, linenum);
378  } else if (strcmp(key, "more") == 0) {
379  treasure_load_more(&treasure->next, fp, filename, linenum);
380  return treasure;
381  } else if (strcmp(key, "end") == 0) {
382  return treasure;
383  } else {
384  error_str = "unrecognized attribute";
385  goto error;
386  }
387  } else if (strcmp(key, "affinity") == 0) {
388  if (start_marker) {
389  FREE_AND_COPY_HASH(treasure->affinity, value);
390  } else {
391  FREE_AND_COPY_HASH(*affinity, value);
392  }
393  } else if (strcmp(key, "artifact_chance") == 0) {
394  if (!string_isdigit(value)) {
395  error_str = "artifact_chance attribute expects a number";
396  goto error;
397  }
398 
399  if (start_marker) {
400  treasure->artifact_chance = atoi(value);
401  } else {
402  *artifact_chance = atoi(value);
403  }
404  } else if (strcmp(key, "arch") == 0) {
405  treasure->item = arch_find(value);
406  if (treasure->item == NULL) {
407  LOG(ERROR, "Treasure lacks archetype: %s", value);
408  exit(1);
409  }
410 
411  start_marker = true;
412  } else if (strcmp(key, "list") == 0) {
413  start_marker = true;
414  FREE_AND_COPY_HASH(treasure->name, value);
415  } else if (strcmp(key, "name") == 0) {
416  FREE_AND_COPY_HASH(treasure->attrs.name, value);
417  } else if (strcmp(key, "title") == 0) {
418  FREE_AND_COPY_HASH(treasure->attrs.title, value);
419  } else if (strcmp(key, "slaying") == 0) {
420  FREE_AND_COPY_HASH(treasure->attrs.slaying, value);
421  } else if (strcmp(key, "item_race") == 0) {
422  if (!string_isdigit(value)) {
423  error_str = "item_race attribute expects a number";
424  goto error;
425  }
426 
427  treasure->attrs.item_race = atoi(value);
428  } else if (strcmp(key, "quality") == 0) {
429  if (!string_isdigit(value)) {
430  error_str = "quality attribute expects a number";
431  goto error;
432  }
433 
434  treasure->attrs.quality = atoi(value);
435  } else if (strcmp(key, "quality_range") == 0) {
436  if (!string_isdigit(value)) {
437  error_str = "quality_range attribute expects a number";
438  goto error;
439  }
440 
441  treasure->attrs.quality_range = atoi(value);
442  } else if (strcmp(key, "material") == 0) {
443  if (!string_isdigit(value)) {
444  error_str = "material attribute expects a number";
445  goto error;
446  }
447 
448  treasure->attrs.material = atoi(value);
449  } else if (strcmp(key, "material_quality") == 0) {
450  if (!string_isdigit(value)) {
451  error_str = "material_quality attribute expects a number";
452  goto error;
453  }
454 
455  treasure->attrs.material_quality = atoi(value);
456  } else if (strcmp(key, "material_range") == 0) {
457  if (!string_isdigit(value)) {
458  error_str = "material_range attribute expects a number";
459  goto error;
460  }
461 
462  treasure->attrs.material_range = atoi(value);
463  } else if (strcmp(key, "chance_fix") == 0) {
464  int val = atoi(value);
465  if (val < 0 || val > INT16_MAX) {
466  LOG(ERROR, "Value out of range: %s %s", key, value);
467  exit(1);
468  }
469 
470  treasure->chance_fix = val;
471  treasure->chance = 0;
472  } else if (strcmp(key, "chance") == 0) {
473  if (!string_isdigit(value)) {
474  error_str = "chance attribute expects a number";
475  goto error;
476  }
477 
478  int val = atoi(value);
479  if (val < 0 || val > 100) {
480  LOG(ERROR, "Value out of range: %s %s", key, value);
481  exit(1);
482  }
483 
484  treasure->chance = val;
485  } else if (strcmp(key, "nrof") == 0) {
486  if (!string_isdigit(value)) {
487  error_str = "nrof attribute expects a number";
488  goto error;
489  }
490 
491  treasure->nrof = atoi(value);
492  } else if (strcmp(key, "magic") == 0) {
493  if (!string_isdigit(value)) {
494  error_str = "magic attribute expects a number";
495  goto error;
496  }
497 
498  treasure->magic = atoi(value);
499  } else if (strcmp(key, "magic_fix") == 0) {
500  if (!string_isdigit(value)) {
501  error_str = "magic_fix attribute expects a number";
502  goto error;
503  }
504 
505  treasure->magic_fix = atoi(value);
506  } else if (strcmp(key, "magic_chance") == 0) {
507  if (!string_isdigit(value)) {
508  error_str = "magic_chance attribute expects a number";
509  goto error;
510  }
511 
512  treasure->magic_chance = atoi(value);
513  } else if (strcmp(key, "difficulty") == 0) {
514  if (!string_isdigit(value)) {
515  error_str = "difficulty attribute expects a number";
516  goto error;
517  }
518 
519  treasure->difficulty = atoi(value);
520  } else {
521  error_str = "unrecognized attribute";
522  goto error;
523  }
524 
525  continue;
526 error:
527  LOG(ERROR,
528  "Error parsing %s, line %" PRIu64 ", %s: %s %s",
529  filename,
530  *linenum,
531  error_str != NULL ? error_str : "",
532  key != NULL ? key : "",
533  value != NULL ? value : "");
534  exit(1);
535  }
536 
537  LOG(ERROR, "Last treasure list lacks 'end'.");
538  exit(1);
539 
540  /* Unreachable. */
541  return NULL;
542 }
543 
556 static void
558  FILE *fp,
559  const char *filename,
560  uint64_t *linenum)
561 {
562  HARD_ASSERT(treasure != NULL);
563  HARD_ASSERT(fp != NULL);
564  HARD_ASSERT(filename != NULL);
565  HARD_ASSERT(linenum != NULL);
566 
567  treasure_affinity_t *affinity = NULL;
568  int artifact_chance = TREASURE_ARTIFACT_CHANCE;
569 
570  *treasure = treasure_load_one(fp,
571  filename,
572  linenum,
573  &affinity,
574  &artifact_chance);
575 
576  if ((*treasure)->artifact_chance == TREASURE_ARTIFACT_CHANCE) {
577  (*treasure)->artifact_chance = artifact_chance;
578  }
579 
580  if ((*treasure)->affinity == NULL) {
581  (*treasure)->affinity = affinity;
582  } else if (affinity != NULL) {
583  free_string_shared(affinity);
584  }
585 }
586 
592 static void
594 {
595  char filename[HUGE_BUF];
596  snprintf(VS(filename), "%s/treasures", settings.libpath);
597 
598  FILE *fp = fopen(filename, "r");
599  if (fp == NULL) {
600  LOG(ERROR, "Can't open treasures file: %s", filename);
601  exit(1);
602  }
603 
604  uint64_t linenum = 0;
605  char buf[MAX_BUF];
606  while (fgets(buf, MAX_BUF, fp) != NULL) {
607  linenum++;
608 
609  char *cp = buf;
610  string_skip_whitespace(cp);
611  string_strip_newline(cp);
612 
613  char *cps[2];
614  if (string_split(cp, cps, arraysize(cps), ' ') < 1) {
615  continue;
616  }
617 
618  const char *key = cps[0], *value = cps[1], *error_str = NULL;
619 
620  if (strcmp(key, "treasureone") == 0 ||
621  strcmp(key, "treasure") == 0) {
623  FREE_AND_COPY_HASH(treasure_list->name, value);
624 
625  /* Add it to the linked list of treasures. */
626  treasure_list->next = first_treasurelist;
627  first_treasurelist = treasure_list;
628 
629  treasure_affinity_t *affinity = NULL;
630  int artifact_chance = TREASURE_ARTIFACT_CHANCE;
631  treasure_list->items = treasure_load_one(fp,
632  filename,
633  &linenum,
634  &affinity,
635  &artifact_chance);
636 
637  if (treasure_list->artifact_chance == TREASURE_ARTIFACT_CHANCE) {
638  treasure_list->artifact_chance = artifact_chance;
639  }
640 
641  if (treasure_list->affinity == NULL) {
642  treasure_list->affinity = affinity;
643  } else if (affinity != NULL) {
644  free_string_shared(affinity);
645  }
646 
647  if (strcmp(key, "treasureone") == 0) {
648  for (treasure_t *treasure = treasure_list->items;
649  treasure != NULL;
650  treasure = treasure->next) {
651  if (treasure->next_yes || treasure->next_no) {
652  LOG(ERROR,
653  "Treasure %s is one item, but on treasure %s "
654  "the next_yes or next_no field is set",
655  treasure_list->name,
656  treasure->item != NULL ? treasure->item->name :
657  treasure->name);
658  exit(1);
659  }
660 
661  treasure_list->total_chance += treasure->chance;
662  }
663  }
664  } else {
665  error_str = "unrecognized attribute";
666  goto error;
667  }
668 
669  continue;
670 error:
671  LOG(ERROR,
672  "Error parsing %s, line %" PRIu64 ", %s: %s %s",
673  filename,
674  linenum,
675  error_str != NULL ? error_str : "",
676  key != NULL ? key : "",
677  value != NULL ? value : "");
678  exit(1);
679  }
680 
681  fclose(fp);
682 }
683 
689 static void
691 {
692  for (int i = 0; coins[i] != NULL; i++) {
693  coins_arch[i] = arch_find(coins[i]);
694  if (coins_arch[i] == NULL) {
695  LOG(ERROR, "Can't find %s.", coins[i]);
696  exit(1);
697  }
698  }
699 }
700 
709 static void
711 {
712  HARD_ASSERT(t != NULL);
713  HARD_ASSERT(tl != NULL);
714 
715  if (t->item == NULL && t->name == NULL) {
716  LOG(ERROR,
717  "Treasurelist %s has element with no name or archetype",
718  tl->name);
719  exit(1);
720  }
721 
722  if (t->chance >= 100 &&
723  t->next_yes != NULL &&
724  (t->next != NULL || t->next_no != NULL)) {
725  LOG(ERROR,
726  "Treasurelist %s has element that has 100%% generation, "
727  "next_yes field as well as next or next_no",
728  tl->name);
729  }
730 
731  if (t->name != NULL && t->name != shstr_cons.NONE) {
732  /* treasure_list_find will drop an error message if the treasure list
733  * cannot be found. */
734  (void) treasure_list_find(t->name);
735  }
736 
737  if (t->next != NULL) {
738  treasure_list_check(t->next, tl);
739  }
740 
741  if (t->next_yes != NULL) {
743  }
744 
745  if (t->next_no != NULL) {
747  }
748 }
749 
753 void
755 {
756  treasure_load();
758 
759  /* Perform some checks on how valid the treasure data actually is.
760  * Verify that list transitions work (ie, the list that it is
761  * supposed to transition to exists). Also, verify that at least the
762  * name or archetype is set for each treasure element. */
764  treasure != NULL;
765  treasure = treasure->next) {
767  }
768 
769  for (int i = 0; i < DIFFLEVELS; i++) {
770  int sum = 0;
771  for (int j = 0; j < MAXMAGIC + 1; j++) {
772  sum += difftomagic_list[i][j];
773  }
774 
775  if (sum != 100) {
776  log_error("Incorrect sum: %d", i);
777  }
778  }
779 }
780 
790 {
791  SOFT_ASSERT_RC(name != NULL, NULL, "name is NULL");
792 
793  /* Still initializing the treasure lists, so return NULL for now. */
794  if (first_treasurelist == NULL) {
795  return NULL;
796  }
797 
798  shstr *name_sh = find_string(name);
799  if (name_sh == NULL) {
800  goto out;
801  }
802 
803  if (name_sh == shstr_cons.none) {
804  return NULL;
805  }
806 
808  treasure_list != NULL;
810  if (name_sh == treasure_list->name) {
811  return treasure_list;
812  }
813  }
814 
815 out:
816  LOG(ERROR, "Couldn't find treasure list: %s", name);
817  return NULL;
818 }
819 
828 static int
829 magic_from_difficulty (int difficulty)
830 {
831  difficulty--;
832 
833  if (difficulty < 0) {
834  difficulty = 0;
835  } else if (difficulty >= DIFFLEVELS) {
836  difficulty = DIFFLEVELS - 1;
837  }
838 
839  int roll = rndm(0, 99);
840 
841  int magic;
842  for (magic = 0; magic < MAXMAGIC + 1; magic++) {
843  roll -= difftomagic_list[difficulty][magic];
844  if (roll < 0) {
845  break;
846  }
847  }
848 
849  if (magic == MAXMAGIC + 1) {
850  log_error("Table for difficulty %d bad", difficulty);
851  magic = 0;
852  }
853 
854  return rndm_chance(20) ? -magic : magic;
855 }
856 
868 static void
869 treasure_set_magical_bonus (object *op, int magic)
870 {
871  HARD_ASSERT(op != NULL);
872  HARD_ASSERT(magic != 0);
873 
875  op->magic = magic;
876 
877  if (magic < 0) {
878  SET_FLAG(op, FLAG_CURSED);
879  }
880 
881  if (op->arch != NULL) {
882  if (magic == 1) {
883  op->value += 5300;
884  } else if (magic == 2) {
885  op->value += 12300;
886  } else if (magic == 3) {
887  op->value += 24300;
888  } else if (magic == 4) {
889  op->value += 52300;
890  } else {
891  op->value += 88300;
892  }
893 
894  if (op->type == ARMOUR) {
895  ARMOUR_SPEED(op) = (ARMOUR_SPEED(&op->arch->clone) *
896  (100 + magic * 10)) / 100;
897  }
898 
899  if (magic < 0 && rndm_chance(3)) {
900  magic = -magic;
901  }
902 
903  op->weight = (op->arch->clone.weight * (100 - magic * 10)) / 100;
904  } else {
905  if (op->type == ARMOUR) {
906  ARMOUR_SPEED(op) = (ARMOUR_SPEED(op) * (100 + magic * 10)) / 100;
907  }
908 
909  if (magic < 0 && rndm_chance(3)) {
910  magic = -magic;
911  }
912 
913  op->weight = (op->weight * (100 - magic * 10)) / 100;
914  }
915 }
916 
936 static void
937 treasure_set_magic (object *op,
938  int difficulty,
939  int max_magic,
940  int fixed_magic,
941  int chance_magic,
942  int flags)
943 {
944  int magic;
945 
946  HARD_ASSERT(op != NULL);
947  HARD_ASSERT(difficulty > 0);
948 
949  /* If we have a fixed value, force it */
950  if (fixed_magic) {
951  magic = fixed_magic;
952  } else {
953  magic = magic_from_difficulty(difficulty);
954  if (magic > max_magic) {
955  magic = max_magic;
956  }
957  }
958 
959  if ((flags & GT_ONLY_GOOD) && magic < 0) {
960  return;
961  }
962 
963  if (magic != 0) {
964  treasure_set_magical_bonus(op, magic);
965  }
966 }
967 
978 static void
979 treasure_insert (object *op, object *creator, int flags)
980 {
981  HARD_ASSERT(op != NULL);
982  HARD_ASSERT(creator != NULL);
983 
984  if (flags & GT_ENVIRONMENT) {
985  op->x = creator->x;
986  op->y = creator->y;
987  object_insert_map(op, creator->map, op, INS_NO_MERGE | INS_NO_WALK_ON);
988  } else {
989  object_insert_into(op, creator, 0);
990  }
991 }
992 
1001 static void
1003 {
1004  HARD_ASSERT(op != NULL);
1005  HARD_ASSERT(attrs != NULL);
1006 
1007  if (attrs->name != NULL) {
1008  FREE_AND_COPY_HASH(op->name, attrs->name);
1009  }
1010 
1011  if (attrs->title != NULL) {
1012  FREE_AND_COPY_HASH(op->title, attrs->title);
1013  }
1014 
1015  if (attrs->slaying != NULL) {
1016  FREE_AND_COPY_HASH(op->slaying, attrs->slaying);
1017  }
1018 }
1019 
1028 static void
1030 {
1031  HARD_ASSERT(op != NULL);
1032  HARD_ASSERT(attrs != NULL);
1033 
1034  if (attrs->quality != -1) {
1035  op->item_quality = attrs->quality;
1036  } else {
1038  }
1039 
1040  if (attrs->quality_range > 0) {
1041  op->item_quality += rndm(0, attrs->quality_range);
1042 
1043  if (op->item_quality > 100) {
1044  op->item_quality = 100;
1045  }
1046  }
1047 
1048  op->item_condition = op->item_quality;
1049 }
1050 
1059 static void
1061 {
1062  HARD_ASSERT(op != NULL);
1063  HARD_ASSERT(attrs != NULL);
1064 
1065  if (op->type == MONEY) {
1066  return;
1067  }
1068 
1069  if (attrs->item_race != -1) {
1070  op->item_race = (uint8_t) attrs->item_race;
1071  }
1072 
1073  if (op->material_real == -1) {
1074  op->material_real = 0;
1075  return;
1076  }
1077 
1078  if (attrs->material != -1) {
1079  op->material_real = attrs->material;
1080 
1081  if (attrs->material_range > 0 && attrs->material != 0) {
1082  op->material_real += rndm(0, attrs->material_range);
1083  }
1084  } else if (op->material_real == 0 && op->material != M_NONE) {
1085  if (op->material & M_PAPER) {
1087  } else if (op->material & M_IRON) {
1089  } else if (op->material & M_GLASS) {
1091  } else if (op->material & M_LEATHER) {
1093  } else if (op->material & M_WOOD) {
1095  } else if (op->material & M_ORGANIC) {
1097  } else if (op->material & M_STONE) {
1099  } else if (op->material & M_CLOTH) {
1101  } else if (op->material & M_ADAMANT) {
1103  } else if (op->material & M_LIQUID) {
1105  } else if (op->material & M_SOFT_METAL) {
1107  } else if (op->material & M_BONE) {
1109  } else if (op->material & M_ICE) {
1110  op->material_real = M_START_ICE;
1111  }
1112  }
1113 
1114  if (attrs->material_quality != -1) {
1115  int best_material = -1;
1116  int material_quality = attrs->material_quality;
1117 
1118  /* Increase the material quality if there's a range. */
1119  if (attrs->material_range > 0) {
1120  material_quality += rndm(0, attrs->material_range);
1121  }
1122 
1123  if (op->material_real != 0) {
1124  int material_tmp = op->material_real / NROFMATERIALS_REAL;
1125 
1126  /* The first entry of the material_real of material table */
1127  material_tmp = material_tmp * 64 + 1;
1128 
1129  for (int i = 0; i < NROFMATERIALS_REAL; i++) {
1130  if (materials_real[material_tmp + i].quality ==
1131  material_quality) {
1132  op->material_real = material_tmp + i;
1133  treasure_set_quality(op, attrs);
1134  return;
1135  }
1136 
1137  if (materials_real[material_tmp + i].quality >=
1138  attrs->material_quality &&
1139  materials_real[material_tmp + i].quality <=
1140  material_quality &&
1141  materials_real[material_tmp + i].quality >
1142  best_material) {
1143  best_material = material_tmp + i;
1144  }
1145  }
1146 
1147  if (best_material == -1) {
1148  op->material_real = material_tmp;
1149  op->item_quality = attrs->material_quality;
1150  op->item_condition = op->item_quality;
1151  return;
1152  }
1153 
1154  /* That's now our best match! */
1155  op->material_real = best_material;
1156  } else {
1157  op->item_quality = material_quality;
1158  op->item_condition = op->item_quality;
1159  return;
1160  }
1161  }
1162 
1163  treasure_set_quality(op, attrs);
1164 }
1165 
1193 static void
1195  object *creator,
1196  int difficulty,
1197  int flags,
1198  int artifact_chance,
1199  treasure_affinity_t *affinity,
1200  int max_magic,
1201  int fixed_magic,
1202  int chance_magic,
1203  treasure_attrs_t *attrs)
1204 {
1205  HARD_ASSERT(op != NULL);
1206 
1207  /* Safety and to prevent polymorphed objects giving attributes. */
1208  if (creator == NULL || creator->type == op->type) {
1209  creator = op;
1210  }
1211 
1212  if (difficulty < 1) {
1213  difficulty = 1;
1214  }
1215 
1216  bool was_magical = op->magic != 0;
1217  bool generated_artifact = false;
1218 
1219  treasure_set_material(op, attrs);
1220 
1221  if (!OBJECT_METHODS(op->type)->override_treasure_processing) {
1222  if (creator->type == 0) {
1223  max_magic /= 2;
1224  }
1225 
1226  if ((op->magic == 0 && max_magic != 0) || fixed_magic != 0) {
1227  treasure_set_magic(op,
1228  difficulty,
1229  max_magic,
1230  fixed_magic,
1231  chance_magic,
1232  flags);
1233  }
1234 
1235  if (artifact_chance != 0) {
1236  if ((!was_magical && rndm_chance(CHANCE_FOR_ARTIFACT)) ||
1237  difficulty >= 999 ||
1238  rndm(1, 100) <= artifact_chance) {
1239  generated_artifact = artifact_generate(op,
1240  difficulty,
1241  affinity);
1242  }
1243  }
1244  }
1245 
1246  object *new_obj;
1247  int res = object_process_treasure(op,
1248  &new_obj,
1249  difficulty,
1250  affinity,
1251  flags);
1252  if (res == OBJECT_METHOD_ERROR) {
1253  return;
1254  } else if (res == OBJECT_METHOD_OK) {
1255  op = new_obj;
1256  } else if (res == OBJECT_METHOD_UNHANDLED && !generated_artifact) {
1257  treasure_apply_attrs(op, attrs);
1258  }
1259 
1260  SOFT_ASSERT(op != NULL, "Object is NULL");
1261 
1262  if ((flags & GT_NO_VALUE) && op->type != MONEY) {
1263  op->value = 0;
1264  }
1265 
1266  if (flags & GT_STARTEQUIP) {
1267  if (op->nrof < 2 &&
1268  op->type != CONTAINER &&
1269  op->type != MONEY &&
1270  !QUERY_FLAG(op, FLAG_IS_THROWN)) {
1272  } else if (op->type != MONEY) {
1273  op->value = 0;
1274  }
1275  }
1276 
1277  if (creator->type == TREASURE) {
1278  /* If treasure is "identified", created items are too. */
1279  if (QUERY_FLAG(creator, FLAG_IDENTIFIED)) {
1281  }
1282 
1283  /* Same with the no-pick attribute. */
1284  if (QUERY_FLAG(creator, FLAG_NO_PICK)) {
1285  SET_FLAG(op, FLAG_NO_PICK);
1286  }
1287  }
1288 
1289  treasure_insert(op, creator, flags);
1290 }
1291 
1312 static void
1314  object *op,
1315  int difficulty,
1316  int flags,
1317  treasure_affinity_t *affinity,
1318  int artifact_chance,
1319  int tries,
1320  treasure_attrs_t *attrs)
1321 {
1322  HARD_ASSERT(treasure != NULL);
1323  HARD_ASSERT(op != NULL);
1324 
1325  object *tmp;
1326 
1327  if (treasure->affinity != NULL) {
1328  affinity = treasure->affinity;
1329  }
1330 
1331  if (treasure->artifact_chance != TREASURE_ARTIFACT_CHANCE) {
1332  artifact_chance = treasure->artifact_chance;
1333  }
1334 
1335  if ((treasure->chance_fix != CHANCE_FIX && rndm_chance(treasure->chance_fix)) || (int) treasure->chance >= 100 || (rndm(1, 100) < (int) treasure->chance)) {
1336  if (treasure->name) {
1337  if (treasure->name != shstr_cons.NONE && difficulty >= treasure->difficulty) {
1338  treasure_generate_internal(treasure_list_find(treasure->name), op, difficulty, flags, affinity, artifact_chance, tries, attrs ? attrs : &treasure->attrs);
1339  }
1340  } else if (difficulty >= treasure->difficulty) {
1341  if (treasure->item->clone.type != WEALTH) {
1342  tmp = arch_to_object(treasure->item);
1343 
1344  if (treasure->nrof && tmp->nrof <= 1) {
1345  tmp->nrof = rndm(1, treasure->nrof);
1346  }
1347 
1349  op,
1350  difficulty,
1351  flags,
1352  artifact_chance,
1353  affinity,
1354  treasure->magic,
1355  treasure->magic_fix,
1356  treasure->magic_chance,
1357  attrs != NULL ? attrs : &treasure->attrs);
1358  } else {
1359  /* We have a wealth object - expand it to real money */
1360 
1361  /* If t->magic is != 0, that's our value - if not use
1362  * default setting */
1363  int i, value = treasure->magic ? treasure->magic : treasure->item->clone.value;
1364 
1365  value *= (difficulty / 2) + 1;
1366 
1367  /* So we have 80% to 120% of the fixed value */
1368  value = (int) ((float) value * 0.8f + (float) value * (rndm(1, 40) / 100.0f));
1369 
1370  for (i = 0; i < NUM_COINS; i++) {
1371  if (value / coins_arch[i]->clone.value > 0) {
1372  tmp = object_get();
1373  object_copy(tmp, &coins_arch[i]->clone, false);
1374  tmp->nrof = value / tmp->value;
1375  value -= tmp->nrof * tmp->value;
1376  treasure_insert(tmp, op, flags);
1377  }
1378  }
1379  }
1380  }
1381 
1382  if (treasure->next_yes != NULL) {
1383  treasure_create_all(treasure->next_yes, op, difficulty, flags, (treasure->next_yes->affinity == NULL) ? affinity : treasure->next_yes->affinity, artifact_chance, tries, attrs);
1384  }
1385  } else if (treasure->next_no != NULL) {
1386  treasure_create_all(treasure->next_no, op, difficulty, flags, (treasure->next_no->affinity == NULL) ? affinity : treasure->next_no->affinity, artifact_chance, tries, attrs);
1387  }
1388 
1389  if (treasure->next != NULL) {
1390  treasure_create_all(treasure->next, op, difficulty, flags, (treasure->next->affinity == NULL) ? affinity : treasure->next->affinity, artifact_chance, tries, attrs);
1391  }
1392 }
1393 
1415 static void
1417  object *op,
1418  int difficulty,
1419  int flags,
1420  treasure_affinity_t *affinity,
1421  int artifact_chance,
1422  int tries,
1423  treasure_attrs_t *attrs)
1424 {
1425  HARD_ASSERT(treasure_list != NULL);
1426  HARD_ASSERT(op != NULL);
1427 
1428  int value, diff_tries = 0;
1429  treasure_t *t;
1430  object *tmp;
1431 
1432  if (tries++ > 100) {
1433  return;
1434  }
1435 
1436  /* Well, at some point we should rework this whole system... */
1437 create_one_treasure_again_jmp:
1438 
1439  if (diff_tries > 10) {
1440  return;
1441  }
1442 
1443  value = rndm(1, treasure_list->total_chance) - 1;
1444 
1445  for (t = treasure_list->items; t != NULL; t = t->next) {
1446  /* chance_fix will overrule the normal chance stuff!. */
1447  if (t->chance_fix != CHANCE_FIX) {
1448  if (rndm_chance(t->chance_fix)) {
1449  /* Only when allowed, we go on! */
1450  if (difficulty >= t->difficulty) {
1451  value = 0;
1452  break;
1453  }
1454 
1455  /* Ok, difficulty is bad let's try again or break! */
1456  if (tries++ > 100) {
1457  return;
1458  }
1459 
1460  diff_tries++;
1461  goto create_one_treasure_again_jmp;
1462  }
1463 
1464  if (!t->chance) {
1465  continue;
1466  }
1467  }
1468 
1469  value -= t->chance;
1470 
1471  /* We got one! */
1472  if (value <= 0) {
1473  /* Only when allowed, we go on! */
1474  if (difficulty >= t->difficulty) {
1475  break;
1476  }
1477 
1478  /* Ok, difficulty is bad let's try again or break! */
1479  if (tries++ > 100) {
1480  return;
1481  }
1482 
1483  diff_tries++;
1484  goto create_one_treasure_again_jmp;
1485  }
1486  }
1487 
1488  if (!t || value > 0) {
1489  LOG(BUG, "create_one_treasure: got null object or not able to find treasure - tl:%s op:%s", treasure_list ? treasure_list->name : "(null)", op ? op->name : "(null)");
1490  return;
1491  }
1492 
1493  if (t->affinity != NULL) {
1494  affinity = t->affinity;
1495  }
1496 
1498  artifact_chance = t->artifact_chance;
1499  }
1500 
1501  if (t->name) {
1502  if (t->name == shstr_cons.NONE) {
1503  return;
1504  }
1505 
1506  if (difficulty >= t->difficulty) {
1507  treasure_generate_internal(treasure_list_find(t->name), op, difficulty, flags, affinity, artifact_chance, tries, attrs);
1508  } else if (t->nrof) {
1509  treasure_create_one(treasure_list, op, difficulty, flags, affinity, artifact_chance, tries, attrs);
1510  }
1511 
1512  return;
1513  }
1514 
1515  if (t->item->clone.type != WEALTH) {
1516  tmp = arch_to_object(t->item);
1517 
1518  if (t->nrof && tmp->nrof <= 1) {
1519  tmp->nrof = rndm(1, t->nrof);
1520  }
1521 
1523  op,
1524  difficulty,
1525  flags,
1526  artifact_chance,
1527  (t->affinity == NULL) ? affinity : t->affinity,
1528  t->magic,
1529  t->magic_fix,
1530  t->magic_chance,
1531  attrs != NULL ? attrs : &t->attrs);
1532  } else {
1533  /* We have a wealth object - expand it to real money */
1534 
1535  /* If t->magic is != 0, that's our value - if not use default
1536  * setting */
1537  int i;
1538 
1539  value = t->magic ? t->magic : t->item->clone.value;
1540  value *= difficulty;
1541 
1542  /* So we have 80% to 120% of the fixed value */
1543  value = (int) ((float) value * 0.8f + (float) value * (rndm(1, 40) / 100.0f));
1544 
1545  for (i = 0; i < NUM_COINS; i++) {
1546  if (value / coins_arch[i]->clone.value > 0) {
1547  tmp = object_get();
1548  object_copy(tmp, &coins_arch[i]->clone, false);
1549  tmp->nrof = value / tmp->value;
1550  value -= tmp->nrof * tmp->value;
1551  treasure_insert(tmp, op, flags);
1552  }
1553  }
1554  }
1555 }
1556 
1578 static void
1580  object *op,
1581  int difficulty,
1582  int flags,
1583  treasure_affinity_t *affinity,
1584  int artifact_chance,
1585  int tries,
1586  treasure_attrs_t *attrs)
1587 {
1588  HARD_ASSERT(treasure_list != NULL);
1589  HARD_ASSERT(op != NULL);
1590 
1591  if (tries++ > 100) {
1592  LOG(ERROR,
1593  "Tries reached maximum for treasure list %s.",
1594  treasure_list->name);
1595  return;
1596  }
1597 
1598  if (treasure_list->affinity != NULL) {
1599  affinity = treasure_list->affinity;
1600  }
1601 
1602  if (treasure_list->artifact_chance != TREASURE_ARTIFACT_CHANCE) {
1603  artifact_chance = treasure_list->artifact_chance;
1604  }
1605 
1606  if (treasure_list->total_chance != 0) {
1607  treasure_create_one(treasure_list,
1608  op,
1609  difficulty,
1610  flags,
1611  affinity,
1612  artifact_chance,
1613  tries,
1614  attrs);
1615  } else {
1616  treasure_create_all(treasure_list->items,
1617  op,
1618  difficulty,
1619  flags,
1620  affinity,
1621  artifact_chance,
1622  tries,
1623  attrs);
1624  }
1625 }
1626 
1640 void
1642  object *op,
1643  int difficulty,
1644  int flags)
1645 {
1646  SOFT_ASSERT(treasure_list != NULL, "NULL treasure list");
1647  SOFT_ASSERT(op != NULL, "NULL object");
1648 
1649  treasure_generate_internal(treasure_list,
1650  op,
1651  difficulty,
1652  flags,
1653  NULL,
1655  0,
1656  NULL);
1657 }
1658 
1671 object *
1673  int difficulty,
1674  int artifact_chance)
1675 {
1676  SOFT_ASSERT_RC(treasure_list != NULL,
1677  NULL,
1678  "NULL treasure list");
1679 
1680  object *op = object_get();
1681  treasure_generate_internal(treasure_list,
1682  op,
1683  difficulty,
1684  0,
1685  treasure_list->affinity,
1686  artifact_chance,
1687  0,
1688  NULL);
1689 
1690  object *tmp = op->inv;
1691  if (tmp != NULL) {
1692  object_remove(tmp, 0);
1693  }
1694 
1695  if (op->inv != NULL) {
1696  LOG(ERROR,
1697  "Created multiple objects, treasure list: %s",
1698  treasure_list->name);
1699  }
1700 
1701  object_destroy(op);
1702 
1703  return tmp;
1704 }
1705 
1713 {
1714  if (t->next) {
1716  }
1717 
1718  if (t->next_yes) {
1720  }
1721 
1722  if (t->next_no) {
1724  }
1725 
1731  efree(t);
1732 }
1733 
1738 {
1739  treasure_list_t *tl, *next;
1740 
1741  for (tl = first_treasurelist; tl; tl = next) {
1742  next = tl->next;
1745 
1746  if (tl->items) {
1748  }
1749 
1750  efree(tl);
1751  }
1752 }
1753 
1762 int get_environment_level(object *op)
1763 {
1764  object *env;
1765 
1766  if (!op) {
1767  return 1;
1768  }
1769 
1770  /* Return object level or map level... */
1771  if (op->level) {
1772  return op->level;
1773  }
1774 
1775  if (op->map) {
1776  return op->map->difficulty ? op->map->difficulty : 1;
1777  }
1778 
1779  /* Let's check for env */
1780  env = op->env;
1781 
1782  while (env) {
1783  if (env->level) {
1784  return env->level;
1785  }
1786 
1787  if (env->map) {
1788  return env->map->difficulty ? env->map->difficulty : 1;
1789  }
1790 
1791  env = env->env;
1792  }
1793 
1794  return 1;
1795 }
treasure_list_t * first_treasurelist
Definition: main.c:61
#define M_START_BONE
Definition: material.h:98
#define M_ORGANIC
Definition: material.h:58
#define GT_ONLY_GOOD
Definition: treasure.h:63
#define FREE_AND_COPY_HASH(_sv_, _nv_)
Definition: global.h:100
void object_destroy(object *ob)
Definition: object.c:1441
static void treasure_set_material(object *op, treasure_attrs_t *attrs)
Definition: treasure.c:1060
shstr * title
Definition: treasure.h:80
struct treasure * next_no
Definition: treasure.h:125
int difficulty
Definition: treasure.h:158
#define GT_STARTEQUIP
Definition: treasure.h:59
#define M_START_SOFT_METAL
Definition: material.h:96
#define FLAG_CURSED
Definition: define.h:1154
#define M_LIQUID
Definition: material.h:66
#define MAXMAGIC
Definition: treasure.h:47
int material_range
Definition: treasure.h:95
int16_t total_chance
Definition: treasure.h:193
#define GT_NO_VALUE
Definition: treasure.h:67
uint16_t material
Definition: object.h:304
static void treasure_process_generated(object *op, object *creator, int difficulty, int flags, int artifact_chance, treasure_affinity_t *affinity, int max_magic, int fixed_magic, int chance_magic, treasure_attrs_t *attrs)
Definition: treasure.c:1194
object * object_get(void)
Definition: object.c:993
void treasure_generate(treasure_list_t *treasure_list, object *op, int difficulty, int flags)
Definition: treasure.c:1641
#define FLAG_IS_THROWN
Definition: define.h:1170
#define OBJECT_METHOD_ERROR
#define M_START_ORGANIC
Definition: material.h:86
#define M_GLASS
Definition: material.h:52
int16_t chance_fix
Definition: treasure.h:165
struct archetype * coins_arch[NUM_COINS]
Definition: treasure.c:258
void object_copy(object *op, const object *src, bool no_speed)
Definition: object.c:886
#define TREASURE
Definition: define.h:134
const char * slaying
Definition: object.h:180
int16_t material_real
Definition: object.h:307
#define MONEY
Definition: define.h:226
#define WEALTH
Definition: define.h:498
uint8_t item_quality
Definition: object.h:366
static void treasure_load(void)
Definition: treasure.c:593
static treasure_list_t * treasure_list_create(void)
Definition: treasure.c:288
#define M_START_LIQUID
Definition: material.h:94
#define M_NONE
Definition: material.h:46
#define GT_ENVIRONMENT
Definition: treasure.h:57
#define QUERY_FLAG(xyz, p)
Definition: define.h:761
#define NROFMATERIALS_REAL
Definition: material.h:37
#define M_START_STONE
Definition: material.h:88
#define M_PAPER
Definition: material.h:48
struct archetype * arch
Definition: object.h:225
void object_remove(object *op, int flags)
Definition: object.c:1623
#define M_IRON
Definition: material.h:50
char libpath[MAX_BUF]
Definition: global.h:338
struct treasure * items
Definition: treasure.h:199
#define NUM_COINS
Definition: treasure.h:37
#define FLAG_STARTEQUIP
Definition: define.h:1004
int magic_chance
Definition: treasure.h:131
static void treasure_insert(object *op, object *creator, int flags)
Definition: treasure.c:979
static void free_treasurestruct(treasure_t *t)
Definition: treasure.c:1712
#define ARMOUR
Definition: define.h:182
material_real_t materials_real[NUM_MATERIALS_REAL]
Definition: material.c:56
shstr * slaying
Definition: treasure.h:83
const char * title
Definition: object.h:171
int16_t y
Definition: object.h:276
int material_quality
Definition: treasure.h:92
shstr * name
Definition: treasure.h:177
static void treasure_load_more(treasure_t **treasure, FILE *fp, const char *filename, uint64_t *linenum)
Definition: treasure.c:557
#define M_START_LEATHER
Definition: material.h:82
#define M_WOOD
Definition: material.h:56
Definition: arch.h:40
#define DIFFLEVELS
Definition: treasure.h:42
uint8_t item_race
Definition: object.h:372
#define M_LEATHER
Definition: material.h:54
uint8_t item_condition
Definition: object.h:369
struct sound_ambient_match * next
Next match rule in a linked list.
Definition: sound_ambient.c:39
uint32_t weight
Definition: object.h:246
int artifact_chance
Definition: treasure.h:149
#define FLAG_NO_PICK
Definition: define.h:900
#define CHANCE_FOR_ARTIFACT
Definition: treasure.h:34
object * object_insert_into(object *op, object *where, int flag)
Definition: object.c:2158
#define M_ICE
Definition: material.h:72
#define M_START_CLOTH
Definition: material.h:90
struct mapdef * map
Definition: object.h:139
int magic_fix
Definition: treasure.h:137
shstr * name
Definition: treasure.h:77
uint8_t chance
Definition: treasure.h:168
shstr * name
Definition: treasure.h:116
treasure_affinity_t * affinity
Definition: treasure.h:128
struct treasure_attrs attrs
Definition: treasure.h:171
const char * name
Definition: object.h:168
#define SET_FLAG(xyz, p)
Definition: define.h:741
struct obj * env
Definition: object.h:130
static const int difftomagic_list[DIFFLEVELS][MAXMAGIC+1]
Definition: treasure.c:51
#define CHANCE_FIX
Definition: treasure.c:261
int artifact_chance
Definition: treasure.h:183
object * arch_to_object(archetype_t *at)
Definition: arch.c:446
static treasure_t * treasure_create(void)
Definition: treasure.c:306
#define CONTAINER
Definition: define.h:493
static treasure_t * treasure_load_one(FILE *fp, const char *filename, uint64_t *linenum, treasure_affinity_t **affinity, int *artifact_chance)
Definition: treasure.c:343
#define INS_NO_WALK_ON
Definition: object.h:570
#define M_START_IRON
Definition: material.h:78
#define M_START_GLASS
Definition: material.h:80
uint32_t nrof
Definition: object.h:264
#define M_STONE
Definition: material.h:60
#define M_BONE
Definition: material.h:70
static void treasure_list_check(treasure_t *t, treasure_list_t *tl)
Definition: treasure.c:710
struct treasure * next_yes
Definition: treasure.h:122
#define OBJECT_METHOD_UNHANDLED
struct treasure * next
Definition: treasure.h:119
const char *const coins[NUM_COINS+1]
Definition: treasure.c:38
#define TREASURE_ARTIFACT_CHANCE
Artifact chance value is not set.
Definition: global.h:173
int16_t x
Definition: object.h:273
static int magic_from_difficulty(int difficulty)
Definition: treasure.c:829
int object_process_treasure(object *op, object **ret, int difficulty, treasure_affinity_t *affinity, int flags)
#define M_START_PAPER
Definition: material.h:76
#define M_ADAMANT
Definition: material.h:64
object * object_insert_map(object *op, mapstruct *m, object *originator, int flag)
Definition: object.c:1741
struct settings_struct settings
Definition: init.c:55
struct treasure_list * next
Definition: treasure.h:196
static void treasure_generate_internal(treasure_list_t *treasure_list, object *op, int difficulty, int flags, treasure_affinity_t *affinity, int artifact_chance, int tries, treasure_attrs_t *attrs)
Definition: treasure.c:1579
int difficulty
Definition: map.h:650
object * treasure_generate_single(treasure_list_t *treasure_list, int difficulty, int artifact_chance)
Definition: treasure.c:1672
#define INS_NO_MERGE
Definition: object.h:564
shstr_constants shstr_cons
Definition: init.c:58
static void treasure_init_coins(void)
Definition: treasure.c:690
#define M_SOFT_METAL
Definition: material.h:68
uint8_t type
Definition: object.h:360
#define M_CLOTH
Definition: material.h:62
treasure_affinity_t * affinity
Definition: treasure.h:180
#define OBJECT_METHODS(type)
shstr * name
More definite name, like "kobold".
Definition: arch.h:46
uint16_t nrof
Definition: treasure.h:161
bool artifact_generate(object *op, int difficulty, treasure_affinity_t *affinity)
Definition: artifact.c:541
static void treasure_create_all(treasure_t *treasure, object *op, int difficulty, int flags, treasure_affinity_t *affinity, int artifact_chance, int tries, treasure_attrs_t *attrs)
Definition: treasure.c:1313
#define OBJECT_METHOD_OK
void free_all_treasures(void)
Definition: treasure.c:1737
static void treasure_apply_attrs(object *op, treasure_attrs_t *attrs)
Definition: treasure.c:1002
#define FLAG_IS_MAGICAL
Definition: define.h:1129
struct obj * inv
Definition: object.h:123
treasure_list_t * treasure_list_find(const char *name)
Definition: treasure.c:789
void treasure_init(void)
Definition: treasure.c:754
int magic
Definition: treasure.h:152
int get_environment_level(object *op)
Definition: treasure.c:1762
#define M_START_ICE
Definition: material.h:100
struct archetype * item
Definition: treasure.h:113
static void treasure_set_quality(object *op, treasure_attrs_t *attrs)
Definition: treasure.c:1029
static void treasure_set_magic(object *op, int difficulty, int max_magic, int fixed_magic, int chance_magic, int flags)
Definition: treasure.c:937
int16_t chance_fix
Definition: treasure.h:186
#define M_START_WOOD
Definition: material.h:84
int quality_range
Definition: treasure.h:101
int8_t level
Definition: object.h:347
static void treasure_set_magical_bonus(object *op, int magic)
Definition: treasure.c:869
int64_t value
Definition: object.h:240
int8_t magic
Definition: object.h:341
object clone
An object from which to do object_copy().
Definition: arch.h:47
archetype_t * arch_find(const char *name)
Definition: arch.c:407
#define FREE_AND_CLEAR_HASH2(_nv_)
Definition: global.h:162
static void treasure_create_one(treasure_list_t *treasure_list, object *op, int difficulty, int flags, treasure_affinity_t *affinity, int artifact_chance, int tries, treasure_attrs_t *attrs)
Definition: treasure.c:1416
#define M_START_ADAMANT
Definition: material.h:92
#define FLAG_IDENTIFIED
Definition: define.h:980