• Tutorials

  • Home
  • Combat Artificial Intelligence Scripting

    The Dungeon Craft engine provides a method of selecting the best action for any combatant that is not under player control. Dungeon Craft creates a list of all possible 'Actions' when a combatant's turn arrives. It then calls the script in AIScript.BLK to determine which of the actions is 'best'.

    'All possible Actions' doe not include those actions that are clearly detrimental to the combatant of other combatants friendly to him. The following actions are eliminated by the engine before the script is run.


    The scripts are written in a simple Forth language. There are two reasonable ways of going about the selection:

    For now, until someone can show that the first option is better, the engine will adopt the second option.

    Each possible action has the following functions defined that provide information about that action. All the functions return a single integer unless otherwise noted. Each function name has a prefix denoting the type of object to which it refers:

    Before using a function which references data in one of the actions, you must have identified which action of the two you are referring to; action A or action B. You accomplish this with the functions “A” and “B”. After using function “A”, for example, all references to data in an action will refer to action A. Likewise, references to a combatant or his weapons will refer to either the active (attacking) combatant or to the target combatant. You should use the functions “Me” or “He” to identify which combatant you are referring to.

    The script will receive two possible actions at a time. They are called 'A' and 'B'. Each of the functions listed above can retrieve information from either of A or B by preceding the function with the word “A” or “B”. They can also retrieve information from either the attacker or the target by preceeding the function with the word “Me” or “He. For example:
    : CompareDamage Me A W:Damage B W:Damage - ;

    This function would return a positive number if the weapon damage of action A was greater than the weapon damage of action B, zero if they are the same, and a negative number if B is greater. If you refer to these very often, you might want to define functions to retrieve them more directly. For example:
    : DamageA Me A W:Damage ;
    : DamageB Me B W:Damage ;


    Explanation of data retrieved by the functions:

    Action Types – Result of function A:T
    The following constants are defined for the possible action types:
    0 CONSTANT A:T:Unknnown
    1 CONSTANT A:T:SpellCaster
    2 CONSTANT A:T:Advance
    3 CONSTANT A:T:RangedWeapon
    4 CONSTANT A:T:MeleeWeapon
    5 CONSTANT A:T:Judo
    6 CONSTANT A:T:SpellLikeAbility
    Weapon Types – Result of function W:Type

    The following constants are defined for the possible types of weapon:

    C:State


    How the engine goes about using the scripts

    1. Clear the list of combatants and available actions
    2. Look at every combatant. Determine his state – friendly, dying, etc. List his shields. Record his location. Add him to the list. The 'Thinking' combatant is always the first in the list.
    3. List the 'ready-able' weapons for the 'Thinking' combatant. For each weapon, determine such things as weapon type (throwing, etc), damage dice, priority, ammotype, etc.
    4. List possible ammo for the 'thinking' combatant. Determine its characteristics such as type, damage dice, rate-of-fire, etc.
    5. List all possible attacks for the monster. Compute damage for each.
    6. List all possible cells that the 'thinking' combatant can reach by walking.
    7. For each combatant (other than himself) list all possible actions for each of the attacker's weapons (or no weapon).
      • If the weapon is a 'spellcasting' weapon, call the 'SpellCasterFilter' to see if the action should be retained as a possible action.
      • If the weapon has a 'SpellLikeAbility' then call the SpellLikeAbilityFilter to see if the action should be retained as a possible action.
      • If the action is a Melee action (adjacent target) then call the MeleeWeaponFilter to determine if the action should be retained as a possible action.
      • If the action is a ranged action then for each type of ammo (or no ammo) call the RangedWeaponFilter to determine if the action should be retained as possible action.
      • If the action is a 'move' (walk; advance) action then the AdvanceFilter is called to see if the action should be retained as a possible action.
      • If the action is an attack without weapon then the JudoFilter is called to see if the action should be retained as a possible action.

    After all the 'possible' actions have been listed the engine calls the 'Think' script to compare them in pairs in order to find the best. This assumes that the comparisons are transitive: *IF* action A is better than action B *AND* action B is better than action C *THEN* action A is better than action C.

    The best action is the one that is taken. If there are no possible actions then the combatant guards.