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.6 by elmex, Sun Sep 3 14:33:45 2006 UTC vs.
Revision 1.7 by root, Sun Sep 10 15:59:57 2006 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines