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

Comparing deliantra/server/common/recipe.C (file contents):
Revision 1.19 by root, Mon Apr 16 06:23:40 2007 UTC vs.
Revision 1.38 by root, Thu Apr 15 21:49:15 2010 UTC

1/*
2 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 *
4 * Copyright (©) 2005,2006,2007,2008,2009,2010 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 * Copyright (©) 2002 Mark Wedel & Crossfire Development Team
6 * Copyright (©) 1992 Frank Tore Johansen
7 *
8 * Deliantra is free software: you can redistribute it and/or modify it under
9 * the terms of the Affero GNU General Public License as published by the
10 * Free Software Foundation, either version 3 of the License, or (at your
11 * 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 Affero GNU General Public License
19 * and the GNU General Public License along with this program. If not, see
20 * <http://www.gnu.org/licenses/>.
21 *
22 * The authors can be reached via e-mail to <support@deliantra.net>
23 */
24
1/* Basic stuff for use with the alchemy code. Clearly some of this stuff 25/* Basic stuff for use with the alchemy code. Clearly some of this stuff
2 * could go into server/alchemy, but I left it here just in case it proves 26 * could go into server/alchemy, but I left it here just in case it proves
3 * more generally useful. 27 * more generally useful.
4 * 28 *
5 * Nov 1995 - file created by b.t. thomas@astro.psu.edu 29 * Nov 1995 - file created by b.t. thomas@astro.psu.edu
26static void build_stringlist (const char *str, char ***result_list, size_t * result_size); 50static void build_stringlist (const char *str, char ***result_list, size_t * result_size);
27 51
28static recipelist *formulalist; 52static recipelist *formulalist;
29 53
30static recipelist * 54static recipelist *
31init_recipelist (void) 55init_recipelist ()
32{ 56{
33 recipelist *tl = new recipelist; 57 recipelist *tl = new recipelist;
34 58
35 tl->total_chance = 0; 59 tl->total_chance = 0;
36 tl->number = 0; 60 tl->number = 0;
39 63
40 return tl; 64 return tl;
41} 65}
42 66
43static recipe * 67static recipe *
44get_empty_formula (void) 68get_empty_formula ()
45{ 69{
46 recipe *t = new recipe; 70 recipe *t = new recipe;
47 71
48 t->chance = 0; 72 t->chance = 0;
49 t->index = 0; 73 t->index = 0;
50 t->transmute = 0; 74 t->transmute = 0;
51 t->yield = 0; 75 t->yield = 0;
52 t->diff = 0; 76 t->diff = 0;
53 t->exp = 0; 77 t->exp = 0;
54 t->keycode = 0; 78 t->keycode = 0;
55 t->title = NULL; 79 t->title = 0;
56 t->arch_names = 0; 80 t->arch_names = 0;
57 t->arch_name = NULL; 81 t->arch_name = 0;
58 t->skill = NULL; 82 t->skill = 0;
59 t->cauldron = NULL; 83 t->cauldron = 0;
60 t->ingred = NULL; 84 t->ingred = 0;
61 t->next = NULL; 85 t->next = 0;
86
62 return t; 87 return t;
63} 88}
64 89
65/* get_formulalist() - returns pointer to the formula list */ 90/* get_formulalist() - returns pointer to the formula list */
66recipelist * 91recipelist *
87 size_t i; 112 size_t i;
88 int result = 1; 113 int result = 1;
89 114
90 for (i = 0; i < rp->arch_names; i++) 115 for (i = 0; i < rp->arch_names; i++)
91 { 116 {
92 if (archetype::find (rp->arch_name[i]) != NULL) 117 if (archetype::find (rp->arch_name[i]))
93 { 118 {
94 artifact *art = locate_recipe_artifact (rp, i); 119 artifact *art = locate_recipe_artifact (rp, i);
95 120
96 if (!art && strcmp (rp->title, "NONE") != 0) 121 if (!art && rp->title != shstr_NONE)
97 { 122 {
98 LOG (llevError, "WARNING: Formula %s of %s has no artifact.\n", rp->arch_name[i], &rp->title); 123 LOG (llevError, "WARNING: Formula %s of %s has no artifact.\n", rp->arch_name[i], &rp->title);
99 result = 0; 124 result = 0;
100 } 125 }
101 } 126 }
105 result = 0; 130 result = 0;
106 } 131 }
107 } 132 }
108 133
109 return result; 134 return result;
110}
111
112/*
113 * init_formulae() - Builds up the lists of formula from the file in
114 * the libdir. -b.t.
115 */
116void
117init_formulae (void)
118{
119 static int has_been_done = 0;
120 FILE *fp;
121 char filename[MAX_BUF], buf[MAX_BUF], *cp, *next;
122 recipe *formula = NULL;
123 recipelist *fl = init_recipelist ();
124 linked_char *tmp;
125 int value, comp;
126
127 if (!formulalist)
128 formulalist = fl;
129
130 if (has_been_done)
131 return;
132 else
133 has_been_done = 1;
134
135 sprintf (filename, "%s/formulae", settings.datadir);
136 LOG (llevDebug, "Reading alchemical formulae from %s...\n", filename);
137 if ((fp = open_and_uncompress (filename, 0, &comp)) == NULL)
138 {
139 LOG (llevError, "Can't open %s.\n", filename);
140 return;
141 }
142
143 while (fgets (buf, MAX_BUF, fp) != NULL)
144 {
145 if (*buf == '#')
146 continue;
147 if ((cp = strchr (buf, '\n')) != NULL)
148 *cp = '\0';
149 cp = buf;
150 while (*cp == ' ') /* Skip blanks */
151 cp++;
152
153 if (!strncmp (cp, "object", 6))
154 {
155 formula = get_empty_formula ();
156 formula->title = strchr (cp, ' ') + 1;
157 }
158 else if (!strncmp (cp, "keycode", 7))
159 formula->keycode = strchr (cp, ' ') + 1;
160 else if (sscanf (cp, "trans %d", &value))
161 formula->transmute = (uint16) value;
162 else if (sscanf (cp, "yield %d", &value))
163 formula->yield = (uint16) value;
164 else if (sscanf (cp, "chance %d", &value))
165 formula->chance = (uint16) value;
166 else if (sscanf (cp, "exp %d", &value))
167 formula->exp = (uint16) value;
168 else if (sscanf (cp, "diff %d", &value))
169 formula->diff = (uint16) value;
170 else if (!strncmp (cp, "ingred", 6))
171 {
172 int numb_ingred = 1;
173
174 cp = strchr (cp, ' ') + 1;
175 do
176 {
177 if ((next = strchr (cp, ',')) != NULL)
178 {
179 *(next++) = '\0';
180 numb_ingred++;
181 }
182
183 tmp = new linked_char;
184
185 tmp->name = cp;
186 tmp->next = formula->ingred;
187 formula->ingred = tmp;
188 /* each ingredient's ASCII value is coadded. Later on this
189 * value will be used allow us to search the formula lists
190 * quickly for the right recipe.
191 */
192 formula->index += strtoint (cp);
193 }
194 while ((cp = next) != NULL);
195
196 /* now find the correct (# of ingred ordered) formulalist */
197 fl = formulalist;
198 while (numb_ingred != 1)
199 {
200 if (!fl->next)
201 fl->next = init_recipelist ();
202
203 fl = fl->next;
204 numb_ingred--;
205 }
206
207 fl->total_chance += formula->chance;
208 fl->number++;
209 formula->next = fl->items;
210 fl->items = formula;
211 }
212 else if (!strncmp (cp, "arch", 4))
213 {
214 build_stringlist (strchr (cp, ' ') + 1, &formula->arch_name, &formula->arch_names);
215 check_recipe (formula);
216 }
217 else if (!strncmp (cp, "skill", 5))
218 formula->skill = strchr (cp, ' ') + 1;
219 else if (!strncmp (cp, "cauldron", 8))
220 formula->cauldron = strchr (cp, ' ') + 1;
221 else
222 LOG (llevError, "Unknown input in file %s: %s\n", filename, buf);
223 }
224
225 LOG (llevDebug, "done.\n");
226 close_and_delete (fp, comp);
227 /* Lastly, lets check for problems in formula we got */
228 check_formulae ();
229} 135}
230 136
231/* check_formulae()- since we are doing a squential search on the 137/* check_formulae()- since we are doing a squential search on the
232 * formulae lists now, we have to be carefull that we dont have 2 138 * formulae lists now, we have to be carefull that we dont have 2
233 * formula with the exact same index value. Under the new nbatches 139 * formula with the exact same index value. Under the new nbatches
234 * code, it is possible to have multiples of ingredients in a cauldron 140 * code, it is possible to have multiples of ingredients in a cauldron
235 * which could result in an index formula mismatch. We *don't* check for 141 * which could result in an index formula mismatch. We *don't* check for
236 * that possibility here. -b.t. 142 * that possibility here. -b.t.
237 */ 143 */
238void 144static void
239check_formulae (void) 145check_formulae ()
240{ 146{
241 recipelist *fl; 147 recipelist *fl;
242 recipe *check, *formula; 148 recipe *check, *formula;
243 int numb = 1; 149 int numb = 1;
244 150
259 165
260 LOG (llevDebug, "done.\n"); 166 LOG (llevDebug, "done.\n");
261 167
262} 168}
263 169
264/* Borrowed (again) from the artifacts code for this */ 170/*
265 171 * init_formulae() - Builds up the lists of formula from the file in
172 * the libdir. -b.t.
173 */
266void 174void
267dump_alchemy (void) 175init_formulae ()
268{ 176{
269 recipelist *fl = formulalist; 177 static int has_been_done = 0;
270 recipe *formula = NULL; 178 FILE *fp;
179 char filename[MAX_BUF], buf[MAX_BUF], *cp, *next;
180 recipelist *fl = init_recipelist ();
271 linked_char *next; 181 linked_char *tmp;
272 int num_ingred = 1; 182 int value, comp;
273 183
274 fprintf (logfile, "\n"); 184 if (!formulalist)
275 while (fl) 185 formulalist = fl;
186
187 if (has_been_done)
188 return;
189 else
190 has_been_done = 1;
191
192 sprintf (filename, "%s/formulae", settings.datadir);
193 LOG (llevDebug, "Reading alchemical formulae from %s...\n", filename);
194
195 object_thawer thawer (filename);
196
197 if (!thawer)
198 {
199 LOG (llevError, "Can't open %s.\n", filename);
200 return;
276 { 201 }
277 fprintf (logfile, "\n Formulae with %d ingredient%s %d Formulae with total_chance=%d\n",
278 num_ingred, num_ingred > 1 ? "s." : ".", fl->number, fl->total_chance);
279 for (formula = fl->items; formula; formula = formula->next)
280 {
281 artifact *art = NULL;
282 char buf[MAX_BUF];
283 size_t i;
284 202
285 for (i = 0; i < formula->arch_names; i++) 203 while (thawer.kw)
204 {
205 if (thawer.kw != KW_object)
206 if (!thawer.parse_error ("formulae file"))
207 break;
208
209 recipe *formula = get_empty_formula ();
210 thawer.get (formula->title);
211
212 for (;;)
213 {
214 thawer.next ();
215
216 switch (thawer.kw)
286 { 217 {
287 const char *string = formula->arch_name[i]; 218 case KW_keycode: thawer.get (formula->keycode ); break;
219 case KW_trans: thawer.get (formula->transmute); break;
220 case KW_yield: thawer.get (formula->yield ); break;
221 case KW_chance: thawer.get (formula->chance ); break;
222 case KW_exp: thawer.get (formula->exp ); break;
223 case KW_diff: thawer.get (formula->diff ); break;
224 case KW_skill: thawer.get (formula->skill ); break;
225 case KW_cauldron: thawer.get (formula->cauldron ); break;
288 226
289 if (archetype::find (string) != NULL) 227 case KW_arch:
290 { 228 {
229 build_stringlist (thawer.value_nn, &formula->arch_name, &formula->arch_names);
291 art = locate_recipe_artifact (formula, i); 230 check_recipe (formula);
292 if (!art && strcmp (formula->title, "NONE"))
293 LOG (llevError, "Formula %s has no artifact!\n", &formula->title);
294 else
295 {
296 if (strcmp (formula->title, "NONE"))
297 sprintf (buf, "%s of %s", string, &formula->title);
298 else
299 sprintf (buf, "%s", string);
300 fprintf (logfile, "%-30s(%d) bookchance %3d ", buf, formula->index, formula->chance);
301 fprintf (logfile, "skill %s", &formula->skill);
302 fprintf (logfile, "\n");
303 if (formula->ingred != NULL)
304 {
305 int nval = 0, tval = 0;
306
307 fprintf (logfile, "\tIngred: ");
308 for (next = formula->ingred; next != NULL; next = next->next)
309 {
310 if (nval != 0)
311 fprintf (logfile, ",");
312 fprintf (logfile, "%s(%d)", &next->name, (nval = strtoint (next->name)));
313 tval += nval;
314 }
315 fprintf (logfile, "\n");
316 if (tval != formula->index)
317 fprintf (logfile, "WARNING:ingredient list and formula values not equal.\n");
318 }
319 if (formula->skill != NULL)
320 fprintf (logfile, "\tSkill Required: %s", &formula->skill);
321 if (formula->cauldron != NULL)
322 fprintf (logfile, "\tCauldron: %s\n", &formula->cauldron);
323 fprintf (logfile, "\tDifficulty: %d\t Exp: %d\n", formula->diff, formula->exp);
324 }
325 } 231 }
232 break;
233
234 case KW_ingred:
235 if (thawer.value)
236 {
237 int numb_ingred = 1;
238 char *cp = thawer.value;
239
240 do
241 {
242 if ((next = strchr (cp, ',')))
243 {
244 *next++ = '\0';
245 ++numb_ingred;
246 }
247
248 tmp = new linked_char;
249
250 tmp->name = cp;
251 tmp->next = formula->ingred;
252 formula->ingred = tmp;
253 /* each ingredient's ASCII value is coadded. Later on this
254 * value will be used allow us to search the formula lists
255 * quickly for the right recipe.
256 */
257 formula->index += strtoint (cp);
258 }
259 while ((cp = next));
260
261 /* now find the correct (# of ingred ordered) formulalist */
262 fl = formulalist;
263 while (numb_ingred != 1)
264 {
265 if (!fl->next)
266 fl->next = init_recipelist ();
267
268 fl = fl->next;
269 numb_ingred--;
270 }
271
272 fl->total_chance += formula->chance;
273 fl->number++;
274 formula->next = fl->items;
275 fl->items = formula;
276 }
277 break;
278
326 else 279 default:
327 LOG (llevError, "Can't find archetype:%s for formula %s\n", string, &formula->title); 280 delete formula;
281 case KW_object:
282 goto next_object;
328 } 283 }
329 } 284 }
330 fprintf (logfile, "\n"); 285
331 fl = fl->next; 286next_object: ;
332 num_ingred++;
333 } 287 }
288
289 LOG (llevDebug, "done.\n");
290 /* Lastly, lets check for problems in formula we got */
291 check_formulae ();
334} 292}
335 293
336/* Find a treasure with a matching name. The 'depth' parameter is 294/* Find a treasure with a matching name. The 'depth' parameter is
337 * only there to prevent infinite loops in treasure lists (a list 295 * only there to prevent infinite loops in treasure lists (a list
338 * referencing another list pointing back to the first one). */ 296 * referencing another list pointing back to the first one). */
339archetype * 297static archetype *
340find_treasure_by_name (const treasure *t, const char *name, int depth) 298find_treasure_by_name (const treasure *t, const char *name, int depth)
341{ 299{
342 if (depth > 10) 300 if (depth > 10)
343 return 0; 301 return 0;
344 302
351 if (archetype *at = find_treasure_by_name (tl->items, name, depth + 1)) 309 if (archetype *at = find_treasure_by_name (tl->items, name, depth + 1))
352 return at; 310 return at;
353 } 311 }
354 else 312 else
355 { 313 {
356 if (t->item && !strcasecmp (t->item->clone.name, name)) 314 if (t->item && !strcasecmp (t->item->object::name, name))
357 return t->item; 315 return t->item;
358 } 316 }
359 317
360 if (t->next_yes) 318 if (t->next_yes)
361 if (archetype *at = find_treasure_by_name (t->next_yes, name, depth)) 319 if (archetype *at = find_treasure_by_name (t->next_yes, name, depth))
369 } 327 }
370 328
371 return 0; 329 return 0;
372} 330}
373 331
374/* If several archetypes have the same name, the value of the first
375 * one with that name will be returned. This happens for the
376 * mushrooms (mushroom_1, mushroom_2 and mushroom_3). For the
377 * monsters' body parts, there may be several monsters with the same
378 * name. This is not a problem if these monsters have the same level
379 * (e.g. sage & c_sage) or if only one of the monsters generates the
380 * body parts that we are looking for (e.g. big_dragon and
381 * big_dragon_worthless). */
382long
383find_ingred_cost (const char *name)
384{
385 archetype *at;
386 archetype *at2;
387 artifactlist *al;
388 artifact *art;
389 long mult;
390 char *cp;
391 char part1[100];
392 char part2[100];
393
394 /* same as atoi(), but skip number */
395 mult = 0;
396 while (isdigit (*name))
397 {
398 mult = 10 * mult + (*name - '0');
399 name++;
400 }
401
402 if (mult > 0)
403 name++;
404 else
405 mult = 1;
406
407 /* first, try to match the name of an archetype */
408 for (at = first_archetype; at != NULL; at = at->next)
409 {
410 if (at->clone.title != NULL)
411 {
412 /* inefficient, but who cares? */
413 sprintf (part1, "%s %s", &at->clone.name, &at->clone.title);
414 if (!strcasecmp (part1, name))
415 return mult * at->clone.value;
416 }
417 if (!strcasecmp (at->clone.name, name))
418 return mult * at->clone.value;
419 }
420
421 /* second, try to match an artifact ("arch of something") */
422 cp = strstr (name, " of ");
423 if (cp != NULL)
424 {
425 strcpy (part1, name);
426 part1[cp - name] = '\0';
427 strcpy (part2, cp + 4);
428 /* find the first archetype matching the first part of the name */
429 for (at = first_archetype; at; at = at->next)
430 if (!strcasecmp (at->clone.name, part1) && at->clone.title == NULL)
431 break;
432 if (at != NULL)
433 {
434 /* find the first artifact derived from that archetype (same type) */
435 for (al = first_artifactlist; al; al = al->next)
436 if (al->type == at->clone.type)
437 {
438 for (art = al->items; art; art = art->next)
439 if (!strcasecmp (art->item->name, part2))
440 return mult * at->clone.value * art->item->value;
441 }
442 }
443 }
444
445 /* third, try to match a body part ("arch's something") */
446 cp = strstr (name, "'s ");
447 if (cp)
448 {
449 strcpy (part1, name);
450 part1[cp - name] = '\0';
451 strcpy (part2, cp + 3);
452 /* examine all archetypes matching the first part of the name */
453 for (at = first_archetype; at; at = at->next)
454 if (!strcasecmp (at->clone.name, part1) && at->clone.title == NULL)
455 {
456 if (at->clone.randomitems)
457 {
458 at2 = find_treasure_by_name (at->clone.randomitems->items, part2, 0);
459 if (at2)
460 return mult * at2->clone.value * isqrt (at->clone.level * 2);
461 }
462 }
463 }
464
465 /* failed to find any matching items -- formula should be checked */
466 return -1;
467}
468
469/* code copied from dump_alchemy() and modified by Raphael Quinet */
470void
471dump_alchemy_costs (void)
472{
473 recipelist *fl = formulalist;
474 recipe *formula = NULL;
475 linked_char *next;
476 int num_ingred = 1;
477 int num_errors = 0;
478 long cost;
479 long tcost;
480
481 fprintf (logfile, "\n");
482 while (fl)
483 {
484 fprintf (logfile, "\n Formulae with %d ingredient%s %d Formulae with total_chance=%d\n",
485 num_ingred, num_ingred > 1 ? "s." : ".", fl->number, fl->total_chance);
486 for (formula = fl->items; formula; formula = formula->next)
487 {
488 artifact *art = NULL;
489 archetype *at = NULL;
490 char buf[MAX_BUF];
491 size_t i;
492
493 for (i = 0; i < formula->arch_names; i++)
494 {
495 const char *string = formula->arch_name[i];
496
497 if ((at = archetype::find (string)) != NULL)
498 {
499 art = locate_recipe_artifact (formula, i);
500 if (!art && strcmp (formula->title, "NONE"))
501 LOG (llevError, "Formula %s has no artifact\n", &formula->title);
502 else
503 {
504 if (!strcmp (formula->title, "NONE"))
505 sprintf (buf, "%s", string);
506 else
507 sprintf (buf, "%s of %s", string, &formula->title);
508 fprintf (logfile, "\n%-40s bookchance %3d skill %s\n", buf, formula->chance, &(formula->skill));
509 if (formula->ingred != NULL)
510 {
511 tcost = 0;
512 for (next = formula->ingred; next != NULL; next = next->next)
513 {
514 cost = find_ingred_cost (next->name);
515 if (cost < 0)
516 num_errors++;
517 fprintf (logfile, "\t%-33s%5ld\n", &next->name, cost);
518 if (cost < 0 || tcost < 0)
519 tcost = -1;
520 else
521 tcost += cost;
522 }
523 if (art != NULL && art->item != NULL)
524 cost = at->clone.value * art->item->value;
525 else
526 cost = at->clone.value;
527 fprintf (logfile, "\t\tBuying result costs: %5ld", cost);
528 if (formula->yield > 1)
529 {
530 fprintf (logfile, " to %ld (max %d items)\n", cost * formula->yield, formula->yield);
531 cost = cost * (formula->yield + 1L) / 2L;
532 }
533 else
534 fprintf (logfile, "\n");
535 fprintf (logfile, "\t\tIngredients cost: %5ld\n\t\tComment: ", tcost);
536 if (tcost < 0)
537 fprintf (logfile, "Could not find some ingredients. Check the formula!\n");
538 else if (tcost > cost)
539 fprintf (logfile, "Ingredients are much too expensive. Useless formula.\n");
540 else if (tcost * 2L > cost)
541 fprintf (logfile, "Ingredients are too expensive.\n");
542 else if (tcost * 10L < cost)
543 fprintf (logfile, "Ingredients are too cheap.\n");
544 else
545 fprintf (logfile, "OK.\n");
546 }
547 }
548 }
549 else
550 LOG (llevError, "Can't find archetype:%s for formula %s\n", string, &formula->title);
551 }
552 }
553 fprintf (logfile, "\n");
554 fl = fl->next;
555 num_ingred++;
556 }
557 if (num_errors > 0)
558 fprintf (logfile, "WARNING: %d objects required by the formulae do not exist in the game.\n", num_errors);
559}
560
561const char * 332static const char *
562ingred_name (const char *name) 333ingred_name (const char *name)
563{ 334{
564 const char *cp = name; 335 const char *cp = name;
565 336
566 if (atoi (cp)) 337 if (atoi (cp))
567 cp = strchr (cp, ' ') + 1; 338 cp = strchr (cp, ' ') + 1;
339
568 return cp; 340 return cp;
569} 341}
570 342
571/* strtoint() - we use this to convert buf into an integer 343static int
572 * equal to the coadded sum of the (lowercase) character
573 * ASCII values in buf (times prepended integers).
574 */
575
576int
577strtoint (const char *buf)
578{
579 const char *cp = ingred_name (buf);
580 int val = 0, len = strlen (cp), mult = numb_ingred (buf);
581
582 while (len)
583 {
584 val += tolower (*cp);
585 cp++;
586 len--;
587 }
588 return val * mult;
589}
590
591artifact *
592locate_recipe_artifact (const recipe *rp, size_t idx)
593{
594 archetype *at = archetype::find (rp->arch_name [idx]);
595
596 if (at)
597 if (artifactlist *al = find_artifactlist (at->clone.type))
598 for (artifact *art = al->items; art; art = art->next)
599 if (art->item->name == rp->title)
600 return art;
601
602 return 0;
603}
604
605int
606numb_ingred (const char *buf) 344numb_ingred (const char *buf)
607{ 345{
608 int numb; 346 int numb;
609 347
610 if ((numb = atoi (buf))) 348 if ((numb = atoi (buf)))
611 return numb; 349 return numb;
612 else 350 else
613 return 1; 351 return 1;
614} 352}
615 353
354/* strtoint() - we use this to convert buf into an integer
355 * equal to the coadded sum of the (lowercase) character
356 * ASCII values in buf (times prepended integers).
357 * Some kind of hashing.
358 */
359int
360strtoint (const char *buf)
361{
362 const char *cp = ingred_name (buf);
363 int val = 0, len = strlen (cp), mult = numb_ingred (buf);
364
365 while (len)
366 {
367 val += tolower (*cp);
368 cp++;
369 len--;
370 }
371
372 return val * mult;
373}
374
375artifact *
376locate_recipe_artifact (const recipe *rp, size_t idx)
377{
378 archetype *at = archetype::find (rp->arch_name [idx]);
379
380 if (at)
381 if (artifactlist *al = find_artifactlist (at->type))
382 for (artifact *art = al->items; art; art = art->next)
383 if (art->item->name == rp->title)
384 return art;
385
386 return 0;
387}
388
616recipelist * 389static recipelist *
617get_random_recipelist (void) 390get_random_recipelist ()
618{ 391{
619 recipelist *fl = NULL; 392 recipelist *fl = NULL;
620 int number = 0, roll = 0; 393 int number = 0, roll = 0;
621 394
622 /* first, determine # of recipelist we have */ 395 /* first, determine # of recipelist we have */
665 if (r < 0) 438 if (r < 0)
666 break; 439 break;
667 } 440 }
668 } 441 }
669 return rp; 442 return rp;
670}
671
672void
673free_all_recipes (void)
674{
675 recipelist *fl = formulalist, *flnext;
676 recipe *formula = NULL, *next;
677 linked_char *lchar, *charnext;
678
679 LOG (llevDebug, "Freeing all the recipes\n");
680 for (fl = formulalist; fl != NULL; fl = flnext)
681 {
682 flnext = fl->next;
683
684 for (formula = fl->items; formula != NULL; formula = next)
685 {
686 next = formula->next;
687
688 free (formula->arch_name[0]);
689 free (formula->arch_name);
690
691 for (lchar = formula->ingred; lchar; lchar = charnext)
692 {
693 charnext = lchar->next;
694 delete lchar;
695 }
696 delete formula;
697 }
698
699 delete fl;
700 }
701} 443}
702 444
703/** 445/**
704 * Split a comma separated string list into words. 446 * Split a comma separated string list into words.
705 * 447 *
719 size_t size; 461 size_t size;
720 size_t i; 462 size_t i;
721 463
722 dup = strdup (str); 464 dup = strdup (str);
723 if (dup == NULL) 465 if (dup == NULL)
724 fatal (OUT_OF_MEMORY); 466 fatal ("out of memory");
725 467
726 size = 0; 468 size = 0;
727 for (p = strtok (dup, ","); p != NULL; p = strtok (NULL, ",")) 469 for (p = strtok (dup, ","); p != NULL; p = strtok (NULL, ","))
728 size++; 470 size++;
729 471
730 *result_list = (char **) malloc (size * sizeof (*result_list)); 472 *result_list = (char **)malloc (size * sizeof (*result_list));
731 473
732 *result_size = size; 474 *result_size = size;
733 475
734 for (i = 0; i < size; i++) 476 for (i = 0; i < size; i++)
735 { 477 {

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines