Crossfire Server, Trunk  R20513
Functions | Variables
alchemy.c File Reference

This contains all alchemy-related functions. More...

#include "global.h"
#include <assert.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include "object.h"
#include "shop.h"
#include "skills.h"
#include "spells.h"
#include "sproto.h"
Include dependency graph for alchemy.c:

Go to the source code of this file.

Functions

static void adjust_product (object *item, int adjust, int yield)
 We adjust the nrof of the final product, based on the item's default parameters, and the relevant caster skill level. More...
 
static void alchemy_failure_effect (object *op, object *cauldron, const recipe *rp, int danger)
 Ouch. More...
 
static void attempt_do_alchemy (object *caster, object *cauldron)
 Main part of the ALCHEMY code. More...
 
static objectattempt_recipe (object *caster, object *cauldron, int ability, const recipe *rp, int nbatches, int ignore_cauldron)
 Essentially a wrapper for make_item_from_recipe() and object_insert_in_ob(). More...
 
static int calc_alch_danger (object *caster, object *cauldron, const recipe *rp)
 "Danger" level, will determine how bad the backfire could be if the user fails to concoct a recipe properly. More...
 
static const char * cauldron_sound (void)
 Returns a random selection from cauldron_effect[]. More...
 
static int content_recipe_value (object *op)
 Recipe value of the entire contents of a container. More...
 
static const recipefind_recipe (const recipelist *fl, int formula, object *ingredients)
 Find a recipe from a recipe list that matches the given formula. More...
 
static objectfind_transmution_ob (object *first_ingred, const recipe *rp, size_t *rp_arch_index, int create_item)
 Looks through the ingredient list. More...
 
static int is_defined_recipe (const recipe *rp, const object *cauldron, object *caster)
 Determines if ingredients in a container match the proper ingredients for a recipe. More...
 
static objectmake_item_from_recipe (object *cauldron, const recipe *rp)
 Using a list of items and a recipe to make an artifact. More...
 
static int numb_ob_inside (const object *op)
 Returns the total number of items in op, excluding ones in item's items. More...
 
static float recipe_chance (const recipe *rp, const object *skill, const object *cauldron)
 Compute the success probability of a recipe. More...
 
static void remove_contents (object *first_ob, object *save_item)
 All but object "save_item" are elimentated from the container list. More...
 
int use_alchemy (object *op)
 Handle use_skill for alchemy-like items. More...
 

Variables

static const char *const cauldron_effect []
 define this for some helpful debuging information More...
 

Detailed Description

This contains all alchemy-related functions.

Definition in file alchemy.c.

Function Documentation

static void adjust_product ( object item,
int  adjust,
int  yield 
)
static

We adjust the nrof of the final product, based on the item's default parameters, and the relevant caster skill level.

Parameters
itemitem to adjust.
adjustnrof adjustment parameter, the higher the better.
yieldhow many products the recipe returns at maximum.

Definition at line 386 of file alchemy.c.

References obj::nrof, and rndm().

Referenced by attempt_recipe().

Here is the call graph for this function:

Here is the caller graph for this function:

static void alchemy_failure_effect ( object op,
object cauldron,
const recipe rp,
int  danger 
)
static

Ouch.

We didnt get the formula we wanted. This fctn simulates the backfire effects–worse effects as the level increases. If SPELL_FAILURE_EFFECTS is defined some really evil things can happen to the would be alchemist. This table probably needs some adjustment for playbalance. -b.t.

Parameters
opwho tried to do alchemy.
cauldroncontainer that was used.
rprecipe that failed, can be NULL.
dangerdanger value, the higher the more evil the effect.

Recipe specifies a special failure archetype, so use it instead of evil random things.

Definition at line 521 of file alchemy.c.

References add_string(), obj::arch, recipestruct::arch_name, recipestruct::arch_names, attempt_recipe(), cast_magic_storm(), cauldron_sound(), change_attr_value(), CLEAR_FLAG, create_archetype(), liv::dam, draw_ext_info(), draw_ext_info_format(), recipestruct::failure_arch, recipestruct::failure_message, fire_arch_from_position(), FLAG_CAN_ROLL, FLAG_CURSED, FLAG_IDENTIFIED, FLAG_KNOWN_CURSED, FLAG_NO_PICK, FOOD, FOR_INV_FINISH, FOR_INV_PREPARE, free_string(), generate_artifact(), get_formulalist(), get_random_mon(), get_random_recipe(), liv::hp, obj::inv, obj::level, llevDebug, llevError, LOG(), LOOSE_MANA, M_STONE, obj::magic, obj::map, obj::material, obj::materialname, monster_npc_call_help(), obj::move_block, MSG_TYPE_SKILL, MSG_TYPE_SKILL_FAILURE, MSG_TYPE_SKILL_SUCCESS, obj::name, archt::name, obj::name_pl, NDI_UNIQUE, numb_ob_inside(), object_free_drop_inventory(), object_insert_in_map_at(), object_insert_in_ob(), object_set_enemy(), PREFER_HIGH, PREFER_LOW, QUERY_FLAG, RANDOM, random_roll(), remove_contents(), rndm(), SET_FLAG, SP_MED_FIREBALL, obj::stats, summon_hostile_monsters(), recipestruct::title, obj::type, obj::value, obj::weight, obj::x, and obj::y.

