void labyrinth_spin_carousels(struct zone_data *zone) { struct room_data *cur_room; struct room_direction_data *dir_save[NUM_DIRS]; for (cur_room = zone->world; cur_room && cur_room->number < zone->top; cur_room = cur_room->next) { if (cur_room->func != labyrinth_carousel) continue; // Spin the room! Wheee! memcpy(dir_save, cur_room->dir_option, sizeof(dir_save)); cur_room->dir_option[NORTH] = dir_save[WEST]; cur_room->dir_option[EAST] = dir_save[NORTH]; cur_room->dir_option[SOUTH] = dir_save[EAST]; cur_room->dir_option[WEST] = dir_save[SOUTH]; if (cur_room->people) continue; // Knock people down and describe if there are observers act("The floor lurches beneath your feet!", true, NULL, NULL, NULL, TO_ROOM); for (GList * it = cur_room->people; it; it = it->next) { struct creature *vict = it->data; if (number(1, 26) > GET_DEX(vict)) { send_to_char(vict, "You fall to the floor! Oof!\r\n"); GET_POSITION(vict) = POS_SITTING; } } } }
static __inline__ int GetPosition(AG_Slider *sl, int *x) { AG_Variable *bMin, *bMax, *bVal; void *pMin, *pMax, *pVal; bVal = AG_GetVariable(sl, "value", &pVal); bMin = AG_GetVariable(sl, "min", &pMin); bMax = AG_GetVariable(sl, "max", &pMax); switch (AG_VARIABLE_TYPE(bVal)) { case AG_VARIABLE_FLOAT: GET_POSITION(float); break; case AG_VARIABLE_DOUBLE: GET_POSITION(double); break; #ifdef HAVE_LONG_DOUBLE case AG_VARIABLE_LONG_DOUBLE: GET_POSITION(long double); break; #endif case AG_VARIABLE_INT: GET_POSITION(int); break; case AG_VARIABLE_UINT: GET_POSITION(Uint); break; case AG_VARIABLE_UINT8: GET_POSITION(Uint8); break; case AG_VARIABLE_SINT8: GET_POSITION(Sint8); break; case AG_VARIABLE_UINT16: GET_POSITION(Uint16); break; case AG_VARIABLE_SINT16: GET_POSITION(Sint16); break; case AG_VARIABLE_UINT32: GET_POSITION(Uint32); break; case AG_VARIABLE_SINT32: GET_POSITION(Sint32); break; #ifdef HAVE_64BIT case AG_VARIABLE_UINT64: GET_POSITION(Uint64); break; case AG_VARIABLE_SINT64: GET_POSITION(Sint64); break; #endif default: *x = 0; break; } AG_UnlockVariable(bMax); AG_UnlockVariable(bMin); AG_UnlockVariable(bVal); return (0); fail: AG_UnlockVariable(bMax); AG_UnlockVariable(bMin); AG_UnlockVariable(bVal); return (-1); }
bool psionic_mob_fight(struct creature *ch, struct creature *precious_vict) { struct creature *vict = NULL; if (!is_fighting(ch)) return false; // pick an enemy if (!(vict = choose_opponent(ch, precious_vict))) return false; int aggression = calculate_mob_aggression(ch, vict); // Psions can't really do anything when there's a psishield in place if (AFF3_FLAGGED(vict, AFF3_PSISHIELD) && can_cast_spell(ch, SPELL_PSIONIC_SHATTER)) { cast_spell(ch, vict, NULL, NULL, SPELL_PSIONIC_SHATTER); return true; } // Prioritize healing with aggression if (GET_HIT(ch) < (GET_MAX_HIT(ch) * MIN(20, MAX(80, aggression)) / 100) && can_cast_spell(ch, SPELL_WOUND_CLOSURE)) { cast_spell(ch, ch, NULL, NULL, SPELL_WOUND_CLOSURE); return true; } if (aggression > 75) { // extremely aggressive - just attack hard if (can_cast_spell(ch, SKILL_PSIBLAST)) { perform_offensive_skill(ch, vict, SKILL_PSIBLAST); return true; } else if (GET_POSITION(vict) > POS_SITTING && can_cast_spell(ch, SPELL_EGO_WHIP)) { cast_spell(ch, vict, NULL, NULL, SPELL_EGO_WHIP); return true; } } if (aggression > 50) { // somewhat aggressive - balance attacking with crippling if (GET_MANA(ch) < GET_MAX_MANA(ch) / 2 && can_cast_spell(ch, SKILL_PSIDRAIN) && can_psidrain(ch, vict, NULL, false)) { perform_psidrain(ch, vict); return true; } else if (!affected_by_spell(vict, SPELL_PSYCHIC_CRUSH) && can_cast_spell(ch, SPELL_PSYCHIC_CRUSH)) { cast_spell(ch, vict, NULL, NULL, SPELL_PSYCHIC_CRUSH); return true; } else if (!affected_by_spell(vict, SPELL_MOTOR_SPASM) && can_cast_spell(ch, SPELL_MOTOR_SPASM)) { cast_spell(ch, vict, NULL, NULL, SPELL_MOTOR_SPASM); return true; } else if (!affected_by_spell(ch, SPELL_ADRENALINE) && can_cast_spell(ch, SPELL_ADRENALINE)) { cast_spell(ch, ch, NULL, NULL, SPELL_ADRENALINE); return true; } else if (GET_POSITION(vict) > POS_SITTING && can_cast_spell(ch, SPELL_EGO_WHIP)) { cast_spell(ch, vict, NULL, NULL, SPELL_EGO_WHIP); return true; } else if (can_cast_spell(ch, SKILL_PSIBLAST)) { perform_offensive_skill(ch, vict, SKILL_PSIBLAST); return true; } } if (aggression > 25) { // not very aggressive - play more defensively if (IS_PSIONIC(vict) && !affected_by_spell(ch, SPELL_PSYCHIC_RESISTANCE) && can_cast_spell(ch, SPELL_PSYCHIC_RESISTANCE)) { cast_spell(ch, ch, NULL, NULL, SPELL_PSYCHIC_RESISTANCE); return true; } else if (!IS_CONFUSED(vict) && can_cast_spell(ch, SPELL_CONFUSION) && (IS_MAGE(vict) || IS_PSIONIC(vict) || IS_CLERIC(vict) || IS_KNIGHT(vict) || IS_PHYSIC(vict))) { cast_spell(ch, vict, NULL, NULL, SPELL_CONFUSION); return true; } else if (GET_MOVE(ch) < GET_MAX_MOVE(ch) / 4 && can_cast_spell(ch, SPELL_ENDURANCE)) { cast_spell(ch, ch, NULL, NULL, SPELL_ENDURANCE); return true; } else if (GET_MOVE(ch) < GET_MAX_MOVE(ch) / 4 && can_cast_spell(ch, SPELL_DERMAL_HARDENING)) { cast_spell(ch, ch, NULL, NULL, SPELL_DERMAL_HARDENING); return true; } else if (!AFF2_FLAGGED(ch, AFF2_VERTIGO) && can_cast_spell(ch, SPELL_VERTIGO)) { cast_spell(ch, vict, NULL, NULL, SPELL_VERTIGO); return true; } else if (!affected_by_spell(vict, SPELL_PSYCHIC_FEEDBACK) && can_cast_spell(ch, SPELL_PSYCHIC_FEEDBACK)) { cast_spell(ch, vict, NULL, NULL, SPELL_PSYCHIC_FEEDBACK); return true; } else if (!affected_by_spell(vict, SPELL_WEAKNESS) && can_cast_spell(ch, SPELL_WEAKNESS)) { cast_spell(ch, vict, NULL, NULL, SPELL_WEAKNESS); return true; } else if (!affected_by_spell(vict, SPELL_CLUMSINESS) && can_cast_spell(ch, SPELL_CLUMSINESS)) { cast_spell(ch, vict, NULL, NULL, SPELL_CLUMSINESS); return true; } else if (can_cast_spell(ch, SKILL_PSIBLAST)) { perform_offensive_skill(ch, vict, SKILL_PSIBLAST); return true; } } if (aggression > 5) { // attempt to neutralize or get away if (GET_POSITION(vict) > POS_SLEEPING && can_cast_spell(ch, SPELL_MELATONIC_FLOOD)) { cast_spell(ch, vict, NULL, NULL, SPELL_MELATONIC_FLOOD); return true; } else if (can_cast_spell(ch, SPELL_ASTRAL_SPELL)) { cast_spell(ch, vict, NULL, NULL, SPELL_ASTRAL_SPELL); return true; } else if (can_cast_spell(ch, SPELL_AMNESIA)) { cast_spell(ch, vict, NULL, NULL, SPELL_AMNESIA); return true; } else if (can_cast_spell(ch, SPELL_FEAR)) { cast_spell(ch, vict, NULL, NULL, SPELL_FEAR); return true; } } return false; }
void psionic_best_attack(struct creature *ch, struct creature *vict) { int aggression = calculate_mob_aggression(ch, vict); // Psions can't really do anything when there's a psishield in place if (AFF3_FLAGGED(vict, AFF3_PSISHIELD) && can_cast_spell(ch, SPELL_PSIONIC_SHATTER)) { cast_spell(ch, vict, NULL, NULL, SPELL_PSIONIC_SHATTER); return; } if (aggression > 75) { // extremely aggressive - just attack hard if (!affected_by_spell(vict, SPELL_PSYCHIC_SURGE) && can_cast_spell(ch, SPELL_PSYCHIC_SURGE)) { cast_spell(ch, vict, NULL, NULL, SPELL_PSYCHIC_SURGE); return; } else if (can_cast_spell(ch, SKILL_PSIBLAST)) { perform_offensive_skill(ch, vict, SKILL_PSIBLAST); return; } else if (GET_POSITION(vict) > POS_SITTING && can_cast_spell(ch, SPELL_EGO_WHIP)) { cast_spell(ch, vict, NULL, NULL, SPELL_EGO_WHIP); return; } } if (aggression > 50) { // somewhat aggressive - balance attacking with crippling if (!affected_by_spell(vict, SPELL_PSYCHIC_CRUSH) && can_cast_spell(ch, SPELL_PSYCHIC_CRUSH)) { cast_spell(ch, vict, NULL, NULL, SPELL_PSYCHIC_CRUSH); return; } else if (!affected_by_spell(vict, SPELL_MOTOR_SPASM) && can_cast_spell(ch, SPELL_MOTOR_SPASM)) { cast_spell(ch, vict, NULL, NULL, SPELL_MOTOR_SPASM); return; } else if (GET_POSITION(vict) > POS_SITTING && can_cast_spell(ch, SPELL_EGO_WHIP)) { cast_spell(ch, vict, NULL, NULL, SPELL_EGO_WHIP); return; } else if (can_cast_spell(ch, SKILL_PSIBLAST)) { perform_offensive_skill(ch, vict, SKILL_PSIBLAST); return; } } if (aggression > 25) { // not very aggressive - play more defensively if (!IS_CONFUSED(vict) && can_cast_spell(ch, SPELL_CONFUSION) && (IS_MAGE(vict) || IS_PSIONIC(vict) || IS_CLERIC(vict) || IS_KNIGHT(vict) || IS_PHYSIC(vict))) { cast_spell(ch, vict, NULL, NULL, SPELL_CONFUSION); return; } else if (!AFF2_FLAGGED(ch, AFF2_VERTIGO) && can_cast_spell(ch, SPELL_VERTIGO)) { cast_spell(ch, vict, NULL, NULL, SPELL_VERTIGO); return; } else if (!affected_by_spell(vict, SPELL_PSYCHIC_FEEDBACK) && can_cast_spell(ch, SPELL_PSYCHIC_FEEDBACK)) { cast_spell(ch, vict, NULL, NULL, SPELL_PSYCHIC_FEEDBACK); return; } else if (nullpsi_is_advisable(vict) && can_cast_spell(ch, SPELL_NULLPSI)) { cast_spell(ch, vict, NULL, NULL, SPELL_NULLPSI); return; } else if (can_cast_spell(ch, SKILL_PSIBLAST)) { perform_offensive_skill(ch, vict, SKILL_PSIBLAST); return; } } if (aggression > 5) { // attempt to neutralize or get away if (GET_POSITION(vict) > POS_SLEEPING && can_cast_spell(ch, SPELL_MELATONIC_FLOOD)) { cast_spell(ch, vict, NULL, NULL, SPELL_MELATONIC_FLOOD); return; } else if (can_cast_spell(ch, SPELL_ASTRAL_SPELL)) { cast_spell(ch, vict, NULL, NULL, SPELL_ASTRAL_SPELL); return; } else if (can_cast_spell(ch, SPELL_AMNESIA)) { cast_spell(ch, vict, NULL, NULL, SPELL_AMNESIA); return; } else if (can_cast_spell(ch, SPELL_FEAR)) { cast_spell(ch, vict, NULL, NULL, SPELL_FEAR); return; } } // desperation - just attack full force, as hard as possible if (!affected_by_spell(vict, SPELL_PSYCHIC_SURGE) && can_cast_spell(ch, SPELL_PSYCHIC_SURGE)) { cast_spell(ch, vict, NULL, NULL, SPELL_PSYCHIC_SURGE); return; } else if (!affected_by_spell(vict, SPELL_PSYCHIC_CRUSH) && can_cast_spell(ch, SPELL_PSYCHIC_CRUSH)) { cast_spell(ch, vict, NULL, NULL, SPELL_PSYCHIC_CRUSH); return; } else if (!affected_by_spell(vict, SPELL_MOTOR_SPASM) && can_cast_spell(ch, SPELL_MOTOR_SPASM)) { cast_spell(ch, vict, NULL, NULL, SPELL_MOTOR_SPASM); return; } else if (can_cast_spell(ch, SKILL_PSIBLAST)) { perform_offensive_skill(ch, vict, SKILL_PSIBLAST); return; } else if (GET_POSITION(vict) > POS_SITTING && can_cast_spell(ch, SPELL_EGO_WHIP)) { cast_spell(ch, vict, NULL, NULL, SPELL_EGO_WHIP); return; } else if (GET_POSITION(vict) > POS_SLEEPING && can_cast_spell(ch, SPELL_MELATONIC_FLOOD)) { cast_spell(ch, vict, NULL, NULL, SPELL_MELATONIC_FLOOD); return; } else if (can_cast_spell(ch, SPELL_ASTRAL_SPELL)) { cast_spell(ch, vict, NULL, NULL, SPELL_ASTRAL_SPELL); return; } else if (can_cast_spell(ch, SPELL_AMNESIA)) { cast_spell(ch, vict, NULL, NULL, SPELL_AMNESIA); return; } else if (can_cast_spell(ch, SPELL_FEAR)) { cast_spell(ch, vict, NULL, NULL, SPELL_FEAR); return; } else { hit(ch, vict, TYPE_UNDEFINED); } }
int getrankIDF( RESULT *r ) { unsigned int *posdata; int meta_bias; IndexFILE *indexf; int words; int i; SWISH *sw; int metaID; int freq; int total_files; int total_words; int average_words; int density; int idf; int total_word_freq; int word_weight; int word_score; /* int density_magic = 2; */ /* the value named 'rank' in getrank() is here named 'word_score'. it's largely semantic, but helps emphasize that *docs* are ranked, but *words* are scored. The doc rank is calculated based on the accrued word scores. However, the hash key name 'rank' is preserved in the r (RESULT) object for compatibility with getrank() */ /* this first part is identical to getrankDEF -- could be optimized as a single function */ int struct_tally[256]; if( DEBUG_RANK ) { for ( i = 0; i <= 255; i++ ) struct_tally[i] = 0; } if ( r->rank >= 0 ) return r->rank; indexf = r->db_results->indexf; sw = indexf->sw; posdata = r->posdata; metaID = r->rank * -1; meta_bias = indexf->header.metaEntryArray[ metaID - 1 ]->rank_bias; if ( !sw->structure_map_set ) { build_struct_map( sw ); } /* here we start to diverge */ word_score = 1; freq = r->frequency; if( DEBUG_RANK ) { fprintf( stderr, "File num: %d Word Score: %d Frequency: %d ", r->filenum, word_score, freq ); } /* don't do this here; let density calc do it if ( freq > 100 ) freq = 100; */ /* IDF is the Inverse Document Frequency, or, the weight of the word in relationship to the collection of documents as a whole. Multiply the weight against the rank to give greater weight to words that appear less often in the collection. The biggest impact should be seen when OR'ing words together instead of AND'ing them. */ total_files = sw->TotalFiles; total_word_freq = r->tfrequency; idf = (int) ( log( total_files / total_word_freq ) * 1000 ); /* *1000 helps create a wider spread between the most common words and the rest of the pack: "word frequencies in natural language obey a power-law distribution" -- Maciej Ceglowski */ if ( idf < 1 ) idf = 1; /* only ubiquitous words like 'the' get idfs < 1. these should probably be stopwords anyway... */ if( DEBUG_RANK ) { fprintf(stderr, "Total files: %d Total word freq: %d IDF: %d \n", total_files, total_word_freq, idf ); } /* calc word density. this normalizes document length so that longer docs don't rank higher out of sheer quantity. Hopefully this is a little more scientific than the out-of-the-air calc in getrankDEF() -- though effectiveness is likely the same... */ words = getTotalWordsInFile( indexf, r->filenum ); total_words = sw->TotalWordPos; average_words = total_words / total_files; if( DEBUG_RANK ) { fprintf(stderr, "Total words: %d Average words: %d Indexed words in this doc: %d ", total_words, average_words, words ); } /* normalizing term density in a collection. Amati & Van Rijsbergen "normalization 2" from A Study of Parameter Tuning for Term Frequency Normalization Ben HE Department of Computing Science University of Glasgow Glasgow, UK [email protected] term_freq_density = term_freq * log( 1 + c * av_doc_leng/doc_leng) where c > 0 (optimized at 2 ... we think...) */ /* density = freq * log( 1 + ( density_magic * ( average_words / words ) ) ); */ /* doesn't work that well with int values. Use below (cruder) instead. NOTE that there is likely a sweet spot for density. A word like 'the' will always have a high density in normal language, but it is not very relevant. A word like 'foo' might have a very low density in doc A but slightly higher in doc B -- doc B is likely more relevant. So low density is not a good indicator and neither is high density. Instead, something like: | density scale ---> | 0 X 100 useless sweet useless */ /* if for some reason there are 0 words in this document, we'll get a divide by zero error in this next calculation. why might a doc have no words in it, and yet be in the set of matches we're evaluating? maybe because stopwords aren't counted? it's a mystery, just like mankind... set words=1 if <1 so that we at least avoid the core dump -- would it be better to somehow skip it altogether? throw an error? let's warn on stderr for now, just to alert the user that something is awry. */ if ( words < 1 ) { fprintf(stderr, "Word count for document %d is zero\n", r->filenum ); words = 1; } density = ( ( average_words * 1000 ) / words ) * freq; /* minimum density */ if (density < 1) density = 1; /* scale word_weight back down by 100 or so, just to make it a little saner */ word_weight = ( density * idf ) / 100; if( DEBUG_RANK ) { fprintf(stderr, "Density: %d Word Weight: %d \n", density, word_weight ); } for(i = 0; i < freq; i++) { /* GET_STRUCTURE must return value in range! */ word_score += word_weight * ( sw->structure_map[ GET_STRUCTURE(posdata[i]) ] + meta_bias ); if( DEBUG_RANK > 1 ) { fprintf(stderr, "Word entry %d at position %d has struct %d\n", i, GET_POSITION(posdata[i]), GET_STRUCTURE(posdata[i]) ); struct_tally[ GET_STRUCTURE(posdata[i]) ]++; } } /* see comment in getrank() about why we make sure score is positive and non-zero */ if ( word_score < 1 ) word_score = 1; if( DEBUG_RANK ) { fprintf(stderr, "Raw score after IDF weighting: %d \n", word_score ); } word_score = scale_word_score( word_score ); if( DEBUG_RANK > 1 ) { fprintf( stderr, "scaled rank: %d\n Structure tally:\n", word_score ); for ( i = 0; i <= 255; i++ ) { if ( struct_tally[i] ) { fprintf( stderr, " struct 0x%x = count of %2d (", i, struct_tally[i] ); if ( i & IN_EMPHASIZED ) fprintf(stderr," EM"); if ( i & IN_HEADER ) fprintf(stderr," HEADING"); if ( i & IN_COMMENTS ) fprintf(stderr," COMMENT"); if ( i & IN_META ) fprintf(stderr," META"); if ( i & IN_BODY ) fprintf(stderr," BODY"); if ( i & IN_HEAD ) fprintf(stderr," HEAD"); if ( i & IN_TITLE ) fprintf(stderr," TITLE"); if ( i & IN_FILE ) fprintf(stderr," FILE"); fprintf(stderr," ) x rank map of %d = %d\n\n", sw->structure_map[i], sw->structure_map[i] * struct_tally[i]); } } } if ( DEBUG_RANK ) { fprintf(stderr, "Scaled score: %d \n", word_score ); } return ( r->rank = word_score ); }
int getrankDEF( RESULT *r ) { unsigned int *posdata; int meta_bias; IndexFILE *indexf; int rank; int reduction; int words; /* number of word positions (total words, not unique) in the given file -- probably should be per metaname */ int i; SWISH *sw; int metaID; int freq; int struct_tally[256]; if( DEBUG_RANK ) { for ( i = 0; i <= 255; i++ ) struct_tally[i] = 0; } /* has rank already been calculated? */ if ( r->rank >= 0 ) return r->rank; /* load data locally */ indexf = r->db_results->indexf; sw = indexf->sw; posdata = r->posdata; /* Get bias for the current metaID - metaID is stored in the rank for ease here */ /* Currently, the rankbias is a number from -10 to +10. It's an arbitrary range. */ /* MetaBias is added to the word value for *each* word position, so it's multipied */ /* times the number of words in the document (r->frequency). */ metaID = r->rank * -1; meta_bias = indexf->header.metaEntryArray[ metaID - 1 ]->rank_bias; /* pre-build the structure map array */ /* this maps a word's structure to a rank value */ if ( !sw->structure_map_set ) { build_struct_map( sw ); } /* Add up the raw word values for each word found in the current document. */ /* Notice the meta_bias added to each position */ /* Might also bias words with low position values, for example */ /* Should really consider r->tfrequency, which is the number of files that have */ /* this word. If the word is not found in many files then it should be ranked higher */ rank = 1; freq = r->frequency; if ( freq > 100 ) freq = 100; for(i = 0; i < freq; i++) { /* GET_STRUCTURE must return value in range! */ rank += sw->structure_map[ GET_STRUCTURE(posdata[i]) ] + meta_bias; if( DEBUG_RANK > 1 ) { fprintf(stderr, "Word entry %d at position %d has struct %d\n", i, GET_POSITION(posdata[i]), GET_STRUCTURE(posdata[i]) ); struct_tally[ GET_STRUCTURE(posdata[i]) ]++; } } if( DEBUG_RANK ) { fprintf( stderr, "File num: %d. Raw Rank: %d. Frequency: %d ", r->filenum, rank, r->frequency ); } /* Ranks could end up less than zero -- but since the *final* rank is calcualted here */ /* we can't know the *lowest* value to use an offset. It might be better to track */ /* the lowest value and delay actual final rank calculation/scaling to when the rank */ /* is printed. Especially when AND or OR'ing resutls. */ if ( rank < 1 ) rank = 1; rank = scale_word_score( rank ); if( DEBUG_RANK > 1 ) { fprintf( stderr, "scaled rank: %d\n Structure tally:\n", rank ); for ( i = 0; i <= 255; i++ ) { if ( struct_tally[i] ) { fprintf( stderr, " struct 0x%x = count of %2d (", i, struct_tally[i] ); if ( i & IN_EMPHASIZED ) fprintf(stderr," EM"); if ( i & IN_HEADER ) fprintf(stderr," HEADING"); if ( i & IN_COMMENTS ) fprintf(stderr," COMMENT"); if ( i & IN_META ) fprintf(stderr," META"); if ( i & IN_BODY ) fprintf(stderr," BODY"); if ( i & IN_HEAD ) fprintf(stderr," HEAD"); if ( i & IN_TITLE ) fprintf(stderr," TITLE"); if ( i & IN_FILE ) fprintf(stderr," FILE"); fprintf(stderr," ) x rank map of %d = %d\n\n", sw->structure_map[i], sw->structure_map[i] * struct_tally[i]); } } } /* Return if IgnoreTotalWordCountWhenRanking is true (the default) */ if ( indexf->header.ignoreTotalWordCountWhenRanking ) return ( r->rank = rank / 100); /* bias by total words in the file -- this is off by default */ /* if word count is significant, reduce rank by a number between 1.0 and 5.0 */ words = getTotalWordsInFile( indexf, r->filenum ); if (words <= 10) reduction = 10000; /* 10000 * log10(10) = 10000 */ else if (words > 1000) { if(words >= 100000) /* log10(10000) is 5 */ reduction = 50000; /* As it was in previous version (5 * 10000) */ /* rare case - do not overrun the static arrays (they only have 1000 entries) */ else reduction = (int) (10000 * (floor(log10((double)words) + 0.5))); } else reduction = swish_log10[words]; r->rank = (rank * 100) / reduction; return r->rank; }
void mage_best_attack(struct creature *ch, struct creature *vict) { int calculate_mob_aggression(struct creature *, struct creature *); int aggression = calculate_mob_aggression(ch, vict); if (aggression > 75) { // extremely aggressive - just attack hard if (mage_damaging_attack(ch, vict)) return; } if (aggression > 50) { // somewhat aggressive - balance attacking with crippling if (GET_POSITION(vict) > POS_SLEEPING && can_cast_spell(ch, SPELL_WORD_STUN)) { cast_spell(ch, vict, NULL, NULL, SPELL_WORD_STUN); return; } else if (GET_POSITION(vict) > POS_SLEEPING && can_cast_spell(ch, SPELL_SLEEP)) { cast_spell(ch, vict, NULL, NULL, SPELL_SLEEP); return; } else if (!AFF_FLAGGED(vict, AFF_BLIND) && can_cast_spell(ch, SPELL_BLINDNESS)) { cast_spell(ch, vict, NULL, NULL, SPELL_BLINDNESS); return; } else if (!AFF_FLAGGED(vict, AFF_CURSE) && can_cast_spell(ch, SPELL_CURSE)) { cast_spell(ch, vict, NULL, NULL, SPELL_CURSE); return; } } if (aggression > 25) { // not very aggressive - play more defensively if (can_cast_spell(ch, SPELL_DISPEL_MAGIC) && dispel_is_advisable(vict)) { cast_spell(ch, vict, NULL, NULL, SPELL_DISPEL_MAGIC); return; } else if (!AFF2_FLAGGED(vict, AFF2_SLOW) && can_cast_spell(ch, SPELL_SLOW)) { cast_spell(ch, vict, NULL, NULL, SPELL_SLOW); return; } else if (mage_damaging_attack(ch, vict)) return; } if (aggression > 5) { if (can_cast_spell(ch, SPELL_ASTRAL_SPELL)) { cast_spell(ch, vict, NULL, NULL, SPELL_ASTRAL_SPELL); return; } else if (can_cast_spell(ch, SPELL_TELEPORT)) { cast_spell(ch, vict, NULL, NULL, SPELL_TELEPORT); return; } else if (can_cast_spell(ch, SPELL_LOCAL_TELEPORT)) { cast_spell(ch, vict, NULL, NULL, SPELL_LOCAL_TELEPORT); return; } } // desperation - just attack full force, as hard as possible if (mage_damaging_attack(ch, vict)) return; else if (can_cast_spell(ch, SKILL_PUNCH)) perform_offensive_skill(ch, vict, SKILL_PUNCH); else hit(ch, vict, TYPE_UNDEFINED); }