ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/treasure.C
(Generate patch)

Comparing deliantra/server/common/treasure.C (file contents):
Revision 1.41 by root, Mon Apr 16 06:23:40 2007 UTC vs.
Revision 1.45 by root, Mon Apr 16 15:41:26 2007 UTC

20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * 21 *
22 * The authors can be reached via e-mail at <crossfire@schmorp.de> 22 * The authors can be reached via e-mail at <crossfire@schmorp.de>
23 */ 23 */
24 24
25#define ALLOWED_COMBINATION
26
27/* TREASURE_DEBUG does some checking on the treasurelists after loading. 25/* TREASURE_DEBUG does some checking on the treasurelists after loading.
28 * It is useful for finding bugs in the treasures file. Since it only 26 * It is useful for finding bugs in the treasures file. Since it only
29 * slows the startup some (and not actual game play), it is by default 27 * slows the startup some (and not actual game play), it is by default
30 * left on 28 * left on
31 */ 29 */
32#define TREASURE_DEBUG 30#define TREASURE_DEBUG
33 31
34/* TREASURE_VERBOSE enables copious output concerning artifact generation */ 32/* TREASURE_VERBOSE enables copious output concerning artifact generation */
35 33
36/* #define TREASURE_VERBOSE */ 34//#define TREASURE_VERBOSE
37 35
38#include <global.h> 36#include <global.h>
39#include <treasure.h> 37#include <treasure.h>
40#include <funcpoint.h> 38#include <funcpoint.h>
41#include <loader.h> 39#include <loader.h>
78 76
79 warn_archetypes = prev_warn; 77 warn_archetypes = prev_warn;
80} 78}
81 79
82/* 80/*
83 * Searches for the given treasurelist in the globally linked list 81 * Searches for the given treasurelist
84 * of treasurelists which has been built by load_treasures().
85 */ 82 */
86treasurelist * 83treasurelist *
87treasurelist::find (const char *name) 84treasurelist::find (const char *name)
88{ 85{
89 if (!name) 86 if (!name)
90 return 0; 87 return 0;
91 88
92 AUTODECL (i, tl_map.find (name)); 89 auto (i, tl_map.find (name));
93 90
94 if (i == tl_map.end ()) 91 if (i == tl_map.end ())
95 return 0; 92 return 0;
96 93
97 return i->second; 94 return i->second;
127 if (tl->items) 124 if (tl->items)
128 { 125 {
129 free_treasurestruct (tl->items); 126 free_treasurestruct (tl->items);
130 tl->items = 0; 127 tl->items = 0;
131 } 128 }
129
130 tl->total_chance = 0;
132} 131}
133 132
134/* 133/*
135 * Reads the lib/treasure file from disk, and parses the contents 134 * Reads the lib/treasure file from disk, and parses the contents
136 * into an internal treasure structure (very linked lists) 135 * into an internal treasure structure (very linked lists)
137 */ 136 */
138
139static treasure * 137static treasure *
140load_treasure (FILE * fp, int *line) 138load_treasure (object_thawer &f)
141{ 139{
142 char buf[MAX_BUF], *cp, variable[MAX_BUF];
143 treasure *t = new treasure; 140 treasure *t = new treasure;
144 int value; 141 int value;
145 142
146 nroftreasures++; 143 nroftreasures++;
147 while (fgets (buf, MAX_BUF, fp) != NULL)
148 {
149 (*line)++;
150 144
151 if (*buf == '#') 145 for (;;)
152 continue; 146 {
153 if ((cp = strchr (buf, '\n')) != NULL) 147 coroapi::cede_every (10);
154 *cp = '\0';
155 cp = buf;
156 while (isspace (*cp)) /* Skip blanks */
157 cp++;
158 148
159 if (sscanf (cp, "arch %s", variable)) 149 f.next ();
160 { 150
161 if ((t->item = archetype::find (variable)) == NULL) 151 switch (f.kw)
162 LOG (llevError, "Treasure lacks archetype: %s\n", variable);
163 } 152 {
164 else if (sscanf (cp, "list %s", variable)) 153 case KW_arch:
165 t->name = variable; 154 if (!(t->item = archetype::find (f.get_str ())))
166 else if (sscanf (cp, "change_name %s", variable)) 155 LOG (llevError, "%s:%d treasure references unknown archetype '%s', skipping.\n", f.name, f.linenum, f.get_str ());
167 t->change_arch.name = variable; 156 break;
168 else if (sscanf (cp, "change_title %s", variable)) 157
169 t->change_arch.title = variable; 158 case KW_list: f.get (t->name); break;
170 else if (sscanf (cp, "change_slaying %s", variable)) 159 case KW_change_name: f.get (t->change_arch.name); break;
171 t->change_arch.slaying = variable; 160 case KW_change_title: f.get (t->change_arch.title); break;
172 else if (sscanf (cp, "chance %d", &value)) 161 case KW_change_slaying: f.get (t->change_arch.slaying); break;
173 t->chance = (uint8) value; 162 case KW_chance: f.get (t->chance); break;
174 else if (sscanf (cp, "nrof %d", &value)) 163 case KW_nrof: f.get (t->nrof); break;
175 t->nrof = (uint16) value; 164 case KW_magic: f.get (t->magic); break;
176 else if (sscanf (cp, "magic %d", &value)) 165
177 t->magic = (uint8) value; 166 case KW_yes: t->next_yes = load_treasure (f); break;
178 else if (!strcmp (cp, "yes")) 167 case KW_no: t->next_no = load_treasure (f); break;
179 t->next_yes = load_treasure (fp, line); 168
180 else if (!strcmp (cp, "no")) 169 case KW_end:
181 t->next_no = load_treasure (fp, line);
182 else if (!strcmp (cp, "end"))
183 return t;
184 else if (!strcmp (cp, "more"))
185 {
186 t->next = load_treasure (fp, line);
187 return t; 170 return t;
171
172 case KW_more:
173 t->next = load_treasure (f);
174 return t;
175
176 default:
177 if (!f.parse_error ("treasure list"))
178 return t; // error
179
180 return t;
188 } 181 }
189 else
190 LOG (llevError, "Unknown treasure-command: '%s', last entry %s, line %d\n", cp, &t->name, *line);
191 } 182 }
192 LOG (llevError, "treasure lacks 'end'.\n");
193 return t;
194} 183}
195 184
196#ifdef TREASURE_DEBUG 185#ifdef TREASURE_DEBUG
197
198/* recursived checks the linked list. Treasurelist is passed only 186/* recursived checks the linked list. Treasurelist is passed only
199 * so that the treasure name can be printed out 187 * so that the treasure name can be printed out
200 */ 188 */
201static void 189static void
202check_treasurelist (const treasure *t, const treasurelist * tl) 190check_treasurelist (const treasure *t, const treasurelist * tl)
217 205
218/* 206/*
219 * Opens LIBDIR/treasure and reads all treasure-declarations from it. 207 * Opens LIBDIR/treasure and reads all treasure-declarations from it.
220 * Each treasure is parsed with the help of load_treasure(). 208 * Each treasure is parsed with the help of load_treasure().
221 */ 209 */
222 210bool
223void 211load_treasure_file (const char *filename)
224load_treasures (void)
225{ 212{
226 FILE *fp;
227 char filename[MAX_BUF], buf[MAX_BUF], name[MAX_BUF];
228 treasure *t; 213 treasure *t;
229 int comp, line = 0; 214 int comp, line = 0;
230 215
231 sprintf (filename, "%s/%s", settings.datadir, settings.treasures); 216 object_thawer f (filename);
232 if ((fp = open_and_uncompress (filename, 0, &comp)) == NULL) 217
218 if (!f)
233 { 219 {
234 LOG (llevError, "Can't open treasure file.\n"); 220 LOG (llevError, "Can't open treasure file.\n");
235 return; 221 return false;
236 }
237 while (fgets (buf, MAX_BUF, fp) != NULL)
238 { 222 }
239 line++;
240 if (*buf == '#' || *buf == '\n')
241 ; // ignore
242 else if (sscanf (buf, "treasureone %s\n", name) || sscanf (buf, "treasure %s\n", name))
243 {
244 treasurelist *tl = treasurelist::get (name);
245 223
246 clear (tl); 224 f.next ();
247 tl->items = load_treasure (fp, &line);
248 225
249 /* This is a one of the many items on the list should be generated. 226 for (;;)
250 * Add up the chance total, and check to make sure the yes & no 227 {
251 * fields of the treasures are not being used. 228 switch (f.kw)
252 */ 229 {
253 if (!strncmp (buf, "treasureone", 11)) 230 case KW_treasure:
231 case KW_treasureone:
254 { 232 {
255 for (t = tl->items; t; t = t->next) 233 bool one = f.kw == KW_treasureone;
234 treasurelist *tl = treasurelist::get (f.get_str ());
235
236 clear (tl);
237 tl->items = load_treasure (f);
238
239 if (!tl->items)
240 return false;
241
242 /* This is a one of the many items on the list should be generated.
243 * Add up the chance total, and check to make sure the yes & no
244 * fields of the treasures are not being used.
245 */
246 if (one)
256 { 247 {
248 for (t = tl->items; t; t = t->next)
249 {
257#ifdef TREASURE_DEBUG 250#ifdef TREASURE_DEBUG
258 if (t->next_yes || t->next_no) 251 if (t->next_yes || t->next_no)
259 { 252 {
260 LOG (llevError, "Treasure %s is one item, but on treasure %s\n", &tl->name, t->item ? &t->item->name : &t->name); 253 LOG (llevError, "Treasure %s is one item, but on treasure %s\n", &tl->name, t->item ? &t->item->name : &t->name);
261 LOG (llevError, " the next_yes or next_no field is set\n"); 254 LOG (llevError, " the next_yes or next_no field is set\n");
255 }
256#endif
257 tl->total_chance += t->chance;
262 } 258 }
263#endif
264 tl->total_chance += t->chance;
265 } 259 }
266 } 260 }
267 } 261 break;
268 else
269 LOG (llevError, "Treasure-list %s didn't understand: %s, line %d\n", filename, buf, line);
270 }
271 262
272 close_and_delete (fp, comp); 263 case KW_EOF:
273
274#ifdef TREASURE_DEBUG 264#ifdef TREASURE_DEBUG
275 /* Perform some checks on how valid the treasure data actually is. 265 /* Perform some checks on how valid the treasure data actually is.
276 * verify that list transitions work (ie, the list that it is supposed 266 * verify that list transitions work (ie, the list that it is supposed
277 * to transition to exists). Also, verify that at least the name 267 * to transition to exists). Also, verify that at least the name
278 * or archetype is set for each treasure element. 268 * or archetype is set for each treasure element.
279 */ 269 */
280 for (treasurelist *tl = first_treasurelist; tl; tl = tl->next) 270 for (treasurelist *tl = first_treasurelist; tl; tl = tl->next)
281 check_treasurelist (tl->items, tl); 271 check_treasurelist (tl->items, tl);
282#endif 272#endif
273 return true;
274
275 default:
276 if (!f.parse_error ("treasure lists"))
277 return false;
278
279 break;
280 }
281
282 f.next ();
283 }
283} 284}
284 285
285/* 286/*
286 * Generates the objects specified by the given treasure. 287 * Generates the objects specified by the given treasure.
287 * It goes recursively through the rest of the linked list. 288 * It goes recursively through the rest of the linked list.
482 * magical bonus "wanted". 483 * magical bonus "wanted".
483 */ 484 */
484 485
485static int difftomagic_list[DIFFLEVELS][MAXMAGIC + 1] = { 486static int difftomagic_list[DIFFLEVELS][MAXMAGIC + 1] = {
486 487
487/*chance of magic difficulty*/ 488// chance of magic difficulty
488
489/* +0 +1 +2 +3 +4 */ 489// +0 +1 +2 +3 +4
490 {95, 2, 2, 1, 0}, /*1 */ 490 {95, 2, 2, 1, 0}, // 1
491 {92, 5, 2, 1, 0}, /*2 */ 491 {92, 5, 2, 1, 0}, // 2
492 {85, 10, 4, 1, 0}, /*3 */ 492 {85, 10, 4, 1, 0}, // 3
493 {80, 14, 4, 2, 0}, /*4 */ 493 {80, 14, 4, 2, 0}, // 4
494 {75, 17, 5, 2, 1}, /*5 */ 494 {75, 17, 5, 2, 1}, // 5
495 {70, 18, 8, 3, 1}, /*6 */ 495 {70, 18, 8, 3, 1}, // 6
496 {65, 21, 10, 3, 1}, /*7 */ 496 {65, 21, 10, 3, 1}, // 7
497 {60, 22, 12, 4, 2}, /*8 */ 497 {60, 22, 12, 4, 2}, // 8
498 {55, 25, 14, 4, 2}, /*9 */ 498 {55, 25, 14, 4, 2}, // 9
499 {50, 27, 16, 5, 2}, /*10 */ 499 {50, 27, 16, 5, 2}, // 10
500 {45, 28, 18, 6, 3}, /*11 */ 500 {45, 28, 18, 6, 3}, // 11
501 {42, 28, 20, 7, 3}, /*12 */ 501 {42, 28, 20, 7, 3}, // 12
502 {40, 27, 21, 8, 4}, /*13 */ 502 {40, 27, 21, 8, 4}, // 13
503 {38, 25, 22, 10, 5}, /*14 */ 503 {38, 25, 22, 10, 5}, // 14
504 {36, 23, 23, 12, 6}, /*15 */ 504 {36, 23, 23, 12, 6}, // 15
505 {33, 21, 24, 14, 8}, /*16 */ 505 {33, 21, 24, 14, 8}, // 16
506 {31, 19, 25, 16, 9}, /*17 */ 506 {31, 19, 25, 16, 9}, // 17
507 {27, 15, 30, 18, 10}, /*18 */ 507 {27, 15, 30, 18, 10}, // 18
508 {20, 12, 30, 25, 13}, /*19 */ 508 {20, 12, 30, 25, 13}, // 19
509 {15, 10, 28, 30, 17}, /*20 */ 509 {15, 10, 28, 30, 17}, // 20
510 {13, 9, 27, 28, 23}, /*21 */ 510 {13, 9, 27, 28, 23}, // 21
511 {10, 8, 25, 28, 29}, /*22 */ 511 {10, 8, 25, 28, 29}, // 22
512 {8, 7, 23, 26, 36}, /*23 */ 512 { 8, 7, 23, 26, 36}, // 23
513 {6, 6, 20, 22, 46}, /*24 */ 513 { 6, 6, 20, 22, 46}, // 24
514 {4, 5, 17, 18, 56}, /*25 */ 514 { 4, 5, 17, 18, 56}, // 25
515 {2, 4, 12, 14, 68}, /*26 */ 515 { 2, 4, 12, 14, 68}, // 26
516 {0, 3, 7, 10, 80}, /*27 */ 516 { 0, 3, 7, 10, 80}, // 27
517 {0, 0, 3, 7, 90}, /*28 */ 517 { 0, 0, 3, 7, 90}, // 28
518 {0, 0, 0, 3, 97}, /*29 */ 518 { 0, 0, 0, 3, 97}, // 29
519 {0, 0, 0, 0, 100}, /*30 */ 519 { 0, 0, 0, 0, 100}, // 30
520 {0, 0, 0, 0, 100}, /*31 */ 520 { 0, 0, 0, 0, 100}, // 31
521}; 521};
522 522
523 523
524/* calculate the appropriate level for wands staves and scrolls. 524/* calculate the appropriate level for wands staves and scrolls.
525 * This code presumes that op has had its spell object created (in op->inv) 525 * This code presumes that op has had its spell object created (in op->inv)
847 847
848 if (op->randomitems && op->type != SPELL) 848 if (op->randomitems && op->type != SPELL)
849 { 849 {
850 create_treasure (op->randomitems, op, flags, difficulty, 0); 850 create_treasure (op->randomitems, op, flags, difficulty, 0);
851 if (!op->inv) 851 if (!op->inv)
852 LOG (llevDebug, "fix_generated_item: Unable to generate treasure for %s\n", &op->name); 852 LOG (llevDebug, "fix_generated_item: Unable to generate treasure for %s\n", op->debug_desc ());
853 853
854 /* So the treasure doesn't get created again */ 854 /* So the treasure doesn't get created again */
855 op->randomitems = NULL; 855 op->randomitems = 0;
856 } 856 }
857 857
858 if (difficulty < 1) 858 if (difficulty < 1)
859 difficulty = 1; 859 difficulty = 1;
860 860
1457 int i, tmp; 1457 int i, tmp;
1458 1458
1459 if (change->face != blank_face) 1459 if (change->face != blank_face)
1460 { 1460 {
1461#ifdef TREASURE_VERBOSE 1461#ifdef TREASURE_VERBOSE
1462 LOG (llevDebug, "FACE: %d\n", change->face->number); 1462 LOG (llevDebug, "add_abilities change face: %d\n", change->face);
1463#endif 1463#endif
1464 op->face = change->face; 1464 op->face = change->face;
1465 } 1465 }
1466 1466
1467 for (i = 0; i < NUM_STATS; i++) 1467 for (i = 0; i < NUM_STATS; i++)
1648 if (art->allowed == (linked_char *) NULL) 1648 if (art->allowed == (linked_char *) NULL)
1649 return 1; /* Ie, "all" */ 1649 return 1; /* Ie, "all" */
1650 for (tmp = art->allowed; tmp; tmp = tmp->next) 1650 for (tmp = art->allowed; tmp; tmp = tmp->next)
1651 { 1651 {
1652#ifdef TREASURE_VERBOSE 1652#ifdef TREASURE_VERBOSE
1653 LOG (llevDebug, "legal_art: %s\n", tmp->name); 1653 LOG (llevDebug, "legal_art: %s\n", &tmp->name);
1654#endif 1654#endif
1655 if (*tmp->name == '!') 1655 if (*tmp->name == '!')
1656 name = tmp->name + 1, neg = 1; 1656 name = tmp->name + 1, neg = 1;
1657 else 1657 else
1658 name = tmp->name, neg = 0; 1658 name = tmp->name, neg = 0;
1753 continue; 1753 continue;
1754 1754
1755 if (!legal_artifact_combination (op, art)) 1755 if (!legal_artifact_combination (op, art))
1756 { 1756 {
1757#ifdef TREASURE_VERBOSE 1757#ifdef TREASURE_VERBOSE
1758 LOG (llevDebug, "%s of %s was not a legal combination.\n", op->name, art->item->name); 1758 LOG (llevDebug, "%s of %s was not a legal combination.\n", &op->name, &art->item->name);
1759#endif 1759#endif
1760 continue; 1760 continue;
1761 } 1761 }
1762
1762 give_artifact_abilities (op, art->item); 1763 give_artifact_abilities (op, art->item);
1763 return; 1764 return;
1764 } 1765 }
1765} 1766}
1766 1767

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines