User Tools

Site Tools


user:loggy:castingai

Loggy's Spellcasting AI reverse engineering notes

This is a complicated topic and won't be finished for a while.

Note for me

The battlefield location array seems to be stored with offsets of ((coord2 * 200) + coord 1) * 0x20 Or is it?

When looking for specific units in squares, it's instead (index, 0-7 inclusive + ((coord2 * 200) + coord1) * 8)

Stupid check

A spell is stupid if:

It is an offensive effect number, its aoe is greater than 600, it does not affect enemies only, and either:

  • The enemy has less than 3 mages, and the caster's army size outnumbers the opponent's by more than 20 times
  • The enemy has less than 3 mages, the caster's army size outnumbers the opponent by more than 10 times, and the caster's side has less than 50 troops

"Offensive effect numbers" may include the following:

  • 2, damage [1]
  • 3, fatigue damage [1]
  • 4, cause fear type 1 [1]
  • 7, poison damage [1]
  • 8, remove fatigue? [-1]
  • 9, undocumented
  • 10, bless/buff type 1 [-1]
  • 11, cause affliction [1]
  • 13, heal [-1]
  • 23, buff type 2 [-1]
  • 24, damage x3 vs demon/undead [1]
  • 28, enslave [1]
  • 29, charm [1]
  • 32, damage x3 vs larger
  • 33, damage x2 vs smaller
  • 66, paralysis [1]
  • 67, weakness [1]
  • 72, stream of life [1]
  • 73, damage x2 vs magic being [1]
  • 74, damage (raise as soulless on kill) [1]
  • 96, shatter [1]
  • 97, cause fear type 2 [1]
  • 134, chain lightning [1]
  • 142, salt damage [1]
  • test 43, edge of field summon
  • test 99 petrify [1]
  • test 103 drain life [1]
  • test 105 disbelieve [1]
  • test 107 damage demons only [1]
  • test 128 stun/fascinate [1]
  • test 129 interrupt damage [1]
  • 124, undocumented [1]

It is one of the following effects: Wrathful Skies, Fire Storm, Acid Storm, Astral Tempest, or Meteor Shower, and:

  • The caster outnumbers the enemy more than 20 to 1, and there are less than 3 enemy mages
  • None of the following three conditions are met:
    • Caster's army size ⇐ enemy army size * 10
    • Enemy army size is 50+ units
    • Enemy has greater than two mages

calcbestspell

Spell attribute 745/0x2e9 (found on most vanilla battle wide spells such as Doom, Wind of Death, Arcane Domination, Master Enslave, Army of Rats…) is some kind of checker for requiring a certain number of targets:

  • Check all hostile units on the field. Add 1 for each unit, and 3 for each commander. This is the hostile unit threshold.
  • If conservative gem usage is on: Fatigue component = fatigue cost / 50, random component = closed d8
  • Otherwise, fatigue component = fatiguecost / 200, random component = closed d3
  • Spell is rejected if (1 + random + fatigue) ⇐ hostile unit threshold

Evaluate spell score.

Evaluate spell score

  • Invalid spells (effect >9999) get nothing.
  • Spells that can't be cast due to underwater/land/specific terrain restrictions/lack of sun get nothing.
  • If you don't have the secondary path requirement, you get nothing.
  • Apply communion path boost. Check to see if you have the path requirement to cast the spell, including the use of one gem to boost if applicable. If not, you get nothing.
  • If the spell costs gems and you aren't allowed to spend (or you don't have enough gems to cast the spell, including the 1 gem levelboost), you get nothing.
  • If the spell is some kind of summoning spell (effects 1, 21, 43, 126):
    • Run the unit summoned through resolvemontag, which resolves montags as well as doing a few other replacements such as making ice elementals
    • The spell's score is (unit attack + unit defence + unit strength + unit max hitpoints) * 2.
    • If the unit is ethereal, add max hitpoints * 4.
    • If the unit is a trampler or has an innate fire shield, add max hitpoints * 4.
    • If the unit has a secondshape, evaluate the score of the secondshape and add that too.
    • Multiply the score by the spell's number of effects at the caster's level.
    • If the spell is more than lingering 4, multiply the score by 3. If it is lingering 2 or 3, multiply by 2 instead.
    • If the score is greater than zero:
      • Calculate a new score: ((closed d120 + 40) * old score) / 100, rounded down. If this value is less than 10, set it to be 10.
      • Some stuff I don't understand that cares about the spell range
      • If the spell effect was 126 (call horror), the score is set to d10 exploding or the actual score, whichever is lower.
  • If the spell is undocumented effect 31, do some stuff that looks very similar to the stuff I don't understand for the above summon group
  • If the spell is a battle enchantment or time stop effect:
    • If the enchantment is already active, you get nothing.
    • If the effect is rigor mortis and the caster is undead, the score is exploding d1000 + 150. If the caster is not undead it is 1.
    • If the effect is wailing winds and, the score is exploding d1000 + 100.
    • If the effect is foul air (10), the score is exploding d1000 + 75.
    • If the effect is soul drain, the score is exploding d1000 + 200.
    • If the effect is heat from hell and some unknown criteria, the score is exploding d1000 + 100. If the criteria are not met the score is 0.
    • If the effect is foul vapours, and the same kind of criteria as heat from hell, the score is exploding d1000 + 75.
    • If the effect is fire storm, and yet more of the unknown criteria, score is exploding d1000 + 200.
    • If grip of winter, and yet more unknown criteria, exploding d1000 + 100.
    • If wrathful skies and yet more more unknown criteria, exploding d1500 + 75.
    • If growing fury, exploding d1000 + 75
    • If rain of stones, exploding d5.
    • If astral tempest, exploding d5.
    • If friendly currents, exploding d1000 + 50.
    • If quagmire, exploding d5.
    • If rain and it is raining, nothing. Otherwise, exploding d5.
    • If blood rain, some significantly longer and more complex criteria
    • If relief, exploding d100.
    • If solar brilliance, exploding d5.
    • If ravenous swarm, exploding d5.
    • If acid storm, exploding d5.
    • Any other enchantment, only 1.
  • Other types of spells:
    • If the spell's AoE is 601+ [smaller % aoe is not handled correctly]:
      • Add up spellunitscores for all units on the field
      • Add an exploding d10 to this and use it as the final score
    • If the spell is self target only, just consider the caster.
    • Work out how many units the effect could usefully target (check every square, add up the number of targets in them), depending on whether it is offensive (look at enemies) or nonoffensive (look at friends). Make a copy of this value called the "reduced number of targets"
    • If the effect is NOT a damaging or buff effect (these are 1 and 0 on the offensive effects lists), the reduced number of squares is half this value.
    • If magic duel effects, the reduced number of squares is divided by 5.
    • Start considering every potential square in turn.
    • If reduced squares is 12+: if min(300, reduced squares) ⇐ closed d300 + 9, check this square. [there is a (squares-9)/300 chance to skip any given square]
    • If the square being considered is out of range, skip it.
    • Calc some values based on range, aoe, and precision:
      • If the spell's AoE is 11+ OR (number of effects is 16+ AND the distance from the caster is 5 or less):
        • square spread = 2
        • accurate square weight = (max(1, aoe) * number of effects * 200)/26
        • inaccurate square weight = (max(1, aoe) * number of effects * 100)/26
      • If the spell's AoE is 0 or 1, OR the spell's number of effects is 1: [This means that fists of iron will always fall into this category, and should always account for friendly fire]
        • square spread = 1
        • accurate square weight = max(1, aoe) * number of effects * 20
        • inaccurate square weight = max(1, aoe) * number of effects * 10
      • If the final precision is 90+ OR the distance being aimed at is less than (final prec/3):
        • square spread = 0
        • accurate square weight = 100
        • inaccurate square weight = 0
      • If the distance being aimed is less than (final prec/2):
        • square spread = 1
        • accurate square weight = 36
        • inaccurate square weight = 8
      • All other cases:
        • square spread = 1
        • accurate square weight = 68
        • inaccurate square weight = 4
    • Check a square of tiles containing units. This square is made up of the picked square, plus (square spread) tiles in each cardinal direction [a square with side lengths (2 * square spread) + 1]. For each square within the big square:
      • Sum the unit scores of the things in that square.
      • If there was more than one thing in the square, and the spell affects only 1 person, divide the summed score by the number of units in the square
      • If the square struck was the originally picked square at the centre of the square spread (and not the extra ones around it), add (this square's score * accurate square weight) to the spell score at this location. Otherwise, add (this square's score * inaccurate square weight) to the spell score.
    • If the total score from all the squares is greater than 0:
      • score = max(1, -5 + closed d10 + (score / 100)) [This divides the weighting multiplied scores from the above by 100 regardless of which spread/weightings were selected]
      • If the spell is being aimed less than 10 squares from the caster, and the spell is an offensive effect number (effects that returned 1 on the list somewhere above)
        • score = max(1, (score * 10)/max(2, distance from caster))
      • Otherwise:
        • If the spell's (NOT FINAL) precision is less than 20:
          • score = max(1, (score * 10)/max(10, distance from caster))
        • Other cases:
          • score = max(1, (score * 15)/max(15, distance from caster))
    • Compare the final score casting the spell at this position to the based saved one. If it's better, take this as the new best.
  • Regardless of your spell's aoe or how you arrived at your score up to this point, if it is greater than zero:
    • score = max(1, (open d10 + ((open d40 + 80) * score)/100 - 5)
  • Calculate a final score: (score * 100) / (fatigue from cast, not including encumbrance + 90) and round down.
  • If over 75 fatigue and casting a reinvigoration spell (effect 8 only):
    • Work out <spell's damage> or (caster's current fatigue - fatigue from cast). Add 5x the value of whichever one is less to the final score.
  • If the fatigue from casting would put the caster over 100, and the spell is not a drain life or reinvigoration spell, divide the final score by 3 and round down.

