-- Populous the Beginning: LUA Scripting Case: Advanced Scripting

-- Import modules and include files
import(Module_System)
import(Module_Players)
import(Module_Defines)
import(Module_PopScript)
import(Module_Game)
import(Module_Objects)
import(Module_Map)
import(Module_Math)
import(Module_Globals)
include("UtilPThings.lua")
include("UtilRefs.lua")
_gsi = gsi()

-- Variables we're going to use
spell_delay = 0
count = 0
building_count = 0

-- Initiate the BLUE tribe
computer_init_player(_gsi.Players[TRIBE_BLUE])

-- Set spell attributes for BLUE
PThing.SpellSet(TRIBE_BLUE, M_SPELL_CONVERT_WILD, TRUE, FALSE)
PThing.SpellSet(TRIBE_BLUE, M_SPELL_BLAST, TRUE, FALSE)
PThing.SpellSet(TRIBE_BLUE, M_SPELL_LAND_BRIDGE, TRUE, FALSE)
PThing.SpellSet(TRIBE_BLUE, M_SPELL_INSECT_PLAGUE, TRUE, FALSE)

-- Set building attributes for BLUE
PThing.BldgSet(TRIBE_BLUE, M_BUILDING_TEPEE, TRUE) -- Hut
PThing.BldgSet(TRIBE_BLUE, M_BUILDING_DRUM_TOWER, TRUE)
PThing.BldgSet(TRIBE_BLUE, M_BUILDING_WARRIOR_TRAIN, TRUE)
PThing.BldgSet(TRIBE_BLUE, M_BUILDING_TEMPLE, TRUE)

-- Set internal attributes for BLUE
WRITE_CP_ATTRIB(TRIBE_BLUE, ATTR_EXPANSION, 50)
WRITE_CP_ATTRIB(TRIBE_BLUE, ATTR_HOUSE_PERCENTAGE, 70)
WRITE_CP_ATTRIB(TRIBE_BLUE, ATTR_MAX_BUILDINGS_ON_GO, 15)
WRITE_CP_ATTRIB(TRIBE_BLUE, ATTR_MAX_TRAIN_AT_ONCE, 5)
WRITE_CP_ATTRIB(TRIBE_BLUE, ATTR_AWAY_BRAVE, 50)
WRITE_CP_ATTRIB(TRIBE_BLUE, ATTR_AWAY_WARRIOR, 0)
WRITE_CP_ATTRIB(TRIBE_BLUE, ATTR_AWAY_SUPER_WARRIOR, 0)
WRITE_CP_ATTRIB(TRIBE_BLUE, ATTR_AWAY_RELIGIOUS, 0)
WRITE_CP_ATTRIB(TRIBE_BLUE, ATTR_AWAY_SPY, 0)
WRITE_CP_ATTRIB(TRIBE_BLUE, ATTR_AWAY_MEDICINE_MAN, 100)
WRITE_CP_ATTRIB(TRIBE_BLUE, ATTR_MAX_ATTACKS, 999)

-- Set states for BLUE
STATE_SET(TRIBE_BLUE, TRUE, CP_AT_TYPE_CONSTRUCT_BUILDING)
STATE_SET(TRIBE_BLUE, TRUE, CP_AT_TYPE_FETCH_WOOD)
STATE_SET(TRIBE_BLUE, TRUE, CP_AT_TYPE_MED_MAN_GET_WILD_PEEPS)
STATE_SET(TRIBE_BLUE, TRUE, CP_AT_TYPE_HOUSE_A_PERSON)
STATE_SET(TRIBE_BLUE, TRUE, CP_AT_TYPE_POPULATE_DRUM_TOWER)
STATE_SET(TRIBE_BLUE, TRUE, CP_AT_TYPE_DEFEND)
STATE_SET(TRIBE_BLUE, TRUE, CP_AT_TYPE_DEFEND_BASE)
STATE_SET(TRIBE_BLUE, TRUE, CP_AT_TYPE_PREACH)
STATE_SET(TRIBE_BLUE, TRUE, CP_AT_TYPE_SPELL_DEFENCE)
STATE_SET(TRIBE_BLUE, TRUE, CP_AT_TYPE_BUILD_VEHICLE)
STATE_SET(TRIBE_BLUE, TRUE, CP_AT_TYPE_FETCH_LOST_PEOPLE)
STATE_SET(TRIBE_BLUE, FALSE, CP_AT_TYPE_FETCH_LOST_VEHICLE)
STATE_SET(TRIBE_BLUE, TRUE, CP_AT_TYPE_FETCH_FAR_VEHICLE)
STATE_SET(TRIBE_BLUE, TRUE, CP_AT_TYPE_TRAIN_PEOPLE) 
STATE_SET(TRIBE_BLUE, TRUE, CP_AT_TYPE_AUTO_ATTACK)

-- Don�t build the drum tower
DELAY_MAIN_DRUM_TOWER(TRUE,TRIBE_BLUE)

-- Spell entries
SET_SPELL_ENTRY(TRIBE_BLUE, 0, M_SPELL_INSECT_PLAGUE, 25000, 64, 3, 0)
SET_SPELL_ENTRY(TRIBE_BLUE, 1, M_SPELL_INSECT_PLAGUE, 25000, 64, 3, 1)

-- Marker entries
for i = 0,7 do
SET_MARKER_ENTRY(TRIBE_BLUE, i, i, i, 0, 0, 2, 0)
end

function OnTurn()
  
    -- A log that tracks the current GameTurn
    --log("Turn: " .. _gsi.Counts.GameTurn)

    -- Activating the marker entries
    if (_gsi.Counts.GameTurn == 512) then
        for i = 3,7 do
        MARKER_ENTRIES(TRIBE_BLUE, i, -1, -1, -1)
        end
        log("Just activated the marker entries!")
    end

    -- Attacking the RED tribe
    if (every2Pow(10) and _gsi.Players[TRIBE_BLUE].NumPeople > 30 and PLAYERS_PEOPLE_OF_TYPE(TRIBE_BLUE, M_PERSON_BRAVE) > 15) then
        log("I will attack!")
        ATTACK(TRIBE_BLUE, TRIBE_RED, 10, ATTACK_BUILDING, -1, 999, M_SPELL_WHIRLWIND, M_SPELL_LIGHTNING_BOLT, M_SPELL_LIGHTNING_BOLT, ATTACK_NORMAL, 0, NO_MARKER, NO_MARKER, NO_MARKER)
    end

    -- Our shaman-only attack
    if (every2Pow(10)) then
        local shaman = getShaman(TRIBE_BLUE)
        if (shaman ~= nil) then
            if IS_SHAMAN_AVAILABLE_FOR_ATTACK(TRIBE_BLUE) then
                log("Moving shaman to marker...")
                MOVE_SHAMAN_TO_MARKER(TRIBE_BLUE, 13)
                log("Here comes a shaman-only attack!")
                --ProcessGlobalTypeList(T_BUILDING, function(t)
                --if (t.Owner == TRIBE_RED) then
                --createThing(T_SPELL, M_SPELL_WHIRLWIND, shaman.Owner, t.Pos.D3, false, false)
                --end
                --return true
                --end)
            end
        end
    end

    -- Our shaman behaviour during the shaman-only attack
    local shaman = getShaman(TRIBE_BLUE)
    if (shaman ~= nil and spell_delay == 0) then
        SearchMapCells(CIRCULAR,0,0,10,world_coord2d_to_map_idx(shaman.Pos.D2),function(me)
        me.MapWhoList:processList(function(t)
        if (t.Type == T_BUILDING) then
            if (t.Owner ~= TRIBE_BLUE) then
                building_count = building_count + 1
                log("Building count: " .. building_count)
                local c2d = Coord2D.new()
                map_ptr_to_world_coord2d(me, c2d)
                local c3d = Coord3D.new()
                coord2D_to_coord3D(c2d, c3d)
                if (building_count > 1) then
                    no_enemy_buildings = count_enemy_buildings(c3d,2)
                    if (no_enemy_buildings > 1 and spell_delay == 0) then
                        createThing(T_SPELL, M_SPELL_LIGHTNING_BOLT, shaman.Owner, c3d, false, false)
                        spell_delay = 120;
                        return false
                    end
                end
            end
        end 
        return true
        end)
        return true
        end)
        building_count = 0
    end

    -- Placing tower plans
    if (_gsi.Counts.GameTurn == 512) then
        log("Trying to build towers!")
        BUILD_DRUM_TOWER(TRIBE_BLUE, 0, 10)
        BUILD_DRUM_TOWER(TRIBE_BLUE, 10, 0)
        BUILD_DRUM_TOWER(TRIBE_BLUE, 240, 240)
        BUILD_DRUM_TOWER(TRIBE_BLUE, 230, 0)
    end

    -- Saving the shaman from drowning with a land bridge spell
    local shaman = getShaman(TRIBE_BLUE)
    if (shaman ~= nil) then
        if (shaman.State == S_PERSON_DROWNING and spell_delay == 0) then
            SearchMapCells(CIRCULAR, 0, 0, 6, world_coord2d_to_map_idx(shaman.Pos.D2), function(me)
            if (is_map_elem_coast(me) > 0) then
                local c2d = Coord2D.new()
                map_ptr_to_world_coord2d(me, c2d)
                local c3d = Coord3D.new()
                coord2D_to_coord3D(c2d, c3d)
                createThing(T_SPELL, M_SPELL_LAND_BRIDGE, shaman.Owner, c3d, false, false)
                spell_delay = 36
                return false
            end
            return true
            end)
        end
    end

    -- Attacking the RED shaman with blast or lightning spells
    local shaman = getShaman(TRIBE_BLUE)
    if (shaman ~= nil) then
        ProcessGlobalTypeList(T_PERSON, function(t)
        if (t.Owner == TRIBE_RED) then
            if (get_world_dist_xyz(shaman.Pos.D3, t.Pos.D3) < 3092 + shaman.Pos.D3.Ypos*3) then
                 if (spell_delay == 0 and is_thing_on_ground(shaman) == 1) then
                    createThing(T_SPELL, M_SPELL_BLAST, shaman.Owner, t.Pos.D3, false, false)
                    spell_delay = 24
                    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 (spell_delay == 0 and is_thing_on_ground(shaman) == 1) then
                    createThing(T_SPELL, M_SPELL_LIGHTNING_BOLT, shaman.Owner, t.Pos.D3, false, false)
                    spell_delay = 60
                    return false
                end
            end
        end
        return true
        end)
    end

    -- Intelligent conversion of wildmen
    if (every2Pow(6)) then
        local shaman = getShaman(TRIBE_BLUE)
        if (shaman ~= nil) then
            ProcessGlobalTypeList(T_PERSON, function(t)
            if (t.Model == M_PERSON_WILD) and (get_world_dist_xyz(shaman.Pos.D3, t.Pos.D3) < 8192 + shaman.Pos.D3.Ypos*3) then
                createThing(T_SPELL, M_SPELL_CONVERT_WILD, shaman.Owner, t.Pos.D3, false, false)
                return false
            end
            return true
            end)
        end
    end

    -- Changing the spell delay every turn
    if (spell_delay > 0) then
    spell_delay = spell_delay - 1
    end

end

-- Function to count enemy buildings from c3d coordinate
function count_enemy_buildings(c3d,radius)
local count = 0;
SearchMapCells(CIRCULAR,0,0,radius,world_coord3d_to_map_idx(c3d),function(me)
me.MapWhoList:processList(function(t)
if (t.Type == T_BUILDING) then
if (t.Owner ~= TRIBE_BLUE) then
			count = count+1
end
end 
return true
end)
return true
end)
return count  
end