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.47 by root, Tue Apr 17 18:24:30 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}
132
133#ifdef TREASURE_DEBUG
134/* recursived checks the linked list. Treasurelist is passed only
135 * so that the treasure name can be printed out
136 */
137static void
138check_treasurelist (const treasure *t, const treasurelist * tl)
139{
140 if (t->chance >= 100 && t->next_yes && (t->next || t->next_no))
141 LOG (llevError, "Treasurelist %s has element that has 100%% generation, next_yes field as well as next or next_no\n", &tl->name);
142
143 if (t->next)
144 check_treasurelist (t->next, tl);
145
146 if (t->next_yes)
147 check_treasurelist (t->next_yes, tl);
148
149 if (t->next_no)
150 check_treasurelist (t->next_no, tl);
151}
152#endif
133 153
134/* 154/*
135 * Reads the lib/treasure file from disk, and parses the contents 155 * Reads the lib/treasure file from disk, and parses the contents
136 * into an internal treasure structure (very linked lists) 156 * into an internal treasure structure (very linked lists)
137 */ 157 */
138
139static treasure * 158static treasure *
140load_treasure (FILE * fp, int *line) 159read_treasure (object_thawer &f)
141{ 160{
142 char buf[MAX_BUF], *cp, variable[MAX_BUF];
143 treasure *t = new treasure; 161 treasure *t = new treasure;
144 int value;
145 162
146 nroftreasures++; 163 f.next ();
147 while (fgets (buf, MAX_BUF, fp) != NULL)
148 {
149 (*line)++;
150 164
151 if (*buf == '#') 165 for (;;)
152 continue; 166 {
153 if ((cp = strchr (buf, '\n')) != NULL) 167 coroapi::cede_to_tick_every (10);
154 *cp = '\0';
155 cp = buf;
156 while (isspace (*cp)) /* Skip blanks */
157 cp++;
158 168
159 if (sscanf (cp, "arch %s", variable)) 169 switch (f.kw)
160 {
161 if ((t->item = archetype::find (variable)) == NULL)
162 LOG (llevError, "Treasure lacks archetype: %s\n", variable);
163 } 170 {
164 else if (sscanf (cp, "list %s", variable)) 171 case KW_arch:
165 t->name = variable; 172 if (!(t->item = archetype::find (f.get_str ())))
166 else if (sscanf (cp, "change_name %s", variable)) 173 LOG (llevError, "%s:%d treasure references unknown archetype '%s', skipping.\n", f.name, f.linenum, f.get_str ());
167 t->change_arch.name = variable; 174 break;
168 else if (sscanf (cp, "change_title %s", variable)) 175
169 t->change_arch.title = variable; 176 case KW_list: f.get (t->name); break;
170 else if (sscanf (cp, "change_slaying %s", variable)) 177 case KW_change_name: f.get (t->change_arch.name); break;
171 t->change_arch.slaying = variable; 178 case KW_change_title: f.get (t->change_arch.title); break;
172 else if (sscanf (cp, "chance %d", &value)) 179 case KW_change_slaying: f.get (t->change_arch.slaying); break;
173 t->chance = (uint8) value; 180 case KW_chance: f.get (t->chance); break;
174 else if (sscanf (cp, "nrof %d", &value)) 181 case KW_nrof: f.get (t->nrof); break;
175 t->nrof = (uint16) value; 182 case KW_magic: f.get (t->magic); break;
176 else if (sscanf (cp, "magic %d", &value)) 183
177 t->magic = (uint8) value; 184 case KW_yes: t->next_yes = read_treasure (f); continue;
178 else if (!strcmp (cp, "yes")) 185 case KW_no: t->next_no = read_treasure (f); continue;
179 t->next_yes = load_treasure (fp, line); 186
180 else if (!strcmp (cp, "no")) 187 case KW_end:
181 t->next_no = load_treasure (fp, line); 188 f.next ();
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; 189 return t;
188 }
189 else
190 LOG (llevError, "Unknown treasure-command: '%s', last entry %s, line %d\n", cp, &t->name, *line);
191 }
192 LOG (llevError, "treasure lacks 'end'.\n");
193 return t;
194}
195 190
196#ifdef TREASURE_DEBUG 191 case KW_more:
192 t->next = read_treasure (f);
193 return t;
197 194
198/* recursived checks the linked list. Treasurelist is passed only 195 default:
199 * so that the treasure name can be printed out 196 if (!f.parse_error ("treasurelist", t->name))
200 */ 197 return 0;
201static void
202check_treasurelist (const treasure *t, const treasurelist * tl)
203{
204 if (t->chance >= 100 && t->next_yes && (t->next || t->next_no))
205 LOG (llevError, "Treasurelist %s has element that has 100%% generation, next_yes field as well as next or next_no\n", &tl->name);
206 198
207 if (t->next) 199 return t;
208 check_treasurelist (t->next, tl); 200 }
209 201
210 if (t->next_yes) 202 f.next ();
211 check_treasurelist (t->next_yes, tl); 203 }
212
213 if (t->next_no)
214 check_treasurelist (t->next_no, tl);
215} 204}
216#endif
217 205
218/* 206/*
219 * Opens LIBDIR/treasure and reads all treasure-declarations from it.
220 * Each treasure is parsed with the help of load_treasure(). 207 * Each treasure is parsed with the help of load_treasure().
221 */ 208 */
222 209treasurelist *
223void 210treasurelist::read (object_thawer &f)
224load_treasures (void)
225{ 211{
226 FILE *fp; 212 assert (f.kw == KW_treasure || f.kw == KW_treasureone);
227 char filename[MAX_BUF], buf[MAX_BUF], name[MAX_BUF];
228 treasure *t;
229 int comp, line = 0;
230 213
231 sprintf (filename, "%s/%s", settings.datadir, settings.treasures); 214 bool one = f.kw == KW_treasureone;
232 if ((fp = open_and_uncompress (filename, 0, &comp)) == NULL) 215 treasurelist *tl = treasurelist::get (f.get_str ());
233 { 216 clear (tl);
234 LOG (llevError, "Can't open treasure file.\n"); 217 tl->items = read_treasure (f);
218 if (!tl->items)
235 return; 219 return 0;
236 }
237 while (fgets (buf, MAX_BUF, fp) != NULL)
238 {
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 220
246 clear (tl);
247 tl->items = load_treasure (fp, &line);
248
249 /* This is a one of the many items on the list should be generated. 221 /* This is a one of the many items on the list should be generated.
250 * Add up the chance total, and check to make sure the yes & no 222 * Add up the chance total, and check to make sure the yes & no
251 * fields of the treasures are not being used. 223 * fields of the treasures are not being used.
252 */ 224 */
253 if (!strncmp (buf, "treasureone", 11)) 225 tl->total_chance = 0;
226
227 if (one)
228 {
229 for (treasure *t = tl->items; t; t = t->next)
230 {
231 if (t->next_yes || t->next_no)
254 { 232 {
255 for (t = tl->items; t; t = t->next)
256 {
257#ifdef TREASURE_DEBUG
258 if (t->next_yes || t->next_no)
259 {
260 LOG (llevError, "Treasure %s is one item, but on treasure %s\n", &tl->name, t->item ? &t->item->name : &t->name); 233 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"); 234 LOG (llevError, " the next_yes or next_no field is set\n");
262 }
263#endif
264 tl->total_chance += t->chance;
265 }
266 } 235 }
267 }
268 else
269 LOG (llevError, "Treasure-list %s didn't understand: %s, line %d\n", filename, buf, line);
270 }
271 236
272 close_and_delete (fp, comp); 237 tl->total_chance += t->chance;
238 }
239 }
273 240
274#ifdef TREASURE_DEBUG 241 return tl;
275 /* Perform some checks on how valid the treasure data actually is.
276 * verify that list transitions work (ie, the list that it is supposed
277 * to transition to exists). Also, verify that at least the name
278 * or archetype is set for each treasure element.
279 */
280 for (treasurelist *tl = first_treasurelist; tl; tl = tl->next)
281 check_treasurelist (tl->items, tl);
282#endif
283} 242}
284 243
285/* 244/*
286 * Generates the objects specified by the given treasure. 245 * Generates the objects specified by the given treasure.
287 * It goes recursively through the rest of the linked list. 246 * It goes recursively through the rest of the linked list.
346 if ((int) t->chance >= 100 || (rndm (100) + 1) < (int) t->chance) 305 if ((int) t->chance >= 100 || (rndm (100) + 1) < (int) t->chance)
347 { 306 {
348 if (t->name) 307 if (t->name)
349 { 308 {
350 if (difficulty >= t->magic) 309 if (difficulty >= t->magic)
310 if (treasurelist *tl = treasurelist::find (t->name))
351 create_treasure (treasurelist::find (t->name), op, flag, difficulty, tries); 311 create_treasure (tl, op, flag, difficulty, tries);
312 else
313 LOG (llevError, "create_all_treasures: undefined reference to treasurelist '%s'.\n", &t->name);
352 } 314 }
353 else 315 else
354 { 316 {
355 if (t->item && (t->item->clone.invisible != 0 || !(flag & GT_INVISIBLE))) 317 if (t->item && (t->item->clone.invisible != 0 || !(flag & GT_INVISIBLE)))
356 { 318 {
482 * magical bonus "wanted". 444 * magical bonus "wanted".
483 */ 445 */
484 446
485static int difftomagic_list[DIFFLEVELS][MAXMAGIC + 1] = { 447static int difftomagic_list[DIFFLEVELS][MAXMAGIC + 1] = {
486 448
487/*chance of magic difficulty*/ 449// chance of magic difficulty
488
489/* +0 +1 +2 +3 +4 */ 450// +0 +1 +2 +3 +4
490 {95, 2, 2, 1, 0}, /*1 */ 451 {95, 2, 2, 1, 0}, // 1
491 {92, 5, 2, 1, 0}, /*2 */ 452 {92, 5, 2, 1, 0}, // 2
492 {85, 10, 4, 1, 0}, /*3 */ 453 {85, 10, 4, 1, 0}, // 3
493 {80, 14, 4, 2, 0}, /*4 */ 454 {80, 14, 4, 2, 0}, // 4
494 {75, 17, 5, 2, 1}, /*5 */ 455 {75, 17, 5, 2, 1}, // 5
495 {70, 18, 8, 3, 1}, /*6 */ 456 {70, 18, 8, 3, 1}, // 6
496 {65, 21, 10, 3, 1}, /*7 */ 457 {65, 21, 10, 3, 1}, // 7
497 {60, 22, 12, 4, 2}, /*8 */ 458 {60, 22, 12, 4, 2}, // 8
498 {55, 25, 14, 4, 2}, /*9 */ 459 {55, 25, 14, 4, 2}, // 9
499 {50, 27, 16, 5, 2}, /*10 */ 460 {50, 27, 16, 5, 2}, // 10
500 {45, 28, 18, 6, 3}, /*11 */ 461 {45, 28, 18, 6, 3}, // 11
501 {42, 28, 20, 7, 3}, /*12 */ 462 {42, 28, 20, 7, 3}, // 12
502 {40, 27, 21, 8, 4}, /*13 */ 463 {40, 27, 21, 8, 4}, // 13
503 {38, 25, 22, 10, 5}, /*14 */ 464 {38, 25, 22, 10, 5}, // 14
504 {36, 23, 23, 12, 6}, /*15 */ 465 {36, 23, 23, 12, 6}, // 15
505 {33, 21, 24, 14, 8}, /*16 */ 466 {33, 21, 24, 14, 8}, // 16
506 {31, 19, 25, 16, 9}, /*17 */ 467 {31, 19, 25, 16, 9}, // 17
507 {27, 15, 30, 18, 10}, /*18 */ 468 {27, 15, 30, 18, 10}, // 18
508 {20, 12, 30, 25, 13}, /*19 */ 469 {20, 12, 30, 25, 13}, // 19
509 {15, 10, 28, 30, 17}, /*20 */ 470 {15, 10, 28, 30, 17}, // 20
510 {13, 9, 27, 28, 23}, /*21 */ 471 {13, 9, 27, 28, 23}, // 21
511 {10, 8, 25, 28, 29}, /*22 */ 472 {10, 8, 25, 28, 29}, // 22
512 {8, 7, 23, 26, 36}, /*23 */ 473 { 8, 7, 23, 26, 36}, // 23
513 {6, 6, 20, 22, 46}, /*24 */ 474 { 6, 6, 20, 22, 46}, // 24
514 {4, 5, 17, 18, 56}, /*25 */ 475 { 4, 5, 17, 18, 56}, // 25
515 {2, 4, 12, 14, 68}, /*26 */ 476 { 2, 4, 12, 14, 68}, // 26
516 {0, 3, 7, 10, 80}, /*27 */ 477 { 0, 3, 7, 10, 80}, // 27
517 {0, 0, 3, 7, 90}, /*28 */ 478 { 0, 0, 3, 7, 90}, // 28
518 {0, 0, 0, 3, 97}, /*29 */ 479 { 0, 0, 0, 3, 97}, // 29
519 {0, 0, 0, 0, 100}, /*30 */ 480 { 0, 0, 0, 0, 100}, // 30
520 {0, 0, 0, 0, 100}, /*31 */ 481 { 0, 0, 0, 0, 100}, // 31
521}; 482};
522 483
523 484
524/* calculate the appropriate level for wands staves and scrolls. 485/* calculate the appropriate level for wands staves and scrolls.
525 * This code presumes that op has had its spell object created (in op->inv) 486 * This code presumes that op has had its spell object created (in op->inv)
847 808
848 if (op->randomitems && op->type != SPELL) 809 if (op->randomitems && op->type != SPELL)
849 { 810 {
850 create_treasure (op->randomitems, op, flags, difficulty, 0); 811 create_treasure (op->randomitems, op, flags, difficulty, 0);
851 if (!op->inv) 812 if (!op->inv)
852 LOG (llevDebug, "fix_generated_item: Unable to generate treasure for %s\n", &op->name); 813 LOG (llevDebug, "fix_generated_item: Unable to generate treasure for %s\n", op->debug_desc ());
853 814
854 /* So the treasure doesn't get created again */ 815 /* So the treasure doesn't get created again */
855 op->randomitems = NULL; 816 op->randomitems = 0;
856 } 817 }
857 818
858 if (difficulty < 1) 819 if (difficulty < 1)
859 difficulty = 1; 820 difficulty = 1;
860 821
1354 { 1315 {
1355 switch (f.kw) 1316 switch (f.kw)
1356 { 1317 {
1357 case KW_allowed: 1318 case KW_allowed:
1358 if (!art) 1319 if (!art)
1359 {
1360 art = get_empty_artifact (); 1320 art = get_empty_artifact ();
1361 nrofartifacts++;
1362 }
1363 1321
1364 { 1322 {
1365 if (!strcmp (f.get_str (), "all")) 1323 if (!strcmp (f.get_str (), "all"))
1366 break; 1324 break;
1367 1325
1368 char *next, *cp = f.get_str (); 1326 char *next, *cp = f.get_str ();
1369 1327
1370 do 1328 do
1371 { 1329 {
1372 nrofallowedstr++;
1373
1374 if ((next = strchr (cp, ','))) 1330 if ((next = strchr (cp, ',')))
1375 *next++ = '\0'; 1331 *next++ = '\0';
1376 1332
1377 linked_char *tmp = new linked_char; 1333 linked_char *tmp = new linked_char;
1378 1334
1428 } 1384 }
1429 1385
1430done: 1386done:
1431 for (al = first_artifactlist; al; al = al->next) 1387 for (al = first_artifactlist; al; al = al->next)
1432 { 1388 {
1389 al->total_chance = 0;
1390
1433 for (art = al->items; art; art = art->next) 1391 for (art = al->items; art; art = art->next)
1434 { 1392 {
1435 if (!art->chance) 1393 if (!art->chance)
1436 LOG (llevError, "Warning: artifact with no chance: %s\n", &art->item->name); 1394 LOG (llevError, "Warning: artifact with no chance: %s\n", &art->item->name);
1437 else 1395 else
1443 } 1401 }
1444 1402
1445 LOG (llevDebug, "done.\n"); 1403 LOG (llevDebug, "done.\n");
1446} 1404}
1447 1405
1448
1449/* 1406/*
1450 * Used in artifact generation. The bonuses of the first object 1407 * Used in artifact generation. The bonuses of the first object
1451 * is modified by the bonuses of the second object. 1408 * is modified by the bonuses of the second object.
1452 */ 1409 */
1453
1454void 1410void
1455add_abilities (object *op, object *change) 1411add_abilities (object *op, object *change)
1456{ 1412{
1457 int i, tmp; 1413 int i, tmp;
1458 1414
1459 if (change->face != blank_face) 1415 if (change->face != blank_face)
1460 { 1416 {
1461#ifdef TREASURE_VERBOSE 1417#ifdef TREASURE_VERBOSE
1462 LOG (llevDebug, "FACE: %d\n", change->face->number); 1418 LOG (llevDebug, "add_abilities change face: %d\n", change->face);
1463#endif 1419#endif
1464 op->face = change->face; 1420 op->face = change->face;
1465 } 1421 }
1466 1422
1467 for (i = 0; i < NUM_STATS; i++) 1423 for (i = 0; i < NUM_STATS; i++)
1648 if (art->allowed == (linked_char *) NULL) 1604 if (art->allowed == (linked_char *) NULL)
1649 return 1; /* Ie, "all" */ 1605 return 1; /* Ie, "all" */
1650 for (tmp = art->allowed; tmp; tmp = tmp->next) 1606 for (tmp = art->allowed; tmp; tmp = tmp->next)
1651 { 1607 {
1652#ifdef TREASURE_VERBOSE 1608#ifdef TREASURE_VERBOSE
1653 LOG (llevDebug, "legal_art: %s\n", tmp->name); 1609 LOG (llevDebug, "legal_art: %s\n", &tmp->name);
1654#endif 1610#endif
1655 if (*tmp->name == '!') 1611 if (*tmp->name == '!')
1656 name = tmp->name + 1, neg = 1; 1612 name = tmp->name + 1, neg = 1;
1657 else 1613 else
1658 name = tmp->name, neg = 0; 1614 name = tmp->name, neg = 0;
1753 continue; 1709 continue;
1754 1710
1755 if (!legal_artifact_combination (op, art)) 1711 if (!legal_artifact_combination (op, art))
1756 { 1712 {
1757#ifdef TREASURE_VERBOSE 1713#ifdef TREASURE_VERBOSE
1758 LOG (llevDebug, "%s of %s was not a legal combination.\n", op->name, art->item->name); 1714 LOG (llevDebug, "%s of %s was not a legal combination.\n", &op->name, &art->item->name);
1759#endif 1715#endif
1760 continue; 1716 continue;
1761 } 1717 }
1718
1762 give_artifact_abilities (op, art->item); 1719 give_artifact_abilities (op, art->item);
1763 return; 1720 return;
1764 } 1721 }
1765} 1722}
1766 1723
1810 SET_FLAG (item, FLAG_NO_STEAL); 1767 SET_FLAG (item, FLAG_NO_STEAL);
1811 } 1768 }
1812} 1769}
1813 1770
1814/* special_potion() - so that old potion code is still done right. */ 1771/* special_potion() - so that old potion code is still done right. */
1815
1816int 1772int
1817special_potion (object *op) 1773special_potion (object *op)
1818{ 1774{
1819 if (op->attacktype) 1775 if (op->attacktype)
1820 return 1; 1776 return 1;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines