// *** Generates lists of spell selections for spell "Chaotic Weave" ***

// Initializes array "preset" from values of the file "%ini_file%"
DEFINE_ACTION_MACRO a7_load_presets
BEGIN
  LOCAL_SET ofs = 0
  LOCAL_SET ofs2 = 0
  LOCAL_SET level = 0
  LOCAL_SET value = 0
  LOCAL_SET spell_level = 0
  LOCAL_SET spell_index = 0
  LOCAL_SPRINT line ~~
  LOCAL_SPRINT resref ~~

  OUTER_FOR (index = 1; index < 10; ++index) BEGIN
    OUTER_SET EVAL ~preset_%index%~ = 0
  END

  COPY - ~%ini_file%~ ~%ini_file%~
    SET ofs = 0
    SET ofs2 = 0
    WHILE (ofs >= 0) BEGIN
      SET ofs2 = INDEX_BUFFER(~%LNL%~ ofs)
      PATCH_IF (ofs2 < 0) BEGIN SET ofs2 = BUFFER_LENGTH END
      PATCH_IF (ofs2 > ofs) BEGIN
        // preparing line
        READ_ASCII ofs line (ofs2 - ofs)

        // removing comments and whitespace
        INNER_PATCH_SAVE line ~%line%~ BEGIN REPLACE_TEXTUALLY ~\([^;]*\)\(;.*\)?%MNL%?~ ~\1~ END
        LPF a7_trim STR_VAR line = EVAL ~%line%~ RET line END

        // parsing line content
        PATCH_IF (~%line%~ STRING_MATCHES_REGEXP ~[1-9]_[0-9]+[ %TAB%]*=[ %TAB%]*.+~ = 0) BEGIN
          INNER_PATCH_SAVE level ~%line%~ BEGIN REPLACE_TEXTUALLY ~\([1-9]\).*~ ~\1~ END
          INNER_PATCH_SAVE resref ~%line%~ BEGIN REPLACE_TEXTUALLY ~[1-9]_[0-9]+[ %TAB%]*=[ %TAB%]*\(.+\)~ ~\1~ END
          TO_UPPER ~resref~

          // resolve symbolic spell name
          SET value = IDS_OF_SYMBOL(~spell~ ~%resref%~)
          PATCH_IF (value >= 2100 && value < 2950) BEGIN
            SET value -= 2000
            SET spell_level = value / 100
            PATCH_IF (level = spell_level) BEGIN
              SET spell_index = value - (spell_level * 100)
              PATCH_IF (spell_index < 10) BEGIN
                SPRINT resref ~SPWI%spell_level%0%spell_index%~
              END ELSE BEGIN
                SPRINT resref ~SPWI%spell_level%%spell_index%~
              END
            END
          END

          // add spell to list
          PATCH_IF (IS_AN_INT ~level~ && FILE_EXISTS_IN_GAME ~%resref%.SPL~) BEGIN
            SET index = EVAL ~preset_%level%~
            TEXT_SPRINT EVAL ~preset_%level%_%index%~ ~%resref%~
            SET EVAL ~preset_%level%~ += 1
          END ELSE BEGIN
            PATCH_LOG ~Skipping preset level %level% spell: "%resref%" does not exist.~
          END
        END
      END

      SET ofs = (ofs2 < BUFFER_LENGTH) ? (ofs2 + 1) : "-1"
    END
  IF_EXISTS
END