Referenced by attempt_do_alchemy().

Here is the call graph for this function:

Here is the caller graph for this function:

static void attempt_do_alchemy ( object caster,
object cauldron 
)
static

Main part of the ALCHEMY code.

From this we call fctns that take a look at the contents of the 'cauldron' and, using these ingredients, we construct an integer formula value which is referenced (randomly) against a formula list (the formula list chosen is based on the # contents of the cauldron).

If we get a match between the recipe indicated in cauldron contents and a randomly chosen one, an item is created and experience awarded. Otherwise various failure effects are possible (getting worse and worse w/ # cauldron ingredients). Note that the 'item' to be made can be *anything *listed on the artifacts list in lib/artifacts which has a recipe listed in lib/formulae.

To those wondering why I am using the funky formula index method: 1) I want to match recipe to ingredients regardless of ordering. 2) I want a fast search for the 'right' recipe.

Note: it is just possible that a totally different combination of ingredients will result in a match with a given recipe. This is not a bug! There is no good reason (in my mind) why alchemical processes have to be unique – such a 'feature' is one reason why players might want to experiment around. :) -b.t.

Parameters
casterwho is doing alchemy.
cauldronthe cauldron in which alchemy should take place.

Definition at line 139 of file alchemy.c.

References alchemy_failure_effect(), recipestruct::arch_name, attempt_recipe(), calc_alch_danger(), recipestruct::cauldron, change_exp(), content_recipe_value(), recipestruct::diff, draw_ext_info(), draw_ext_info_format(), recipestruct::exp, find_recipe(), find_skill_by_name(), FLAG_WIZ, FOR_INV_FINISH, FOR_INV_PREPARE, get_formulalist(), recipestruct::index, obj::inv, is_defined_recipe(), obj::level, llevDebug, LOG(), obj::magic, recipestruct::min_level, MSG_TYPE_SKILL, MSG_TYPE_SKILL_FAILURE, MSG_TYPE_SKILL_MISSING, obj::name, NDI_UNIQUE, numb_ob_inside(), PLAYER, PREFER_LOW, price_base(), QUERY_FLAG, random_roll(), recipe_chance(), SK_EXP_NONE, recipestruct::skill, recipestruct::title, and obj::type.

Referenced by use_alchemy().

Here is the call graph for this function:

Here is the caller graph for this function:

static object * attempt_recipe ( object caster,
object cauldron,
int  ability,
const recipe rp,
int  nbatches,
int  ignore_cauldron 
)
static

Essentially a wrapper for make_item_from_recipe() and object_insert_in_ob().

If the caster has some alchemy skill, then they might gain some exp from (successfull) fabrication of the product. If nbatches==-1, don't give exp for this creation (random generation/ failed recipe) If ignore_cauldron, don't check if we are using the matching cauldron type (shadow alchemy)

Parameters
casterwho is trying to do alchemy.
cauldroncontainer used for alchemy.
ability?
rprecipe attempted.
nbatches?
ignore_cauldronif 0, checks the recipe uses the right cauldron type, else no check is done.
Returns
generated item, can be NULL if contents were destroyed.
Todo:
check meaning of ability/nbatches.

Definition at line 320 of file alchemy.c.

References adjust_product(), obj::arch, recipestruct::cauldron, cauldron_sound(), draw_ext_info(), draw_ext_info_format(), obj::env, find_skill_by_name(), FORCE, obj::inv, recipestruct::keycode, obj::level, llevDebug, LOG(), make_item_from_recipe(), MAX, MSG_TYPE_SKILL, MSG_TYPE_SKILL_ERROR, MSG_TYPE_SKILL_FAILURE, MSG_TYPE_SKILL_SUCCESS, obj::name, archt::name, NDI_UNIQUE, object_find_by_type_and_slaying(), object_insert_in_ob(), POTION, remove_contents(), recipestruct::skill, recipestruct::title, obj::type, and recipestruct::yield.