When you actually are about to cast a spell...

  • If you can't cast the spell you're asking to due to missing ability or being mindless (and the spell requires some of these), set the score to some negative value. Otherwise it's 0.
  • Randomspell has a x% chance to set Random favchance to 100 / max(2, number of spell choices)
  • If you have no scripted spell, there is a random favchance% probability to
    • do something I don't understand that governs how randomspell operates (but this isn't as big a question anyway)
  • Scripted spells gain 1000000 to their score
  • If you have more than 50 spell choices and the spell being considered is not scripted, there is a chance to not consider the spell. This is 1% per spell choice available over 50, to a max of 50% at 100+ choices.
  • If the spell costs a game AND it's not scripted AND gem usage is not allowed, set score to negative because you're not allowed to spend gems.
  • Check #aibadlvl and set score to negative if it fails
  • If the spell wasn't scripted, check for #ainocast and set score to negative if it exists
  • If the spell wasn't scripted, check for stupidity (as per above) and set to score to negative if stupid
  • Run evalspell and use that as the spell score
  • After this, evaluate item spells separately.
  • Then do the actual casting of whatever you decided to cast, wherever you decided to cast it

spellunitscore

This scores how effective the AI thinks a spell is against a given victim.

Friendly bias: 1 if the victim is the same nation as you, else -1. This seems backwards, but is the reason this is usually multiplied by negative numbers

Early buff bias:

  • If combat round 2+, this is always 1.
  • In assassination, this is 2 - round
  • In other cases, this is (2 - round)*2

Self buff bias is 2 if the caster is the spell's target AND it is before round 2, otherwise it is 1

Work out spell's damage.

Conditional damage modifications:

  • If damage x3 vs undead/demon, mult by 3 if victim is demon or undead
  • If damage x2 vs demon, mult by 2 if victim is demon
  • If undocumented effect 124, mult by 2 if victim is undead
  • If salt damage, set damage to 0 if victim has no salt vuln
  • If x2 vs magic beings or x2 vs magic being unlife damage, mult by 2 if victim magic being
  • If shatter, set damage to 0 if victim not inanimate
  • If disbelieve dmg, set damage to 0 if victim not an illusion
  • If petrification, set damage to 0 if victim is a stone being
  • If magic duel, set damage to 0 if victim has no astral level
  • If fear, set damage to 0 if victim's base morale is 20+ or victim is gone berserk
  • If fatigue damage, divide damage by 2 if victim is 130+ fatigue
  • If polymorph, set damage to 0 if victim has polymorph immunity or is already the creature type the spell is trying to turn them into

Spec value modifications:

  • If sacreds only, zero damage if victim is sacred or prophet or god
  • If the spell is a fire effect, subtract victim's fire res
  • If the spell is a cold effect, subtract victim's cold res
  • If the spell is a poison effect, subtract victim's poison res
  • If the spell is a shock effect, subtract victim's shock res
  • If the spell doesn't affect mindless and the victim is mindless, set damage to 0
  • If the spell doesn't affect void sanity and the victim has it, set damage to 0
  • If the spell affects animals only and the target is not an animal, set damage to 0
  • If the spell affects demons/undead only and the target isn't, set damage to 0
  • If the spell doesn't affect undead and the target is, set damage to 0
  • If the spell doesn't affect demons and the target is, set damage to 0
  • If the spell affects magic beings only and the target isn't, set damage to 0
  • If the spell affects air breathers only and the target isn't, set damage to 0
  • If the spell does fatigue damage and the target is 0 enc, set damage to 0 [THIS ONE MAY BE CONTROVERSIAL]
  • If the spell affects enemies only and the target is friendly, set damage to 0
  • If the spell affects friendlies only and the target is hostile, set damage to 0

If the effect is cause affliction:

  • If the spell sets things on fire and the victim can't be set on fire, set damage to 0
  • If the spell freezes things and the victim can't be frozen, set damage to 0
  • If the spell blinds things and the victim has blind fighting, set damage to 0

If the effect is enslave or charm, and the victim cannot be charmed/controlled, set damage to 0

If the spell doesn't affect floaters/flyers and the victim is, set damage to 0.

If your damage got reduced below one by any of the above, return a score of 0 and abort this function. [practically, this means that elemental damage > resist is a requirement for the casting AI to allow casting elemental evos on things]

For the following effects:

  • 4 fear
  • 10 buff type 1
  • 11 cause affliction
  • 15 returning
  • 17 temp morale boost
  • 23 buff type 2
  • 27 magic duel
  • 54 polymorph
  • 81 battlefield enchantment
  • 101 age caster
  • 108 banish to other plane
  • 116 swallow if smaller
  • 121 swallow size 1+2 only
  • 133 time stop
  • 500-699 add effect to effect slots

Your damage is considered to be 999. For everything else:

  • If spell is AN, add 1 to damage.
  • If spell is AP, add (1 - (victim's prot/2))
  • Otherwise, add (1 - victim's prot)

If the current damage value is greater than (victim chassis max hp + 5), set it to that value [shouldn't this be current hp instead?]

If the spell offers either (or both) an easy or hard MR check:

  • If the spell offers an easy mr check, consider victim's mr as 4 higher.
  • If the spell does not offer a normal MR check, and (user's pen bonus + 8) ⇐ (victim's MR + 4), multiply damage by 2/3. [shouldn't this be banded like regular MR? This means that easy MR soul slay will be preferred to normal soul slay vs high MR targets…]
  • If the spell offers a normal MR check, do the first one that applies:
    • if (mr >= pen bonus + 23), divide damage by 24
    • if (mr >= pen bonus + 20), divide damage by 12
    • if (mr >= pen bonus + 17), divide damage by 6
    • if (mr >= pen bonus + 14), divide damage by 3
    • if (mr >= pen bonus + 11), divide damage by 2
    • if (mr >= pen bonus + 8), multiply damage by 2/3
    • Otherwise, do nothing to damage

If MR check for half damage, multiply damage by 2/3 [shouldn't this be banded?]

If spell is defence negate OR (is not AoE and does not ignore shields), multiply damage by 2/3 [couldn't these be split and done a bit better?]

Look up the victim's chassis' strength score, and subtract 10 from it, and add the spell's damage. If the result is less than 1, consider it to be 1. This is the "strength value" going to be used for some effects later.

If the effect is buff type 1:

  • If the victim has all the buffs this spell applies already, return 0
  • If the spell has blessing:
    • The score is (victim's HP * friendly bias * early buff bias * bless score)/300
    • Bless score is calculated as:
      • This is quite long and probably not very interesting, but it depends entirely on what your bless contains (and what's more cached into a global array for some reason)
  • If the spell contains luck, and the victim is neither inanimate nor undead:
    • score = max(10, (55 - victim's current hp/2)) * friendly bias * early buff bias * self buff bias
  • If the spell contains +prec:
    • If the unit's fatigue is 71+, score is 1
    • If the unit has no non-holy paths or 70+ fatigue, score is 5 * friendly bias * early buff bias
    • Otherwise, it is 30 * friendly bias * early buff bias
  • If the spell contains airshield:
    • If the enemy has 0 units with ranged weapons, the score is simply the friendly bias
    • If there is a storm, (victim's current HP)/2 * friendly bias * self buff bias * early buff bias
    • Otherwise, victim's current HP * friendly bias * self buff bias * early buff bias * 3
  • If the spell contains barkskin and the recipient doesn't have stone or ironskin:
    • If the victim's chassis base natural protection is less than 8, victim current HP * friendly bias * self buff bias * early buff bias * 2
    • Otherwise, (victim current HP/10) * friendly bias * self buff bias * early buff bias
  • If the spell contains stoneskin and the recipient doesn't have ironskin:
    • If the victim's chassis base natural protection is less than 13, victim current HP * friendly bias * self buff bias * early buff bias * 4
    • Otherwise, (victim current HP/2) * friendly bias * self buff bias * early buff bias
  • If the spell contains ironskin:
    • If the victim's chassis base natural protection is less than 17, victim current HP * friendly bias * self buff bias * early buff bias * 8
    • Otherwise, (victim current HP) * 2 * friendly bias * self buff bias * early buff bias
  • If the spell contains regeneration, and the recipient's current regeneration value is less than 100%:
    • victim MAXIMUM HP * friendly bias * early buff bias * 3
  • If the spell contains the legions of steel buff, and the recipient has some armor:
    • (victim current HP/2 + victim prot*3) * friendly buff bias * early buff bias
  • If the spell contains the strength buff:
    • victim current hp * friendly bias * early buff bias
  • If the spell contains the heat aura buff
    • victim current hp * friendly bias * early buff bias
  • If the spell contains piercing resistance, and the unit does not have it (innately or from buff) already:
    • victim current hp * friendly bias * early buff bias * 3
  • If the spell contains bludgeon resistance, and the unit does not have it (innately or from buff) already:
    • victim current hp * friendly bias * early buff bias * 3
  • If the spell contains slashing resistance, and the unit does not have it (innately or from buff) already:
    • victim current hp * friendly bias * early buff bias * 3
  • If the spell confers gone berserk:
    • If the victim has magic paths, score is friendly bias * -100 [THIS MAKES IT BE TARGETED AS A VERY OFFENSIVE EFFECT]
    • If the victim has no ranged weapons, score is victim current HP * friendly bias * 3
    • Otherwise, score is (victim current HP / 5) * friendly bias
  • If the spell confers pain transfer:
    • score = min(1, (number of available blood slaves - 5) * 3) * friendly bias * self buff bias * early buff bias
    • If the caster's skill in the path is less than 2, divide score by 2 (rounded up)
  • If the spell confers +10 Poison Res, and the recipient has less than 20 PR:
    • If foul vapors is cast, victim's current HP * friendly bias * self buff bias * early buff bias * 3
    • If the enemy has any nature mages or creatures with poison aura, victim's current HP * friendly bias * self buff bias * early buff bias
    • Otherwise, just friendly bias
  • If the spell confers +5 fire res, and the recipient has less than 20 FR:
    • If fire storm and/or heat from hell are cast, victim's current HP * friendly bias * self buff bias * early buff bias * 4
    • If the enemy has any fire mages or creatures with fire shield (innate or buffed), victim's current HP * friendly bias * self buff bias * early buff bias
    • Otherwise, just friendly bias
  • If the spell confers +5 shockres, and the recipient has less than 20 SR:
    • If wrathful skies is cast, victim's current HP * friendly bias * self buff bias * early buff bias * 4
    • If the enemy has any air mages, victim's current HP * friendly bias * self buff bias * early buff bias
    • Otherwise, just friendly bias
  • If the spell confers +5 cold res, and the recipient has less than 20 CR:
    • If grip of winter is cast, victim's current HP * friendly bias * self buff bias * early buff bias * 4
    • If the enemy has any water mages or creatures with chill aura (buffed only?), victim's current HP * friendly bias * self buff bias * early buff bias
    • Otherwise, just friendly bias
  • If the spell grants chill aura
    • If all enemies have cold resistance, score = 1
    • If the spell is self cast and the caster is a communion master, score = 1
    • score = (victim's current hp * friendly bias)/3, to a minimum of 1
    • add the cold aura buff to the victim
    • add the spellscore of "area10 cold dmg 3" to this [this is almost certainly the cause of why things refuse to cast it]
    • remove the cold aura buff to the victim [this is so the victim gets to see what their cold res would be for the spellscore]
  • If the spell confers communion master, and the victim is not already a communion master:
    • score = friendly bias
  • If the spell confers communion slave, and the victim is not an innate caster, a com slave already, and there are friendly non-comslave mages in the battle:
    • score = friendly bias
  • If the spell confers flight and the victim isn't flying already:
    • score = friendly bias
  • If the spell confers quickness:
    • score = victim's current HP * friendly bias * self buff bias * early buff bias * 4
  • If the spell confers AP weapons, and the recipent has a weapon:
    • score = (victim's current HP + attack skill) * friendly bias * early buff bias
  • If the spell confers astral weapons, and the recipient has a weapon:
    • score = (victim's current HP + attack skill * 2) * friendly bias * early buff bias
  • If the spell confers life after death:
    • score = friendly bias * 60
  • If the spell confers holy avenger:
    • score = victim current HP * friendly bias * early buff bias * 5
  • If the spell confers enlarge, and the recipient's size < 6:
    • score = victim's current HP * friendly bias * self buff bias * early buff bias * 3
  • If the spell confers sermon of courage +1 mor, and the recipient's morale < 20:
    • score = victim's current HP * friendly bias
  • If the spell confers flaming arrows and the recipient has a ranged weapon:
    • score = victim's current HP * friendly bias * early buff bias
  • If the spell confers +4 mr:
    • If the enemy has no mages, score = friendly bias * self buff bias * early buff bias * 2
    • Otherwise, score = victim's current HP * friendly bias * self buff bias * early buff bias
  • If the spell confers etherealness and the victim isn't ethereal innately:
    • score = victim's current HP * friendly bias * self buff bias * early buff bias * 10
  • If the spell confers protective force and the victim has less than 17 prot force already:
    • score = victim's current HP * friendly bias * self buff bias * early buff bias * 5

If the spell effect is buffs type 2:

  • If the victim has all the buffs this spell confers already, return 0.
  • If the spell confers twist fate:
    • score = max(10, 20 - victim's current HP/2) * friendly bias * self buff bias * early buff bias
  • If the spell confers invuln 25:
    • If the recipient's prot < 22, score = min(45000, victim current HP * friendly bias * self buff bias * early buff bias * 50)
    • Otherwise, score = friendly bias
  • If the spell confers invuln 15 and does not confer invuln 25:
    • If the recipient's prot < 12, score = min(45000, victim current HP * friendly bias * self buff bias * early buff bias * 50)
    • Otherwise, score = friendly bias
  • If the spell confers invuln 15 to wolves only, and neither of the two above invuln effects, and the victim is a wolf:
    • If the recipient's prot < 13, score = min(45000, victim current HP * friendly bias * self buff bias * early buff bias * 50)
    • Otherwise, score = friendly bias
  • If the spell confers power of the spheres:
    • If the recipient has no non-holy paths, score = 0
    • Otherwise, score = friendly bias * self buff bias * early buff bias * 25
  • If the spell confers mossbody:
    • If the recipient has less than 50 PR, score = victim's current HP * friendly bias * self buff bias * early buff bias * 2
    • Otherwise, score = victim's current HP * friendly bias * self buff bias * early buff bias * 5
  • If the spell confers soul vortex:
    • If the recipient is the caster, and is a communion master, score = 1
    • TODO: this is complicated but it is looking at positions of units, likely penalised for friendlies and + for enemies?
  • If the spell confers charge body 20AN:
    • score = friendly bias * 30
  • If the spell confers fire shield and the recipient has no fire shield already:
    • ? if the enemy has both fire mages and fire resistant units, score = friendly bias
    • ? if the enemy has only one of these things, score = current HP * friendly bias * early buff bias
    • Otherwise:
      • If the recipient has 20+ HP:
        • score = max(current HP - 8)*7, ?? prot - 150) * friendly bias * early buff bias
      • Else:
        • score = max(current HP - 8)*7, ?? prot - 150)/3 * friendly bias * early buff bias
  • If the spell confers astral shield:
    • If the recipient has 20+ HP:
      • score = max(current HP - 8)*7, ?? prot - 150) * friendly bias * early buff bias
    • Else:
      • score = max(current HP - 8)*7, ?? prot - 150)/3 * friendly bias * early buff bias
  • If the spell confers water shield:
    • score = (current HP+5) * friendly bias * early buff bias * 2
  • If the spell confers mistform:
    • score = current HP * friendly bias * early buff bias * 5
  • If the spell confers swiftness, and the recipient is not immobile:
    • score = ((current HP + 1)*friendly bias * early buff bias)/2
  • If the spell confers hell power:
    • score = current HP * friendly bias * early buff bias
  • If the spell confers fire power:
    • score = current HP * friendly bias * early buff bias * self buff bias * 20
  • If the spell confers water power:
    • score = friendly bias * early buff bias * self buff bias * 20
  • If the spell confers earth power:
    • score = friendly bias * early buff bias * self buff bias * 20
  • If the spell confers reinvigoration and the recipient does not have earth power:
    • If the recipient has no nonholy paths, score = friendly bias * early buff bias * self buff bias * 3
    • Otherwise, score = friendly bias * early buff bias * self buff bias * 15
  • If the spell confers regeneration:
    • score = MAX HITPOINTS * friendly bias * early buff bias * 4
  • If the spell confers storm power:
    • If there is no storm, score = 1
    • Otherwise, score = friendly bias * early buff bias * self buff bias * 20
  • If the spell confers nature power:
    • score = current HP * friendly bias * early buff bias * 10
  • If the spell confers unholy power:
    • score = current HP * friendly bias * early buff bias
  • If the spell confers fear:
    • score = current HP * friendly bias * early buff bias * 4
  • If the spell confers phoenix pyre:
    • If the caster is the recipient and they are a communion master, score = 1
    • Otherwise, score = friendly bias * early buff bias * 150
  • If the spell confers mirror image:
    • score = max(5, 50 - current HP) * friendly bias * early buff bias
  • If the spell confers awakened tattoos and the recipient has tattoos:
    • score = friendly bias * early buff bias * 25

If the spell effect is cause affliction:

  • If the victim has all afflictions caused by this spell, return 0
  • If the spell causes disease, the victim is not undead, the victim is not a demon, and the victim has less than 100 disease resistance:
    • score = current HP * - friendly bias
  • If the spell causes curse and the victim is not a blood slave:
    • score = current HP * - friendly bias
  • If the spell causes plague:
    • score = current HP * - friendly bias * 10
  • If the spell causes curse of stones and the victim is not a blood slave:
    • score = current HP * - friendly bias * 3
  • If the spell causes entangle and the victim is not a blood slave:
    • score = current HP * - friendly bias * 2
  • If the spell causes web:
    • score = current HP * - friendly bias * 2
  • If the spell causes netting:
    • score = current HP * - friendly bias * 2
  • If the spell causes rage:
    • score = current HP * - friendly bias * 5
  • If the spell causes confusion:
    • score = current HP * - friendly bias * 5
  • If the spell causes decay:
    • score = current HP * - friendly bias * 4
  • If the spell causes slow:
    • score = current HP * - friendly bias * 4
  • If the spell causes bleeding:
    • score = current HP * - friendly bias * 3
  • If the spell causes broken armor:
    • score = armor prot * - friendly bias * 3
  • If the spell causes rusted equipment:
    • TODO: This is quite complicated (likely looking for iron armour parts)
  • If the spell causes blind:
    • score = current HP * - friendly bias * 5
  • If the spell causes chest wounds:
    • score = current HP * - friendly bias * 2
  • If the spell causes limps:
    • score = current HP * - friendly bias * 2
  • If the spell causes cripple:
    • score = armor prot * - friendly bias * 4
  • If the spell causes earthgrip:
    • if victim's str is 16: score = current HP * - friendly bias * 2
    • otherwise: score = current HP * - friendly bias * 4
  • If the spell causes fire bonds:
    • score = current HP * - friendly bias * 3
  • If the spell causes false fetters:
    • score = current HP * - friendly bias * 2
  • If the spell causes slime:
    • score = armor prot * - friendly bias
  • If the spell sets things on fire, and the victim can be set on fire:
    • score = prot * - friendly bias * 3 + 5
  • If the spell freezes things, and the victim can be frozen:
    • score = prot * current HP * - friendly bias
  • If the spell shrinks victims:
    • score = current HP * - friendly bias * 3
  • If the spell causes sleep:
    • score = (current HP * - friendly bias * 3)/2

For the following effects:

  • 2 damage
  • 24 x3 vs undead or demons
  • 73 x2 vs magic beings
  • 96 shatter damage
  • 99 petrify
  • 105 disbelieve dmg
  • 107 x2 vs demon
  • 109 capped dmg
  • 124 undocumented
  • 134 chain lightning
  • 142 salt damage

score = strength value * - friendly bias * 10

  • For unlife damage or unlife damage x2 vs magic beings:
    • score = strength value * - friendly bias * 10
    • If the victim is not inanimate and not undead, add 25
  • For magic duel:
    • score = min(10, strength value) * - friendly bias
  • For drain life:
    • score = caster's fatigue + (strength value * - friendly bias * 10) + max(0, 10 * (caster's max hp - caster's current hp))
  • For fear:
    • If the victim is already routed, score 0
    • Otherwise, score = strength value * - friendly bias * 5
  • For poison HP damage and capped poison damage:
    • score = strength value * - friendly bias * -8
  • For fatigue damage:
    • score = (strength value * - friendly bias * victim max HP)/10, rounded down
  • For interrupt damage:
    • If the victim has no magic skill, score 0 [mundane commanders casting spells via items will not be targeted]
    • score = (victim's max HP * (strength value + 25) * - friendly bias) / 32
  • For weakening spells:
    • score = (9 - victim's max HP * friendly bias * strength value)/10 [friendly bias is negative when aimed at enemies]
  • For spells that directly add age:
    • score = (19 - victim's max HP * friendly bias * strength value)/20) [friendly bias is negative when aimed at enemies]
  • For paralyze damage:
    • If the victim is already paralyzed for 10+ ticks, OR (strength value/2) is less than paralysis ticks:
      • score = 2
    • otherwise, score = (victim current HP * - friendly bias * strength value)/4
  • For stun/fascination:
    • If the victim is stun immune, score 0
    • If the victim is stunned for 2000-4999 ticks, score = 2
    • If the victim is stunned for 5000+ ticks, score = 0
    • Otherwise, score = victim current HP * - friendly bias * 2
  • For effects 500-599 (capped add unit effect) inclusive:
    • If the victim does not have the effect already:
      • If the spell confers damage reversal, score = victim current HP * friendly bias * 15
      • If the spell confers desiccation, score = victim current HP * - friendly bias * 2
      • If the spell confers anything else, score = 1
    • If the victim has the effect already at some magnitude [NOTE: this checks TOTAL magnitude already, not what is in slots, which means that a unit that has 10 FR will refuse to put +10FR into their slots with these spells, despite the fact units will happily use the +5 buff until 20+]:
      • If the spell is trying to add less magnitude than the effect has already, score = 0
      • If the spell confers damage reversal, score = victim current HP * friendly bias * 10
      • If the spell confers desiccation, score = victim current HP * - friendly bias
      • If the spell confers anything else, score = 1
  • For effects 600-699 (uncapped add unit effect) inclusive:
    • If the spell horror marks:
      • score = victim current HP * - friendly bias
    • If the spell applies encase in ice, and the target's encase in ice value is less than 100:
      • score = max(2, victim prot - 17) * victim current HP * - friendly bias
      • If the victim already has any amount of encase in ice, score = above score / (encase in ice value / 20 + 2)
    • Any other case scores 0
  • For stream of life:
    • score = victim current HP * - friendly bias * 7
  • For enslave and charm:
    • If the victim cannot be charmed, score = 0
    • score = strength value * - friendly bias * 20
  • For polymorph:
    • score = max(1, strength value - 5) * - friendly bias * 10
  • For plane banishment:
    • If the victim has no void sanity and there is a source of astral fetters on the battlefield, score = 0
    • Otherwise, score = victim current HP * - friendly bias * 100
  • For healing spells:
    • score = victim's missing hp * friendly bias * 10
  • For fatigue removal spells:
    • score = (min(strength score, target's fatigue) * friendly bias)/2
  • For the unused temp morale boost effect:
    • If the recipient isn't routed:
      • score = (5 - recipient's current fear morale modifier * friendly bias)
  • For returning:
    • If some (TODO: what is this - looks like being in other planes) criteria, you get 0. Otherwise, 1.
  • For blink:
    • score = 1
  • For either kind of armour damage spells:
    • TODO as with rust, insufficient current knowledge of how items and armor are handled
  • Any other effects score 0

If the final score > 3, the victim is an enemy of the caster, and is immobilized, divide final score by 2.

If no nation has wholly routed:

  • If final score > 3 and the victim is routing, divide the score by 2, and use this (to a minimum of 3)

If a nation HAS routed:

  • If the spell targets an enemy and its score was positive, multiply its score by 3
user/loggy/castingai.txt · Last modified: 2023/02/24 19:01 by loggy