// Initializes the array "struct" with spell names.
// "struct" is the prefix for the structure containing available spells. 
// First index indicates spell level, second index indicates spell name.
// Example: struct_1 = number of level 1 spells, struct_1_0 contains spell name of first available level 1 spell, ...
// Parameters: STR_VAR struct
DEFINE_ACTION_MACRO a7_create_spell_list
BEGIN
  LOCAL_SET index = 0
  LOCAL_SET level = 0
  LOCAL_SET row = 0
  LOCAL_SET value = 0
  LOCAL_SET valid = 0
  LOCAL_SPRINT code ~~
  LOCAL_SPRINT resref ~~

  // "exclude" array containst list of spells to exclude
  OUTER_SET exclude = 0
  COPY_EXISTING - ~hidespl.2da~ ~override~
    READ_2DA_ENTRIES_NOW hide 4
    FOR (row = 0; row < hide; ++row) BEGIN
      READ_2DA_ENTRY_FORMER hide row 0 resref
      READ_2DA_ENTRY_FORMER hide row 1 value
      PATCH_IF (value != 0 && ~%resref%~ STRING_MATCHES_REGEXP ~SPWI[1-9].*~ = 0) BEGIN
        // only list valid mage spells
        TEXT_SPRINT EVAL ~exclude_%exclude%~ ~%resref%~
        SET exclude += 1
      END
    END
  IF_EXISTS

  OUTER_FOR (level = 1; level < 10; ++level) BEGIN
    OUTER_SET EVAL ~%struct%_%level%~ = 0
  END

  // adding special spells
  ACTION_FOR_EACH resref IN ~SPWI222~ ~A7_SP03~ ~SPWI723~ ~A7_SP04~ BEGIN
    COPY - ~%MOD_FOLDER%/spells/%resref%.spl~ ~override~
      READ_LONG 0x34 level
    BUT_ONLY
    OUTER_SET index = EVAL ~%struct%_%level%~
    OUTER_TEXT_SPRINT EVAL ~%struct%_%level%_%index%~ ~%resref%~
    OUTER_SET EVAL ~%struct%_%level%~ = index + 1
  END

  // scanning available spells
  COPY_EXISTING - ~spell.ids~ ~override~
    READ_2DA_ENTRIES_NOW table 2
    FOR (row = 0; row < table; ++row) BEGIN
      READ_2DA_ENTRY_FORMER table row 0 code
      PATCH_IF (IS_AN_INT ~code~ && code >= 2100 && code < 2950) BEGIN
        SET code -= 2000
        SET level = code / 100
        SET value = code - (level * 100)
        PATCH_IF (value > 0 && value < 50) BEGIN
          SPRINT resref ~SPWI%code%~

          SET valid = 1

          // exclude fixed list of spells
          PATCH_FOR_EACH name IN ~SPWI110~ BEGIN  // Identify
            PATCH_IF (~%name%~ STR_EQ ~%resref%~) BEGIN
              SET valid = 0
            END
          END

          PATCH_IF (valid) BEGIN
            // validate spell properties
            INNER_ACTION BEGIN
              COPY_EXISTING - ~%resref%.spl~ ~override~
                PATCH_IF ((SHORT_AT 0x1c) != 1 ||             // Wizard spell?
                          (LONG_AT 0x1e) BAND BIT14 ||        // Generalist mage not excluded?
                          (LONG_AT NAME1) <= 0 ||             // valid spell name?
                          (LONG_AT 0x34) != level) BEGIN      // spell level matches?
                  SET valid = 0
                END
              IF_EXISTS
            END
          END

          // check if resref already exists
          PATCH_IF (valid) BEGIN
            SET value = EVAL ~%struct%_%level%~
            FOR (index = 0; index < value; ++index) BEGIN
              PATCH_IF (EVAL ~%%struct%_%level%_%index%%~ STR_EQ ~%resref%~) BEGIN
                SET index = value
                SET valid = 0
              END
            END
          END

          PATCH_IF (valid) BEGIN
            // check if resref is excluded
            FOR (index = 0; index < exclude; ++index) BEGIN
              PATCH_IF (EVAL ~%exclude_%index%%~ STR_EQ ~%resref%~) BEGIN
                SET index = exclude
                SET valid = 0
              END
            END
          END

          PATCH_IF (valid) BEGIN
            // adding spell name
            SET index = EVAL ~%struct%_%level%~
            TEXT_SPRINT EVAL ~%struct%_%level%_%index%~ ~%resref%~
            SET EVAL ~%struct%_%level%~ = index + 1
          END
        END
      END
    END
  IF_EXISTS
END


// Generates a 2DA file containing spell entries based on specified parameters
DEFINE_ACTION_FUNCTION a7_create_spell_list_file
INT_VAR
  // percent of spells to add to list
  level_1 = 0
  level_2 = 0
  level_3 = 0
  level_4 = 0
  level_5 = 0
  level_6 = 0
  level_7 = 0
  level_8 = 0
  level_9 = 0
STR_VAR
  // predefined spell table (always added)
  fixed_table = ~~
  // dynamically generated spell table to choose from
  spell_table = ~~
  // output filename
  file_name   = ~~
BEGIN
  ACTION_IF (NOT ~%spell_table%~ STR_EQ ~~ && 
             NOT ~%file_name%~ STR_EQ ~~) BEGIN
<<<<<<<< .../inlined/spell_table.2da
2DA V1.0
****
        ResRef  Type
>>>>>>>>
  END
  COPY ~.../inlined/spell_table.2da~ ~override/%file_name%~

  // generating list of spells to add: spell_list
  OUTER_FOR (level = 1; level < 10; ++level) BEGIN
    OUTER_SET EVAL ~spell_list_%level%~ = 0
    ACTION_IF (EVAL ~level_%level%~ > 0) BEGIN
      OUTER_SET numSpells = (EVAL ~%spell_table%_%level%~ * EVAL ~level_%level%~) / 100
      OUTER_SET numFixed = (~%fixed_table%~ STR_EQ ~~) ? 0 : EVAL ~%fixed_table%_%level%~
      OUTER_SET numSpells = (numSpells > numFixed) ? (numSpells - numFixed) : 0

      // fill local list with spells of current level
      OUTER_SET cur_list = 0
      OUTER_FOR (idx = 0; idx < EVAL ~%spell_table%_%level%~; ++idx) BEGIN
        OUTER_TEXT_SPRINT resref EVAL ~%%spell_table%_%level%_%idx%%~
        OUTER_TEXT_SPRINT EVAL ~cur_list_%idx%~ ~%resref%~
        OUTER_SET cur_list += 1

        // always add preset spells
        OUTER_FOR (idx2 = 0; idx2 < numFixed; ++idx2) BEGIN
          ACTION_IF (EVAL ~%%fixed_table%_%level%_%idx2%%~ STR_EQ ~%resref%~) BEGIN
            OUTER_SET value = EVAL ~spell_list_%level%~
            OUTER_TEXT_SPRINT EVAL ~spell_list_%level%_%value%~ ~%resref%~
            OUTER_TEXT_SPRINT EVAL ~cur_list_%idx%~ ~~
            OUTER_SET EVAL ~spell_list_%level%~ += 1
          END
        END
      END

      // add random spells
      OUTER_WHILE (numSpells > 0) BEGIN
        OUTER_SET chance = RANDOM(0 99)
        OUTER_SET max = cur_list - 1
        OUTER_SET index = RANDOM(0 max)
        ACTION_IF (chance < EVAL ~level_%level%~ && 
                   NOT EVAL ~%cur_list_%index%%~ STR_EQ ~~) BEGIN
          OUTER_SET value = EVAL ~spell_list_%level%~
          OUTER_TEXT_SPRINT EVAL ~spell_list_%level%_%value%~ EVAL ~%cur_list_%index%%~
          OUTER_TEXT_SPRINT EVAL ~cur_list_%index%~ ~~
          OUTER_SET EVAL ~spell_list_%level%~ += 1
          OUTER_SET numSpells -= 1
        END
      END
    END
  END

  // Add selected spells to 2da file
  OUTER_FOR (level = 1; level < 10; ++level) BEGIN
    OUTER_SET numSpells = EVAL ~spell_list_%level%~
    OUTER_FOR (idx = 0; idx < numSpells; ++idx) BEGIN
      OUTER_TEXT_SPRINT resref EVAL ~%spell_list_%level%_%idx%%~
      OUTER_TEXT_SPRINT line ~level%level%_%idx%   %resref%  3~
      APPEND ~%file_name%~ ~%line%~
    END
  END
END


// defining preset list of important spells
ACTION_IF (SPELL_REV) BEGIN
  OUTER_TEXT_SPRINT ini_file "%MOD_FOLDER%/lib/presets_spellrev.ini"
END ELSE BEGIN
  OUTER_TEXT_SPRINT ini_file "%MOD_FOLDER%/lib/presets.ini"
END
LAM a7_load_presets


OUTER_TEXT_SPRINT struct ~spellTable~
LAM a7_create_spell_list

// generate spell lists for each tier
RANDOM_SEED ~now~   // force to use current time

// Order of entries: table name, level 1 percentage, level 2 percentage, ... => dummy name
ACTION_DEFINE_ASSOCIATIVE_ARRAY spell_def BEGIN
  // Tier 1
  ~a7_sp1a~, ~75~, ~50~, ~25~ => ~1~
  ~a7_sp1b~, ~75~, ~50~, ~25~ => ~2~
  ~a7_sp1c~, ~75~, ~50~, ~25~ => ~3~
  ~a7_sp1d~, ~100~, ~75~, ~50~, ~25~ => ~4~
  ~a7_sp1e~, ~100~, ~75~, ~50~, ~25~ => ~5~
  ~a7_sp1f~, ~100~, ~75~, ~50~, ~25~ => ~6~
  ~a7_sp1g~, ~100~, ~100~, ~75~, ~50~, ~25~ => ~7~
  ~a7_sp1h~, ~100~, ~100~, ~75~, ~50~, ~25~ => ~8~
  ~a7_sp1i~, ~100~, ~100~, ~100~, ~75~, ~50~, ~25~ => ~9~
  ~a7_sp1j~, ~100~, ~100~, ~100~, ~75~, ~50~, ~25~ => ~10~
  ~a7_sp1k~, ~100~, ~100~, ~100~, ~100~, ~75~, ~50~, ~25~ => ~11~
  ~a7_sp1l~, ~100~, ~100~, ~100~, ~100~, ~75~, ~50~, ~25~ => ~12~
  ~a7_sp1m~, ~100~, ~100~, ~100~, ~100~, ~100~, ~75~, ~50~, ~25~ => ~13~
  ~a7_sp1n~, ~100~, ~100~, ~100~, ~100~, ~100~, ~75~, ~50~, ~25~ => ~14~
  // Tier 2
  ~a7_sp2a~, ~100~, ~75~, ~50~, ~25~ => ~1~
  ~a7_sp2b~, ~100~, ~75~, ~50~, ~25~ => ~2~
  ~a7_sp2c~, ~100~, ~75~, ~50~, ~25~ => ~3~
  ~a7_sp2d~, ~100~, ~100~, ~75~, ~50~, ~25~ => ~4~
  ~a7_sp2e~, ~100~, ~100~, ~75~, ~50~, ~25~ => ~5~
  ~a7_sp2f~, ~100~, ~100~, ~75~, ~50~, ~25~ => ~6~
  ~a7_sp2g~, ~100~, ~100~, ~100~, ~75~, ~50~, ~25~ => ~7~
  ~a7_sp2h~, ~100~, ~100~, ~100~, ~75~, ~50~, ~25~ => ~8~
  ~a7_sp2i~, ~100~, ~100~, ~100~, ~100~, ~75~, ~50~, ~25~ => ~9~
  ~a7_sp2j~, ~100~, ~100~, ~100~, ~100~, ~75~, ~50~, ~25~ => ~10~
  ~a7_sp2k~, ~100~, ~100~, ~100~, ~100~, ~100~, ~75~, ~50~, ~25~ => ~11~
  ~a7_sp2l~, ~100~, ~100~, ~100~, ~100~, ~100~, ~75~, ~50~, ~25~ => ~12~
  ~a7_sp2m~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~, ~75~, ~50~, ~25~ => ~13~
  ~a7_sp2n~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~, ~75~, ~50~, ~25~ => ~14~
  // Tier 3
  ~a7_sp3a~, ~100~, ~100~, ~75~, ~50~, ~25~ => ~1~
  ~a7_sp3b~, ~100~, ~100~, ~75~, ~50~, ~25~ => ~2~
  ~a7_sp3c~, ~100~, ~100~, ~75~, ~50~, ~25~ => ~3~
  ~a7_sp3d~, ~100~, ~100~, ~100~, ~75~, ~50~, ~25~ => ~4~
  ~a7_sp3e~, ~100~, ~100~, ~100~, ~75~, ~50~, ~25~ => ~5~
  ~a7_sp3f~, ~100~, ~100~, ~100~, ~75~, ~50~, ~25~ => ~6~
  ~a7_sp3g~, ~100~, ~100~, ~100~, ~100~, ~75~, ~50~, ~25~ => ~7~
  ~a7_sp3h~, ~100~, ~100~, ~100~, ~100~, ~75~, ~50~, ~25~ => ~8~
  ~a7_sp3i~, ~100~, ~100~, ~100~, ~100~, ~100~, ~75~, ~50~, ~25~ => ~9~
  ~a7_sp3j~, ~100~, ~100~, ~100~, ~100~, ~100~, ~75~, ~50~, ~25~ => ~10~
  ~a7_sp3k~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~, ~75~, ~50~, ~25~ => ~11~
  ~a7_sp3l~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~, ~75~, ~50~, ~25~ => ~12~
  ~a7_sp3m~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~, ~75~, ~50~ => ~13~
  ~a7_sp3n~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~, ~75~, ~50~ => ~14~
  // Tier 4
  ~a7_sp4a~, ~100~, ~100~, ~100~, ~100~, ~75~, ~50~, ~25~ => ~1~
  ~a7_sp4b~, ~100~, ~100~, ~100~, ~100~, ~75~, ~50~, ~25~ => ~2~
  ~a7_sp4c~, ~100~, ~100~, ~100~, ~100~, ~75~, ~50~, ~25~ => ~3~
  ~a7_sp4d~, ~100~, ~100~, ~100~, ~100~, ~100~, ~50~, ~25~ => ~4~
  ~a7_sp4e~, ~100~, ~100~, ~100~, ~100~, ~100~, ~50~, ~25~ => ~5~
  ~a7_sp4f~, ~100~, ~100~, ~100~, ~100~, ~100~, ~50~, ~25~ => ~6~
  ~a7_sp4g~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~, ~50~, ~25~ => ~7~
  ~a7_sp4h~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~, ~50~, ~25~ => ~8~
  ~a7_sp4i~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~, ~50~, ~25~ => ~9~
  ~a7_sp4j~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~, ~50~, ~25~ => ~10~
  ~a7_sp4k~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~, ~75~, ~50~ => ~11~
  ~a7_sp4l~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~, ~75~, ~50~ => ~12~
  ~a7_sp4m~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~, ~75~ => ~13~
  // Tier 5
  ~a7_sp5a~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~, ~75~, ~25~ => ~1~
  ~a7_sp5b~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~, ~75~, ~25~ => ~2~
  ~a7_sp5c~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~, ~50~ => ~3~
  ~a7_sp5d~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~, ~50~ => ~4~
  ~a7_sp5e~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~ => ~5~
  // Tier 6
  ~a7_sp6a~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~, ~100~ => ~1~
END

ACTION_PHP_EACH spell_def AS data => _ BEGIN
  OUTER_FOR (idx = 1; idx <= 9; ++idx) BEGIN
    ACTION_IF (VARIABLE_IS_SET EVAL ~data_%idx%~) BEGIN
      OUTER_SET EVAL ~l_%idx%~ = EVAL ~data_%idx%~
    END ELSE BEGIN
      OUTER_SET EVAL ~l_%idx%~ = 0
    END
  END
  LAF a7_create_spell_list_file
  INT_VAR
    level_1 = l_1
    level_2 = l_2
    level_3 = l_3
    level_4 = l_4
    level_5 = l_5
    level_6 = l_6
    level_7 = l_7
    level_8 = l_8
    level_9 = l_9
  STR_VAR
    fixed_table = ~preset~
    spell_table = ~spellTable~
    file_name   = EVAL ~%data_0%.2da~
  END
END
