                 /----------------------------------------\
                <       Adding new skill-based powers      >
                 \----------------------------------------/

    === Introduction ===

    This is very much in the same vein as adding a racial/extra power, but has to
    be tied into skills, and we're defining more than one spell at once. You should
    have read the scripting introduction and
    racial power tutorial before going much further. Both of the above files
    contain some fairly fundamental information which you will find necessary for
    full understanding of this file.

    === Getting started ===

    Open construc.lua (you have downloaded the example scripts from
    http://www.moppy.co.uk/angband.htm, haven't you?). The idea behind this
    script is that it adds a skill which affects you ability to build/knock down
    stuff. It treats the equivalent of stone-to-mud and trap-door destruction
    spells as if they were "building skills". It also adds quite a few high-level
    'spells' which do funky things like carving out corridors and chambers in a
    single turn, and building doors and stuff. Just think of it as if the person
    who has plenty of skills in this area would be a builder-type with lots of
    strength and constitution...

    In order to add these powers we're going to edit the s_info.txt file which
    lives in the edit folder, and add a new skill, underneath the 'misc' tree,
    called construction.  The powers will then be accessed through the 'm' menu, in
    a similar way to mindcraft or alchemy skills or such. (That is, no books are
    needed to cast them, as we're treating them as a craft that has been  learnt,
    rather than spells.) Our fist line of the script file reads:

    SKILL_CONSTRUCT = 57

    This merely links the skill index that we'll be defining in s_info.txt to this
    file. We'll come back to this at the end of the tutorial.

    constructor_powers = add_magic

    In a similar way to the add_power function we called when we added the
    Phoenix racial ability, this line calls a special function which we use to
    define new skills. It follows a very specific, but easy to understand form. It
    starts with a brace, which indicates the add_magic function will be storing
    these values in a table. Don't worry about this too much, but understand that a
    table starts and ends with braces { and } respectively. Each key
    (or field name) takes the format "key" = value, (the comma is
    important!).

      ["fail"] =      function()
                      msg_print("You decide now is a good time for a cuppa")
      end,
      ["stat"] =      A_STR,
      ["get_level"] =         function()
                      return get_skill_scale(SKILL_CONSTRUCT, 50)
      end,
      ["spell_list"] =

    "fail" is a function that is called whenever you ##fail to cast the
    spells##. Here it does nothing spectacular.
    "stat" defines the stat used to cast the spells. Here it is strength.
    Any other stat can be used, prefix it with A_.
    "get_level" is used to determine the level of the spell. It's associated
    with spells that increase in power the more points that are invested in the
    associated skill. I know that's not terribly clear, I'll come back to it in a
    moment.
    "spell_list" is just that, a list of all the spells.
    Each of these four properties within the table must end with a comma. If a
    function is defined in the property itself then we add the comma after the
    closing end. Again compare with conmstruct.lua to see it. Any line NOT
    ending wit a comma will cause a lua error on startup, probably of the type
    '}' expected to close '{' at line <whatever>.

    === The spell list ===

    Each spell, within the "spell_list" key has it's own set of properties
    that we need to define from a sub-table so we open another set of braces to
    start the spell list, and then a third set of braces to start the first spell.
    So with all this, our first spell looks like:

      ["spell_list"] =
      {
              {
                      ["name"] =
                      ["desc"] =
                      ["mana"] =
                      ["level"] =
                      ["fail"] =
                      ["spell"] =
                      ["info"] =
              },

    "name" is, as you would expect, the name of the spell, as you want it to
    appear in the spell list when choosing a spell. The maximum number of
    characters for this is 29.
    "desc" is the description received when you hit the capital letter of
    that spell in the menu. (i.e., press 'a' to cast the first spell, but press 'A'
    to receive info about the first spell.
    "mana" is the amount of mana required to cast the spell.
    "level" is the level required to use that spell (that's level of the (in
    this case construction) skill, not character level!).
    "fail" is base fail rate.
    "spell" is the function that is executed when the spell is cast. Note
    that it MUST take the form function() blah end even if you're calling
    a C function direct. If you have a look at the end of the file, you'll see the
    "rebuild dungeon" spell which is identical to the "alter_reality" spell.
    However, rather than reading "spell" = alter_reality(), it reads:

    ["spell"] = function()
              alter_reality()
    end,

    which appears to be a long way round to do the same thing, but this is how it
    must be done.

    In a  similar way, the "info" key must begin with a function()
    and return the value of what is to be displayed along side the spell name,
    level and mana in the spell list. The maximum  number of characters that can be
    displayed here is dependent on the width of the users screen,  but try and keep
    it under 12 if you can, as this will fit in a standard 80x24 terminal screen.
    The first character will need to be a space otherwise you'll have the info line
    squashed right up against the fail rate and it will look odd. If you wish to
    have this part blank in the spell list, you still need to return a value, so
    just a single space will do : return " "

    All of these keys are repeated for each spell. with each spell in it's own
    table (therefore, it's own set of braces). Again, check the lua file for
    clarification.

    When entering the spells in the "spell_list", you must take care to specify
    them in the order which they are gained, otherwise they display incorrectly in
    the spell list.

    You should by now be experienced enough to understand most of what's going on
    in the actual spell functions (especially if you dig around in the source a
    bit, and check out Chris Hadgis excellent spell.pkg helper
    files. I'm not going to go through the whole file line by line, as this is
    something you should do yourself, figuring out what's going on. I'm going to
    examine a few of the things we haven't covered before though, so pay attention.

    === The get_level() function ===

    Probably one of the most important functions that you see reappearing in the
    file is the get_level() function. All this does is return the numerical
    value of the power that is given as the first argument. So get_level
    (constructor_power) will return the current level of the constructor power.
    Given that the level of this is taken directly from the construction skill, (we
    defined that in the "get_level" key, by saying get_skill_scale
    (SKILL_CONSTRUCT, 50) ) it will return the value of your construction skill.
    constructor_power is the name of the whole power, we named it thus on
    the second line of the script!

    get_level takes the following arguments: get_level(power, max,
    min). The power is obviously which power we're taking the value from, and the
    max and min allow you to define boundaries for the spell. For instance the
    current maximum value that get_level(constructor_power) can return is
    50, as that is the maximum number of skill points you can have in that skill.
    If you were using this as the basis for the damage of a low-level bolt spell,
    you might decide that having a damage of 50 would be too much (unlikely, but
    still possible). You could therefore define a maximum value of 20 so that when
    the value of the construction skill was over 50, the maximum value for
    damage of that spell would be 20. To achieve this you'd have:
    get_level(constructor_power, 20). In a similar way, you can force the
    minimum value of the spell to be higher than the actual construction skill
    level, with a get_level(constructor_power, 50, 15). This would be useful
    say for spells that you wanted to be available when the construction skill
    level reaches 10, but for whom you wanted a (for example) base damage of 15
    right from the word go. These re-scale values rather than capping them!

    You can leave out the minimum value as I have done above. You can also leave
    the maximum value out (it will default to 50). If you want to specify a minimum
    value though, you MUST specify a maximum value as well.

    As you have hopefully been able to tell, the get_level() function
    enables us to have spells that increase in usefulness as you gain levels. Lets
    take the "Dismantle" spell. The function in the "spell" key is as
    follows:

    function()
      local ret, dir, dam

      if (get_level(constructor_powers, 50) >= 11) then
              ret, dir = get_aim_dir();
              if (ret == FALSE) then return end
              fire_beam(GF_KILL_TRAP, dir, 1)
      else
              fire_ball(GF_KILL_TRAP, 0, 1, 1)
      end
    end,

    The if statement is obviously what really interests us here. You'll
    notice that this has the amendment of an else clause, which the if
    statement we used in the previous tutorial did not. As you would expect, if the
    condition on the first line of this statement is met, then the instructions
    immediately below it are carried out. If the condition is not met, then the
    statements that follow the else are executed.

    Coming back to the get_level function, we learnt from above, that the
    get_level part of this function translates as, "if the value of the
    construction_power level (which happens to be identical to the construction
    skill level) is greater than or equal to 11, cast a beam of trap disarming in
    the specified direction. (The first part of this is all straightforward,
    getting a direction, and cancelling correctly if the player presses 'ESC'.)
    Otherwise, cast a ball of trap disarming with a radius of one, centred on the
    player."

    In the same way, as you look at the construc.lua file, you will see that
    get_level() is used many times in this way, to increase the power of
    detection spells, to change bolt spells to ball spells, to keep a constantly
    increasing damage going, and so on.

    === Elseif's and things ===

    If you want to provide more than one alternative condition, in an
    if-then-else statement, you can use elseifs which do what you
    might expect. Take a look at the first spell, "Survey area", for an example of
    this:

    if (get_level(constructor_powers, 50) >= 28) then
      wiz_lite()
    elseif (get_level(constructor_powers, 50) >= 15) then
      map_area()
      detect_traps(DEFAULT_RADIUS)
    elseif (get_level(constructor_powers, 50) >= 5) then
      detect_traps(DEFAULT_RADIUS)
      detect_stairs(DEFAULT_RADIUS)
      detect_doors(DEFAULT_RADIUS)
    else
      detect_stairs(DEFAULT_RADIUS)
      detect_doors(DEFAULT_RADIUS)
    end

    If the level of constructor powers is greater or equal to 28, then the function
    wiz_lite() is performed, and no other part of the if statement is
    executed. wiz_lite() is just the enlightenment spell. If it is less than
    28, the next condition is examined: that if the level of constructor powers is
    greater than or equal to 15, then map_area()(Magic mapping) and detect
    traps are called. If the level of constructor power is less than 15, it moves
    onto the next condition, which says that if the level of constructor power is
    greater than 5, then detect stairs, traps and doors. If none of these
    conditions are met,(that is, if the level of construction skill is less than 5)
    then we just detect doors and stairs.

    You'll note that each of the detection spells includes a DEFAULT_RADIUS
    constant. You could change this to a numerical value, or a variable defined
    somewhere else in your script. eg detect_traps(2) would detect traps
    with a radius of 2 centred on the player.

    === Registering the skill type ===

    This is what we do at the end of the file, and is what ties the powers we've
    defined to the action of pressing the 'm' key in game. Once more we're calling
    a special function add_mkey() which takes it's arguments for a table.
    There are only two keys in this table though which keeps things simple.

    add_mkey
    {
            ["mkey"] =      MKEY_CONSTRUCT_POWERS,
            ["fct"] =       function()
                      execute_magic(constructor_powers)
                      energy_use = energy_use + 100;
            end
    }

    "mkey" must be a UNIQUE value > 1000 . Here I've defined it as a
    constant, MKEY_CONSTRUCT_POWERS, which has the value 1004. This value
    we'll call again in the s_info.txt file.
    "fct" is the function that's called when the user presses the key in the
    'm' menu. SO Here, it calls the execute_magic function which actually
    displays a list of powers for the user to choose from. The argument it takes is
    the powers it will use (alchemy, mindcraft etc, or in this case constructor),
    and then the energy_use line tells the game to take one game turn to do
    the action.

    === Adding the skill in s_info.txt ===

    Take a look in the S-info.txt file, under the Misc section. You'll see,

    N:57:Construction
    D:Ability to use constructor powers
    D:Construction powers use strength
    A:1004:Build or knock down stuff
    I:1000

    The first line is the index of the skill, again this must be unique. The second
    property is the name of the skill. The D lines are the lines displayed
    when the skill is highlighted in the skill screen.
    The first entry on the A line  is the value of the "mkey" we
    defined in the add_mkey function in our script. The second entry is the
    display for selecting the construction power in the 'm' menu.
    The I line is currently unused, but add a 1000 there anyway. That's what
    all the others have so when it's introduced, at least it will affect your
    powers identically to how it affects all the other powers.

    If you scroll to the very bottom of the file now, you'll see I've placed the
    skill at the bottom of the Misc branch of the skills tree. I then made a new
    class, constructor, which you can see in p_info.txt.

    That is all that is NEEDED when writing a script to add a skill - defining an
    mkey using add_mkey, and defining any powers that are called in the
    "fct" (generally using add_magic ).

    And I've added the line

    tome_dofile("construc.lua")

    in init.lua so the script is loaded on start-up!

    Below I'm going to talk in depth about a few other functions that you may find
    useful in your scripting.

    === fire_bolt() and fire_beam() ===

    In the last help file we looked at the routine for firing a ball -
    fire_ball(). Here's a quick note about beams and bolts...
    fire_beam() and fire_bolt() take 2 arguments:
    (type, direction, damage). So in the dismantle spell we have the
    direction passed from get_aim_dir() (the function that asks the player
    for a direction), the type of damage is GF_KILL_TRAP, which as you might
    expect disarms traps. And the damage is only 1 because it's not going to hurt
    monsters, just dismantle traps.

    === set_oppose_elec() ===

    OK here's another thing. Wander on down to the sparky_skills spell.  After the
    appropriate bolt/ball is fired, we have the line:

    if player.oppose_elec == 0 then
      set_oppose_elec(randint(10) + 20 + get_level(constructor_powers, 20)*3)
    end

    This is the bit that grants temporary resist electricity. we've called the
    function set_oppose_elec(turns), which sets the players resist
    electricity to "on" for the time specified in the argument "turns". We're only
    calling this if the player is not already granted temporary resist electricity,
    and we've linked the number of turns it is active for to the level of the
    construction skill. I've limited the maximum value of get_level to 20 in this
    instance. A similar idea can be used for temporarily granting levitation,
    extended infravision, protection against evil, resist fire, stuns, cuts and so
    on and so on. Have a look in player.pkg in the source for a full list....

                                 This file by fearoffours (fearoffours@moppy.co.uk)