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.18 by pippijn, Mon Jan 15 21:06:19 2007 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines