Included are the patches to make luck work per my proposal. I have added the die_roll and random_roll functions to common/player.c, because it wasn't obvious to me where such procedures would go, and it generally seemed to fit the concept of the other functions in that file. I have also modified spell_util.c as an example of how my code is to be implemented. In addition.. I am a bit confused as to where to add my function prototypes. I would have expected them to live in player.h, but there is the sproto.h, which seems to be machine generated, and I wasn't sure what to do with that. Finally, I might like to add two defines to one of the .h files, PREFER_HIGH and PREFER_LOW, rather than using 1 and 0 for the goodbad argument to the functions. I think it would improve code readability significantly (and make it immediately obvious if a high or low roll is good to coders) but I'm not sure what the coding style is WRT this. BTW- you really want diff -C? diff -u is so much easier to read. *** common/player.c.orig Sun Sep 16 13:53:35 2001 --- common/player.c Sun Sep 16 17:48:11 2001 *************** *** 132,134 **** --- 132,196 ---- } return skill1; } + + /* + * Roll a random number between min and max. Uses op to determine luck, + * and if goodbad is non-zero, luck increases the roll, if zero, it decreases. + * Generally, op should be the player/caster/hitter requesting the roll, + * not the recipient (ie, the poor slob getting hit). [garbled 20010916] + */ + + int random_roll(int min, int max, object *op, int goodbad) { + int omin, diff, luck; + + omin = min; + diff = max - min + 1; + + if (op->type != PLAYER) + return((RANDOM()%diff)+min); + + luck = op->stats.luck; + if (RANDOM()%20 < MIN(10, abs(luck))) { + /* we have a winner */ + ((luck > 0) ? (luck = 1) : (luck = -1)); + diff -= luck; + ((goodbad) ? (min += luck) : (diff)); + + return(MAX(omin, MIN(max, (RANDOM()%diff)+min))); + } + return((RANDOM()%diff)+min); + } + + /* + * Roll a number of dice (2d3, 4d6). Uses op to determine luck, + * If goodbad is non-zero, luck increases the roll, if zero, it decreases. + * Generally, op should be the player/caster/hitter requesting the roll, + * not the recipient (ie, the poor slob getting hit). + * The args are num D size (ie 4d6) [garbled 20010916] + */ + + int die_roll(int num, int size, object *op, int goodbad) { + int min, diff, luck, total, i, gotlucky; + + diff = size; + min = 1; + luck = total = gotlucky = 0; + + if (op->type == PLAYER) + luck = op->stats.luck; + + for (i = 0; i < num; i++) { + if (RANDOM()%20 < MIN(10, abs(luck)) && !gotlucky) { + /* we have a winner */ + gotlucky++; + ((luck > 0) ? (luck = 1) : (luck = -1)); + diff -= luck; + ((goodbad) ? (min += luck) : (diff)); + total += MAX(1, MIN(size, (RANDOM()%diff)+min)); + } else { + total += RANDOM()%size+1; + } + } + return(total); + } + *** server/spell_util.c.orig Sun May 13 14:55:41 2001 --- server/spell_util.c Sun Sep 16 17:41:43 2001 *************** *** 212,218 **** *Instead of subtracting 10 from the roll, add in grace (which is * negative). This puts a real limit on things. */ ! if( (RANDOM()%op->stats.Wis) +op->stats.grace - 10*SP_level_spellpoint_cost(op,caster,type)/op->stats.maxgrace >0) { #ifdef MULTIPLE_GODS new_draw_info_format(NDI_UNIQUE, 0,op, --- 212,218 ---- *Instead of subtracting 10 from the roll, add in grace (which is * negative). This puts a real limit on things. */ ! if(random_roll(0, op->stats.Wis, op, 1) + op->stats.grace - 10*SP_level_spellpoint_cost(op,caster,type)/op->stats.maxgrace >0) { #ifdef MULTIPLE_GODS new_draw_info_format(NDI_UNIQUE, 0,op, *************** *** 311,320 **** return 0; } if(item == spellNormal && op->type==PLAYER&&s->cleric&& ! /* RANDOM()%100< s->level*2 - op->level + cleric_chance[op->stats.Wis]- ! op->stats.luck*3) {*/ ! RANDOM()%100 < s->level/(float)MAX(1,op->level) * cleric_chance[op->stats.Wis]- ! op->stats.luck*3) { play_sound_player_only(op->contr, SOUND_FUMBLE_SPELL,0,0); new_draw_info(NDI_UNIQUE, 0,op,"You fumble the spell."); #ifdef CASTING_TIME --- 311,319 ---- return 0; } if(item == spellNormal && op->type==PLAYER&&s->cleric&& ! random_roll(0, 99, op, 1) < s->level/(float)MAX(1,op->level) * ! cleric_chance[op->stats.Wis]) { ! play_sound_player_only(op->contr, SOUND_FUMBLE_SPELL,0,0); new_draw_info(NDI_UNIQUE, 0,op,"You fumble the spell."); #ifdef CASTING_TIME *************** *** 327,340 **** } #ifdef SPELL_ENCUMBRANCE if(item == spellNormal && op->type==PLAYER && (!s->cleric) ) { ! int failure = (RANDOM()%200) - op->contr->encumbrance +op->level -s->level +35; if( failure < 0) { new_draw_info(NDI_UNIQUE, 0,op,"You bungle the spell because you have too much heavy equipment in use."); #ifdef SPELL_FAILURE_EFFECTS spell_failure(op,failure,SP_level_spellpoint_cost(op,caster,type)); #endif ! return RANDOM()%(SP_level_spellpoint_cost(op,caster,type)+ 1); } } #endif /*SPELL_ENCUMBRANCE*/ --- 326,339 ---- } #ifdef SPELL_ENCUMBRANCE if(item == spellNormal && op->type==PLAYER && (!s->cleric) ) { ! int failure = random_roll(0, 199, op, 0) - op->contr->encumbrance +op->level -s->level +35; if( failure < 0) { new_draw_info(NDI_UNIQUE, 0,op,"You bungle the spell because you have too much heavy equipment in use."); #ifdef SPELL_FAILURE_EFFECTS spell_failure(op,failure,SP_level_spellpoint_cost(op,caster,type)); #endif ! return(random_roll(1, SP_level_spellpoint_cost(op,caster,type), op, 0)); } } #endif /*SPELL_ENCUMBRANCE*/ *************** *** 608,642 **** success = fire_arch(op,caster,dir,spellarch[type],type,!ability); break; case SP_METEOR_SWARM: { - int n; - n=RANDOM()%3 + RANDOM()%3 + RANDOM()%3 +3 + - SP_level_strength_adjust(op,caster, type); success = 1; ! fire_swarm(op,caster,dir,spellarch[type],SP_METEOR,n,0); break; } case SP_BULLET_SWARM: { - int n; - n=RANDOM()%3 + RANDOM()%3 + RANDOM()%3 +3 + - SP_level_strength_adjust(op,caster, type); success = 1; ! fire_swarm(op,caster,dir,spellarch[type],SP_BULLET,n,1); break; } case SP_BULLET_STORM: { - int n; - n=RANDOM()%3 + RANDOM()%3 + RANDOM()%3 +3 + - SP_level_strength_adjust(op,caster, type); success = 1; ! fire_swarm(op,caster,dir,spellarch[type],SP_LARGE_BULLET,n,1); break; } case SP_CAUSE_MANY: { - int n; - n=RANDOM()%3 + RANDOM()%3 + RANDOM()%3 +3 + - SP_level_strength_adjust(op,caster, type); success = 1; ! fire_swarm(op,caster,dir,spellarch[type],SP_CAUSE_HEAVY,n,1); break; } case SP_METEOR: --- 607,633 ---- success = fire_arch(op,caster,dir,spellarch[type],type,!ability); break; case SP_METEOR_SWARM: { success = 1; ! fire_swarm(op, caster, dir, spellarch[type], SP_METEOR, ! die_roll(3, 3, op, 1) + SP_level_strength_adjust(op,caster, type), 0); break; } case SP_BULLET_SWARM: { success = 1; ! fire_swarm(op, caster, dir, spellarch[type], SP_BULLET, ! die_roll(3, 3, op, 1) + SP_level_strength_adjust(op,caster, type), 0); break; } case SP_BULLET_STORM: { success = 1; ! fire_swarm(op, caster, dir, spellarch[type], SP_LARGE_BULLET, ! die_roll(3, 3, op, 1) + SP_level_strength_adjust(op,caster, type), 0); break; } case SP_CAUSE_MANY: { success = 1; ! fire_swarm(op, caster, dir, spellarch[type], SP_CAUSE_HEAVY, ! die_roll(3, 3, op, 1) + SP_level_strength_adjust(op,caster, type), 0); break; } case SP_METEOR: *************** *** 2259,2265 **** insert_ob_in_ob(new_aura, op); return 1; } ! /* look_up_spell_by_name: peterm this function attempts to find the spell spname in spells[]. if it doesn't exist, or if the op cannot cast that spname, --- 2250,2256 ---- insert_ob_in_ob(new_aura, op); return 1; } ! /* look_up_spell_by_name: peterm this function attempts to find the spell spname in spells[]. if it doesn't exist, or if the op cannot cast that spname, --- Tim Rightnour < root at garbled.net > NetBSD: Free multi-architecture OS http://www.netbsd.org/ NetBSD supported hardware database: http://mail-index.netbsd.org/cgi-bin/hw.cgi