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

1/*
2 * static char *rcsid_alchemy_c =
3 * "$Id: alchemy.C,v 1.6 2006/09/03 14:33:45 elmex 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) { 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) { 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) {
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
278 294
279 LOG(llevDebug,"A %s <=> %s\n", &(rp->cauldron), &(cauldron->arch->name)); 295 LOG (llevDebug, "A %s <=> %s\n", &(rp->cauldron), &(cauldron->arch->name));
280 /* is the cauldron the right type? */ 296 /* is the cauldron the right type? */
281 if (strcmp(rp->cauldron, cauldron->arch->name) != 0) { 297 if (strcmp (rp->cauldron, cauldron->arch->name) != 0)
298 {
282 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.");
283 " facilities for this formula.");
284 return 0; 300 return 0;
285 } 301 }
286 302
287 skop = find_skill_by_name(caster, rp->skill); 303 skop = find_skill_by_name (caster, rp->skill);
288 /* does the caster have the skill? */ 304 /* does the caster have the skill? */
289 if (!skop) 305 if (!skop)
290 return 0; 306 return 0;
291 307
292 /* code required for this recipe, search the caster */ 308 /* code required for this recipe, search the caster */
293 if(rp->keycode) { 309 if (rp->keycode)
310 {
294 object *tmp; 311 object *tmp;
312
295 for(tmp=caster->inv; tmp != NULL; tmp=tmp->below) { 313 for (tmp = caster->inv; tmp != NULL; tmp = tmp->below)
296 if(tmp->type==FORCE && tmp->slaying && 314 {
297 !strcmp(rp->keycode, tmp->slaying)) 315 if (tmp->type == FORCE && tmp->slaying && !strcmp (rp->keycode, tmp->slaying))
298 break; 316 break;
299 } 317 }
300 if(tmp==NULL) { /* failure--no code found */ 318 if (tmp == NULL)
301 new_draw_info(NDI_UNIQUE, 0, caster, "You know the ingredients," 319 { /* failure--no code found */
302 " 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.");
303 return 0; 321 return 0;
304 } 322 }
305 } 323 }
306 324
307#ifdef EXTREME_ALCHEMY_DEBUG 325#ifdef EXTREME_ALCHEMY_DEBUG
308 LOG(llevDebug,"attempt_recipe(): got %d nbatches\n",nbatches); 326 LOG (llevDebug, "attempt_recipe(): got %d nbatches\n", nbatches);
309 LOG(llevDebug,"attempt_recipe(): using recipe %s\n", 327 LOG (llevDebug, "attempt_recipe(): using recipe %s\n", rp->title ? rp->title : "unknown");
310 rp->title?rp->title:"unknown");
311#endif 328#endif
312 329
313 if((item=make_item_from_recipe(cauldron, rp))!=NULL) { 330 if ((item = make_item_from_recipe (cauldron, rp)) != NULL)
331 {
314 remove_contents(cauldron->inv, item); 332 remove_contents (cauldron->inv, item);
315 /* 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 */
316 sum_weight(cauldron); 334 sum_weight (cauldron);
317 /* adj lvl, nrof on caster level */ 335 /* adj lvl, nrof on caster level */
318 adjust_product(item, ability, rp->yield?(rp->yield*batches):batches); 336 adjust_product (item, ability, rp->yield ? (rp->yield * batches) : batches);
319 if(!item->env && (item=insert_ob_in_ob(item,cauldron)) == NULL) { 337 if (!item->env && (item = insert_ob_in_ob (item, cauldron)) == NULL)
338 {
320 new_draw_info(NDI_UNIQUE, 0,caster,"Nothing happened."); 339 new_draw_info (NDI_UNIQUE, 0, caster, "Nothing happened.");
321 /* new_draw_info_format(NDI_UNIQUE, 0,caster, 340 /* new_draw_info_format(NDI_UNIQUE, 0,caster,
322 "Your spell causes the %s to explode!",&cauldron->name); */ 341 "Your spell causes the %s to explode!",&cauldron->name); */
323 /* kaboom_cauldron(); */ 342 /* kaboom_cauldron(); */
343 }
324 } else { 344 else
325 new_draw_info_format(NDI_UNIQUE, 0,caster,
326 "The %s %s.", &cauldron->name,cauldron_sound());
327 } 345 {
346 new_draw_info_format (NDI_UNIQUE, 0, caster, "The %s %s.", &cauldron->name, cauldron_sound ());
347 }
328 } 348 }
329 return item; 349 return item;
330} 350}
331 351
332 352
333 353
334/** 354/**
335 * 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
336 * 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.
337 */ 357 */
338 358 void
339void adjust_product(object *item, int lvl, int yield) { 359adjust_product (object *item, int lvl, int yield)
360{
340 int nrof=1; 361 int nrof = 1;
341 362
342 if (!yield) 363 if (!yield)
343 yield = 1; 364 yield = 1;
344 if (lvl<=0) 365 if (lvl <= 0)
345 lvl = 1; /* lets avoid div by zero! */ 366 lvl = 1; /* lets avoid div by zero! */
346 if (item->nrof) { 367 if (item->nrof)
347 nrof = (int) ( 368 {
348 (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);
349 (rndm(0, yield-1) + rndm(0, yield-1) + rndm(0, yield-1)) + 1
350 );
351 if (nrof > yield) 370 if (nrof > yield)
352 nrof = yield; 371 nrof = yield;
353 item->nrof=nrof; 372 item->nrof = nrof;
354 } 373 }
355} 374}
356 375
357 376
358/** 377/**
363 * @param rp the recipe to make the artifact from 382 * @param rp the recipe to make the artifact from
364 * 383 *
365 * @return the newly created object, NULL if something failed 384 * @return the newly created object, NULL if something failed
366 */ 385 */
367 386
387object *
368object * make_item_from_recipe(object *cauldron, recipe *rp) { 388make_item_from_recipe (object *cauldron, recipe *rp)
389{
369 artifact *art=NULL; 390 artifact *art = NULL;
370 object *item=NULL; 391 object *item = NULL;
371 size_t rp_arch_index; 392 size_t rp_arch_index;
372 393
394 if (rp == NULL)
373 if(rp==NULL) return (object *) NULL; 395 return (object *) NULL;
374 396
375 /* Find the appropriate object to transform...*/ 397 /* Find the appropriate object to transform... */
376 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 {
377 LOG(llevDebug,"make_alchemy_item(): failed to create alchemical object.\n"); 400 LOG (llevDebug, "make_alchemy_item(): failed to create alchemical object.\n");
378 return (object *) NULL; 401 return (object *) NULL;
379 } 402 }
380 403
381 /* Find the appropriate artifact template...*/ 404 /* Find the appropriate artifact template... */
382 if(strcmp(rp->title,"NONE")) { 405 if (strcmp (rp->title, "NONE"))
406 {
383 if((art=locate_recipe_artifact(rp, rp_arch_index))==NULL) { 407 if ((art = locate_recipe_artifact (rp, rp_arch_index)) == NULL)
408 {
384 LOG(llevError,"make_alchemy_item(): failed to locate recipe artifact.\n"); 409 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); 410 LOG (llevDebug, " --requested recipe: %s of %s.\n", rp->arch_name[0], &rp->title);
386 return (object *) NULL; 411 return (object *) NULL;
387 } 412 }
388 transmute_materialname(item, art->item); 413 transmute_materialname (item, art->item);
389 give_artifact_abilities(item, art->item); 414 give_artifact_abilities (item, art->item);
390 } 415 }
391 416
392 if(QUERY_FLAG(cauldron,FLAG_CURSED)) SET_FLAG(item,FLAG_CURSED); 417 if (QUERY_FLAG (cauldron, FLAG_CURSED))
393 if(QUERY_FLAG(cauldron,FLAG_DAMNED)) SET_FLAG(item,FLAG_DAMNED); 418 SET_FLAG (item, FLAG_CURSED);
394 419 if (QUERY_FLAG (cauldron, FLAG_DAMNED))
420 SET_FLAG (item, FLAG_DAMNED);
421
395 return item; 422 return item;
396} 423}
397 424
398 425
399/** 426/**
400 * Looks through the ingredient list. If we find a 427 * Looks through the ingredient list. If we find a
402 * 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.
403 * 430 *
404 * @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;
405 * set to zero if not using a transmution formula 432 * set to zero if not using a transmution formula
406 */ 433 */
407 434
435object *
408object * 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{
409 object *item=NULL; 438 object *item = NULL;
410 439
411 *rp_arch_index = 0; 440 *rp_arch_index = 0;
412 441
413 if(rp->transmute) /* look for matching ingredient/prod archs */ 442 if (rp->transmute) /* look for matching ingredient/prod archs */
414 for(item=first_ingred;item;item=item->below) { 443 for (item = first_ingred; item; item = item->below)
444 {
415 size_t i; 445 size_t i;
416 446
417 for (i = 0; i < rp->arch_names; i++) { 447 for (i = 0; i < rp->arch_names; i++)
448 {
418 if(strcmp(item->arch->name, rp->arch_name[i]) == 0) { 449 if (strcmp (item->arch->name, rp->arch_name[i]) == 0)
450 {
419 *rp_arch_index = i; 451 *rp_arch_index = i;
420 break;
421 }
422 }
423 if (i < rp->arch_names)
424 break; 452 break;
453 }
425 } 454 }
426 455 if (i < rp->arch_names)
456 break;
457 }
458
427 /* 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
428 * allow players to create massive amounts of artifacts easily */ 460 * allow players to create massive amounts of artifacts easily */
429 if(create_item && (!item || item->nrof > 1)) { 461 if (create_item && (!item || item->nrof > 1))
462 {
430 *rp_arch_index = RANDOM()%rp->arch_names; 463 *rp_arch_index = RANDOM () % rp->arch_names;
431 item = get_archetype(rp->arch_name[*rp_arch_index]); 464 item = get_archetype (rp->arch_name[*rp_arch_index]);
432 } 465 }
433 466
434#ifdef ALCHEMY_DEBUG 467#ifdef ALCHEMY_DEBUG
435 LOG(llevDebug,"recipe calls for%stransmution.\n",rp->transmute?" ":" no "); 468 LOG (llevDebug, "recipe calls for%stransmution.\n", rp->transmute ? " " : " no ");
436 if (item != NULL) { 469 if (item != NULL)
437 LOG(llevDebug," find_transmutable_ob(): returns arch %s(sp:%d)\n",
438 item->arch->name,item->stats.sp);
439 } 470 {
471 LOG (llevDebug, " find_transmutable_ob(): returns arch %s(sp:%d)\n", item->arch->name, item->stats.sp);
472 }
440#endif 473#endif
441 474
442 return item; 475 return item;
443} 476}
444 477
445 478
446/** 479/**
447 * Ouch. We didnt get the formula we wanted. 480 * Ouch. We didnt get the formula we wanted.
448 * This fctn simulates the backfire effects--worse effects as the level 481 * This fctn simulates the backfire effects--worse effects as the level
449 * increases. If SPELL_FAILURE_EFFECTS is defined some really evil things 482 * increases. If SPELL_FAILURE_EFFECTS is defined some really evil things
450 * 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
451 * adjustment for playbalance. -b.t. 484 * adjustment for playbalance. -b.t.
452 */ 485 */
453 486
487void
454void alchemy_failure_effect(object *op,object *cauldron,recipe *rp,int danger) { 488alchemy_failure_effect (object *op, object *cauldron, recipe *rp, int danger)
489{
455 int level=0; 490 int level = 0;
456 491
457 if(!op || !cauldron) return; 492 if (!op || !cauldron)
493 return;
458 494
495 if (danger > 1)
459 if(danger>1) level=random_roll(1, danger, op, PREFER_LOW); 496 level = random_roll (1, danger, op, PREFER_LOW);
460 497
461#ifdef ALCHEMY_DEBUG 498#ifdef ALCHEMY_DEBUG
462 LOG(llevDebug,"Alchemy_failure_effect(): using level=%d\n",level); 499 LOG (llevDebug, "Alchemy_failure_effect(): using level=%d\n", level);
463#endif 500#endif
464 501
465 /* possible outcomes based on level */ 502 /* possible outcomes based on level */
466 if(level<25) { /* INGREDIENTS USED/SLAGGED */ 503 if (level < 25)
504 { /* INGREDIENTS USED/SLAGGED */
467 object *item=NULL; 505 object *item = NULL;
468 506
469 if(rndm(0, 2)) { /* slag created */ 507 if (rndm (0, 2))
508 { /* slag created */
470 object *tmp=cauldron->inv; 509 object *tmp = cauldron->inv;
471 int weight=0; 510 int weight = 0;
472 uint16 material=M_STONE; 511 uint16 material = M_STONE;
473 512
513 while (tmp)
474 while(tmp) { /* slag has coadded ingredient properties */ 514 { /* slag has coadded ingredient properties */
475 weight+=tmp->weight; 515 weight += tmp->weight;
476 if(!(material&tmp->material)) 516 if (!(material & tmp->material))
477 material |= tmp->material; 517 material |= tmp->material;
478 tmp=tmp->below; 518 tmp = tmp->below;
479 } 519 }
480 tmp = get_archetype("rock"); 520 tmp = get_archetype ("rock");
481 tmp->weight=weight; 521 tmp->weight = weight;
482 tmp->value=0; 522 tmp->value = 0;
483 tmp->material=material; 523 tmp->material = material;
484 tmp->materialname = "stone"; 524 tmp->materialname = "stone";
485 tmp->name="slag"; 525 tmp->name = "slag";
486 tmp->name_pl="slags"; 526 tmp->name_pl = "slags";
487 item=insert_ob_in_ob(tmp,cauldron); 527 item = insert_ob_in_ob (tmp, cauldron);
488 CLEAR_FLAG(tmp,FLAG_CAN_ROLL); 528 CLEAR_FLAG (tmp, FLAG_CAN_ROLL);
489 CLEAR_FLAG(tmp,FLAG_NO_PICK); 529 CLEAR_FLAG (tmp, FLAG_NO_PICK);
490 tmp->move_block = 0; 530 tmp->move_block = 0;
491 } 531 }
492 remove_contents(cauldron->inv,item); 532 remove_contents (cauldron->inv, item);
493 new_draw_info_format(NDI_UNIQUE,0,op, 533 new_draw_info_format (NDI_UNIQUE, 0, op, "The %s %s.", &cauldron->name, cauldron_sound ());
494 "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)
495 return; 542 return;
496 } else if (level< 40) { /* MAKE TAINTED ITEM */
497 object *tmp=NULL;
498 543
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))) { 544 if ((tmp = attempt_recipe (op, cauldron, 1, rp, -1)))
545 {
504 if(!QUERY_FLAG(tmp,FLAG_CURSED)) /* curse it */ 546 if (!QUERY_FLAG (tmp, FLAG_CURSED)) /* curse it */
505 SET_FLAG(tmp,FLAG_CURSED); 547 SET_FLAG (tmp, FLAG_CURSED);
506 548
507 /* the apply code for potions already deals with cursed 549 /* the apply code for potions already deals with cursed
508 * potions, so any code here is basically ignored. 550 * potions, so any code here is basically ignored.
509 */ 551 */
510 if(tmp->type==FOOD) { 552 if (tmp->type == FOOD)
553 {
511 tmp->stats.hp=random_roll(0, 149, op, PREFER_LOW); 554 tmp->stats.hp = random_roll (0, 149, op, PREFER_LOW);
512 } 555 }
513 tmp->value = 0; /* unsaleable item */ 556 tmp->value = 0; /* unsaleable item */
514 557
515 /* change stats downward */ 558 /* change stats downward */
516 do { 559 do
560 {
517 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 }
518 } while (rndm(0, 2)); 563 while (rndm (0, 2));
519 } 564 }
520 return; 565 return;
566 }
567 if (level == 40)
521 } if(level==40) { /* MAKE RANDOM RECIPE */ 568 { /* MAKE RANDOM RECIPE */
522 recipelist *fl; 569 recipelist *fl;
523 int numb=numb_ob_inside(cauldron); 570 int numb = numb_ob_inside (cauldron);
524 571
525 fl=get_formulalist(numb-1); /* take a lower recipe list */ 572 fl = get_formulalist (numb - 1); /* take a lower recipe list */
526 if(fl &&(rp=get_random_recipe(fl))) 573 if (fl && (rp = get_random_recipe (fl)))
527 /* even though random, don't grant user any EXP for it */ 574 /* even though random, don't grant user any EXP for it */
528 (void) attempt_recipe(op,cauldron,1,rp,-1); 575 (void) attempt_recipe (op, cauldron, 1, rp, -1);
529 else 576 else
530 alchemy_failure_effect(op,cauldron,rp,level-1); 577 alchemy_failure_effect (op, cauldron, rp, level - 1);
531 return; 578 return;
532 579
533 } else if (level<45) { /* INFURIATE NPC's */ 580 }
581 else if (level < 45)
582 { /* INFURIATE NPC's */
534 /* this is kind of kludgy I know...*/ 583 /* this is kind of kludgy I know... */
535 cauldron->enemy=op; 584 cauldron->enemy = op;
536 npc_call_help(cauldron); 585 npc_call_help (cauldron);
537 cauldron->enemy=NULL; 586 cauldron->enemy = NULL;
538 587
539 alchemy_failure_effect(op,cauldron,rp,level-5); 588 alchemy_failure_effect (op, cauldron, rp, level - 5);
540 return; 589 return;
541 } else if (level<50) { /* MINOR EXPLOSION/FIREBALL */ 590 }
591 else if (level < 50)
592 { /* MINOR EXPLOSION/FIREBALL */
542 object *tmp; 593 object *tmp;
594
543 remove_contents(cauldron->inv,NULL); 595 remove_contents (cauldron->inv, NULL);
544 switch(rndm(0, 2)) { 596 switch (rndm (0, 2))
597 {
545 case 0: 598 case 0:
546 tmp=get_archetype("bomb"); 599 tmp = get_archetype ("bomb");
547 tmp->stats.dam=random_roll(1, level, op, PREFER_LOW); 600 tmp->stats.dam = random_roll (1, level, op, PREFER_LOW);
548 tmp->stats.hp=random_roll(1, level, op, PREFER_LOW); 601 tmp->stats.hp = random_roll (1, level, op, PREFER_LOW);
549 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);
550 &cauldron->name);
551 break; 603 break;
552 604
553 default: 605 default:
554 tmp=get_archetype("fireball"); 606 tmp = get_archetype ("fireball");
555 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;
556 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;
557 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);
558 &cauldron->name);
559 break; 610 break;
560 } 611 }
561 tmp->x=cauldron->x,tmp->y=cauldron->y; 612
562 insert_ob_in_map(tmp,op->map,NULL,0); 613 op->insert_at (cauldron);
563 return; 614 return;
564 615
565 } else if (level<60) { /* CREATE MONSTER */ 616 }
566 new_draw_info_format(NDI_UNIQUE,0,op, 617 else if (level < 60)
567 "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 ());
568 remove_contents(cauldron->inv,NULL); 620 remove_contents (cauldron->inv, NULL);
569 return; 621 return;
570 } else if (level<80) { /* MAJOR FIRE */ 622 }
623 else if (level < 80)
624 { /* MAJOR FIRE */
571 object *fb = get_archetype(SP_MED_FIREBALL); 625 object *fb = get_archetype (SP_MED_FIREBALL);
626
572 remove_contents(cauldron->inv,NULL); 627 remove_contents (cauldron->inv, NULL);
573 fire_arch_from_position(cauldron, cauldron,cauldron->x, cauldron->y, 628 fire_arch_from_position (cauldron, cauldron, cauldron->x, cauldron->y, 0, fb);
574 0, fb); 629 fb->destroy ();
575 free_object(fb);
576 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);
577 &cauldron->name);
578 return; 631 return;
579 632
580 } else if (level<100) { /* WHAMMY the CAULDRON */ 633 }
634 else if (level < 100)
635 { /* WHAMMY the CAULDRON */
581 if(!QUERY_FLAG(cauldron,FLAG_CURSED)) 636 if (!QUERY_FLAG (cauldron, FLAG_CURSED))
582 SET_FLAG(cauldron,FLAG_CURSED); 637 SET_FLAG (cauldron, FLAG_CURSED);
638 else
583 else cauldron->magic--; 639 cauldron->magic--;
584 cauldron->magic -= random_roll(0, 4, op, PREFER_LOW); 640 cauldron->magic -= random_roll (0, 4, op, PREFER_LOW);
585 if(rndm(0, 1)) { 641 if (rndm (0, 1))
642 {
586 remove_contents(cauldron->inv,NULL); 643 remove_contents (cauldron->inv, NULL);
587 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);
588 "Your %s turns darker then makes a gulping sound!", 645 }
589 &cauldron->name);
590 } else 646 else
591 new_draw_info_format(NDI_UNIQUE,0,op, 647 new_draw_info_format (NDI_UNIQUE, 0, op, "Your %s becomes darker.", &cauldron->name);
592 "Your %s becomes darker.",&cauldron->name);
593 return; 648 return;
594 649
595 } else if (level<110) { /* SUMMON EVIL MONSTERS */ 650 }
651 else if (level < 110)
652 { /* SUMMON EVIL MONSTERS */
596 object *tmp=get_random_mon(level/5); 653 object *tmp = get_random_mon (level / 5);
597 654
598 remove_contents(cauldron->inv,NULL); 655 remove_contents (cauldron->inv, NULL);
599 if(!tmp) 656 if (!tmp)
600 alchemy_failure_effect(op,cauldron,rp,level); 657 alchemy_failure_effect (op, cauldron, rp, level);
601 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))
602 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 ());
603 "The %s %s and then pours forth monsters!",
604 &cauldron->name,cauldron_sound());
605 return; 660 return;
606 661
607 } else if (level<150) { /* COMBO EFFECT */ 662 }
663 else if (level < 150)
664 { /* COMBO EFFECT */
608 int roll = rndm(1, 3); 665 int roll = rndm (1, 3);
666
609 while(roll) { 667 while (roll)
668 {
610 alchemy_failure_effect(op,cauldron,rp,level-39); 669 alchemy_failure_effect (op, cauldron, rp, level - 39);
611 roll--; 670 roll--;
612 } 671 }
613 return; 672 return;
614 } else if (level==151) { /* CREATE RANDOM ARTIFACT */ 673 }
674 else if (level == 151)
675 { /* CREATE RANDOM ARTIFACT */
615 object *tmp; 676 object *tmp;
677
616 /* this is meant to be better than prior possiblity, 678 /* this is meant to be better than prior possiblity,
617 * in this one, we allow *any* valid alchemy artifact 679 * in this one, we allow *any* valid alchemy artifact
618 * to be made (rather than only those on the given 680 * to be made (rather than only those on the given
619 * formulalist) */ 681 * formulalist) */
682 if (!rp)
620 if(!rp) rp=get_random_recipe((recipelist *) NULL); 683 rp = get_random_recipe ((recipelist *) NULL);
621 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 {
622 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);
623 if((tmp=insert_ob_in_ob(tmp,cauldron))) { 687 if ((tmp = insert_ob_in_ob (tmp, cauldron)))
688 {
624 remove_contents(cauldron->inv,tmp); 689 remove_contents (cauldron->inv, tmp);
625 new_draw_info_format(NDI_UNIQUE, 0,op, 690 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 } 691 }
692 }
629 return; 693 return;
694 }
695 else
630 } else { /* MANA STORM - watch out!! */ 696 { /* MANA STORM - watch out!! */
631 object *tmp = get_archetype(LOOSE_MANA); 697 object *tmp = get_archetype (LOOSE_MANA);
698
632 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!");
633 remove_contents (cauldron->inv,NULL); 700 remove_contents (cauldron->inv, NULL);
634 cast_magic_storm(op,tmp, level); 701 cast_magic_storm (op, tmp, level);
635 return; 702 return;
636 } 703 }
637} 704}
638 705
639 706
640/** 707/*
641 * All but object "save_item" are elimentated from 708 * All but object "save_item" are elimentated from
642 * 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
643 * 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).
644 */ 711 */
645 712
713void
646void remove_contents (object *first_ob, object *save_item) { 714remove_contents (object *first_ob, object *save_item)
715{
647 object *next,*tmp=first_ob; 716 object *next, *tmp = first_ob;
648 717
649 while(tmp) { 718 while (tmp)
719 {
650 next = tmp->below; 720 next = tmp->below;
721
651 if(tmp==save_item) { 722 if (tmp == save_item)
652 if(!(tmp=next)) break;
653 else next=next->below;
654 } 723 {
724 if (!(tmp = next))
725 break;
726 else
727 next = next->below;
728 }
729
730 if (tmp->inv)
655 if(tmp->inv) remove_contents(tmp->inv,NULL); 731 remove_contents (tmp->inv, NULL);
656 remove_ob(tmp); 732
657 free_object(tmp); 733 tmp->destroy ();
658 tmp=next; 734 tmp = next;
659 } 735 }
660} 736}
661 737
662/** 738/**
663 *"Danger" level, will determine how bad the backfire 739 *"Danger" level, will determine how bad the backfire
667 * mixing device (aka "cauldron"). Higher values of 'danger' indicate more 743 * 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 744 * 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) 745 * skill *before* this routine is called. (no longer auto-readies that skill)
670 * -b.t. 746 * -b.t.
671 */ 747 */
672 748
749int
673int calc_alch_danger(object *caster,object *cauldron, recipe *rp) { 750calc_alch_danger (object *caster, object *cauldron, recipe *rp)
751{
674 object *item; 752 object *item;
675 char name[MAX_BUF]; 753 char name[MAX_BUF];
676 int danger=0,nrofi=0; 754 int danger = 0, nrofi = 0;
677 755
678 /* Knowing alchemy skill reduces yer risk */ 756 /* Knowing alchemy skill reduces yer risk */
679 danger -= caster->chosen_skill?caster->chosen_skill->level:caster->level; 757 danger -= caster->chosen_skill ? caster->chosen_skill->level : caster->level;
680 758
681 /* better cauldrons reduce risk */ 759 /* better cauldrons reduce risk */
682 danger -= cauldron->magic; 760 danger -= cauldron->magic;
683 761
684 /* Higher Int, lower the risk */ 762 /* Higher Int, lower the risk */
685 danger -= 3 * (caster->stats.Int - 15); 763 danger -= 3 * (caster->stats.Int - 15);
686 764
687 /* Ingredients. Longer names usually mean rarer stuff. 765 /* Ingredients. Longer names usually mean rarer stuff.
688 * Thus the backfire is worse. Also, more ingredients 766 * Thus the backfire is worse. Also, more ingredients
689 * means we are attempting a more powerfull potion, 767 * means we are attempting a more powerfull potion,
690 * and thus the backfire will be worse. */ 768 * and thus the backfire will be worse. */
691 for(item=cauldron->inv;item;item=item->below) { 769 for (item = cauldron->inv; item; item = item->below)
770 {
692 strcpy(name,item->name); 771 strcpy (name, item->name);
772 if (item->title)
693 if(item->title) sprintf(name,"%s %s", &item->name, &item->title); 773 sprintf (name, "%s %s", &item->name, &item->title);
694 danger += (strtoint(name)/1000) + 3; 774 danger += (strtoint (name) / 1000) + 3;
695 nrofi++; 775 nrofi++;
696 } 776 }
697 if (rp == NULL) 777 if (rp == NULL)
698 danger += 110; 778 danger += 110;
699 else 779 else
700 danger += rp->diff*3; 780 danger += rp->diff * 3;
701 781
702 /* Using a bad device is *majorly* stupid */ 782 /* Using a bad device is *majorly* stupid */
703 if(QUERY_FLAG(cauldron,FLAG_CURSED)) danger +=80; 783 if (QUERY_FLAG (cauldron, FLAG_CURSED))
784 danger += 80;
704 if(QUERY_FLAG(cauldron,FLAG_DAMNED)) danger +=200; 785 if (QUERY_FLAG (cauldron, FLAG_DAMNED))
786 danger += 200;
705 787
706#ifdef ALCHEMY_DEBUG 788#ifdef ALCHEMY_DEBUG
707 LOG(llevDebug,"calc_alch_danger() returned danger=%d\n",danger); 789 LOG (llevDebug, "calc_alch_danger() returned danger=%d\n", danger);
708#endif 790#endif
709 791
710 return danger; 792 return danger;
711} 793}
712 794
713/** 795/**
714 * Determines if ingredients in a container match the 796 * Determines if ingredients in a container match the
715 * proper ingredients for a recipe. 797 * proper ingredients for a recipe.
722 * the defined recipe iff 804 * the defined recipe iff
723 * - 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
724 * - all ingredients of the recipe are found in the container 806 * - all ingredients of the recipe are found in the container
725 * - the number of batches is the same for all ingredients 807 * - the number of batches is the same for all ingredients
726 */ 808 */
809static int
727static int is_defined_recipe(const recipe *rp, const object *cauldron, object *caster) 810is_defined_recipe (const recipe *rp, const object *cauldron, object *caster)
728{ 811{
729 uint32 batches_in_cauldron; 812 uint32 batches_in_cauldron;
730 const linked_char *ingredient; 813 const linked_char *ingredient;
731 int number; 814 int number;
732 const object *ob; 815 const object *ob;
733 816
734 /* check for matching number of ingredients */ 817 /* check for matching number of ingredients */
735 number = 0; 818 number = 0;
736 for(ingredient = rp->ingred; ingredient != NULL; ingredient = ingredient->next) 819 for (ingredient = rp->ingred; ingredient != NULL; ingredient = ingredient->next)
737 number++; 820 number++;
738 for(ob = cauldron->inv; ob != NULL; ob = ob->below) 821 for (ob = cauldron->inv; ob != NULL; ob = ob->below)
739 number--; 822 number--;
740 if(number != 0) 823 if (number != 0)
741 return 0; 824 return 0;
742 825
743 /* check for matching ingredients */ 826 /* check for matching ingredients */
744 batches_in_cauldron = 0; 827 batches_in_cauldron = 0;
745 for(ingredient = rp->ingred; ingredient != NULL; ingredient = ingredient->next) { 828 for (ingredient = rp->ingred; ingredient != NULL; ingredient = ingredient->next)
829 {
746 uint32 nrof; 830 uint32 nrof;
747 const char *name; 831 const char *name;
748 int ok; 832 int ok;
749 833
750 /* determine and remove nrof from name */ 834 /* determine and remove nrof from name */
751 name = ingredient->name; 835 name = ingredient->name;
752 nrof = 0; 836 nrof = 0;
753 while(isdigit(*name)) { 837 while (isdigit (*name))
838 {
754 nrof = 10*nrof+(*name-'0'); 839 nrof = 10 * nrof + (*name - '0');
755 name++; 840 name++;
756 } 841 }
757 if(nrof == 0) 842 if (nrof == 0)
758 nrof = 1; 843 nrof = 1;
759 while(*name == ' ') 844 while (*name == ' ')
760 name++; 845 name++;
761 846
762 /* find the current ingredient in the cauldron */ 847 /* find the current ingredient in the cauldron */
763 ok = 0; 848 ok = 0;
764 for(ob = cauldron->inv; ob != NULL; ob = ob->below) { 849 for (ob = cauldron->inv; ob != NULL; ob = ob->below)
850 {
765 char name_ob[MAX_BUF]; 851 char name_ob[MAX_BUF];
766 const char *name2; 852 const char *name2;
767 853
768 if(ob->title == NULL) 854 if (ob->title == NULL)
769 name2 = ob->name; 855 name2 = ob->name;
770 else { 856 else
857 {
771 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);
772 name2 = name_ob; 859 name2 = name_ob;
773 } 860 }
774 861
775 if(strcmp(name2, name) == 0) { 862 if (strcmp (name2, name) == 0)
863 {
776 if(ob->nrof%nrof == 0) { 864 if (ob->nrof % nrof == 0)
865 {
777 uint32 batches; 866 uint32 batches;
778 867
779 batches = ob->nrof/nrof; 868 batches = ob->nrof / nrof;
780 if(batches_in_cauldron == 0) { 869 if (batches_in_cauldron == 0)
870 {
781 batches_in_cauldron = batches; 871 batches_in_cauldron = batches;
782 ok = 1; 872 ok = 1;
873 }
783 } else if(batches_in_cauldron == batches) 874 else if (batches_in_cauldron == batches)
784 ok = 1; 875 ok = 1;
785 } 876 }
786 break; 877 break;
787 }
788 } 878 }
879 }
789 if(!ok) 880 if (!ok)
790 return(0); 881 return (0);
791 } 882 }
792 883
793 return(1); 884 return (1);
794} 885}
795 886
796/** 887/**
797 * 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
798 * 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
799 * transmuting recipe matches, it only considers matching transmuting recipes. 890 * transmuting recipe matches, it only considers matching transmuting recipes.
800 * 891 *
801 * @return one matching recipe, or NULL if no recipe matches 892 * @return one matching recipe, or NULL if no recipe matches
802 */ 893 */
894static recipe *
803static recipe *find_recipe(recipelist *fl, int formula, object *ingredients) 895find_recipe (recipelist * fl, int formula, object *ingredients)
804{ 896{
805 recipe *rp; 897 recipe *rp;
806 recipe *result; /* winning recipe, or NULL if no recipe found */ 898 recipe *result; /* winning recipe, or NULL if no recipe found */
807 int recipes_matching; /* total number of matching recipes so far */ 899 int recipes_matching; /* total number of matching recipes so far */
808 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 */
809 size_t rp_arch_index; 901 size_t rp_arch_index;
810 902
811#ifdef EXTREME_ALCHEMY_DEBUG 903#ifdef EXTREME_ALCHEMY_DEBUG
812 LOG(llevDebug, "looking for formula %d:\n", formula); 904 LOG (llevDebug, "looking for formula %d:\n", formula);
813#endif 905#endif
814 result = NULL; 906 result = NULL;
815 recipes_matching = 0; 907 recipes_matching = 0;
816 transmute_found = 0; 908 transmute_found = 0;
817 for (rp = fl->items; rp != NULL; rp = rp->next) { 909 for (rp = fl->items; rp != NULL; rp = rp->next)
910 {
818 /* check if recipe matches at all */ 911 /* check if recipe matches at all */
819 if (formula%rp->index != 0) { 912 if (formula % rp->index != 0)
913 {
820#ifdef EXTREME_ALCHEMY_DEBUG 914#ifdef EXTREME_ALCHEMY_DEBUG
821 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);
822#endif 916#endif
823 continue; 917 continue;
824 } 918 }
825 919
826 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 {
827#ifdef EXTREME_ALCHEMY_DEBUG 922#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); 923 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 924#endif
830 /* transmution recipe with matching base ingredient */ 925 /* transmution recipe with matching base ingredient */
831 if (!transmute_found) { 926 if (!transmute_found)
927 {
832 transmute_found = 1; 928 transmute_found = 1;
833 recipes_matching = 0; 929 recipes_matching = 0;
930 }
834 } 931 }
835 } else if (transmute_found) { 932 else if (transmute_found)
933 {
836#ifdef EXTREME_ALCHEMY_DEBUG 934#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); 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);
838#endif 937#endif
839 /* "normal" recipe found after previous transmution recipe => ignore this recipe */ 938 /* "normal" recipe found after previous transmution recipe => ignore this recipe */
840 continue; 939 continue;
841 } 940 }
842#ifdef EXTREME_ALCHEMY_DEBUG 941#ifdef EXTREME_ALCHEMY_DEBUG
843 else { 942 else
943 {
844 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);
845 } 945 }
846#endif 946#endif
847 947
848 if (rndm(0, recipes_matching) == 0) 948 if (rndm (0, recipes_matching) == 0)
849 result = rp; 949 result = rp;
850 950
851 recipes_matching++; 951 recipes_matching++;
852 } 952 }
853 953
854 if (result == NULL) { 954 if (result == NULL)
955 {
855#ifdef ALCHEMY_DEBUG 956#ifdef ALCHEMY_DEBUG
856 LOG(llevDebug, "couldn't find formula for ingredients.\n"); 957 LOG (llevDebug, "couldn't find formula for ingredients.\n");
857#endif 958#endif
858 return NULL; 959 return NULL;
859 } 960 }
860 961
861#ifdef ALCHEMY_DEBUG 962#ifdef ALCHEMY_DEBUG
862 if(strcmp(result->title, "NONE") != 0) 963 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); 964 LOG (llevDebug, "got formula: %s of %s (nbatches:%d)\n", result->arch_name[0], result->title, formula / result->index);
864 else 965 else
865 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);
866#endif 967#endif
867 return result; 968 return result;
868} 969}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines