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.15 by root, Tue Dec 26 20:04:09 2006 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines