41 #define EXTREME_ALCHEMY_DEBUG 47 "produces a cloud of steam",
48 "emits bright flames",
49 "pours forth heavy black smoke",
51 "shoots out small flames",
58 "makes chugging sounds",
59 "smokes heavily for a while" 68 static object *
attempt_recipe(
object *caster,
object *cauldron,
int ability,
const recipe *rp,
int nbatches,
int ignore_cauldron);
91 return MAX(.01, .3 - (diff - 10) * .03);
94 return .5 + .02 * (float)(-diff);
96 return MIN(.95, .70 + (-diff - 10) * .01);
126 const int cauldron_add_skill = (cauldron->
magic + 1) / 2;
127 const int eff_skill = skill->
level + cauldron_add_skill;
162 float success_chance;
163 int numb, ability = 1;
184 if (strcmp(rp->
title,
"NONE"))
191 LOG(
llevDebug,
"WIZ couldn't find formula for ingredients.\n");
198 uint64_t value_ingredients;
200 int attempt_shadow_alchemy;
203 if (rp->
skill != NULL) {
207 "You do not have the proper skill for this recipe");
209 ability += skop->
level*((4.0+cauldron->
magic)/4.0);
223 "You aren't skilled enough to try this recipe.");
228 value_ingredients = 0;
236 if ((item =
attempt_recipe(caster, cauldron, ability, rp, formula/rp->
index, attempt_shadow_alchemy)) != NULL) {
241 LOG(
llevDebug,
"percent success chance = %f ab%d / diff%d*lev%d\n", success_chance, ability, rp->
diff, item->
level);
245 if (attempt_shadow_alchemy && value_item > value_ingredients) {
248 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);
250 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);
277 int tval = 0, formula = 0;
283 snprintf(name,
sizeof(name),
"%s %s", tmp->name, tmp->title);
310 LOG(
llevDebug,
"numb_ob_inside(%s): found %d ingredients\n", op->
name, o_number);
340 static object *
attempt_recipe(
object *caster,
object *cauldron,
int ability,
const recipe *rp,
int nbatches,
int ignore_cauldron) {
341 object *item = NULL, *skop;
343 int batches = abs(nbatches);
346 if (!ignore_cauldron && (strcmp(rp->
cauldron, cauldron->
arch->
name) != 0)) {
348 "You are not using the proper facilities for this formula.");
364 "You know the ingredients, but not the technique. Go learn how to do this recipe.");
369 #ifdef EXTREME_ALCHEMY_DEBUG 370 LOG(
llevDebug,
"attempt_recipe(): got %d nbatches\n", nbatches);
385 "Nothing happened.");
419 nrof = (1.0-1.0/(adjust/10.0+1.0))*(
rndm(0, yield-1)+
rndm(0, yield-1)+
rndm(0, yield-1))+1;
439 size_t rp_arch_index;
442 return (
object *)NULL;
446 LOG(
llevDebug,
"make_alchemy_item(): failed to create alchemical object.\n");
447 return (
object *)NULL;
451 if (item->
env != NULL)
455 if (strcmp(rp->
title,
"NONE")) {
456 int item_power_delta = 0;
458 LOG(
llevError,
"make_alchemy_item(): failed to locate recipe artifact.\n");
460 return (
object *)NULL;
476 if (item->
env != NULL)
517 if (i < rp->arch_names)
524 if (create_item && (!item || item->
nrof > 1)) {
558 if (!op || !cauldron)
582 LOG(
llevDebug,
"Alchemy_failure_effect(): using level=%d\n", level);
595 weight += inv->weight;
596 if (!(material&inv->material))
597 material |= inv->material;
619 }
else if (level < 40) {
636 if ((tmp = cauldron->
inv)) {
654 }
while (
rndm(0, 2));
688 }
else if (level < 50) {
692 switch (
rndm(0, 2)) {
698 "The %s creates a bomb!",
707 "The %s erupts in flame!",
713 }
else if (level < 60) {
718 }
else if (level < 80) {
725 "The %s erupts in flame!",
728 }
else if (level < 100) {
739 "Your %s turns darker then makes a gulping sound!",
743 "Your %s becomes darker.",
746 }
else if (level < 110) {
754 "The %s %s and then pours forth monsters!",
757 }
else if (level < 150) {
758 int roll =
rndm(1, 3);
764 }
else if (level == 151) {
787 "You unwisely release potent forces!");
808 if (tmp != save_item) {
845 danger -= cauldron->
magic;
863 danger += rp->
diff*3;
872 LOG(
llevDebug,
"calc_alch_danger() returned danger=%d\n", danger);
896 uint32_t batches_in_cauldron;
902 for (ingredient = rp->
ingred; ingredient != NULL; ingredient = ingredient->
next)
906 LOG(
llevDebug,
"cauldron %s, item %s, number %d->%d\n", cauldron->
name, ob->name, number, number - 1);
914 batches_in_cauldron = 0;
915 for (ingredient = rp->
ingred; ingredient != NULL; ingredient = ingredient->
next) {
921 name = ingredient->
name;
923 while (isdigit(*name)) {
924 nrof = 10*nrof+(*name-
'0');
938 if (ob->title == NULL)
941 snprintf(name_ob,
sizeof(name_ob),
"%s %s", ob->name, ob->title);
945 if (strcmp(name2, name) == 0) {
946 if (ob->nrof%nrof == 0) {
950 batches = (ob->nrof ? ob->nrof : 1)/nrof;
952 LOG(
llevDebug,
"batches of ingred %s: %d; batches prior: %d\n", name, batches, batches_in_cauldron);
954 if (batches_in_cauldron == 0) {
955 batches_in_cauldron = batches;
957 }
else if (batches_in_cauldron == batches)
987 int recipes_matching;
989 size_t rp_arch_index;
991 #ifdef EXTREME_ALCHEMY_DEBUG 995 recipes_matching = 0;
997 for (rp = fl->
items; rp != NULL; rp = rp->
next) {
1000 #ifdef EXTREME_ALCHEMY_DEBUG 1006 object *ingredients = cauldron->
inv;
1007 if (rp->
transmute && find_transmution_ob(ingredients, rp, &rp_arch_index, 0) != NULL) {
1008 #ifdef EXTREME_ALCHEMY_DEBUG 1012 if (!transmute_found) {
1013 transmute_found = 1;
1014 recipes_matching = 0;
1016 }
else if (transmute_found) {
1017 #ifdef EXTREME_ALCHEMY_DEBUG 1023 #ifdef EXTREME_ALCHEMY_DEBUG 1029 if (
rndm(0, recipes_matching) == 0)
1035 if (result == NULL) {
1036 #ifdef ALCHEMY_DEBUG 1037 LOG(
llevDebug,
"couldn't find formula for ingredients.\n");
1042 #ifdef ALCHEMY_DEBUG 1043 if (strcmp(result->
title,
"NONE") != 0)
1063 object *unpaid_cauldron = NULL;
1064 object *unpaid_item = NULL;
1065 int did_alchemy = 0;
1074 unpaid_cauldron = tmp;
1078 if (unpaid_item != NULL)
1087 if (unpaid_cauldron) {
1090 "You must pay for your %s first!",
1092 }
else if (unpaid_item) {
1095 "You must pay for your %s first!",
#define FLAG_DAMNED
The object is very cursed.
#define FLAG_UNPAID
Object hasn't been paid for yet.
Spell-related defines: spellpath, subtypes, ...
int8_t item_power
Power rating of the object.
static float recipe_chance(const recipe *rp, const object *skill, const object *cauldron)
Compute the success probability of a recipe.
struct archetype * arch
Pointer to archetype.
int diff
Alchemical dfficulty level.
void object_add_weight(object *op, signed long weight)
object_add_weight(object, weight) adds the specified weight to an object, and also updates how much t...
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
int rndm(int min, int max)
Returns a number between min and max.
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...) PRINTF_ARGS(6
recipe * get_random_recipe(recipelist *rpl)
Gets a random recipe from a list, based on chance.
object * object_find_by_flag(const object *who, int flag)
Find object in inventory by flag.
static int is_defined_recipe(const recipe *rp, const object *cauldron)
Determines if ingredients in a container match the proper ingredients for a recipe.
void object_remove(object *op)
This function removes the object op from the linked list of objects which it is currently tied to...
object * get_random_mon(int level)
Returns a random monster selected from linked list of all monsters in the current game...
void knowledge_give(player *pl, const char *marker, const object *book)
Give a knowledge item from its code.
static uint32_t NROF(const object *const ob)
Returns ob->nrof, unless it is 0, in which case return 1.
void object_sub_weight(object *op, signed long weight)
Recursively (outwards) subtracts a number from the weight of an object (and what is carried by it's e...
sstring add_string(const char *str)
Share a string.
int32_t value
How much money it is worth (or contains)
void esrv_send_inventory(object *pl, object *op)
Sends inventory of a container.
void change_exp(object *op, int64_t exp, const char *skill_name, int flag)
Changes experience to a player/monster.
void generate_artifact(object *op, int difficulty)
Decides randomly which artifact the object should be turned into.
#define MSG_TYPE_SKILL_MISSING
Don't have the skill.
sstring title
Distinguishing name of product.
int16_t y
Position in the map for this object.
int8_t magic
Any magical bonuses to this item.
uint16_t material
What materials this object consist of.
MoveType move_block
What movement types this blocks.
linked_char * ingred
List of ingredients.
#define MSG_TYPE_SKILL_ERROR
Doing something wrong.
recipe * items
Pointer to first recipe in this list.
int index
Index value derived from formula ingredients.
Global type definitions and header inclusions.
struct player * contr
Pointer to the player which control this object.
sstring skill
Skill name used to make this recipe.
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
Sends message to player(s).
int transmute
If defined, one of the formula ingredients is used as the basis for the product object.
object * object_find_by_type_and_slaying(const object *who, int type, const char *slaying)
Find object in inventory by type and slaying.
#define FOR_OB_AND_BELOW_FINISH()
Finishes FOR_OB_AND_BELOW_PREPARE().
int32_t weight
Attributes of the object.
#define FLAG_CAN_ROLL
Object can be rolled.
void free_string(sstring str)
This will reduce the refcount, and if it has reached 0, str will be freed.
int16_t level
Level of creature or object.
static const recipe * find_recipe(const recipelist *fl, int formula, object *cauldron)
Find a recipe from a recipe list that matches the given formula.
sstring failure_message
Specific failure message.
#define MSG_TYPE_COMMAND
Responses to commands, eg, who.
static object * find_transmution_ob(object *first_ingred, const recipe *rp, size_t *rp_arch_index, int create_item)
Looks through the ingredient list.
sstring materialname
Specific material name.
sstring name
More definite name, like "generate_kobold".
int exp
How much exp to give for this formulae.
size_t arch_names
Size of the arch_name[] array.
object * create_archetype(const char *name)
Finds which archetype matches the given name, and returns a new object containing a copy of the arche...
object * env
Pointer to the object which is the environment.
#define QUERY_FLAG(xyz, p)
void monster_npc_call_help(object *op)
A monster calls for help against its enemy.
static void attempt_do_alchemy(object *caster, object *cauldron)
Main part of the ALCHEMY code.
void give_artifact_abilities(object *op, const object *artifact)
Fixes the given object, giving it the abilities and titles it should have due to the second artifact-...
void object_give_identified_properties(object *op)
Ensure op has all its "identified" properties set.
static object * attempt_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().
sstring keycode
Optional keycode needed to use the recipe.
int summon_hostile_monsters(object *op, int n, const char *monstername)
Summons hostile monsters and places them in nearby squares.
struct linked_char * next
void object_free_drop_inventory(object *ob)
Frees everything allocated by an object, removes it from the list of used objects, and puts it on the list of free objects.
#define FLAG_IDENTIFIED
Item is identifiable (e.g.
#define FOR_INV_FINISH()
Finishes FOR_INV_PREPARE().
List of recipes with a certain number of ingredients.
static void alchemy_failure_effect(object *op, object *cauldron, const recipe *rp, int danger)
Ouch.
int yield
Maximum number of items produced by the recipe.
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 pr...
int is_identified(const object *op)
Return true if the item is identified, either because it is of a type that doesn't ever need identifi...
#define FLAG_IS_CAULDRON
container can make alchemical stuff
int use_alchemy(object *op)
Handle use_skill for alchemy-like items.
const artifact * locate_recipe_artifact(const recipe *rp, size_t idx)
Finds an artifact for a recipe.
#define MSG_TYPE_SKILL_FAILURE
Failure in using skill.
void cast_magic_storm(object *op, object *tmp, int lvl)
This is really used mostly for spell fumbles and the like.
recipelist * get_formulalist(int i)
Gets a formula list by ingredients count.
int random_roll(int min, int max, const object *op, int goodbad)
Roll a random number between min and max.
int16_t dam
How much damage this object does when hitting.
static void adjust_product(object *item, int lvl, int yield)
We adjust the nrof of the final product, based on the item's default parameters, and the relevant cas...
#define FLAG_WIZ
Object has special privilegies.
living stats
Str, Con, Dex, etc.
#define MAX_BUF
Used for all kinds of things.
static float chance_fn(int diff)
Compute a success probability, between .01 and .95, based on the level difference.
int strtoint(const char *buf)
Convert buf into an integer equal to the coadded sum of the (lowercase) character.
uint64_t price_base(const object *obj)
Price an item based on its value or archetype value, type, identification/BUC status, and other heuristics.
static int content_recipe_value(object *op)
Recipe value of the entire contents of a container.
struct mapstruct * map
Pointer to the map in which this object is present.
Skill-related defines, including subtypes.
static int numb_ob_inside(const object *op)
Returns the total number of items in op, excluding ones in item's items.
static void remove_contents(object *first_ob, object *save_item)
All but object "save_item" are elimentated from the container list.
static object * make_item_from_recipe(object *cauldron, const recipe *rp)
Using a list of items and a recipe to make an artifact.
#define FOR_MAP_FINISH()
Finishes FOR_MAP_PREPARE().
#define FLAG_KNOWN_CURSED
The object is known to be cursed.
#define FLAG_CURSED
The object is cursed.
sstring name_pl
The plural name of the object.
Object structure, the core of Crossfire.
void query_base_name(const object *op, int plural, char *buf, size_t size)
Query a short name for the item.
void transmute_materialname(object *op, const object *change)
When doing transmutation of objects, we have to recheck the resistances, as some that did not apply p...
#define SP_MED_FIREBALL
These are some hard coded values that are used within the code for spell failure effects or pieces of...
sstring name
The name of the object, obviously...
sstring title
Of foo, etc.
Only for debugging purposes.
uint32_t nrof
Number of objects.
sstring failure_arch
Arch of the item to generate on failure, instead of blowing up stuff.
int min_level
Minimum level to have in the skill to be able to use the formulae.
void object_set_enemy(object *op, object *enemy)
Sets the enemy of an object.
static const char *const cauldron_effect[]
define this for some helpful debuging information
#define SK_EXP_NONE
Player gets nothing.
#define CLEAR_FLAG(xyz, p)
uint8_t type
PLAYER, BULLET, etc.
#define FLAG_APPLIED
Object is ready for use by living.
void change_attr_value(living *stats, int attr, int8_t value)
Like set_attr_value(), but instead the value (which can be negative) is added to the specified stat...
object * inv
Pointer to the first object in the inventory.
int fire_arch_from_position(object *op, object *caster, int16_t x, int16_t y, int dir, object *spell)
Fires an archetype.
#define FOR_OB_AND_BELOW_PREPARE(op_)
Constructs a loop iterating over an object and all objects below it in the same pile.
recipe * next
Next recipe with the same number of ingredients.
char ** arch_name
Possible archetypes of the final product made.
void formula_knowledge_code(const recipe *r, char *buf, size_t len)
Store the textual knowledge marker code for recipe R in BUF.
#define MSG_TYPE_SKILL
Messages related to skill use.
#define NDI_UNIQUE
Print immediately, don't buffer.
static const char * cauldron_sound(void)
Returns a random selection from cauldron_effect[].
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Constructs a loop iterating over all objects of a map tile.
#define MSG_TYPE_SKILL_SUCCESS
Successfully used skill.
object * object_insert_in_ob(object *op, object *where)
This function inserts the object op in the linked list inside the object environment.
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Same as object_insert_in_map() except it handle separate coordinates and do a clean job preparing mul...
#define FLAG_NO_PICK
Object can't be picked up.
sstring cauldron
Arch of the cauldron/workbench used to house the formulae.
This is one artifact, ie one special item.
object * find_skill_by_name(object *who, const char *name)
This returns the skill pointer of the given name (the one that accumulates exp, has the level...
object clone
An object from which to do object_copy()
#define FOR_INV_PREPARE(op_, it_)
Constructs a loop iterating over the inventory of an object.
#define MSG_TYPE_COMMAND_DM
DM related commands.
object * item
Special values of the artifact.