Referenced by alchemy_failure_effect(), and attempt_do_alchemy().

Here is the call graph for this function:

Here is the caller graph for this function:

static int calc_alch_danger ( object caster,
object cauldron,
const recipe rp 
)
static

"Danger" level, will determine how bad the backfire could be if the user fails to concoct a recipe properly.

Factors include the number of ingredients, the magical nature of ingredients, the user's effective level, the user's Int and the enchantment on the mixing device (aka "cauldron"). Higher values of 'danger' indicate more danger. Note that we assume that we have had the caster ready the alchemy skill *before *this routine is called. (no longer auto-readies that skill) -b.t.

Parameters
casterwho is trying alchemy.
cauldroncontainer used.
rprecipe attempted.
Returns
danger value.

Definition at line 802 of file alchemy.c.

References obj::chosen_skill, recipestruct::diff, FLAG_CURSED, FLAG_DAMNED, FOR_INV_FINISH, FOR_INV_PREPARE, liv::Int, obj::level, llevDebug, LOG(), obj::magic, QUERY_FLAG, and obj::stats.

Referenced by attempt_do_alchemy().

Here is the call graph for this function:

Here is the caller graph for this function:

static const char* cauldron_sound ( void  )
static

Returns a random selection from cauldron_effect[].

Definition at line 77 of file alchemy.c.

References cauldron_effect, and rndm().

Referenced by alchemy_failure_effect(), and attempt_recipe().

Here is the call graph for this function:

Here is the caller graph for this function:

static int content_recipe_value ( object op)
static

Recipe value of the entire contents of a container.

This appears to just generate a hash value, which I guess for now works ok, but the possibility of duplicate hashes is certainly possible - msw

Parameters
opcontained for which to generate a hash.
Returns
hash value.

Definition at line 255 of file alchemy.c.

References FOR_INV_FINISH, FOR_INV_PREPARE, llevDebug, LOG(), MAX_BUF, account_struct::name, safe_strncpy, snprintf, and strtoint().

Referenced by attempt_do_alchemy().

Here is the call graph for this function:

Here is the caller graph for this function:

static const recipe * find_recipe ( const recipelist fl,
int  formula,
object ingredients 
)
static

Find a recipe from a recipe list that matches the given formula.

If there is more than one matching recipe, it selects a random one. If at least one transmuting recipe matches, it only considers matching transmuting recipes.

Parameters
fllist containing the potential formulae based on the number of ingredients.
formulahash of the ingredients.
ingredientsingredients, linked through the 'below' field.
Returns
one matching recipe, or NULL if no recipe matches

Definition at line 943 of file alchemy.c.

References recipestruct::arch_name, recipestruct::index, recipeliststruct::items, llevDebug, LOG(), recipestruct::next, rndm(), recipestruct::title, and recipestruct::transmute.

Referenced by attempt_do_alchemy().

Here is the call graph for this function:

Here is the caller graph for this function:

static object * find_transmution_ob ( object first_ingred,
const recipe rp,
size_t *  rp_arch_index,
int  create_item 
)
static

Looks through the ingredient list.

If we find a suitable object in it - we will use that to make the requested artifact. Otherwise the code returns a 'generic' item if create_item is set. -b.t.

Parameters
first_ingredpointer to first item to check
rprecipe the player is trying
rp_arch_indexpointer to return value; set to arch index for recipe; set to zero if not using a transmution formula
create_itemif set, will create a generic item if no suitable item is found.
Returns
NULL if no suitable item was found and create_item is 0, existing or new item else.

Definition at line 467 of file alchemy.c.

References obj::arch, recipestruct::arch_name, recipestruct::arch_names, create_archetype(), FOR_OB_AND_BELOW_FINISH, FOR_OB_AND_BELOW_PREPARE, llevDebug, LOG(), archt::name, obj::nrof, RANDOM, liv::sp, obj::stats, and recipestruct::transmute.

Referenced by make_item_from_recipe().

Here is the call graph for this function:

Here is the caller graph for this function:

static int is_defined_recipe ( const recipe rp,
const object cauldron,
object caster 
)
static

Determines if ingredients in a container match the proper ingredients for a recipe.

This functions tries to find each defined ingredient in the container. It is the defined recipe iff

  • the number of ingredients of the recipe and in the container is equal
  • all ingredients of the recipe are found in the container
  • the number of batches is the same for all ingredients
Parameters
rprecipe to check.
cauldroncontainer that holds the ingredients.
casterwho is trying to cast.
Returns
1 if the ingredients match the recipe, 0 if not.

Definition at line 861 of file alchemy.c.

References FOR_INV_FINISH, FOR_INV_PREPARE, recipestruct::ingred, MAX_BUF, account_struct::name, linked_char::name, linked_char::next, and snprintf.

Referenced by attempt_do_alchemy().

Here is the caller graph for this function:

static object * make_item_from_recipe ( object cauldron,
const recipe rp 
)
static

Using a list of items and a recipe to make an artifact.

Parameters
cauldronthe cauldron (including the ingredients) used to make the item
rpthe recipe to make the artifact from
Returns
the newly created object, NULL if something failed

Definition at line 411 of file alchemy.c.

References recipestruct::arch_name, obj::env, find_transmution_ob(), FLAG_CURSED, FLAG_DAMNED, FLAG_IDENTIFIED, give_artifact_abilities(), obj::inv, artifactstruct::item, llevDebug, llevError, locate_recipe_artifact(), LOG(), need_identify(), obj::nrof, object_add_weight(), object_give_identified_properties(), object_sub_weight(), QUERY_FLAG, SET_FLAG, recipestruct::title, transmute_materialname(), and obj::weight.

Referenced by attempt_recipe().

Here is the call graph for this function:

Here is the caller graph for this function:

static int numb_ob_inside ( const object op)
static

Returns the total number of items in op, excluding ones in item's items.

Parameters
opcontainer.
Returns
total item count.

Definition at line 283 of file alchemy.c.

References FOR_INV_FINISH, FOR_INV_PREPARE, llevDebug, LOG(), and obj::name.

Referenced by alchemy_failure_effect(), and attempt_do_alchemy().

Here is the call graph for this function:

Here is the caller graph for this function:

static float recipe_chance ( const recipe rp,
const object skill,
const object cauldron 
)
static

Compute the success probability of a recipe.

The scale is kind of linear, with 3 steps depending on the level difference between recipe and skill.

Parameters
rprecipe to attempt.
skillskill being used.
cauldronprovides the magic of the used device.
Returns
chance between 0.01 and .95.

Definition at line 93 of file alchemy.c.

References recipestruct::diff, obj::level, obj::magic, MAX, and MIN.

Referenced by attempt_do_alchemy().

Here is the caller graph for this function:

static void remove_contents ( object first_ob,
object save_item 
)
static

All but object "save_item" are elimentated from the container list.

Note we have to becareful to remove the inventories of objects in the cauldron inventory (ex icecube has stuff in it).

Parameters
first_obcontainer from which to remove.
save_itemwhat item to not remove. Can be NULL.

Definition at line 769 of file alchemy.c.

References FOR_OB_AND_BELOW_FINISH, FOR_OB_AND_BELOW_PREPARE, obj::inv, object_free_drop_inventory(), and object_remove().

Referenced by alchemy_failure_effect(), and attempt_recipe().

Here is the call graph for this function:

Here is the caller graph for this function:

int use_alchemy ( object op)

Handle use_skill for alchemy-like items.

Parameters
opplayer trying to do alchemy.
Returns
1 if any recipe was attempted, 0 else.
Note
Will inform player if attempting to use unpaid cauldron or ingredient.
Todo:
check if no superflous message when 2 cauldrons on same spot, one unpaid? (shouldn't happen, but well).

Definition at line 1020 of file alchemy.c.

References attempt_do_alchemy(), draw_ext_info(), draw_ext_info_format(), esrv_send_inventory(), FLAG_APPLIED, FLAG_IS_CAULDRON, FLAG_UNPAID, FLAG_WIZ, FOR_MAP_FINISH, FOR_MAP_PREPARE, obj::map, MAX_BUF, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM, MSG_TYPE_SKILL, MSG_TYPE_SKILL_ERROR, account_struct::name, NDI_UNIQUE, object_find_by_flag(), query_base_name(), QUERY_FLAG, obj::x, and obj::y.

Referenced by do_skill().

Here is the call graph for this function:

Here is the caller graph for this function:

Variable Documentation

const char* const cauldron_effect[]
static
Initial value:
= {
"vibrates briefly",
"produces a cloud of steam",
"emits bright flames",
"pours forth heavy black smoke",
"emits sparks",
"shoots out small flames",
"whines painfully",
"hiccups loudly",
"wheezes",
"burps",
"shakes",
"rattles",
"makes chugging sounds",
"smokes heavily for a while"
}

define this for some helpful debuging information

define this for loads of (marginal) debuging information Random cauldrons effects

Definition at line 45 of file alchemy.c.

Referenced by cauldron_sound().