import(Module_Defines)
import(Module_PopScript)
import(Module_Commands)
import(Module_Game)
import(Module_Objects)
import(Module_Map)
import(Module_MapWho)
import(Module_Math)
import(Module_Helpers)
import(Module_System)
import(Module_Features)

include("UtilPThings.lua")
include("UtilRefs.lua")

local STurn = GetTurn()

_c.MaxManaValue = 2500000
_c.ShamenDeadManaPer256Gained = 64

enable_feature(F_MINIMAP_ENEMIES);
enable_feature(F_WILD_NO_RESPAWN);

wilds = {}
spell_delay = {0,0,0,0,0,0,0}
spell_ms_delay = {720,720,720,720,720,720,720}
spell_ms_used = {5,5,5,5,5,5,5}
spell_ms_radius = 3
spell_ms_max_use = 5
spell_ms_charge_time = 720
l_charges = {4,4,4,4,4,4,4}
h_charges = {3,3,3,3,3,3,3}
l_charge_time = {540, 540, 540, 540, 540, 540, 540}
h_charge_time = {720, 720, 720, 720, 720, 720, 720}
prayer = nil
index = 1
availableNums = {4,5,7,0,1,2,3}
numthings = 16
local diff_easy = 0
local diff_medium = 1
local diff_hard = 2
local diff_expert = 3
current_difficulty = get_game_difficulty()
if (current_difficulty == diff_expert) then
  srate = 4
  uprate=7
else
  srate = 5
  uprate=9
end
if (current_difficulty == diff_hard) then
  _c.ShamenDeadManaPer256Gained = 32
elseif (current_difficulty == diff_expert) then
  _c.ShamenDeadManaPer256Gained = 16
end
if (current_difficulty == diff_easy) then
  lite_attack = {
    GetTurn() + (1536 + G_RANDOM(512)),
    GetTurn() + (1536 + G_RANDOM(512)),
    GetTurn() + (1536 + G_RANDOM(512)),
    GetTurn() + (1536 + G_RANDOM(512)),
    GetTurn() + (1536 + G_RANDOM(512)),
    GetTurn() + (1536 + G_RANDOM(512)),
    GetTurn() + (1536 + G_RANDOM(512))
  }
  heavy_attack = {
    GetTurn() + (4096 + G_RANDOM(1536)),
    GetTurn() + (4096 + G_RANDOM(1536)),
    GetTurn() + (4096 + G_RANDOM(1536)),
    GetTurn() + (4096 + G_RANDOM(1536)),
    GetTurn() + (4096 + G_RANDOM(1536)),
    GetTurn() + (4096 + G_RANDOM(1536)),
    GetTurn() + (4096 + G_RANDOM(1536))
  }
  shaman_attack = {
    GetTurn() + (2048 + G_RANDOM(1024)),
    GetTurn() + (2048 + G_RANDOM(1024)),
    GetTurn() + (2048 + G_RANDOM(1024)),
    GetTurn() + (2048 + G_RANDOM(1024)),
    GetTurn() + (2048 + G_RANDOM(1024)),
    GetTurn() + (2048 + G_RANDOM(1024)),
    GetTurn() + (2048 + G_RANDOM(1024))
  }
elseif (current_difficulty == diff_medium) then
  lite_attack = {
    GetTurn() + (1024 + G_RANDOM(512)),
    GetTurn() + (1024 + G_RANDOM(512)),
    GetTurn() + (1024 + G_RANDOM(512)),
    GetTurn() + (1024 + G_RANDOM(512)),
    GetTurn() + (1024 + G_RANDOM(512)),
    GetTurn() + (1024 + G_RANDOM(512)),
    GetTurn() + (1024 + G_RANDOM(512))
  }
  heavy_attack = {
    GetTurn() + (3072 + G_RANDOM(1536)),
    GetTurn() + (3072 + G_RANDOM(1536)),
    GetTurn() + (3072 + G_RANDOM(1536)),
    GetTurn() + (3072 + G_RANDOM(1536)),
    GetTurn() + (3072 + G_RANDOM(1536)),
    GetTurn() + (3072 + G_RANDOM(1536)),
    GetTurn() + (3072 + G_RANDOM(1536))
  }
  shaman_attack = {
    GetTurn() + (1536 + G_RANDOM(1024)),
    GetTurn() + (1536 + G_RANDOM(1024)),
    GetTurn() + (1536 + G_RANDOM(1024)),
    GetTurn() + (1536 + G_RANDOM(1024)),
    GetTurn() + (1536 + G_RANDOM(1024)),
    GetTurn() + (1536 + G_RANDOM(1024)),
    GetTurn() + (1536 + G_RANDOM(1024))
  }
elseif (current_difficulty == diff_hard) then
  lite_attack = {
    GetTurn() + (512 + G_RANDOM(512)),
    GetTurn() + (512 + G_RANDOM(512)),
    GetTurn() + (512 + G_RANDOM(512)),
    GetTurn() + (512 + G_RANDOM(512)),
    GetTurn() + (512 + G_RANDOM(512)),
    GetTurn() + (512 + G_RANDOM(512)),
    GetTurn() + (512 + G_RANDOM(512))
  }
  heavy_attack = {
    GetTurn() + (2048 + G_RANDOM(1024)),
    GetTurn() + (2048 + G_RANDOM(1024)),
    GetTurn() + (2048 + G_RANDOM(1024)),
    GetTurn() + (2048 + G_RANDOM(1024)),
    GetTurn() + (2048 + G_RANDOM(1024)),
    GetTurn() + (2048 + G_RANDOM(1024)),
    GetTurn() + (2048 + G_RANDOM(1024))
  }
  shaman_attack = {
    GetTurn() + (1024 + G_RANDOM(512)),
    GetTurn() + (1024 + G_RANDOM(512)),
    GetTurn() + (1024 + G_RANDOM(512)),
    GetTurn() + (1024 + G_RANDOM(512)),
    GetTurn() + (1024 + G_RANDOM(512)),
    GetTurn() + (1024 + G_RANDOM(512)),
    GetTurn() + (1024 + G_RANDOM(512))
  }
elseif (current_difficulty == diff_expert) then
  lite_attack = {
    GetTurn() + (512 + G_RANDOM(256)),
    GetTurn() + (512 + G_RANDOM(256)),
    GetTurn() + (512 + G_RANDOM(256)),
    GetTurn() + (512 + G_RANDOM(256)),
    GetTurn() + (512 + G_RANDOM(256)),
    GetTurn() + (512 + G_RANDOM(256)),
    GetTurn() + (512 + G_RANDOM(256))
  }
  heavy_attack = {
    GetTurn() + (1536 + G_RANDOM(1024)),
    GetTurn() + (1536 + G_RANDOM(1024)),
    GetTurn() + (1536 + G_RANDOM(1024)),
    GetTurn() + (1536 + G_RANDOM(1024)),
    GetTurn() + (1536 + G_RANDOM(1024)),
    GetTurn() + (1536 + G_RANDOM(1024)),
    GetTurn() + (1536 + G_RANDOM(1024))
  }
  shaman_attack = {
    GetTurn() + (512 + G_RANDOM(512)),
    GetTurn() + (512 + G_RANDOM(512)),
    GetTurn() + (512 + G_RANDOM(512)),
    GetTurn() + (512 + G_RANDOM(512)),
    GetTurn() + (512 + G_RANDOM(512)),
    GetTurn() + (512 + G_RANDOM(512)),
    GetTurn() + (512 + G_RANDOM(512))
  }
end
blueTowers = {MAP_XZ_2_WORLD_XYZ(96, 20),
               MAP_XZ_2_WORLD_XYZ(98, 50),
               MAP_XZ_2_WORLD_XYZ(130, 16),
               MAP_XZ_2_WORLD_XYZ(92, 228),
               MAP_XZ_2_WORLD_XYZ(134, 226),
               MAP_XZ_2_WORLD_XYZ(146, 234),
               MAP_XZ_2_WORLD_XYZ(156, 242)
}
redTowers = {MAP_XZ_2_WORLD_XYZ(70, 174),
             MAP_XZ_2_WORLD_XYZ(84, 188),
             MAP_XZ_2_WORLD_XYZ(102, 184),
             MAP_XZ_2_WORLD_XYZ(102, 140),
             MAP_XZ_2_WORLD_XYZ(100, 108),
             MAP_XZ_2_WORLD_XYZ(82, 102),
             MAP_XZ_2_WORLD_XYZ(64, 130)
}
yellowTowers = {MAP_XZ_2_WORLD_XYZ(216, 142),
                MAP_XZ_2_WORLD_XYZ(220, 82),
                MAP_XZ_2_WORLD_XYZ(202, 80),
                MAP_XZ_2_WORLD_XYZ(162, 110),
                MAP_XZ_2_WORLD_XYZ(196, 144),
                MAP_XZ_2_WORLD_XYZ(144, 110),
                MAP_XZ_2_WORLD_XYZ(162, 128)
}
greenTowers = {MAP_XZ_2_WORLD_XYZ(14, 136),
               MAP_XZ_2_WORLD_XYZ(46, 134),
               MAP_XZ_2_WORLD_XYZ(44, 114),
               MAP_XZ_2_WORLD_XYZ(46, 96),
               MAP_XZ_2_WORLD_XYZ(46, 64),
               MAP_XZ_2_WORLD_XYZ(0, 48),
               MAP_XZ_2_WORLD_XYZ(8, 38)
}
cyanTowers = {MAP_XZ_2_WORLD_XYZ(218, 182),
              MAP_XZ_2_WORLD_XYZ(170, 180),
              MAP_XZ_2_WORLD_XYZ(168, 208),
              MAP_XZ_2_WORLD_XYZ(194, 220),
              MAP_XZ_2_WORLD_XYZ(216, 210)
}
magentaTowers = {MAP_XZ_2_WORLD_XYZ(230, 54),
                 MAP_XZ_2_WORLD_XYZ(218, 18),
                 MAP_XZ_2_WORLD_XYZ(188, 12),
                 MAP_XZ_2_WORLD_XYZ(174, 24),
                 MAP_XZ_2_WORLD_XYZ(174, 46),
                 MAP_XZ_2_WORLD_XYZ(192, 58)
}
orangeTowers = {MAP_XZ_2_WORLD_XYZ(16, 194),
                MAP_XZ_2_WORLD_XYZ(246, 246),
                MAP_XZ_2_WORLD_XYZ(14, 234),
                MAP_XZ_2_WORLD_XYZ(36, 2),
                MAP_XZ_2_WORLD_XYZ(62, 206),
                MAP_XZ_2_WORLD_XYZ(50, 196),
                MAP_XZ_2_WORLD_XYZ(58, 12),
                MAP_XZ_2_WORLD_XYZ(36, 192)
}
conv_center_pos = {
MAP_XZ_2_WORLD_XYZ(192, 206),
MAP_XZ_2_WORLD_XYZ(200, 36),
MAP_XZ_2_WORLD_XYZ(20, 232),
MAP_XZ_2_WORLD_XYZ(112, 4), 
MAP_XZ_2_WORLD_XYZ(98, 148),
MAP_XZ_2_WORLD_XYZ(202, 114),
MAP_XZ_2_WORLD_XYZ(22, 86)

}
botSpells = {M_SPELL_CONVERT_WILD,
             M_SPELL_BLAST,
             M_SPELL_LAND_BRIDGE,
             M_SPELL_LIGHTNING_BOLT,
             M_SPELL_INSECT_PLAGUE,
             M_SPELL_GHOST_ARMY,
             M_SPELL_SWAMP,
             M_SPELL_HYPNOTISM,
             M_SPELL_WHIRLWIND,
             M_SPELL_EARTHQUAKE,
             M_SPELL_FIRESTORM,
             M_SPELL_SHIELD,
             M_SPELL_INVISIBILITY
}
botBldgs = {M_BUILDING_TEPEE,
            M_BUILDING_DRUM_TOWER,
            M_BUILDING_WARRIOR_TRAIN,
            M_BUILDING_TEMPLE,
            M_BUILDING_SUPER_TRAIN,
            M_BUILDING_SPY_TRAIN
}

for i = 1,7 do
  for u,v in ipairs(botSpells) do
    PThing.SpellSet(availableNums[i], v, TRUE, FALSE)
  end

  for y,v in ipairs(botBldgs) do
    PThing.BldgSet(availableNums[i], v, TRUE)
  end

  computer_init_player(_gsi.Players[availableNums[i]])

  WRITE_CP_ATTRIB(availableNums[i], ATTR_PREF_WARRIOR_TRAINS, 0)
  WRITE_CP_ATTRIB(availableNums[i], ATTR_PREF_WARRIOR_PEOPLE, 0)
  WRITE_CP_ATTRIB(availableNums[i], ATTR_PREF_RELIGIOUS_TRAINS, 0)
  WRITE_CP_ATTRIB(availableNums[i], ATTR_PREF_RELIGIOUS_PEOPLE, 0)
  WRITE_CP_ATTRIB(availableNums[i], ATTR_PREF_SUPER_WARRIOR_TRAINS, 0)
  WRITE_CP_ATTRIB(availableNums[i], ATTR_PREF_SUPER_WARRIOR_PEOPLE, 0)
  WRITE_CP_ATTRIB(availableNums[i], ATTR_PREF_SPY_TRAINS, G_RANDOM(2))
  WRITE_CP_ATTRIB(availableNums[i], ATTR_PREF_SPY_PEOPLE, G_RANDOM(5)+2)
  WRITE_CP_ATTRIB(availableNums[i], ATTR_AWAY_BRAVE, 5)
  WRITE_CP_ATTRIB(availableNums[i], ATTR_AWAY_WARRIOR, 80)
  WRITE_CP_ATTRIB(availableNums[i], ATTR_AWAY_RELIGIOUS, 69)
  WRITE_CP_ATTRIB(availableNums[i], ATTR_AWAY_SUPER_WARRIOR, 47)
  WRITE_CP_ATTRIB(availableNums[i], ATTR_AWAY_SPY, 5)
  WRITE_CP_ATTRIB(availableNums[i], ATTR_AWAY_MEDICINE_MAN, 100)
  WRITE_CP_ATTRIB(availableNums[i], ATTR_USE_PREACHER_FOR_DEFENCE, 1)
  WRITE_CP_ATTRIB(availableNums[i], ATTR_DEFENSE_RAD_INCR, 6)
  WRITE_CP_ATTRIB(availableNums[i], ATTR_MAX_DEFENSIVE_ACTIONS, 3)
  WRITE_CP_ATTRIB(availableNums[i], ATTR_ATTACK_PERCENTAGE, 125)
  WRITE_CP_ATTRIB(availableNums[i], ATTR_MAX_ATTACKS, 80)
  WRITE_CP_ATTRIB(availableNums[i], ATTR_BASE_UNDER_ATTACK_RETREAT, 0)
  WRITE_CP_ATTRIB(availableNums[i], ATTR_RANDOM_BUILD_SIDE, 1)
  WRITE_CP_ATTRIB(availableNums[i], ATTR_GROUP_OPTION, 0)
  WRITE_CP_ATTRIB(availableNums[i], ATTR_PEOPLE_PER_BOAT, 7)
  WRITE_CP_ATTRIB(availableNums[i], ATTR_PEOPLE_PER_BALLOON, 8)
  WRITE_CP_ATTRIB(availableNums[i], ATTR_ENEMY_SPY_MAX_STAND, 255)
  WRITE_CP_ATTRIB(availableNums[i], ATTR_SPY_CHECK_FREQUENCY, 128)
  WRITE_CP_ATTRIB(availableNums[i], ATTR_SPY_DISCOVER_CHANCE, 30)
  WRITE_CP_ATTRIB(availableNums[i], ATTR_MAX_TRAIN_AT_ONCE, 5)
  WRITE_CP_ATTRIB(availableNums[i], ATTR_SHAMEN_BLAST, 8)
  WRITE_CP_ATTRIB(availableNums[i], ATTR_HOUSE_PERCENTAGE, 30+G_RANDOM(28))

  if (current_difficulty == diff_easy) then
    WRITE_CP_ATTRIB(availableNums[i], ATTR_EXPANSION, 18+G_RANDOM(15))
    WRITE_CP_ATTRIB(availableNums[i], ATTR_MAX_BUILDINGS_ON_GO, 3+G_RANDOM(2))
    WRITE_CP_ATTRIB(availableNums[i], ATTR_RETREAT_VALUE, 1+G_RANDOM(15))
  elseif (current_difficulty == diff_medium) then
    WRITE_CP_ATTRIB(availableNums[i], ATTR_EXPANSION, 25+G_RANDOM(20))
    WRITE_CP_ATTRIB(availableNums[i], ATTR_MAX_BUILDINGS_ON_GO, 5+G_RANDOM(5))
    WRITE_CP_ATTRIB(availableNums[i], ATTR_RETREAT_VALUE, 5+G_RANDOM(20))
  elseif (current_difficulty == diff_hard) then
    WRITE_CP_ATTRIB(availableNums[i], ATTR_EXPANSION, 30+G_RANDOM(25))
    WRITE_CP_ATTRIB(availableNums[i], ATTR_MAX_BUILDINGS_ON_GO, 8+G_RANDOM(5))
    WRITE_CP_ATTRIB(availableNums[i], ATTR_RETREAT_VALUE, 8+G_RANDOM(25))
  elseif (current_difficulty == diff_expert) then
    WRITE_CP_ATTRIB(availableNums[i], ATTR_EXPANSION, 35+G_RANDOM(28))
    WRITE_CP_ATTRIB(availableNums[i], ATTR_MAX_BUILDINGS_ON_GO, 10+G_RANDOM(6))
    WRITE_CP_ATTRIB(availableNums[i], ATTR_RETREAT_VALUE, 15+G_RANDOM(30))
  end


  STATE_SET(availableNums[i], TRUE, CP_AT_TYPE_FETCH_WOOD)
  STATE_SET(availableNums[i], TRUE, CP_AT_TYPE_CONSTRUCT_BUILDING)
  STATE_SET(availableNums[i], TRUE, CP_AT_TYPE_BUILD_OUTER_DEFENCES)
  STATE_SET(availableNums[i], TRUE, CP_AT_TYPE_DEFEND)
  STATE_SET(availableNums[i], TRUE, CP_AT_TYPE_DEFEND_BASE)
  STATE_SET(availableNums[i], TRUE, CP_AT_TYPE_PREACH)
  STATE_SET(availableNums[i], TRUE, CP_AT_TYPE_BRING_NEW_PEOPLE_BACK)
  STATE_SET(availableNums[i], TRUE, CP_AT_TYPE_SUPER_DEFEND)
  STATE_SET(availableNums[i], TRUE, CP_AT_TYPE_TRAIN_PEOPLE)
  STATE_SET(availableNums[i], TRUE, CP_AT_TYPE_AUTO_ATTACK)
  STATE_SET(availableNums[i], TRUE, CP_AT_TYPE_HOUSE_A_PERSON)
  STATE_SET(availableNums[i], TRUE, CP_AT_TYPE_POPULATE_DRUM_TOWER)
  STATE_SET(availableNums[i], TRUE, CP_AT_TYPE_FETCH_LOST_PEOPLE)
  STATE_SET(availableNums[i], TRUE, CP_AT_TYPE_MED_MAN_GET_WILD_PEEPS)

  SET_BUCKET_USAGE(availableNums[i], TRUE)
  SET_BUCKET_COUNT_FOR_SPELL(availableNums[i], M_SPELL_BLAST, 8)
  SET_BUCKET_COUNT_FOR_SPELL(availableNums[i], M_SPELL_CONVERT_WILD, 8)
  SET_BUCKET_COUNT_FOR_SPELL(availableNums[i], M_SPELL_GHOST_ARMY, 12)
  SET_BUCKET_COUNT_FOR_SPELL(availableNums[i], M_SPELL_LAND_BRIDGE, 32)
  SET_BUCKET_COUNT_FOR_SPELL(availableNums[i], M_SPELL_INSECT_PLAGUE, 36)
  SET_BUCKET_COUNT_FOR_SPELL(availableNums[i], M_SPELL_LIGHTNING_BOLT, 40)
  SET_BUCKET_COUNT_FOR_SPELL(availableNums[i], M_SPELL_HYPNOTISM, 50)
  SET_BUCKET_COUNT_FOR_SPELL(availableNums[i], M_SPELL_WHIRLWIND, 80)
  SET_BUCKET_COUNT_FOR_SPELL(availableNums[i], M_SPELL_SWAMP, 100)
  SET_BUCKET_COUNT_FOR_SPELL(availableNums[i], M_SPELL_EARTHQUAKE, 175)
  SET_BUCKET_COUNT_FOR_SPELL(availableNums[i], M_SPELL_FIRESTORM, 275)
  SET_BUCKET_COUNT_FOR_SPELL(availableNums[i], M_SPELL_SHIELD, 28)
  SET_BUCKET_COUNT_FOR_SPELL(availableNums[i], M_SPELL_INVISIBILITY, 30)

  SET_DEFENCE_RADIUS(availableNums[i], 7)
  SET_SPELL_ENTRY(availableNums[i], 0, M_SPELL_INSECT_PLAGUE, 25000, 64, 3, 0)
  SET_SPELL_ENTRY(availableNums[i], 1, M_SPELL_LIGHTNING_BOLT, 40000, 64, 2, 0)
  SET_SPELL_ENTRY(availableNums[i], 2, M_SPELL_INSECT_PLAGUE, 25000, 64, 3, 1)
  SET_SPELL_ENTRY(availableNums[i], 3, M_SPELL_LIGHTNING_BOLT, 40000, 64, 2, 1)
  SET_SPELL_ENTRY(availableNums[i], 4, M_SPELL_HYPNOTISM, 50000, 64, 4, 0)
  SET_SPELL_ENTRY(availableNums[i], 5, M_SPELL_HYPNOTISM, 50000, 64, 4, 1)
end

SHAMAN_DEFEND(TRIBE_CYAN, 192, 206, TRUE)
SHAMAN_DEFEND(TRIBE_PINK, 200, 36, TRUE)
SHAMAN_DEFEND(TRIBE_ORANGE, 20, 232, TRUE)
SHAMAN_DEFEND(TRIBE_BLUE, 112, 4, TRUE)
SHAMAN_DEFEND(TRIBE_RED, 98, 148, TRUE)
SHAMAN_DEFEND(TRIBE_YELLOW, 202, 114, TRUE)
SHAMAN_DEFEND(TRIBE_GREEN, 22, 86, TRUE)
SET_DRUM_TOWER_POS(TRIBE_CYAN, 192, 206)
SET_DRUM_TOWER_POS(TRIBE_PINK, 200, 36)
SET_DRUM_TOWER_POS(TRIBE_ORANGE, 20, 232)
SET_DRUM_TOWER_POS(TRIBE_BLUE, 112, 4)
SET_DRUM_TOWER_POS(TRIBE_RED, 98, 148)
SET_DRUM_TOWER_POS(TRIBE_YELLOW, 202, 114)
SET_DRUM_TOWER_POS(TRIBE_GREEN, 22, 86)

function OnTurn()
  if (GetTurn() > STurn + 1) then
    if (GetTurn() == 64) then
      local goofy_ahh = G_RANDOM(7)
      if goofy_ahh == 6 then
        goofy_ahh = 7
      end
      log_msg(goofy_ahh, "Map by MelonYeeter!")
    end

    if every2Pow(2) then
      for i,t in ipairs(heavy_attack) do
        if (GetTurn() > t) then
          if (FREE_ENTRIES(availableNums[i]) > 2) then
            if (current_difficulty == diff_easy) then
              if (count_troops(availableNums[i]) > 14) then
                if (IS_SHAMAN_AVAILABLE_FOR_ATTACK(availableNums[i]) > 0 and MANA(availableNums[i]) > 200000) then
                  local e = decide_an_enemy_to_attack(availableNums[i])
                  if (NAV_CHECK(availableNums[i],e,ATTACK_BUILDING,1,0) > 0) then
                    WRITE_CP_ATTRIB(availableNums[i], ATTR_AWAY_MEDICINE_MAN, 1)
                    ATTACK(availableNums[i],e,8+G_RANDOM(7),ATTACK_BUILDING,M_BUILDING_TEPEE,999,7,7,7,ATTACK_NORMAL,0,-1,-1,0)
                    WRITE_CP_ATTRIB(availableNums[i], ATTR_AWAY_MEDICINE_MAN, 0)
                    heavy_attack[i] = GetTurn() + (3072 + G_RANDOM(2048))
                    lite_attack[i] = GetTurn() + (1024 + G_RANDOM(512))
                  end
                end
              end
            elseif (current_difficulty == diff_medium) then
              if (count_troops(availableNums[i]) > 19) then
                if (IS_SHAMAN_AVAILABLE_FOR_ATTACK(availableNums[i]) > 0 and MANA(availableNums[i]) > 200000) then
                  local e = decide_an_enemy_to_attack(availableNums[i])
                  if (NAV_CHECK(availableNums[i],e,ATTACK_BUILDING,1,0) > 0) then
                    WRITE_CP_ATTRIB(availableNums[i], ATTR_AWAY_MEDICINE_MAN, 1)
                    ATTACK(availableNums[i],e,10+G_RANDOM(8),ATTACK_BUILDING,M_BUILDING_TEPEE,999,7,7,7,ATTACK_NORMAL,0,-1,-1,0)
                    WRITE_CP_ATTRIB(availableNums[i], ATTR_AWAY_MEDICINE_MAN, 0)
                    heavy_attack[i] = GetTurn() + (2048 + G_RANDOM(1536))
                    lite_attack[i] = GetTurn() + (512 + G_RANDOM(512))
                  end
                end
              end
            elseif (current_difficulty == diff_hard) then
              if (count_troops(availableNums[i]) > 24) then
                if (IS_SHAMAN_AVAILABLE_FOR_ATTACK(availableNums[i]) > 0 and MANA(availableNums[i]) > 200000) then
                  local e = decide_an_enemy_to_attack(availableNums[i])
                  if (NAV_CHECK(availableNums[i],e,ATTACK_BUILDING,1,0) > 0) then
                    WRITE_CP_ATTRIB(availableNums[i], ATTR_AWAY_MEDICINE_MAN, 1)
                    ATTACK(availableNums[i],e,12+G_RANDOM(12),ATTACK_BUILDING,M_BUILDING_TEPEE,999,6,7,7,ATTACK_NORMAL,0,-1,-1,0)
                    WRITE_CP_ATTRIB(availableNums[i], ATTR_AWAY_MEDICINE_MAN, 0)
                    heavy_attack[i] = GetTurn() + (1536 + G_RANDOM(1536))
                    lite_attack[i] = GetTurn() + (512 + G_RANDOM(512))
                  end
                end
              end
            elseif (current_difficulty == diff_expert) then
              if (count_troops(availableNums[i]) > 29) then
                if (IS_SHAMAN_AVAILABLE_FOR_ATTACK(availableNums[i]) > 0 and MANA(availableNums[i]) > 200000) then
                  local e = decide_an_enemy_to_attack(availableNums[i])
                  if (NAV_CHECK(availableNums[i],e,ATTACK_BUILDING,1,0) > 0) then
                    WRITE_CP_ATTRIB(availableNums[i], ATTR_AWAY_MEDICINE_MAN, 1)
                    ATTACK(availableNums[i],e,20+G_RANDOM(10),ATTACK_BUILDING,M_BUILDING_TEPEE,999,6,7,7,ATTACK_NORMAL,0,-1,-1,0)
                    WRITE_CP_ATTRIB(availableNums[i], ATTR_AWAY_MEDICINE_MAN, 0)
                    heavy_attack[i] = GetTurn() + (1024 + G_RANDOM(1024))
                    lite_attack[i] = GetTurn() + (512 + G_RANDOM(256))
                  end
                end
              end
            end
          end
        end
      end
    end

    if every2Pow(2) then
      for i,t in ipairs(lite_attack) do
        if (GetTurn() > t) then
          if (FREE_ENTRIES(availableNums[i]) > 2) then
            if (current_difficulty == diff_easy) then
              if (count_troops(availableNums[i]) > 7) then
                local e = decide_an_enemy_to_attack(availableNums[i])
                if (NAV_CHECK(availableNums[i],e,ATTACK_BUILDING,4,0) > 0) then
                  WRITE_CP_ATTRIB(availableNums[i], ATTR_AWAY_MEDICINE_MAN,0)
                  ATTACK(availableNums[i],e,2+G_RANDOM(2),ATTACK_BUILDING,4,750,0,0,0,ATTACK_NORMAL,0,-1,-1,0)
                  WRITE_CP_ATTRIB(availableNums[i], ATTR_AWAY_MEDICINE_MAN,1)
                  lite_attack[i] = GetTurn() + (1024 + G_RANDOM(1024))
                end
              end
            elseif (current_difficulty == diff_medium) then
              if (count_troops(availableNums[i]) > 7) then
                local e = decide_an_enemy_to_attack(availableNums[i])
                if (NAV_CHECK(availableNums[i],e,ATTACK_BUILDING,4,0) > 0) then
                  WRITE_CP_ATTRIB(availableNums[i], ATTR_AWAY_MEDICINE_MAN,0)
                  ATTACK(availableNums[i],e,2+G_RANDOM(4),ATTACK_BUILDING,4,750,0,0,0,ATTACK_NORMAL,0,-1,-1,0)
                  WRITE_CP_ATTRIB(availableNums[i], ATTR_AWAY_MEDICINE_MAN,1)
                  lite_attack[i] = GetTurn() + (1024 + G_RANDOM(512))
                end
              end
            elseif (current_difficulty == diff_hard) then
              if (count_troops(availableNums[i]) > 8) then
                local e = decide_an_enemy_to_attack(availableNums[i])
                if (NAV_CHECK(availableNums[i],e,ATTACK_BUILDING,4,0) > 0) then
                  WRITE_CP_ATTRIB(availableNums[i], ATTR_AWAY_MEDICINE_MAN,0)
                  ATTACK(availableNums[i],e,4+G_RANDOM(4),ATTACK_BUILDING,4,750,0,0,0,ATTACK_NORMAL,0,-1,-1,0)
                  WRITE_CP_ATTRIB(availableNums[i], ATTR_AWAY_MEDICINE_MAN,1)
                  lite_attack[i] = GetTurn() + (768 + G_RANDOM(512))
                end
              end
            elseif (current_difficulty == diff_expert) then
              if (count_troops(availableNums[i]) > 11) then
                local e = decide_an_enemy_to_attack(availableNums[i])
                if (NAV_CHECK(availableNums[i],e,ATTACK_BUILDING,4,0) > 0) then
                  WRITE_CP_ATTRIB(availableNums[i], ATTR_AWAY_MEDICINE_MAN,0)
                  ATTACK(availableNums[i],e,6+G_RANDOM(6),ATTACK_BUILDING,4,999,6,0,0,ATTACK_NORMAL,0,-1,-1,0)
                  WRITE_CP_ATTRIB(availableNums[i], ATTR_AWAY_MEDICINE_MAN,1)
                  lite_attack[i] = GetTurn() + (512 + G_RANDOM(256))
                end
              end
            end
          end
        end
      end
    end
    
    if every2Pow(2) then
      for i,t in ipairs(shaman_attack) do
        if (GetTurn() > t) then
          if (FREE_ENTRIES(availableNums[i]) > 2) then
            if (IS_SHAMAN_AVAILABLE_FOR_ATTACK(availableNums[i]) > 0 and MANA(availableNums[i]) > 200000) then
              local e = decide_an_enemy_to_attack(availableNums[i])
              if (NAV_CHECK(availableNums[i],e,ATTACK_BUILDING,1,0) > 0) then
                WRITE_CP_ATTRIB(availableNums[i], ATTR_AWAY_MEDICINE_MAN, 1)
                ATTACK(availableNums[i],e,0,ATTACK_BUILDING,1+G_RANDOM(3),999,7,7,7,ATTACK_NORMAL,0,-1,-1,0)
                WRITE_CP_ATTRIB(availableNums[i], ATTR_AWAY_MEDICINE_MAN, 0)
                if (current_difficulty == diff_easy) then
                  shaman_attack[i] = GetTurn() + (2048 + G_RANDOM(1024))
                elseif (current_difficulty == diff_medium) then
                  shaman_attack[i] = GetTurn() + (1536 + G_RANDOM(1024))
                elseif (current_difficulty == diff_hard) then
                  shaman_attack[i] = GetTurn() + (1024 + G_RANDOM(1024))
                elseif (current_difficulty == diff_expert) then
                  shaman_attack[i] = GetTurn() + (1024 + G_RANDOM(512))
                end
              end
            end
          end
        end
      end
    end

    if (every2Pow(9)) then
      for i = 0,5 do
        if (current_difficulty == diff_hard) then
          GIVE_MANA_TO_PLAYER(i,10000+G_RANDOM(20000))
        elseif (current_difficulty == diff_expert) then
          GIVE_MANA_TO_PLAYER(i,30000+G_RANDOM(20000))
        end
        if (PLAYERS_PEOPLE_OF_TYPE(i, M_PERSON_BRAVE) > 10 and _gsi.Players[i].NumPeople > 20) then
          if (current_difficulty == diff_easy) then
            WRITE_CP_ATTRIB(i, ATTR_PREF_WARRIOR_TRAINS, 1)
            WRITE_CP_ATTRIB(i, ATTR_PREF_WARRIOR_PEOPLE, 15+G_RANDOM(12))
            WRITE_CP_ATTRIB(i, ATTR_PREF_RELIGIOUS_TRAINS, 1)
            WRITE_CP_ATTRIB(i, ATTR_PREF_RELIGIOUS_PEOPLE, 12+G_RANDOM(10))
            WRITE_CP_ATTRIB(i, ATTR_PREF_SUPER_WARRIOR_TRAINS, 1)
            WRITE_CP_ATTRIB(i, ATTR_PREF_SUPER_WARRIOR_PEOPLE, 13+G_RANDOM(11))
            STATE_SET(i, FALSE, CP_AT_TYPE_MED_MAN_GET_WILD_PEEPS)
          elseif (current_difficulty == diff_medium) then
            WRITE_CP_ATTRIB(i, ATTR_PREF_WARRIOR_TRAINS, 1)
            WRITE_CP_ATTRIB(i, ATTR_PREF_WARRIOR_PEOPLE, 18+G_RANDOM(17))
            WRITE_CP_ATTRIB(i, ATTR_PREF_RELIGIOUS_TRAINS, 1)
            WRITE_CP_ATTRIB(i, ATTR_PREF_RELIGIOUS_PEOPLE, 15+G_RANDOM(15))
            WRITE_CP_ATTRIB(i, ATTR_PREF_SUPER_WARRIOR_TRAINS, 1)
            WRITE_CP_ATTRIB(i, ATTR_PREF_SUPER_WARRIOR_PEOPLE, 16+G_RANDOM(15))
            STATE_SET(i, FALSE, CP_AT_TYPE_MED_MAN_GET_WILD_PEEPS)
          elseif (current_difficulty == diff_hard) then
            WRITE_CP_ATTRIB(i, ATTR_PREF_WARRIOR_TRAINS, 1)
            WRITE_CP_ATTRIB(i, ATTR_PREF_WARRIOR_PEOPLE, 22+G_RANDOM(18))
            WRITE_CP_ATTRIB(i, ATTR_PREF_RELIGIOUS_TRAINS, 1)
            WRITE_CP_ATTRIB(i, ATTR_PREF_RELIGIOUS_PEOPLE, 18+G_RANDOM(16))
            WRITE_CP_ATTRIB(i, ATTR_PREF_SUPER_WARRIOR_TRAINS, 1)
            WRITE_CP_ATTRIB(i, ATTR_PREF_SUPER_WARRIOR_PEOPLE, 20+G_RANDOM(17))
            STATE_SET(i, FALSE, CP_AT_TYPE_MED_MAN_GET_WILD_PEEPS)
          elseif (current_difficulty == diff_expert) then
            WRITE_CP_ATTRIB(i, ATTR_PREF_WARRIOR_TRAINS, 1)
            WRITE_CP_ATTRIB(i, ATTR_PREF_WARRIOR_PEOPLE, 28+G_RANDOM(18))
            WRITE_CP_ATTRIB(i, ATTR_PREF_RELIGIOUS_TRAINS, 1)
            WRITE_CP_ATTRIB(i, ATTR_PREF_RELIGIOUS_PEOPLE, 22+G_RANDOM(18))
            WRITE_CP_ATTRIB(i, ATTR_PREF_SUPER_WARRIOR_TRAINS, 1)
            WRITE_CP_ATTRIB(i, ATTR_PREF_SUPER_WARRIOR_PEOPLE, 25+G_RANDOM(18))
            STATE_SET(i, FALSE, CP_AT_TYPE_MED_MAN_GET_WILD_PEEPS)
          end
        else
          WRITE_CP_ATTRIB(i, ATTR_PREF_WARRIOR_TRAINS, 0)
          WRITE_CP_ATTRIB(i, ATTR_PREF_WARRIOR_PEOPLE, 5)
          WRITE_CP_ATTRIB(i, ATTR_PREF_RELIGIOUS_TRAINS, 0)
          WRITE_CP_ATTRIB(i, ATTR_PREF_RELIGIOUS_PEOPLE, 5)
          WRITE_CP_ATTRIB(i, ATTR_PREF_SUPER_WARRIOR_TRAINS, 0)
          WRITE_CP_ATTRIB(i, ATTR_PREF_SUPER_WARRIOR_PEOPLE, 5)
          STATE_SET(i, TRUE, CP_AT_TYPE_MED_MAN_GET_WILD_PEEPS)
        end

        if (READ_CP_ATTRIB(i,ATTR_HOUSE_PERCENTAGE) < 180 and GetPlayerPeople(i) > READ_CP_ATTRIB(i,ATTR_HOUSE_PERCENTAGE)) then
          WRITE_CP_ATTRIB(i,ATTR_HOUSE_PERCENTAGE,READ_CP_ATTRIB(i,ATTR_HOUSE_PERCENTAGE)+2)
        end
      end
      if (current_difficulty == diff_hard) then
        GIVE_MANA_TO_PLAYER(7,10000+G_RANDOM(20000))
      elseif (current_difficulty == diff_expert) then
        GIVE_MANA_TO_PLAYER(7,30000+G_RANDOM(20000))
      end
      if (PLAYERS_PEOPLE_OF_TYPE(7, M_PERSON_BRAVE) > 10 and _gsi.Players[7].NumPeople > 20) then
        if (current_difficulty == diff_easy) then
          WRITE_CP_ATTRIB(7, ATTR_PREF_WARRIOR_TRAINS, 1)
          WRITE_CP_ATTRIB(7, ATTR_PREF_WARRIOR_PEOPLE, 15+G_RANDOM(12))
          WRITE_CP_ATTRIB(7, ATTR_PREF_RELIGIOUS_TRAINS, 1)
          WRITE_CP_ATTRIB(7, ATTR_PREF_RELIGIOUS_PEOPLE, 12+G_RANDOM(10))
          WRITE_CP_ATTRIB(7, ATTR_PREF_SUPER_WARRIOR_TRAINS, 1)
          WRITE_CP_ATTRIB(7, ATTR_PREF_SUPER_WARRIOR_PEOPLE, 13+G_RANDOM(11))
          STATE_SET(7, FALSE, CP_AT_TYPE_MED_MAN_GET_WILD_PEEPS)
        elseif (current_difficulty == diff_medium) then
          WRITE_CP_ATTRIB(7, ATTR_PREF_WARRIOR_TRAINS, 1)
          WRITE_CP_ATTRIB(7, ATTR_PREF_WARRIOR_PEOPLE, 18+G_RANDOM(17))
          WRITE_CP_ATTRIB(7, ATTR_PREF_RELIGIOUS_TRAINS, 1)
          WRITE_CP_ATTRIB(7, ATTR_PREF_RELIGIOUS_PEOPLE, 15+G_RANDOM(15))
          WRITE_CP_ATTRIB(7, ATTR_PREF_SUPER_WARRIOR_TRAINS, 1)
          WRITE_CP_ATTRIB(7, ATTR_PREF_SUPER_WARRIOR_PEOPLE, 16+G_RANDOM(15))
          STATE_SET(7, FALSE, CP_AT_TYPE_MED_MAN_GET_WILD_PEEPS)
        elseif (current_difficulty == diff_hard) then
          WRITE_CP_ATTRIB(7, ATTR_PREF_WARRIOR_TRAINS, 1)
          WRITE_CP_ATTRIB(7, ATTR_PREF_WARRIOR_PEOPLE, 22+G_RANDOM(18))
          WRITE_CP_ATTRIB(7, ATTR_PREF_RELIGIOUS_TRAINS, 1)
          WRITE_CP_ATTRIB(7, ATTR_PREF_RELIGIOUS_PEOPLE, 18+G_RANDOM(16))
          WRITE_CP_ATTRIB(7, ATTR_PREF_SUPER_WARRIOR_TRAINS, 1)
          WRITE_CP_ATTRIB(7, ATTR_PREF_SUPER_WARRIOR_PEOPLE, 20+G_RANDOM(17))
          STATE_SET(7, FALSE, CP_AT_TYPE_MED_MAN_GET_WILD_PEEPS)
        elseif (current_difficulty == diff_expert) then
          WRITE_CP_ATTRIB(7, ATTR_PREF_WARRIOR_TRAINS, 1)
          WRITE_CP_ATTRIB(7, ATTR_PREF_WARRIOR_PEOPLE, 28+G_RANDOM(18))
          WRITE_CP_ATTRIB(7, ATTR_PREF_RELIGIOUS_TRAINS, 1)
          WRITE_CP_ATTRIB(7, ATTR_PREF_RELIGIOUS_PEOPLE, 22+G_RANDOM(18))
          WRITE_CP_ATTRIB(7, ATTR_PREF_SUPER_WARRIOR_TRAINS, 1)
          WRITE_CP_ATTRIB(7, ATTR_PREF_SUPER_WARRIOR_PEOPLE, 25+G_RANDOM(18))
          STATE_SET(7, FALSE, CP_AT_TYPE_MED_MAN_GET_WILD_PEEPS)
        end
      else
        WRITE_CP_ATTRIB(7, ATTR_PREF_WARRIOR_TRAINS, 0)
        WRITE_CP_ATTRIB(7, ATTR_PREF_WARRIOR_PEOPLE, 5)
        WRITE_CP_ATTRIB(7, ATTR_PREF_RELIGIOUS_TRAINS, 0)
        WRITE_CP_ATTRIB(7, ATTR_PREF_RELIGIOUS_PEOPLE, 5)
        WRITE_CP_ATTRIB(7, ATTR_PREF_SUPER_WARRIOR_TRAINS, 0)
        WRITE_CP_ATTRIB(7, ATTR_PREF_SUPER_WARRIOR_PEOPLE, 5)
        STATE_SET(7, TRUE, CP_AT_TYPE_MED_MAN_GET_WILD_PEEPS)
      end

      if (READ_CP_ATTRIB(7,ATTR_HOUSE_PERCENTAGE) < 180 and GetPlayerPeople(7) > READ_CP_ATTRIB(7,ATTR_HOUSE_PERCENTAGE)) then
        WRITE_CP_ATTRIB(7,ATTR_HOUSE_PERCENTAGE,READ_CP_ATTRIB(7,ATTR_HOUSE_PERCENTAGE)+2)
        end
    end

    if (every2Pow(uprate)) then
      ProcessGlobalTypeList(T_BUILDING, function(t)
        if (t.Model < 4 and t.Owner ~= 6) then
          if (t.u.Bldg.SproggingCount < 2000) then
            t.u.Bldg.SproggingCount = t.u.Bldg.SproggingCount + 1500
          end
        end

        if (t.Model < 3 and t.Owner ~= 6) then
          if (t.u.Bldg.UpgradeCount < 1825) then
            t.u.Bldg.UpgradeCount = t.u.Bldg.UpgradeCount + 350
          end
        end

        return true
      end)
    end

    if (every2Pow(9)) then
      if (tablelength(blueTowers) > 0 and GetPlayerPeople(0) > 0 and (_gsi.Players[TRIBE_BLUE].NumPeopleOfType[M_PERSON_SUPER_WARRIOR] > 0 or _gsi.Players[TRIBE_BLUE].NumPeopleOfType[M_PERSON_RELIGIOUS] > 0)) then
        local t_idx = tablelength(blueTowers)
        local t_rnd = G_RANDOM(t_idx)+1
        if (blueTowers[t_rnd] ~= nil and FREE_ENTRIES(TRIBE_BLUE) > 1) then
          local map_idx = MapPosXZ.new()
          map_idx.Pos = world_coord3d_to_map_idx(blueTowers[t_rnd])
          BUILD_DRUM_TOWER(TRIBE_BLUE, map_idx.XZ.X, map_idx.XZ.Z)
          table.remove(blueTowers, t_rnd)
        end
      end

      if (tablelength(redTowers) > 0 and GetPlayerPeople(1) > 0 and (_gsi.Players[TRIBE_RED].NumPeopleOfType[M_PERSON_SUPER_WARRIOR] > 0 or _gsi.Players[TRIBE_RED].NumPeopleOfType[M_PERSON_RELIGIOUS] > 0)) then
        local t_idx = tablelength(redTowers)
        local t_rnd = G_RANDOM(t_idx)+1
        if (redTowers[t_rnd] ~= nil and FREE_ENTRIES(TRIBE_RED) > 1) then
          local map_idx = MapPosXZ.new()
          map_idx.Pos = world_coord3d_to_map_idx(redTowers[t_rnd])
          BUILD_DRUM_TOWER(TRIBE_RED, map_idx.XZ.X, map_idx.XZ.Z)
          table.remove(redTowers, t_rnd)
        end
      end

      if (tablelength(yellowTowers) > 0 and GetPlayerPeople(2) > 0 and (_gsi.Players[TRIBE_YELLOW].NumPeopleOfType[M_PERSON_SUPER_WARRIOR] > 0 or _gsi.Players[TRIBE_YELLOW].NumPeopleOfType[M_PERSON_RELIGIOUS] > 0)) then
        local t_idx = tablelength(yellowTowers)
        local t_rnd = G_RANDOM(t_idx)+1
        if (yellowTowers[t_rnd] ~= nil and FREE_ENTRIES(TRIBE_YELLOW) > 1) then
          local map_idx = MapPosXZ.new()
          map_idx.Pos = world_coord3d_to_map_idx(yellowTowers[t_rnd])
          BUILD_DRUM_TOWER(TRIBE_YELLOW, map_idx.XZ.X, map_idx.XZ.Z)
          table.remove(yellowTowers, t_rnd)
        end
      end

      if (tablelength(greenTowers) > 0 and GetPlayerPeople(3) > 0 and (_gsi.Players[TRIBE_GREEN].NumPeopleOfType[M_PERSON_SUPER_WARRIOR] > 0 or _gsi.Players[TRIBE_GREEN].NumPeopleOfType[M_PERSON_RELIGIOUS] > 0)) then
        local t_idx = tablelength(greenTowers)
        local t_rnd = G_RANDOM(t_idx)+1
        if (greenTowers[t_rnd] ~= nil and FREE_ENTRIES(TRIBE_GREEN) > 1) then
          local map_idx = MapPosXZ.new()
          map_idx.Pos = world_coord3d_to_map_idx(greenTowers[t_rnd])
          BUILD_DRUM_TOWER(TRIBE_GREEN, map_idx.XZ.X, map_idx.XZ.Z)
          table.remove(greenTowers, t_rnd)
        end
      end

      if (tablelength(cyanTowers) > 0 and GetPlayerPeople(4) > 0 and (_gsi.Players[TRIBE_CYAN].NumPeopleOfType[M_PERSON_SUPER_WARRIOR] > 0 or _gsi.Players[TRIBE_CYAN].NumPeopleOfType[M_PERSON_RELIGIOUS] > 0)) then
        local t_idx = tablelength(cyanTowers)
        local t_rnd = G_RANDOM(t_idx)+1
        if (cyanTowers[t_rnd] ~= nil and FREE_ENTRIES(TRIBE_CYAN) > 1) then
          local map_idx = MapPosXZ.new()
          map_idx.Pos = world_coord3d_to_map_idx(cyanTowers[t_rnd])
          BUILD_DRUM_TOWER(TRIBE_CYAN, map_idx.XZ.X, map_idx.XZ.Z)
          table.remove(cyanTowers, t_rnd)
        end
      end

      if (tablelength(magentaTowers) > 0 and GetPlayerPeople(5) > 0 and (_gsi.Players[TRIBE_PINK].NumPeopleOfType[M_PERSON_SUPER_WARRIOR] > 0 or _gsi.Players[TRIBE_PINK].NumPeopleOfType[M_PERSON_RELIGIOUS] > 0)) then
        local t_idx = tablelength(magentaTowers)
        local t_rnd = G_RANDOM(t_idx)+1
        if (magentaTowers[t_rnd] ~= nil and FREE_ENTRIES(TRIBE_PINK) > 1) then
          local map_idx = MapPosXZ.new()
          map_idx.Pos = world_coord3d_to_map_idx(magentaTowers[t_rnd])
          BUILD_DRUM_TOWER(TRIBE_PINK, map_idx.XZ.X, map_idx.XZ.Z)
          table.remove(magentaTowers, t_rnd)
        end
      end

      if (tablelength(orangeTowers) > 0 and GetPlayerPeople(7) > 0 and (_gsi.Players[TRIBE_ORANGE].NumPeopleOfType[M_PERSON_SUPER_WARRIOR] > 0 or _gsi.Players[TRIBE_ORANGE].NumPeopleOfType[M_PERSON_RELIGIOUS] > 0)) then
        local t_idx = tablelength(orangeTowers)
        local t_rnd = G_RANDOM(t_idx)+1
        if (orangeTowers[t_rnd] ~= nil and FREE_ENTRIES(TRIBE_ORANGE) > 1) then
          local map_idx = MapPosXZ.new()
          map_idx.Pos = world_coord3d_to_map_idx(orangeTowers[t_rnd])
          BUILD_DRUM_TOWER(TRIBE_ORANGE, map_idx.XZ.X, map_idx.XZ.Z)
          table.remove(orangeTowers, t_rnd)
        end
      end
    end

    if (every2Pow(2)) then
      if (current_difficulty > diff_easy) then
        for i=1,tablelength(availableNums) do
          local shaman = getShaman(availableNums[i])
          if (shaman ~= nil) then
            if (shaman.State == S_PERSON_DROWNING) then
              SearchMapCells(CIRCULAR, 0, 0, 6, world_coord2d_to_map_idx(shaman.Pos.D2), function(me)
                if (is_map_elem_coast(me) > 0 and spell_delay[i] == 0) then
                  local c2d = Coord2D.new()
                  map_ptr_to_world_coord2d(me, c2d)
                  local c3d = Coord3D.new()
                  coord2D_to_coord3D(c2d, c3d)
                  if (current_difficulty == diff_medium) then
                    if (G_RANDOM(3) == 1) then
                      createThing(T_SPELL, M_SPELL_LAND_BRIDGE, shaman.Owner, c3d, false, false)
                    end
                  else
                    createThing(T_SPELL, M_SPELL_LAND_BRIDGE, shaman.Owner, c3d, false, false)
                  end
                  if (current_difficulty == diff_expert) then
                    spell_delay[i] = 48
                  else
                    spell_delay[i] = 128
                  end
                  return false
                end

                return true
              end)
            end
          end
        end
      end
    end

    if (every2Pow(3)) then
      if (_gsi.Players[TRIBE_YELLOW].NumPeople +
          _gsi.Players[TRIBE_GREEN].NumPeople +
          _gsi.Players[TRIBE_RED].NumPeople +
          _gsi.Players[TRIBE_PINK].NumPeople +
          _gsi.Players[TRIBE_CYAN].NumPeople +
          _gsi.Players[TRIBE_ORANGE].NumPeople +
          _gsi.Players[TRIBE_BLUE].NumPeople < 500 and
          GetTurn() < STurn + (12*60)*4 and
          GetTurn() > STurn + (12*10)) then
        process(numthings)
      end
    end

    if (every2Pow(srate)) then
      if (current_difficulty > diff_easy) then
        for i,v in ipairs(availableNums) do
          if (spell_ms_used[i] < spell_ms_max_use) then
            local s = getShaman(v)
            if (s ~= nil and is_thing_on_ground(s) == 1) then
              local last_thing = nil
              local total_count = 0
              SearchMapCells(SQUARE,0,0,spell_ms_radius,world_coord2d_to_map_idx(s.Pos.D2),function(me)
                local count = 0
                me.MapWhoList:processList(function(t)
                  if (count < 6) then
                    if (t.Type == T_PERSON) then
                      if (t.Model > 2 and t.Model < 7 and t.Owner == s.Owner and not isFlagEnabled(t.Flags3, TF3_SHIELD_ACTIVE)) then
                        count=count+1
                        if (count > 0) then
                         last_thing = t
                         total_count=total_count+1
                        end
                      end
                    end
                    return true
                  else return false
                  end
                end)
                return true
              end)

              if (last_thing ~= nil and total_count > 2) then
                local thing_s = M_SPELL_SHIELD
                if (current_difficulty == diff_expert) then
                  if (G_RANDOM(8) == 1) then
                    thing_s = M_SPELL_BLOODLUST
                  end
                end
                createThing(T_SPELL,thing_s,s.Owner,last_thing.Pos.D3,false,false)
                spell_ms_used[i]=spell_ms_used[i]+1
                if (spell_ms_delay[i] == 0) then
                  spell_ms_delay[i]=calc_limit(v)
                end
              end
            end
          end
        end
      end
    end

    for i,v in ipairs(spell_ms_delay) do
      if (spell_ms_delay[i] > 0 and spell_ms_used[i] > 0) then
        spell_ms_delay[i]=v-1
      elseif(spell_ms_delay[i] == 0 and spell_ms_used[i] > 0) then
        spell_ms_delay[i]=calc_limit(i)
        spell_ms_used[i]=spell_ms_used[i]-1
      end
    end

    for i,v in ipairs(spell_delay) do
      if (v > 0) then
        spell_delay[i] = v-1
      end
    end
  end

  if (every2Pow(5)) then
    if (current_difficulty >= diff_hard) then
      for i,v in ipairs(availableNums) do
        local shaman = getShaman(v)
        if (shaman ~= nil) then
          ProcessGlobalTypeList(T_PERSON, function(t)
            if (t.Owner ~= v) then
              if (get_world_dist_xyz(shaman.Pos.D3, t.Pos.D3) < 3500 + shaman.Pos.D3.Ypos*3 and t.Model > 2 and t.Model < 7 and isFlagEnabled(t.Flags3, TF3_SHIELD_ACTIVE) and h_charges[i] > 0 and not isFlagEnabled(t.Flags2, TF2_THING_IS_AN_INVISIBLE_PERSON)) then
                if (is_thing_on_ground(shaman) == 1) then
                  createThing(T_SPELL, M_SPELL_HYPNOTISM, shaman.Owner, t.Pos.D3, false, false)
                  h_charges[i] = h_charges[i] - 1
                  return false
                end
              elseif (get_world_dist_xyz(shaman.Pos.D3, t.Pos.D3) < 6000 + shaman.Pos.D3.Ypos*3 and t.Model == M_PERSON_MEDICINE_MAN) then
                if (l_charges[i] > 0 and is_thing_on_ground(shaman) == 1) then
                  createThing(T_SPELL, M_SPELL_LIGHTNING_BOLT, shaman.Owner, t.Pos.D3, false, false)
                  l_charges[i] = l_charges[i] - 1
                  return false
                end
              end
            end

            return true
          end)
        end
      end
    end
  end

  for i = 1,7 do
    if (l_charges[i] < 4) then
      l_charge_time[i] = l_charge_time[i] - 1
      if (l_charge_time[i] < 1) then
        l_charges[i] = l_charges[i] + 1
        l_charge_time[i] = 540
      end
    end
    if (h_charges[i] < 3) then
      h_charge_time[i] = h_charge_time[i] - 1
      if (h_charge_time[i] < 1) then
        h_charges[i] = h_charges[i] + 1
        h_charge_time[i] = 720
      end
    end
  end
end

ProcessGlobalTypeList(T_PERSON, function(t)
  if (t.Model == M_PERSON_WILD) then
    table.insert(wilds, t)
  end
  return true
end)

function OnCreateThing(t)
  if (t.Type == T_PERSON and t.Model == M_PERSON_WILD) then
    table.insert(wilds, t)
  end
end

function process(n)
  for i = 0,n do
    if (index < tablelength(wilds)) then
      local t = GetThing(wilds[index].ThingNum)
      if (t ~= nil and t.Type == T_PERSON and t.Model == M_PERSON_WILD) then
        local idx = G_RANDOM(tablelength(availableNums))+1
        local s = getShaman(availableNums[idx])
        if (s ~= nil) then
          if(get_world_dist_xyz(t.Pos.D3, s.Pos.D3) < (8192 + s.Pos.D3.Ypos*3) and spell_delay[idx] == 0) then
            createThing(T_SPELL, M_SPELL_CONVERT_WILD, s.Owner, t.Pos.D3, false, false)
            spell_delay[idx] = 24
          elseif(get_world_dist_xyz(t.Pos.D3, conv_center_pos[idx]) < 512*16 and get_thing_curr_cmd_list_ptr(s) == nil) then
            command_person_go_to_coord2d(s, t.Pos.D2)
          end
        end
      else
        table.remove(wilds, index)
      end
      index = index+1
    else
      index = 1
    end
  end
end

function calc_limit(pn)
  if (_gsi.Players[pn].NumPeople > spell_ms_charge_time) then
    return 1 else return spell_ms_charge_time-_gsi.Players[pn].NumPeople
  end
end

function count_enemy_bldgs_around(myself,x,z,radiii)
  local count = 0
  local c3d = MAP_XZ_2_WORLD_XYZ(x,z)
  SearchMapCells(SQUARE,0,0,radiii,world_coord3d_to_map_idx(c3d),function(me)
    me.MapWhoList:processList(function(t)
      if (t.Type == T_BUILDING) then
        if (t.Owner ~= myself and are_players_allied(t.Owner,myself) == 0) then
          count=count+1
        end
      end
      return true
    end)
    return true
  end)
  return count
end

function count_people(myself,coord2,radii)
  local count = 0
  SearchMapCells(CIRCULAR, 0, 0, radii, world_coord3d_to_map_idx(coord2), function(me)
    me.MapWhoList:processList(function (t)
      if (t.Type == T_PERSON) then
        if (t.Owner ~= myself and are_players_allied(myself,t.Owner) == 0) then
          count = count+1
        end
      end
      return true
    end)
    return true
  end)

  return count
end

function decide_an_enemy_to_attack(myself)
  local i = myself
  local tries = 16
  while (tries > 0) do
    tries=tries-1
    if (current_difficulty == diff_easy) then
      if (G_RANDOM(7) == 1) then
        i = 1 + G_RANDOM(MAX_NUM_REAL_PLAYERS-1)
        if (i == 6) then
          i = 0
        end
      else
        i = G_RANDOM(MAX_NUM_REAL_PLAYERS)
      end
    elseif (current_difficulty == diff_hard) then
      if (getPlayer(6).NumPeople > 249) then
        i = 6
      else
        if (G_RANDOM(8) == 1) then
          i = 6
        else
          i = G_RANDOM(MAX_NUM_REAL_PLAYERS)
        end
      end
    elseif (current_difficulty == diff_expert) then
      if (getPlayer(6).NumPeople > 199) then
        i = 6
      else
        if (G_RANDOM(5) == 1) then
          i = 6
        else
          i = G_RANDOM(MAX_NUM_REAL_PLAYERS)
        end
      end
    else
      if (getPlayer(6).NumPeople > 274) then
        i = 6
      else
        i = G_RANDOM(MAX_NUM_REAL_PLAYERS)
      end
    end
    if (i ~= myself and are_players_allied(i,myself) == 0) then
      if (GetPlayerPeople(i) > 0) then
        if (NAV_CHECK(myself,i,ATTACK_BUILDING,0,0) == 1) then
          break
        end
      end
    end
  end
  return i
end

function count_troops(pn)
  local count = 0
  ProcessGlobalTypeList(T_PERSON, function(t)
    if (t.Owner == pn) then
      if (t.Model == M_PERSON_WARRIOR) then
        count=count+1
      end
      if (t.Model == M_PERSON_RELIGIOUS) then
        count=count+1
      end
      if (t.Model == M_PERSON_SUPER_WARRIOR) then
        count=count+1
      end
    end
    return true
  end)

  return count
end
