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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines