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

Comparing deliantra/server/server/alchemy.C (file contents):
Revision 1.5 by root, Sun Sep 3 00:18:42 2006 UTC vs.
Revision 1.20 by root, Mon Feb 5 02:07:40 2007 UTC

1/* 1/*
2 * static char *rcsid_alchemy_c =
3 * "$Id: alchemy.C,v 1.5 2006/09/03 00:18:42 root Exp $";
4 */
5
6/*
7 CrossFire, A Multiplayer game for X-windows 2 * CrossFire, A Multiplayer game for X-windows
8 3 *
4 * Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team
9 Copyright (C) 2002 Mark Wedel & Crossfire Development Team 5 * Copyright (C) 2002 Mark Wedel & Crossfire Development Team
10 Copyright (C) 1992 Frank Tore Johansen 6 * Copyright (C) 1992 Frank Tore Johansen
11 7 *
12 This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by 9 * it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or 10 * the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version. 11 * (at your option) any later version.
16 12 *
17 This program is distributed in the hope that it will be useful, 13 * This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details. 16 * GNU General Public License for more details.
21 17 *
22 You should have received a copy of the GNU General Public License 18 * You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software 19 * along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 21 *
26 The authors can be reached via e-mail at crossfire-devel@real-time.com 22 * The authors can be reached via e-mail at <crossfire@schmorp.de>
27*/ 23 */
28 24
29/* March 96 - Laid down original code. -b.t. thomas@astro.psu.edu */ 25/* March 96 - Laid down original code. -b.t. thomas@astro.psu.edu */
30 26
31#include <global.h> 27#include <global.h>
32#include <object.h> 28#include <object.h>
33#ifndef __CEXTRACT__
34#include <sproto.h> 29#include <sproto.h>
35#endif
36#include <skills.h> 30#include <skills.h>
37#include <spells.h> 31#include <spells.h>
38 32
39/** define this for some helpful debuging information */ 33/** define this for some helpful debuging information */
40#if 0 34#if 0
41#define ALCHEMY_DEBUG 35# define ALCHEMY_DEBUG
42#endif 36#endif
43 37
44/** define this for loads of (marginal) debuging information */ 38/** define this for loads of (marginal) debuging information */
45#if 0 39#if 0
46#define EXTREME_ALCHEMY_DEBUG 40# define EXTREME_ALCHEMY_DEBUG
47#endif 41#endif
48 42
49/** Random cauldrons effects */ 43/** Random cauldrons effects */
50static const char* const cauldron_effect [] = { 44static const char *const cauldron_effect[] = {
51 "vibrates briefly", 45 "vibrates briefly",
52 "produces a cloud of steam", 46 "produces a cloud of steam",
53 "emits bright flames", 47 "emits bright flames",
54 "pours forth heavy black smoke", 48 "pours forth heavy black smoke",
55 "emits sparks", 49 "emits sparks",
56 "shoots out small flames", 50 "shoots out small flames",
57 "whines painfully", 51 "whines painfully",
58 "hiccups loudly", 52 "hiccups loudly",
59 "wheezes", 53 "wheezes",
60 "burps", 54 "burps",
61 "shakes", 55 "shakes",
62 "rattles", 56 "rattles",
63 "makes chugging sounds", 57 "makes chugging sounds",
64 "smokes heavily for a while" 58 "smokes heavily for a while"
65}; 59};
66 60
67 61
68static int is_defined_recipe(const recipe *rp, const object *cauldron, object *caster); 62static int is_defined_recipe (const recipe *rp, const object *cauldron, object *caster);
69static recipe *find_recipe(recipelist *fl, int formula, object *ingredients); 63static recipe *find_recipe (recipelist * fl, int formula, object *ingredients);
70 64
71 65
72/** Returns a random selection from cauldron_effect[] */ 66/** Returns a random selection from cauldron_effect[] */
73static const char *cauldron_sound(void) { 67static const char *
68cauldron_sound (void)
69{
74 int size=sizeof(cauldron_effect)/sizeof(char *); 70 int size = sizeof (cauldron_effect) / sizeof (char *);
75 71
76 return cauldron_effect[rndm(0, size-1)]; 72 return cauldron_effect[rndm (0, size - 1)];
77} 73}
78 74
79/** 75/**
80 * Main part of the ALCHEMY code. From this we call fctns 76 * Main part of the ALCHEMY code. From this we call fctns
81 * that take a look at the contents of the 'cauldron' and, using these ingredients, 77 * that take a look at the contents of the 'cauldron' and, using these ingredients,
97 * There is no good reason (in my mind) why alchemical processes have to be 93 * There is no good reason (in my mind) why alchemical processes have to be
98 * unique -- such a 'feature' is one reason why players might want to experiment 94 * unique -- such a 'feature' is one reason why players might want to experiment
99 * around. :) 95 * around. :)
100 * -b.t. 96 * -b.t.
101 */ 97 */
102 98
99void
103void attempt_do_alchemy(object *caster, object *cauldron) { 100attempt_do_alchemy (object *caster, object *cauldron)
101{
104 recipelist *fl; 102 recipelist *fl;
105 recipe *rp=NULL; 103 recipe *rp = NULL;
106 float success_chance; 104 float success_chance;
107 int numb, ability=1; 105 int numb, ability = 1;
108 int formula=0; 106 int formula = 0;
109 float ave_chance; 107 float ave_chance;
110 object *item, *skop; 108 object *item, *skop;
111 109
112 if (caster->type!=PLAYER) 110 if (caster->type != PLAYER)
113 return; /* only players for now */ 111 return; /* only players for now */
114 112
115 if (get_map_flags(caster->map, NULL, caster->x, caster->y, NULL, NULL) & P_SAFE) 113 if (get_map_flags (caster->map, NULL, caster->x, caster->y, NULL, NULL) & P_SAFE)
116 { 114 {
117 new_draw_info (NDI_UNIQUE, 0, caster,
118 "This is sacred ground, the gods prevent you from using this device." 115 new_draw_info (NDI_UNIQUE, 0, caster, "This is sacred ground, the gods prevent you from using this device.");
119 );
120 return; 116 return;
121 } 117 }
122 118
123 /* if no ingredients, no formula! lets forget it */ 119 /* if no ingredients, no formula! lets forget it */
124 if (!(formula=content_recipe_value(cauldron))) return; 120 if (!(formula = content_recipe_value (cauldron)))
125 121 return;
122
126 numb=numb_ob_inside(cauldron); 123 numb = numb_ob_inside (cauldron);
127 if ((fl=get_formulalist(numb))) { 124 if ((fl = get_formulalist (numb)))
125 {
128 if (QUERY_FLAG(caster, FLAG_WIZ)) { 126 if (QUERY_FLAG (caster, FLAG_WIZ))
127 {
129 rp = find_recipe(fl, formula, cauldron->inv); 128 rp = find_recipe (fl, formula, cauldron->inv);
130 if (rp != NULL) { 129 if (rp != NULL)
130 {
131#ifdef ALCHEMY_DEBUG 131#ifdef ALCHEMY_DEBUG
132 if(strcmp(rp->title, "NONE")) 132 if (strcmp (rp->title, "NONE"))
133 LOG(llevDebug, "WIZ got formula: %s of %s\n", 133 LOG (llevDebug, "WIZ got formula: %s of %s\n", rp->arch_name[0], rp->title);
134 rp->arch_name[0], rp->title);
135 else 134 else
136 LOG(llevDebug, "WIZ got formula: %s (nbatches:%d)\n", 135 LOG (llevDebug, "WIZ got formula: %s (nbatches:%d)\n", rp->arch_name[0], formula / rp->index);
137 rp->arch_name[0], formula/rp->index);
138#endif 136#endif
139 attempt_recipe(caster, cauldron, ability, rp, formula/rp->index); 137 attempt_recipe (caster, cauldron, ability, rp, formula / rp->index);
138 }
139 else
140 } else LOG(llevDebug, "WIZ couldn't find formula for ingredients.\n"); 140 LOG (llevDebug, "WIZ couldn't find formula for ingredients.\n");
141 return; 141 return;
142 } /* End of WIZ alchemy */ 142 } /* End of WIZ alchemy */
143 143
144 /* find the recipe */ 144 /* find the recipe */
145 rp = find_recipe(fl, formula, cauldron->inv); 145 rp = find_recipe (fl, formula, cauldron->inv);
146 if (rp != NULL) { 146 if (rp)
147 {
147 uint64 value_ingredients; 148 uint64 value_ingredients;
148 uint64 value_item; 149 uint64 value_item;
149 object *tmp; 150 object *tmp;
150 int attempt_shadow_alchemy; 151 int attempt_shadow_alchemy;
151 152
152 ave_chance = fl->total_chance/(float)fl->number; 153 ave_chance = fl->total_chance / (float) fl->number;
153 /* the caster gets an increase in ability based on thier skill lvl */ 154 /* the caster gets an increase in ability based on thier skill lvl */
154 if (rp->skill != NULL) { 155 if (rp->skill)
156 {
155 skop = find_skill_by_name(caster, rp->skill); 157 skop = find_skill_by_name (caster, rp->skill);
156 if (!skop) { 158 if (!skop)
157 new_draw_info(NDI_UNIQUE, 0, caster, "You do not have the proper skill for this recipe"); 159 new_draw_info (NDI_UNIQUE, 0, caster, "You do not have the proper skill for this recipe");
158 } else { 160 else
159 ability+= (int) (skop->level*((4.0 + cauldron->magic)/4.0)); 161 ability += (int) (skop->level * ((4.0 + cauldron->magic) / 4.0));
162 }
163 else
164 {
165 LOG (llevDebug, "Recipe %s has NULL skill!\n", &rp->title);
166 return;
167 }
168
169 if (!rp->cauldron)
170 {
171 LOG (llevDebug, "Recipe %s has NULL cauldron!\n", &rp->title);
172 return;
173 }
174
175 /* determine value of ingredients */
176 value_ingredients = 0;
177 for (tmp = cauldron->inv; tmp != NULL; tmp = tmp->below)
178 value_ingredients += query_cost (tmp, NULL, F_TRUE);
179
180 attempt_shadow_alchemy = !is_defined_recipe (rp, cauldron, caster);
181
182 /* create the object **FIRST**, then decide whether to keep it. */
183 if ((item = attempt_recipe (caster, cauldron, ability, rp, formula / rp->index)) != NULL)
184 {
185 /* compute base chance of recipe success */
186 success_chance = ((float) ability / (float) (rp->diff * (item->level + 2)));
187 if (ave_chance == 0)
188 ave_chance = 1;
189
190#ifdef ALCHEMY_DEBUG
191 LOG (llevDebug, "percent success chance = %f ab%d / diff%d*lev%d\n", success_chance, ability, rp->diff, item->level);
192#endif
193
194 value_item = query_cost (item, NULL, F_TRUE | F_IDENTIFIED | F_NOT_CURSED);
195 if (attempt_shadow_alchemy && value_item > value_ingredients)
196 {
197#ifdef ALCHEMY_DEBUG
198 LOG (llevDebug,
199 "Forcing failure for shadow alchemy recipe because price of ingredients (%llu) is less than price of result (%llu).\n",
200 value_ingredients, value_item);
201#endif
160 } 202 }
203 /* roll the dice */
204 else if ((float) (random_roll (0, 101, caster, PREFER_LOW)) <= 100.0 * success_chance)
161 } else { 205 {
162 LOG(llevDebug, "Recipe %s has NULL skill!\n", rp->title); 206 change_exp (caster, rp->exp, rp->skill, SK_EXP_NONE);
207
208 // let alchemy consume some time, so that exploits are less easy
209 caster->speed_left -= 1.0;
210
163 return; 211 return;
164 }
165
166 if (rp->cauldron == NULL) {
167 LOG(llevDebug, "Recipe %s has NULL cauldron!\n", rp->title);
168 return;
169 }
170
171 /* determine value of ingredients */
172 value_ingredients = 0;
173 for(tmp = cauldron->inv; tmp != NULL; tmp = tmp->below)
174 value_ingredients += query_cost(tmp, NULL, F_TRUE);
175
176 attempt_shadow_alchemy = !is_defined_recipe(rp, cauldron, caster);
177
178 /* create the object **FIRST**, then decide whether to keep it. */
179 if ((item=attempt_recipe(caster, cauldron, ability, rp, formula/rp->index)) != NULL) {
180 /* compute base chance of recipe success */
181 success_chance = ((float)ability /
182 (float)(rp->diff * (item->level+2)));
183 if (ave_chance == 0)
184 ave_chance = 1;
185
186#ifdef ALCHEMY_DEBUG
187 LOG(llevDebug, "percent success chance = %f ab%d / diff%d*lev%d\n",
188 success_chance, ability, rp->diff, item->level);
189#endif
190
191 value_item = query_cost(item, NULL, F_TRUE|F_IDENTIFIED|F_NOT_CURSED);
192 if(attempt_shadow_alchemy && value_item > value_ingredients) {
193#ifdef ALCHEMY_DEBUG
194#ifndef WIN32
195 LOG(llevDebug, "Forcing failure for shadow alchemy recipe because price of ingredients (%llu) is less than price of result (%llu).\n", value_ingredients, value_item);
196#else
197 LOG(llevDebug, "Forcing failure for shadow alchemy recipe because price of ingredients (%I64d) is less than price of result (%I64d).\n", value_ingredients, value_item);
198#endif
199#endif
200 } 212 }
201 /* roll the dice */
202 else if ((float)(random_roll(0, 101, caster, PREFER_LOW)) <= 100.0 * success_chance) {
203 change_exp(caster, rp->exp, rp->skill, SK_EXP_NONE);
204 return;
205 } 213 }
206 } 214 }
207 }
208 } 215 }
216
209 /* if we get here, we failed!! */ 217 /* if we get here, we failed!! */
210 alchemy_failure_effect(caster, cauldron, rp, 218 alchemy_failure_effect (caster, cauldron, rp, calc_alch_danger (caster, cauldron, rp));
211 calc_alch_danger(caster, cauldron, rp));
212} 219}
213 220
214/** 221/**
215 * Recipe value of the entire contents of a container. 222 * Recipe value of the entire contents of a container.
216 * This appears to just generate a hash value, which I guess for now works 223 * This appears to just generate a hash value, which I guess for now works
217 * ok, but the possibility of duplicate hashes is certainly possible - msw 224 * ok, but the possibility of duplicate hashes is certainly possible - msw
218 */ 225 */
219 226
227int
220int content_recipe_value (object *op) { 228content_recipe_value (object *op)
229{
221 char name[MAX_BUF]; 230 char name[MAX_BUF];
222 object *tmp=op->inv; 231 object *tmp = op->inv;
223 int tval=0, formula=0; 232 int tval = 0, formula = 0;
224 233
225 while(tmp) { 234 while (tmp)
235 {
226 tval=0; 236 tval = 0;
227 strcpy(name, tmp->name); 237 assign (name, tmp->name);
228 if (tmp->title) 238 if (tmp->title)
229 sprintf (name, "%s %s", &tmp->name, &tmp->title); 239 sprintf (name, "%s %s", &tmp->name, &tmp->title);
230 tval = (strtoint(name) * (tmp->nrof?tmp->nrof:1)); 240 tval = (strtoint (name) * (tmp->nrof ? tmp->nrof : 1));
231#ifdef ALCHEMY_DEBUG 241#ifdef ALCHEMY_DEBUG
232 LOG(llevDebug,"Got ingredient %d %s(%d)\n", tmp->nrof?tmp->nrof:1, 242 LOG (llevDebug, "Got ingredient %d %s(%d)\n", tmp->nrof ? tmp->nrof : 1, name, tval);
233 name, tval);
234#endif 243#endif
235 formula += tval; 244 formula += tval;
236 tmp=tmp->below; 245 tmp = tmp->below;
237 } 246 }
238#ifdef ALCHEMY_DEBUG 247#ifdef ALCHEMY_DEBUG
239 LOG(llevDebug, " Formula value=%d\n", formula); 248 LOG (llevDebug, " Formula value=%d\n", formula);
240#endif 249#endif
241 return formula; 250 return formula;
242} 251}
243 252
244/** 253/**
245 * Returns total number of items in op 254 * Returns total number of items in op
246 */ 255 */
247 256
257int
248int numb_ob_inside (object *op) { 258numb_ob_inside (object *op)
259{
249 object *tmp=op->inv; 260 object *tmp = op->inv;
250 int number=0,o_number=0; 261 int number = 0, o_number = 0;
251 262
252 while(tmp) { 263 while (tmp)
264 {
265 if (tmp->nrof)
253 if(tmp->nrof) number += tmp->nrof; 266 number += tmp->nrof;
254 else number++; 267 else
255 o_number++; 268 number++;
269 o_number++;
256 tmp=tmp->below; 270 tmp = tmp->below;
257 } 271 }
258#ifdef ALCHEMY_DEBUG 272#ifdef ALCHEMY_DEBUG
259 LOG(llevDebug,"numb_ob_inside(%s): found %d ingredients\n",op->name,o_number); 273 LOG (llevDebug, "numb_ob_inside(%s): found %d ingredients\n", op->name, o_number);
260#endif 274#endif
261 return o_number; 275 return o_number;
262} 276}
263 277
264/** 278/**
265 * Essentially a wrapper for make_item_from_recipe() and 279 * Essentially a wrapper for make_item_from_recipe() and
266 * insert_ob_in_ob. If the caster has some alchemy skill, then they might 280 * insert_ob_in_ob. If the caster has some alchemy skill, then they might
267 * gain some exp from (successfull) fabrication of the product. 281 * gain some exp from (successfull) fabrication of the product.
268 * If nbatches==-1, don't give exp for this creation (random generation/ 282 * If nbatches==-1, don't give exp for this creation (random generation/
269 * failed recipe) 283 * failed recipe)
270 */ 284 */
271 285
286object *
272object * attempt_recipe(object *caster, object *cauldron, int ability, recipe *rp, int nbatches) { 287attempt_recipe (object *caster, object *cauldron, int ability, recipe *rp, int nbatches)
288{
273 289
274 object *item=NULL, *skop; 290 object *item = NULL, *skop;
291
275 /* this should be passed to this fctn, not effiecent cpu use this way */ 292 /* this should be passed to this fctn, not effiecent cpu use this way */
276 int batches=abs(nbatches); 293 int batches = abs (nbatches);
277 294
295
278 /* is the cauldron the right type? */ 296 /* is the cauldron the right type? */
279 if (strcmp(rp->cauldron, cauldron->arch->name) != 0) { 297 if (rp->cauldron != cauldron->arch->name)
298 {
280 new_draw_info(NDI_UNIQUE, 0, caster, "You are not using the proper" 299 new_draw_info (NDI_UNIQUE, 0, caster, "You are not using the proper" " facilities for this formula.");
281 " facilities for this formula.");
282 return 0; 300 return 0;
283 } 301 }
284 302
285 skop = find_skill_by_name(caster, rp->skill); 303 skop = find_skill_by_name (caster, rp->skill);
286 /* does the caster have the skill? */ 304 /* does the caster have the skill? */
287 if (!skop) 305 if (!skop)
288 return 0; 306 return 0;
289 307
290 /* code required for this recipe, search the caster */ 308 /* code required for this recipe, search the caster */
291 if(rp->keycode) { 309 if (rp->keycode)
310 {
292 object *tmp; 311 object *tmp;
312
293 for(tmp=caster->inv; tmp != NULL; tmp=tmp->below) { 313 for (tmp = caster->inv; tmp; tmp = tmp->below)
294 if(tmp->type==FORCE && tmp->slaying && 314 {
295 !strcmp(rp->keycode, tmp->slaying)) 315 if (tmp->type == FORCE && tmp->slaying && rp->keycode == tmp->slaying)
296 break; 316 break;
297 } 317 }
298 if(tmp==NULL) { /* failure--no code found */ 318
299 new_draw_info(NDI_UNIQUE, 0, caster, "You know the ingredients," 319 if (!tmp)
300 " but not the technique. Go learn how to do this recipe."); 320 { /* failure--no code found */
321 new_draw_info (NDI_UNIQUE, 0, caster, "You know the ingredients," " but not the technique. Go learn how to do this recipe.");
301 return 0; 322 return 0;
302 } 323 }
303 } 324 }
304 325
305#ifdef EXTREME_ALCHEMY_DEBUG 326#ifdef EXTREME_ALCHEMY_DEBUG
306 LOG(llevDebug,"attempt_recipe(): got %d nbatches\n",nbatches); 327 LOG (llevDebug, "attempt_recipe(): got %d nbatches\n", nbatches);
307 LOG(llevDebug,"attempt_recipe(): using recipe %s\n", 328 LOG (llevDebug, "attempt_recipe(): using recipe %s\n", rp->title ? rp->title : "unknown");
308 rp->title?rp->title:"unknown");
309#endif 329#endif
310 330
311 if((item=make_item_from_recipe(cauldron, rp))!=NULL) { 331 if ((item = make_item_from_recipe (cauldron, rp)) != NULL)
332 {
312 remove_contents(cauldron->inv, item); 333 remove_contents (cauldron->inv, item);
313 /* Recalc carrying of the cauldron, in case recipe did not conserve mass */ 334 /* Recalc carrying of the cauldron, in case recipe did not conserve mass */
314 sum_weight(cauldron); 335 sum_weight (cauldron);
315 /* adj lvl, nrof on caster level */ 336 /* adj lvl, nrof on caster level */
316 adjust_product(item, ability, rp->yield?(rp->yield*batches):batches); 337 adjust_product (item, ability, rp->yield ? (rp->yield * batches) : batches);
317 if(!item->env && (item=insert_ob_in_ob(item,cauldron)) == NULL) { 338 if (!item->env && (item = insert_ob_in_ob (item, cauldron)) == NULL)
339 {
318 new_draw_info(NDI_UNIQUE, 0,caster,"Nothing happened."); 340 new_draw_info (NDI_UNIQUE, 0, caster, "Nothing happened.");
319 /* new_draw_info_format(NDI_UNIQUE, 0,caster, 341 /* new_draw_info_format(NDI_UNIQUE, 0,caster,
320 "Your spell causes the %s to explode!",&cauldron->name); */ 342 "Your spell causes the %s to explode!",&cauldron->name); */
321 /* kaboom_cauldron(); */ 343 /* kaboom_cauldron(); */
344 }
322 } else { 345 else
323 new_draw_info_format(NDI_UNIQUE, 0,caster, 346 new_draw_info_format (NDI_UNIQUE, 0, caster, "The %s %s.", &cauldron->name, cauldron_sound ());
324 "The %s %s.", &cauldron->name,cauldron_sound());
325 }
326 } 347 }
348
327 return item; 349 return item;
328} 350}
329 351
330 352
331 353
332/** 354/**
333 * We adjust the nrof, exp and level of the final product, based 355 * We adjust the nrof, exp and level of the final product, based
334 * on the item's default parameters, and the relevant caster skill level. 356 * on the item's default parameters, and the relevant caster skill level.
335 */ 357 */
336 358void
337void adjust_product(object *item, int lvl, int yield) { 359adjust_product (object *item, int lvl, int yield)
360{
338 int nrof=1; 361 int nrof = 1;
339 362
340 if (!yield) 363 if (!yield)
341 yield = 1; 364 yield = 1;
365
342 if (lvl<=0) 366 if (lvl <= 0)
343 lvl = 1; /* lets avoid div by zero! */ 367 lvl = 1; /* lets avoid div by zero! */
368
344 if (item->nrof) { 369 if (item->nrof)
345 nrof = (int) ( 370 {
346 (1.0 - 1.0/(lvl/10.0 + 1.0)) * 371 nrof = (int) ((1.0 - 1.0 / (lvl / 10.0 + 1.0)) * (rndm (0, yield - 1) + rndm (0, yield - 1) + rndm (0, yield - 1)) + 1);
347 (rndm(0, yield-1) + rndm(0, yield-1) + rndm(0, yield-1)) + 1 372
348 );
349 if (nrof > yield) 373 if (nrof > yield)
350 nrof = yield; 374 nrof = yield;
375
351 item->nrof=nrof; 376 item->nrof = nrof;
352 } 377 }
353} 378}
354 379
355 380
356/** 381/**
361 * @param rp the recipe to make the artifact from 386 * @param rp the recipe to make the artifact from
362 * 387 *
363 * @return the newly created object, NULL if something failed 388 * @return the newly created object, NULL if something failed
364 */ 389 */
365 390
391object *
366object * make_item_from_recipe(object *cauldron, recipe *rp) { 392make_item_from_recipe (object *cauldron, recipe *rp)
393{
367 artifact *art=NULL; 394 artifact *art = NULL;
368 object *item=NULL; 395 object *item = NULL;
369 size_t rp_arch_index; 396 size_t rp_arch_index;
370 397
398 if (rp == NULL)
371 if(rp==NULL) return (object *) NULL; 399 return (object *) NULL;
372 400
373 /* Find the appropriate object to transform...*/ 401 /* Find the appropriate object to transform... */
374 if((item=find_transmution_ob(cauldron->inv, rp, &rp_arch_index, 1))==NULL) { 402 if ((item = find_transmution_ob (cauldron->inv, rp, &rp_arch_index, 1)) == NULL)
403 {
375 LOG(llevDebug,"make_alchemy_item(): failed to create alchemical object.\n"); 404 LOG (llevDebug, "make_alchemy_item(): failed to create alchemical object.\n");
376 return (object *) NULL; 405 return (object *) NULL;
377 } 406 }
378 407
379 /* Find the appropriate artifact template...*/ 408 /* Find the appropriate artifact template... */
380 if(strcmp(rp->title,"NONE")) { 409 if (strcmp (rp->title, "NONE"))
410 {
381 if((art=locate_recipe_artifact(rp, rp_arch_index))==NULL) { 411 if ((art = locate_recipe_artifact (rp, rp_arch_index)) == NULL)
412 {
382 LOG(llevError,"make_alchemy_item(): failed to locate recipe artifact.\n"); 413 LOG (llevError, "make_alchemy_item(): failed to locate recipe artifact.\n");
383 LOG(llevDebug," --requested recipe: %s of %s.\n",rp->arch_name[0],rp->title); 414 LOG (llevDebug, " --requested recipe: %s of %s.\n", rp->arch_name[0], &rp->title);
384 return (object *) NULL; 415 return (object *) NULL;
385 } 416 }
386 transmute_materialname(item, art->item); 417 transmute_materialname (item, art->item);
387 give_artifact_abilities(item, art->item); 418 give_artifact_abilities (item, art->item);
388 } 419 }
389 420
390 if(QUERY_FLAG(cauldron,FLAG_CURSED)) SET_FLAG(item,FLAG_CURSED); 421 if (QUERY_FLAG (cauldron, FLAG_CURSED))
391 if(QUERY_FLAG(cauldron,FLAG_DAMNED)) SET_FLAG(item,FLAG_DAMNED); 422 SET_FLAG (item, FLAG_CURSED);
392 423 if (QUERY_FLAG (cauldron, FLAG_DAMNED))
424 SET_FLAG (item, FLAG_DAMNED);
425
393 return item; 426 return item;
394} 427}
395 428
396 429
397/** 430/**
398 * Looks through the ingredient list. If we find a 431 * Looks through the ingredient list. If we find a
400 * Otherwise the code returns a 'generic' item if create_item is set. -b.t. 433 * Otherwise the code returns a 'generic' item if create_item is set. -b.t.
401 * 434 *
402 * @param rp_arch_index pointer to return value; set to arch index for recipe; 435 * @param rp_arch_index pointer to return value; set to arch index for recipe;
403 * set to zero if not using a transmution formula 436 * set to zero if not using a transmution formula
404 */ 437 */
405 438
439object *
406object * find_transmution_ob ( object *first_ingred, recipe *rp, size_t *rp_arch_index, int create_item) { 440find_transmution_ob (object *first_ingred, recipe *rp, size_t * rp_arch_index, int create_item)
441{
407 object *item=NULL; 442 object *item = NULL;
408 443
409 *rp_arch_index = 0; 444 *rp_arch_index = 0;
410 445
411 if(rp->transmute) /* look for matching ingredient/prod archs */ 446 if (rp->transmute) /* look for matching ingredient/prod archs */
412 for(item=first_ingred;item;item=item->below) { 447 for (item = first_ingred; item; item = item->below)
448 {
413 size_t i; 449 size_t i;
414 450
415 for (i = 0; i < rp->arch_names; i++) { 451 for (i = 0; i < rp->arch_names; i++)
452 {
416 if(strcmp(item->arch->name, rp->arch_name[i]) == 0) { 453 if (item->arch->name == rp->arch_name[i])
454 {
417 *rp_arch_index = i; 455 *rp_arch_index = i;
418 break;
419 }
420 }
421 if (i < rp->arch_names)
422 break; 456 break;
457 }
423 } 458 }
424 459
460 if (i < rp->arch_names)
461 break;
462 }
463
425 /* failed, create a fresh object. Note no nrof>1 because that would 464 /* failed, create a fresh object. Note no nrof>1 because that would
426 * allow players to create massive amounts of artifacts easily */ 465 * allow players to create massive amounts of artifacts easily */
427 if(create_item && (!item || item->nrof > 1)) { 466 if (create_item && (!item || item->nrof > 1))
467 {
428 *rp_arch_index = RANDOM()%rp->arch_names; 468 *rp_arch_index = RANDOM () % rp->arch_names;
429 item = get_archetype(rp->arch_name[*rp_arch_index]); 469 item = get_archetype (rp->arch_name[*rp_arch_index]);
430 } 470 }
431 471
432#ifdef ALCHEMY_DEBUG 472#ifdef ALCHEMY_DEBUG
433 LOG(llevDebug,"recipe calls for%stransmution.\n",rp->transmute?" ":" no "); 473 LOG (llevDebug, "recipe calls for%stransmution.\n", rp->transmute ? " " : " no ");
434 if (item != NULL) { 474 if (item != NULL)
435 LOG(llevDebug," find_transmutable_ob(): returns arch %s(sp:%d)\n",
436 item->arch->name,item->stats.sp);
437 } 475 {
476 LOG (llevDebug, " find_transmutable_ob(): returns arch %s(sp:%d)\n", item->arch->name, item->stats.sp);
477 }
438#endif 478#endif
439 479
440 return item; 480 return item;
441} 481}
442 482
443 483
444/** 484/**
445 * Ouch. We didnt get the formula we wanted. 485 * Ouch. We didnt get the formula we wanted.
446 * This fctn simulates the backfire effects--worse effects as the level 486 * This fctn simulates the backfire effects--worse effects as the level
447 * increases. If SPELL_FAILURE_EFFECTS is defined some really evil things 487 * increases. If SPELL_FAILURE_EFFECTS is defined some really evil things
448 * can happen to the would be alchemist. This table probably needs some 488 * can happen to the would be alchemist. This table probably needs some
449 * adjustment for playbalance. -b.t. 489 * adjustment for playbalance. -b.t.
450 */ 490 */
451 491
492void
452void alchemy_failure_effect(object *op,object *cauldron,recipe *rp,int danger) { 493alchemy_failure_effect (object *op, object *cauldron, recipe *rp, int danger)
494{
453 int level=0; 495 int level = 0;
454 496
455 if(!op || !cauldron) return; 497 if (!op || !cauldron)
498 return;
456 499
500 if (danger > 1)
457 if(danger>1) level=random_roll(1, danger, op, PREFER_LOW); 501 level = random_roll (1, danger, op, PREFER_LOW);
458 502
459#ifdef ALCHEMY_DEBUG 503#ifdef ALCHEMY_DEBUG
460 LOG(llevDebug,"Alchemy_failure_effect(): using level=%d\n",level); 504 LOG (llevDebug, "Alchemy_failure_effect(): using level=%d\n", level);
461#endif 505#endif
462 506
463 /* possible outcomes based on level */ 507 /* possible outcomes based on level */
464 if(level<25) { /* INGREDIENTS USED/SLAGGED */ 508 if (level < 25)
509 { /* INGREDIENTS USED/SLAGGED */
465 object *item=NULL; 510 object *item = NULL;
466 511
467 if(rndm(0, 2)) { /* slag created */ 512 if (rndm (0, 2))
513 { /* slag created */
468 object *tmp=cauldron->inv; 514 object *tmp = cauldron->inv;
469 int weight=0; 515 int weight = 0;
470 uint16 material=M_STONE; 516 uint16 material = M_STONE;
471 517
518 while (tmp)
472 while(tmp) { /* slag has coadded ingredient properties */ 519 { /* slag has coadded ingredient properties */
473 weight+=tmp->weight; 520 weight += tmp->weight;
474 if(!(material&tmp->material)) 521 if (!(material & tmp->material))
475 material |= tmp->material; 522 material |= tmp->material;
476 tmp=tmp->below; 523 tmp = tmp->below;
477 } 524 }
478 tmp = get_archetype("rock"); 525 tmp = get_archetype ("rock");
479 tmp->weight=weight; 526 tmp->weight = weight;
480 tmp->value=0; 527 tmp->value = 0;
481 tmp->material=material; 528 tmp->material = material;
482 tmp->materialname = "stone"; 529 tmp->materialname = "stone";
483 tmp->name="slag"; 530 tmp->name = "slag";
484 tmp->name_pl="slags"; 531 tmp->name_pl = "slags";
485 item=insert_ob_in_ob(tmp,cauldron); 532 item = insert_ob_in_ob (tmp, cauldron);
486 CLEAR_FLAG(tmp,FLAG_CAN_ROLL); 533 CLEAR_FLAG (tmp, FLAG_CAN_ROLL);
487 CLEAR_FLAG(tmp,FLAG_NO_PICK); 534 CLEAR_FLAG (tmp, FLAG_NO_PICK);
488 tmp->move_block = 0; 535 tmp->move_block = 0;
489 } 536 }
490 remove_contents(cauldron->inv,item); 537 remove_contents (cauldron->inv, item);
491 new_draw_info_format(NDI_UNIQUE,0,op, 538 new_draw_info_format (NDI_UNIQUE, 0, op, "The %s %s.", &cauldron->name, cauldron_sound ());
492 "The %s %s.", &cauldron->name,cauldron_sound()); 539 return;
540 }
541 else if (level < 40)
542 { /* MAKE TAINTED ITEM */
543 object *tmp = NULL;
544
545 if (!rp)
546 if ((rp = get_random_recipe ((recipelist *) NULL)) == NULL)
493 return; 547 return;
494 } else if (level< 40) { /* MAKE TAINTED ITEM */
495 object *tmp=NULL;
496 548
497 if (!rp)
498 if((rp=get_random_recipe((recipelist *) NULL))==NULL)
499 return;
500
501 if((tmp=attempt_recipe(op,cauldron,1,rp,-1))) { 549 if ((tmp = attempt_recipe (op, cauldron, 1, rp, -1)))
550 {
502 if(!QUERY_FLAG(tmp,FLAG_CURSED)) /* curse it */ 551 if (!QUERY_FLAG (tmp, FLAG_CURSED)) /* curse it */
503 SET_FLAG(tmp,FLAG_CURSED); 552 SET_FLAG (tmp, FLAG_CURSED);
504 553
505 /* the apply code for potions already deals with cursed 554 /* the apply code for potions already deals with cursed
506 * potions, so any code here is basically ignored. 555 * potions, so any code here is basically ignored.
507 */ 556 */
508 if(tmp->type==FOOD) { 557 if (tmp->type == FOOD)
558 {
509 tmp->stats.hp=random_roll(0, 149, op, PREFER_LOW); 559 tmp->stats.hp = random_roll (0, 149, op, PREFER_LOW);
510 } 560 }
511 tmp->value = 0; /* unsaleable item */ 561 tmp->value = 0; /* unsaleable item */
512 562
513 /* change stats downward */ 563 /* change stats downward */
514 do { 564 do
565 {
515 change_attr_value(&tmp->stats,rndm(0, 6),-1*(rndm(1, 3))); 566 change_attr_value (&tmp->stats, rndm (0, 6), -1 * (rndm (1, 3)));
567 }
516 } while (rndm(0, 2)); 568 while (rndm (0, 2));
517 } 569 }
518 return; 570 return;
571 }
572 if (level == 40)
519 } if(level==40) { /* MAKE RANDOM RECIPE */ 573 { /* MAKE RANDOM RECIPE */
520 recipelist *fl; 574 recipelist *fl;
521 int numb=numb_ob_inside(cauldron); 575 int numb = numb_ob_inside (cauldron);
522 576
523 fl=get_formulalist(numb-1); /* take a lower recipe list */ 577 fl = get_formulalist (numb - 1); /* take a lower recipe list */
524 if(fl &&(rp=get_random_recipe(fl))) 578 if (fl && (rp = get_random_recipe (fl)))
525 /* even though random, don't grant user any EXP for it */ 579 /* even though random, don't grant user any EXP for it */
526 (void) attempt_recipe(op,cauldron,1,rp,-1); 580 (void) attempt_recipe (op, cauldron, 1, rp, -1);
527 else 581 else
528 alchemy_failure_effect(op,cauldron,rp,level-1); 582 alchemy_failure_effect (op, cauldron, rp, level - 1);
529 return; 583 return;
530 584
531 } else if (level<45) { /* INFURIATE NPC's */ 585 }
586 else if (level < 45)
587 { /* INFURIATE NPC's */
532 /* this is kind of kludgy I know...*/ 588 /* this is kind of kludgy I know... */
533 cauldron->enemy=op; 589 cauldron->enemy = op;
534 npc_call_help(cauldron); 590 npc_call_help (cauldron);
535 cauldron->enemy=NULL; 591 cauldron->enemy = NULL;
536 592
537 alchemy_failure_effect(op,cauldron,rp,level-5); 593 alchemy_failure_effect (op, cauldron, rp, level - 5);
538 return; 594 return;
539 } else if (level<50) { /* MINOR EXPLOSION/FIREBALL */ 595 }
596 else if (level < 50)
597 { /* MINOR EXPLOSION/FIREBALL */
540 object *tmp; 598 object *tmp;
599
541 remove_contents(cauldron->inv,NULL); 600 remove_contents (cauldron->inv, NULL);
542 switch(rndm(0, 2)) { 601 switch (rndm (0, 2))
602 {
543 case 0: 603 case 0:
544 tmp=get_archetype("bomb"); 604 tmp = get_archetype ("bomb");
545 tmp->stats.dam=random_roll(1, level, op, PREFER_LOW); 605 tmp->stats.dam = random_roll (1, level, op, PREFER_LOW);
546 tmp->stats.hp=random_roll(1, level, op, PREFER_LOW); 606 tmp->stats.hp = random_roll (1, level, op, PREFER_LOW);
547 new_draw_info_format(NDI_UNIQUE,0,op,"The %s creates a bomb!", 607 new_draw_info_format (NDI_UNIQUE, 0, op, "The %s creates a bomb!", &cauldron->name);
548 &cauldron->name);
549 break; 608 break;
550 609
551 default: 610 default:
552 tmp=get_archetype("fireball"); 611 tmp = get_archetype ("fireball");
553 tmp->stats.dam=random_roll(1, level, op, PREFER_LOW)/5+1; 612 tmp->stats.dam = random_roll (1, level, op, PREFER_LOW) / 5 + 1;
554 tmp->stats.hp=random_roll(1, level, op, PREFER_LOW)/10+2; 613 tmp->stats.hp = random_roll (1, level, op, PREFER_LOW) / 10 + 2;
555 new_draw_info_format(NDI_UNIQUE,0,op,"The %s erupts in flame!", 614 new_draw_info_format (NDI_UNIQUE, 0, op, "The %s erupts in flame!", &cauldron->name);
556 &cauldron->name);
557 break; 615 break;
558 } 616 }
559 tmp->x=cauldron->x,tmp->y=cauldron->y; 617
560 insert_ob_in_map(tmp,op->map,NULL,0); 618 op->insert_at (cauldron);
561 return; 619 return;
562 620
563 } else if (level<60) { /* CREATE MONSTER */ 621 }
564 new_draw_info_format(NDI_UNIQUE,0,op, 622 else if (level < 60)
565 "The %s %s.",&cauldron->name,cauldron_sound()); 623 { /* CREATE MONSTER */
624 new_draw_info_format (NDI_UNIQUE, 0, op, "The %s %s.", &cauldron->name, cauldron_sound ());
566 remove_contents(cauldron->inv,NULL); 625 remove_contents (cauldron->inv, NULL);
567 return; 626 return;
568 } else if (level<80) { /* MAJOR FIRE */ 627 }
628 else if (level < 80)
629 { /* MAJOR FIRE */
569 object *fb = get_archetype(SP_MED_FIREBALL); 630 object *fb = get_archetype (SP_MED_FIREBALL);
631
570 remove_contents(cauldron->inv,NULL); 632 remove_contents (cauldron->inv, NULL);
571 fire_arch_from_position(cauldron, cauldron,cauldron->x, cauldron->y, 633 fire_arch_from_position (cauldron, cauldron, cauldron->x, cauldron->y, 0, fb);
572 0, fb); 634 fb->destroy ();
573 free_object(fb);
574 new_draw_info_format(NDI_UNIQUE,0,op,"The %s erupts in flame!", 635 new_draw_info_format (NDI_UNIQUE, 0, op, "The %s erupts in flame!", &cauldron->name);
575 &cauldron->name);
576 return; 636 return;
577 637
578 } else if (level<100) { /* WHAMMY the CAULDRON */ 638 }
639 else if (level < 100)
640 { /* WHAMMY the CAULDRON */
579 if(!QUERY_FLAG(cauldron,FLAG_CURSED)) 641 if (!QUERY_FLAG (cauldron, FLAG_CURSED))
580 SET_FLAG(cauldron,FLAG_CURSED); 642 SET_FLAG (cauldron, FLAG_CURSED);
643 else
581 else cauldron->magic--; 644 cauldron->magic--;
582 cauldron->magic -= random_roll(0, 4, op, PREFER_LOW); 645 cauldron->magic -= random_roll (0, 4, op, PREFER_LOW);
583 if(rndm(0, 1)) { 646 if (rndm (0, 1))
647 {
584 remove_contents(cauldron->inv,NULL); 648 remove_contents (cauldron->inv, NULL);
585 new_draw_info_format(NDI_UNIQUE,0,op, 649 new_draw_info_format (NDI_UNIQUE, 0, op, "Your %s turns darker then makes a gulping sound!", &cauldron->name);
586 "Your %s turns darker then makes a gulping sound!", 650 }
587 &cauldron->name);
588 } else 651 else
589 new_draw_info_format(NDI_UNIQUE,0,op, 652 new_draw_info_format (NDI_UNIQUE, 0, op, "Your %s becomes darker.", &cauldron->name);
590 "Your %s becomes darker.",&cauldron->name);
591 return; 653 return;
592 654
593 } else if (level<110) { /* SUMMON EVIL MONSTERS */ 655 }
656 else if (level < 110)
657 { /* SUMMON EVIL MONSTERS */
594 object *tmp=get_random_mon(level/5); 658 object *tmp = get_random_mon (level / 5);
595 659
596 remove_contents(cauldron->inv,NULL); 660 remove_contents (cauldron->inv, NULL);
597 if(!tmp) 661 if (!tmp)
598 alchemy_failure_effect(op,cauldron,rp,level); 662 alchemy_failure_effect (op, cauldron, rp, level);
599 else if(summon_hostile_monsters(cauldron, random_roll(1, 10, op, PREFER_LOW), tmp->arch->name)) 663 else if (summon_hostile_monsters (cauldron, random_roll (1, 10, op, PREFER_LOW), tmp->arch->name))
600 new_draw_info_format(NDI_UNIQUE, 0,op, 664 new_draw_info_format (NDI_UNIQUE, 0, op, "The %s %s and then pours forth monsters!", &cauldron->name, cauldron_sound ());
601 "The %s %s and then pours forth monsters!",
602 &cauldron->name,cauldron_sound());
603 return; 665 return;
604 666
605 } else if (level<150) { /* COMBO EFFECT */ 667 }
668 else if (level < 150)
669 { /* COMBO EFFECT */
606 int roll = rndm(1, 3); 670 int roll = rndm (1, 3);
671
607 while(roll) { 672 while (roll)
673 {
608 alchemy_failure_effect(op,cauldron,rp,level-39); 674 alchemy_failure_effect (op, cauldron, rp, level - 39);
609 roll--; 675 roll--;
610 } 676 }
611 return; 677 return;
612 } else if (level==151) { /* CREATE RANDOM ARTIFACT */ 678 }
679 else if (level == 151)
680 { /* CREATE RANDOM ARTIFACT */
613 object *tmp; 681 object *tmp;
682
614 /* this is meant to be better than prior possiblity, 683 /* this is meant to be better than prior possiblity,
615 * in this one, we allow *any* valid alchemy artifact 684 * in this one, we allow *any* valid alchemy artifact
616 * to be made (rather than only those on the given 685 * to be made (rather than only those on the given
617 * formulalist) */ 686 * formulalist) */
687 if (!rp)
618 if(!rp) rp=get_random_recipe((recipelist *) NULL); 688 rp = get_random_recipe ((recipelist *) NULL);
619 if(rp && (tmp=get_archetype(rp->arch_name[RANDOM()%rp->arch_names]))) { 689 if (rp && (tmp = get_archetype (rp->arch_name[RANDOM () % rp->arch_names])))
690 {
620 generate_artifact(tmp,random_roll(1, op->level/2+1, op, PREFER_HIGH)+1); 691 generate_artifact (tmp, random_roll (1, op->level / 2 + 1, op, PREFER_HIGH) + 1);
621 if((tmp=insert_ob_in_ob(tmp,cauldron))) { 692 if ((tmp = insert_ob_in_ob (tmp, cauldron)))
693 {
622 remove_contents(cauldron->inv,tmp); 694 remove_contents (cauldron->inv, tmp);
623 new_draw_info_format(NDI_UNIQUE, 0,op, 695 new_draw_info_format (NDI_UNIQUE, 0, op, "The %s %s.", &cauldron->name, cauldron_sound ());
624 "The %s %s.",&cauldron->name,cauldron_sound());
625 }
626 } 696 }
697 }
627 return; 698 return;
699 }
700 else
628 } else { /* MANA STORM - watch out!! */ 701 { /* MANA STORM - watch out!! */
629 object *tmp = get_archetype(LOOSE_MANA); 702 object *tmp = get_archetype (LOOSE_MANA);
703
630 new_draw_info(NDI_UNIQUE,0,op,"You unwisely release potent forces!"); 704 new_draw_info (NDI_UNIQUE, 0, op, "You unwisely release potent forces!");
631 remove_contents (cauldron->inv,NULL); 705 remove_contents (cauldron->inv, NULL);
632 cast_magic_storm(op,tmp, level); 706 cast_magic_storm (op, tmp, level);
633 return; 707 return;
634 } 708 }
635} 709}
636 710
637 711
638/** 712/*
639 * All but object "save_item" are elimentated from 713 * All but object "save_item" are elimentated from
640 * the container list. Note we have to becareful to remove the inventories 714 * the container list. Note we have to becareful to remove the inventories
641 * of objects in the cauldron inventory (ex icecube has stuff in it). 715 * of objects in the cauldron inventory (ex icecube has stuff in it).
642 */ 716 */
643 717
718void
644void remove_contents (object *first_ob, object *save_item) { 719remove_contents (object *first_ob, object *save_item)
720{
645 object *next,*tmp=first_ob; 721 object *next, *tmp = first_ob;
646 722
647 while(tmp) { 723 while (tmp)
724 {
648 next = tmp->below; 725 next = tmp->below;
726
649 if(tmp==save_item) { 727 if (tmp == save_item)
650 if(!(tmp=next)) break;
651 else next=next->below;
652 } 728 {
729 if (!(tmp = next))
730 break;
731 else
732 next = next->below;
733 }
734
735 if (tmp->inv)
653 if(tmp->inv) remove_contents(tmp->inv,NULL); 736 remove_contents (tmp->inv, NULL);
654 remove_ob(tmp); 737
655 free_object(tmp); 738 tmp->destroy ();
656 tmp=next; 739 tmp = next;
657 } 740 }
658} 741}
659 742
660/** 743/**
661 *"Danger" level, will determine how bad the backfire 744 *"Danger" level, will determine how bad the backfire
665 * mixing device (aka "cauldron"). Higher values of 'danger' indicate more 748 * mixing device (aka "cauldron"). Higher values of 'danger' indicate more
666 * danger. Note that we assume that we have had the caster ready the alchemy 749 * danger. Note that we assume that we have had the caster ready the alchemy
667 * skill *before* this routine is called. (no longer auto-readies that skill) 750 * skill *before* this routine is called. (no longer auto-readies that skill)
668 * -b.t. 751 * -b.t.
669 */ 752 */
670 753
754int
671int calc_alch_danger(object *caster,object *cauldron, recipe *rp) { 755calc_alch_danger (object *caster, object *cauldron, recipe *rp)
756{
672 object *item; 757 object *item;
673 char name[MAX_BUF]; 758 char name[MAX_BUF];
674 int danger=0,nrofi=0; 759 int danger = 0, nrofi = 0;
675 760
676 /* Knowing alchemy skill reduces yer risk */ 761 /* Knowing alchemy skill reduces yer risk */
677 danger -= caster->chosen_skill?caster->chosen_skill->level:caster->level; 762 danger -= caster->chosen_skill ? caster->chosen_skill->level : caster->level;
678 763
679 /* better cauldrons reduce risk */ 764 /* better cauldrons reduce risk */
680 danger -= cauldron->magic; 765 danger -= cauldron->magic;
681 766
682 /* Higher Int, lower the risk */ 767 /* Higher Int, lower the risk */
683 danger -= 3 * (caster->stats.Int - 15); 768 danger -= 3 * (caster->stats.Int - 15);
684 769
685 /* Ingredients. Longer names usually mean rarer stuff. 770 /* Ingredients. Longer names usually mean rarer stuff.
686 * Thus the backfire is worse. Also, more ingredients 771 * Thus the backfire is worse. Also, more ingredients
687 * means we are attempting a more powerfull potion, 772 * means we are attempting a more powerfull potion,
688 * and thus the backfire will be worse. */ 773 * and thus the backfire will be worse. */
689 for(item=cauldron->inv;item;item=item->below) { 774 for (item = cauldron->inv; item; item = item->below)
775 {
690 strcpy(name,item->name); 776 assign (name, item->name);
777 if (item->title)
691 if(item->title) sprintf(name,"%s %s", &item->name, &item->title); 778 sprintf (name, "%s %s", &item->name, &item->title);
692 danger += (strtoint(name)/1000) + 3; 779 danger += (strtoint (name) / 1000) + 3;
693 nrofi++; 780 nrofi++;
694 } 781 }
695 if (rp == NULL) 782 if (rp == NULL)
696 danger += 110; 783 danger += 110;
697 else 784 else
698 danger += rp->diff*3; 785 danger += rp->diff * 3;
699 786
700 /* Using a bad device is *majorly* stupid */ 787 /* Using a bad device is *majorly* stupid */
701 if(QUERY_FLAG(cauldron,FLAG_CURSED)) danger +=80; 788 if (QUERY_FLAG (cauldron, FLAG_CURSED))
789 danger += 80;
702 if(QUERY_FLAG(cauldron,FLAG_DAMNED)) danger +=200; 790 if (QUERY_FLAG (cauldron, FLAG_DAMNED))
791 danger += 200;
703 792
704#ifdef ALCHEMY_DEBUG 793#ifdef ALCHEMY_DEBUG
705 LOG(llevDebug,"calc_alch_danger() returned danger=%d\n",danger); 794 LOG (llevDebug, "calc_alch_danger() returned danger=%d\n", danger);
706#endif 795#endif
707 796
708 return danger; 797 return danger;
709} 798}
710 799
711/** 800/**
712 * Determines if ingredients in a container match the 801 * Determines if ingredients in a container match the
713 * proper ingredients for a recipe. 802 * proper ingredients for a recipe.
720 * the defined recipe iff 809 * the defined recipe iff
721 * - the number of ingredients of the recipe and in the container is equal 810 * - the number of ingredients of the recipe and in the container is equal
722 * - all ingredients of the recipe are found in the container 811 * - all ingredients of the recipe are found in the container
723 * - the number of batches is the same for all ingredients 812 * - the number of batches is the same for all ingredients
724 */ 813 */
814static int
725static int is_defined_recipe(const recipe *rp, const object *cauldron, object *caster) 815is_defined_recipe (const recipe *rp, const object *cauldron, object *caster)
726{ 816{
727 uint32 batches_in_cauldron; 817 uint32 batches_in_cauldron;
728 const linked_char *ingredient; 818 const linked_char *ingredient;
729 int number; 819 int number;
730 const object *ob; 820 const object *ob;
731 821
732 /* check for matching number of ingredients */ 822 /* check for matching number of ingredients */
733 number = 0; 823 number = 0;
734 for(ingredient = rp->ingred; ingredient != NULL; ingredient = ingredient->next) 824 for (ingredient = rp->ingred; ingredient != NULL; ingredient = ingredient->next)
735 number++; 825 number++;
736 for(ob = cauldron->inv; ob != NULL; ob = ob->below) 826 for (ob = cauldron->inv; ob != NULL; ob = ob->below)
737 number--; 827 number--;
738 if(number != 0) 828 if (number != 0)
739 return 0; 829 return 0;
740 830
741 /* check for matching ingredients */ 831 /* check for matching ingredients */
742 batches_in_cauldron = 0; 832 batches_in_cauldron = 0;
743 for(ingredient = rp->ingred; ingredient != NULL; ingredient = ingredient->next) { 833 for (ingredient = rp->ingred; ingredient != NULL; ingredient = ingredient->next)
834 {
744 uint32 nrof; 835 uint32 nrof;
745 const char *name; 836 const char *name;
746 int ok; 837 int ok;
747 838
748 /* determine and remove nrof from name */ 839 /* determine and remove nrof from name */
749 name = ingredient->name; 840 name = ingredient->name;
750 nrof = 0; 841 nrof = 0;
751 while(isdigit(*name)) { 842 while (isdigit (*name))
843 {
752 nrof = 10*nrof+(*name-'0'); 844 nrof = 10 * nrof + (*name - '0');
753 name++; 845 name++;
754 } 846 }
755 if(nrof == 0) 847 if (nrof == 0)
756 nrof = 1; 848 nrof = 1;
757 while(*name == ' ') 849 while (*name == ' ')
758 name++; 850 name++;
759 851
760 /* find the current ingredient in the cauldron */ 852 /* find the current ingredient in the cauldron */
761 ok = 0; 853 ok = 0;
762 for(ob = cauldron->inv; ob != NULL; ob = ob->below) { 854 for (ob = cauldron->inv; ob != NULL; ob = ob->below)
855 {
763 char name_ob[MAX_BUF]; 856 char name_ob[MAX_BUF];
764 const char *name2; 857 const char *name2;
765 858
766 if(ob->title == NULL) 859 if (ob->title == NULL)
767 name2 = ob->name; 860 name2 = ob->name;
768 else { 861 else
862 {
769 snprintf(name_ob, sizeof(name_ob), "%s %s", &ob->name, &ob->title); 863 snprintf (name_ob, sizeof (name_ob), "%s %s", &ob->name, &ob->title);
770 name2 = name_ob; 864 name2 = name_ob;
771 } 865 }
772 866
773 if(strcmp(name2, name) == 0) { 867 if (strcmp (name2, name) == 0)
868 {
774 if(ob->nrof%nrof == 0) { 869 if (ob->nrof % nrof == 0)
870 {
775 uint32 batches; 871 uint32 batches;
776 872
777 batches = ob->nrof/nrof; 873 batches = ob->nrof / nrof;
778 if(batches_in_cauldron == 0) { 874 if (batches_in_cauldron == 0)
875 {
779 batches_in_cauldron = batches; 876 batches_in_cauldron = batches;
780 ok = 1; 877 ok = 1;
878 }
781 } else if(batches_in_cauldron == batches) 879 else if (batches_in_cauldron == batches)
782 ok = 1; 880 ok = 1;
783 } 881 }
784 break; 882 break;
785 }
786 } 883 }
884 }
787 if(!ok) 885 if (!ok)
788 return(0); 886 return (0);
789 } 887 }
790 888
791 return(1); 889 return (1);
792} 890}
793 891
794/** 892/**
795 * Find a recipe from a recipe list that matches the given formula. If there 893 * Find a recipe from a recipe list that matches the given formula. If there
796 * is more than one matching recipe, it selects a random one. If at least one 894 * is more than one matching recipe, it selects a random one. If at least one
797 * transmuting recipe matches, it only considers matching transmuting recipes. 895 * transmuting recipe matches, it only considers matching transmuting recipes.
798 * 896 *
799 * @return one matching recipe, or NULL if no recipe matches 897 * @return one matching recipe, or NULL if no recipe matches
800 */ 898 */
899static recipe *
801static recipe *find_recipe(recipelist *fl, int formula, object *ingredients) 900find_recipe (recipelist * fl, int formula, object *ingredients)
802{ 901{
803 recipe *rp; 902 recipe *rp;
804 recipe *result; /* winning recipe, or NULL if no recipe found */ 903 recipe *result; /* winning recipe, or NULL if no recipe found */
805 int recipes_matching; /* total number of matching recipes so far */ 904 int recipes_matching; /* total number of matching recipes so far */
806 int transmute_found; /* records whether a transmuting recipe was found so far */ 905 int transmute_found; /* records whether a transmuting recipe was found so far */
807 size_t rp_arch_index; 906 size_t rp_arch_index;
808 907
809#ifdef EXTREME_ALCHEMY_DEBUG 908#ifdef EXTREME_ALCHEMY_DEBUG
810 LOG(llevDebug, "looking for formula %d:\n", formula); 909 LOG (llevDebug, "looking for formula %d:\n", formula);
811#endif 910#endif
812 result = NULL; 911 result = NULL;
813 recipes_matching = 0; 912 recipes_matching = 0;
814 transmute_found = 0; 913 transmute_found = 0;
815 for (rp = fl->items; rp != NULL; rp = rp->next) { 914 for (rp = fl->items; rp != NULL; rp = rp->next)
915 {
816 /* check if recipe matches at all */ 916 /* check if recipe matches at all */
817 if (formula%rp->index != 0) { 917 if (formula % rp->index != 0)
918 {
818#ifdef EXTREME_ALCHEMY_DEBUG 919#ifdef EXTREME_ALCHEMY_DEBUG
819 LOG(llevDebug, " formula %s of %s (%d) does not match\n", rp->arch_name[0], rp->title, rp->index); 920 LOG (llevDebug, " formula %s of %s (%d) does not match\n", rp->arch_name[0], rp->title, rp->index);
820#endif 921#endif
821 continue; 922 continue;
822 } 923 }
823 924
824 if (rp->transmute && find_transmution_ob(ingredients, rp, &rp_arch_index, 0) != NULL) { 925 if (rp->transmute && find_transmution_ob (ingredients, rp, &rp_arch_index, 0) != NULL)
926 {
825#ifdef EXTREME_ALCHEMY_DEBUG 927#ifdef EXTREME_ALCHEMY_DEBUG
826 LOG(llevDebug, " formula %s of %s (%d) is a matching transmuting formula\n", rp->arch_name[rp_arch_index], rp->title, rp->index); 928 LOG (llevDebug, " formula %s of %s (%d) is a matching transmuting formula\n", rp->arch_name[rp_arch_index], rp->title, rp->index);
827#endif 929#endif
828 /* transmution recipe with matching base ingredient */ 930 /* transmution recipe with matching base ingredient */
829 if (!transmute_found) { 931 if (!transmute_found)
932 {
830 transmute_found = 1; 933 transmute_found = 1;
831 recipes_matching = 0; 934 recipes_matching = 0;
935 }
832 } 936 }
833 } else if (transmute_found) { 937 else if (transmute_found)
938 {
834#ifdef EXTREME_ALCHEMY_DEBUG 939#ifdef EXTREME_ALCHEMY_DEBUG
835 LOG(llevDebug, " formula %s of %s (%d) matches but is not a matching transmuting formula\n", rp->arch_name[0], rp->title, rp->index); 940 LOG (llevDebug, " formula %s of %s (%d) matches but is not a matching transmuting formula\n", rp->arch_name[0], rp->title,
941 rp->index);
836#endif 942#endif
837 /* "normal" recipe found after previous transmution recipe => ignore this recipe */ 943 /* "normal" recipe found after previous transmution recipe => ignore this recipe */
838 continue; 944 continue;
839 } 945 }
840#ifdef EXTREME_ALCHEMY_DEBUG 946#ifdef EXTREME_ALCHEMY_DEBUG
841 else { 947 else
948 {
842 LOG(llevDebug, " formula %s of %s (%d) matches\n", rp->arch_name[0], rp->title, rp->index); 949 LOG (llevDebug, " formula %s of %s (%d) matches\n", rp->arch_name[0], rp->title, rp->index);
843 } 950 }
844#endif 951#endif
845 952
846 if (rndm(0, recipes_matching) == 0) 953 if (rndm (0, recipes_matching) == 0)
847 result = rp; 954 result = rp;
848 955
849 recipes_matching++; 956 recipes_matching++;
850 } 957 }
851 958
852 if (result == NULL) { 959 if (result == NULL)
960 {
853#ifdef ALCHEMY_DEBUG 961#ifdef ALCHEMY_DEBUG
854 LOG(llevDebug, "couldn't find formula for ingredients.\n"); 962 LOG (llevDebug, "couldn't find formula for ingredients.\n");
855#endif 963#endif
856 return NULL; 964 return NULL;
857 } 965 }
858 966
859#ifdef ALCHEMY_DEBUG 967#ifdef ALCHEMY_DEBUG
860 if(strcmp(result->title, "NONE") != 0) 968 if (strcmp (result->title, "NONE") != 0)
861 LOG(llevDebug, "got formula: %s of %s (nbatches:%d)\n", result->arch_name[0], result->title, formula/result->index); 969 LOG (llevDebug, "got formula: %s of %s (nbatches:%d)\n", result->arch_name[0], result->title, formula / result->index);
862 else 970 else
863 LOG(llevDebug, "got formula: %s (nbatches:%d)\n", result->arch_name[0], formula/result->index); 971 LOG (llevDebug, "got formula: %s (nbatches:%d)\n", result->arch_name[0], formula / result->index);
864#endif 972#endif
865 return result; 973 return result;
866} 974}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines