1
0
mirror of https://github.com/veden/Rampant.git synced 2025-01-07 23:01:39 +02:00
Rampant/libs/AIPlanning.lua
2019-12-15 17:16:56 -08:00

353 lines
14 KiB
Lua
Executable File

if aiPlanningG then
return aiPlanningG
end
local aiPlanning = {}
-- imports
local constants = require("Constants")
local mathUtils = require("MathUtils")
-- local aiPredicates = require("AIPredicates")
-- constants
local NO_RETREAT_BASE_PERCENT = constants.NO_RETREAT_BASE_PERCENT
local NO_RETREAT_EVOLUTION_BONUS_MAX = constants.NO_RETREAT_EVOLUTION_BONUS_MAX
local AI_STATE_PEACEFUL = constants.AI_STATE_PEACEFUL
local AI_STATE_AGGRESSIVE = constants.AI_STATE_AGGRESSIVE
local AI_STATE_RAIDING = constants.AI_STATE_RAIDING
local AI_STATE_MIGRATING = constants.AI_STATE_MIGRATING
local AI_STATE_ONSLAUGHT = constants.AI_STATE_ONSLAUGHT
local AI_STATE_SIEGE = constants.AI_STATE_SIEGE
local AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION = constants.AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION
local AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION = constants.AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION
local AI_UNIT_REFUND = constants.AI_UNIT_REFUND
local AI_MAX_POINTS = constants.AI_MAX_POINTS
local AI_POINT_GENERATOR_AMOUNT = constants.AI_POINT_GENERATOR_AMOUNT
local AI_MIN_STATE_DURATION = constants.AI_MIN_STATE_DURATION
local AI_MIN_TEMPERAMENT_DURATION = constants.AI_MIN_TEMPERAMENT_DURATION
local AI_MAX_STATE_DURATION = constants.AI_MAX_STATE_DURATION
local AI_MAX_TEMPERAMENT_DURATION = constants.AI_MAX_TEMPERAMENT_DURATION
local BASE_RALLY_CHANCE = constants.BASE_RALLY_CHANCE
local BONUS_RALLY_CHANCE = constants.BONUS_RALLY_CHANCE
local RETREAT_MOVEMENT_PHEROMONE_LEVEL_MIN = constants.RETREAT_MOVEMENT_PHEROMONE_LEVEL_MIN
local RETREAT_MOVEMENT_PHEROMONE_LEVEL_MAX = constants.RETREAT_MOVEMENT_PHEROMONE_LEVEL_MAX
-- imported functions
local randomTickEvent = mathUtils.randomTickEvent
local linearInterpolation = mathUtils.linearInterpolation
local mFloor = math.floor
local mRandom = math.random
local mMax = math.max
local mMin = math.min
-- module code
function aiPlanning.planning(natives, evolution_factor, tick)
natives.evolutionLevel = evolution_factor
local maxPoints = AI_MAX_POINTS * evolution_factor
if not natives.ranIncompatibleMessage and natives.newEnemies and (game.active_mods["bobenemies"] or game.active_mods["Natural_Evolution_Enemies"]) then
natives.ranIncompatibleMessage = true
for i,p in ipairs(game.connected_players) do
p.print("Bobs enemies or NEE has been detected with Rampant's new enemies, the artifacts from each of these mods will still work with Rampant's new enemies. The generation of bobs or NEE unit spawners explicitly by Rampant is no longer supported when the Rampant's new enemies are active.")
end
end
local maxOverflowPoints = maxPoints * 3
local attackWaveMaxSize = natives.attackWaveMaxSize
natives.retreatThreshold = linearInterpolation(evolution_factor, RETREAT_MOVEMENT_PHEROMONE_LEVEL_MIN, RETREAT_MOVEMENT_PHEROMONE_LEVEL_MAX)
natives.rallyThreshold = BASE_RALLY_CHANCE + (evolution_factor * BONUS_RALLY_CHANCE)
natives.formSquadThreshold = mMax((0.25 * evolution_factor), 0.10)
natives.attackWaveSize = attackWaveMaxSize * (evolution_factor ^ 1.66667)
natives.attackWaveDeviation = (attackWaveMaxSize * 0.5) * 0.333
natives.attackWaveUpperBound = attackWaveMaxSize + (attackWaveMaxSize * 0.25)
natives.settlerWaveSize = linearInterpolation(evolution_factor ^ 1.66667, natives.expansionMinSize, natives.expansionMaxSize)
natives.settlerWaveDeviation = (natives.settlerWaveSize * 0.33)
natives.settlerCooldown = mFloor(linearInterpolation(evolution_factor ^ 1.66667, natives.expansionMaxTime, natives.expansionMinTime))
natives.unitRefundAmount = AI_UNIT_REFUND * evolution_factor
natives.kamikazeThreshold = NO_RETREAT_BASE_PERCENT + (evolution_factor * NO_RETREAT_EVOLUTION_BONUS_MAX)
local points = mFloor((AI_POINT_GENERATOR_AMOUNT * mRandom()) + ((AI_POINT_GENERATOR_AMOUNT * 0.7) * (evolution_factor ^ 2.5)) * natives.aiPointsScaler)
if (natives.state == AI_STATE_ONSLAUGHT) then
points = points * 2
end
natives.baseIncrement = points
local currentPoints = natives.points
if (currentPoints < maxPoints) then
natives.points = currentPoints + points
end
if (currentPoints > maxOverflowPoints) then
natives.points = maxOverflowPoints
end
if (natives.stateTick <= tick) then
-- local roll = mRandom() * mMax(1 - evolution_factor, 0.15) * natives.aiAggressiveness
local roll = mRandom()
if (natives.temperament < 0.05) then -- 0 - 0.05
if natives.enabledMigration then
natives.state = AI_STATE_SIEGE
else
if natives.raidAIToggle then
if (roll < 0.85) then
natives.state = AI_STATE_AGGRESSIVE
natives.canAttackTick = randomTickEvent(tick,
AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION,
AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION)
else
natives.state = AI_STATE_RAIDING
end
else
natives.state = AI_STATE_AGGRESSIVE
natives.canAttackTick = randomTickEvent(tick,
AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION,
AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION)
end
end
elseif (natives.temperament < 0.20) then -- 0.05 - 0.2
if (natives.enabledMigration) then
if (roll < 0.4) then
natives.state = AI_STATE_SIEGE
else
natives.state = AI_STATE_MIGRATING
end
else
if natives.raidAIToggle then
if (roll < 0.95) then
natives.state = AI_STATE_AGGRESSIVE
natives.canAttackTick = randomTickEvent(tick,
AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION,
AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION)
else
natives.state = AI_STATE_RAIDING
end
else
natives.state = AI_STATE_AGGRESSIVE
natives.canAttackTick = randomTickEvent(tick,
AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION,
AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION)
end
end
elseif (natives.temperament < 0.4) then -- 0.2 - 0.4
if (natives.enabledMigration) then
if (roll < 0.2) then
natives.state = AI_STATE_AGGRESSIVE
natives.canAttackTick = randomTickEvent(tick,
AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION,
AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION)
elseif (roll < 0.8) then
natives.state = AI_STATE_MIGRATING
else
natives.state = AI_STATE_PEACEFUL
end
else
if (roll < 0.6) then
natives.state = AI_STATE_AGGRESSIVE
natives.canAttackTick = randomTickEvent(tick,
AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION,
AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION)
else
natives.state = AI_STATE_PEACEFUL
end
end
elseif (natives.temperament < 0.6) then -- 0.4 - 0.6
if (roll < 0.5) then
natives.state = AI_STATE_AGGRESSIVE
natives.canAttackTick = randomTickEvent(tick,
AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION,
AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION)
else
natives.state = AI_STATE_PEACEFUL
end
elseif (natives.temperament < 0.8) then -- 0.6 - 0.8
if (roll < 0.6) then
natives.state = AI_STATE_AGGRESSIVE
natives.canAttackTick = randomTickEvent(tick,
AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION,
AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION)
elseif (roll < 0.8) then
natives.state = AI_STATE_ONSLAUGHT
else
natives.state = AI_STATE_PEACEFUL
end
else -- 0.8 - 1
if (natives.enabledMigration and natives.raidAIToggle) then
if (roll < 0.3) then
natives.state = AI_STATE_SIEGE
elseif (roll < 0.6) then
natives.state = AI_STATE_ONSLAUGHT
elseif (roll < 0.8) then
natives.state = AI_STATE_RAIDING
else
natives.state = AI_STATE_AGGRESSIVE
natives.canAttackTick = randomTickEvent(tick,
AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION,
AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION)
end
elseif (natives.enabledMigration) then
if (roll < 0.3) then
natives.state = AI_STATE_SIEGE
elseif (roll < 0.7) then
natives.state = AI_STATE_ONSLAUGHT
else
natives.state = AI_STATE_AGGRESSIVE
natives.canAttackTick = randomTickEvent(tick,
AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION,
AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION)
end
elseif (natives.raidAIToggle) then
if (roll < 0.4) then
natives.state = AI_STATE_ONSLAUGHT
elseif (roll < 0.7) then
natives.state = AI_STATE_RAIDING
else
natives.state = AI_STATE_AGGRESSIVE
natives.canAttackTick = randomTickEvent(tick,
AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION,
AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION)
end
else
if (roll < 0.6) then
natives.state = AI_STATE_ONSLAUGHT
else
natives.state = AI_STATE_AGGRESSIVE
natives.canAttackTick = randomTickEvent(tick,
AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION,
AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION)
end
end
end
-- print("changing state", natives.state)
natives.stateTick = randomTickEvent(tick, AI_MIN_STATE_DURATION, AI_MAX_STATE_DURATION)
end
end
function aiPlanning.temperamentPlanner(natives)
local destroyPlayerBuildings = natives.destroyPlayerBuildings
local lostEnemyUnits = natives.lostEnemyUnits
local lostEnemyBuilding = natives.lostEnemyBuilding
local rocketLaunched = natives.rocketLaunched
local builtEnemyBuilding = natives.builtEnemyBuilding
local ionCannonBlasts = natives.ionCannonBlasts
local artilleryBlasts = natives.artilleryBlasts
local activeNests = natives.activeNests
local activeRaidNests = natives.activeRaidNests
local currentTemperament = natives.temperamentScore
local delta = 0
if activeNests > 0 then
local val = (1.5 * activeNests)
delta = delta + val
if destroyPlayerBuildings > 0 then
delta = delta - (200 * destroyPlayerBuildings)
end
else
delta = delta - 1
if destroyPlayerBuildings > 0 then
if (currentTemperament > 0) then
delta = delta - (200 * destroyPlayerBuildings)
else
delta = delta + (200 * destroyPlayerBuildings)
end
end
end
if activeRaidNests > 0 then
local val = (0.008 * activeRaidNests)
delta = delta - val
else
delta = delta - 0.5
end
if lostEnemyUnits > 0 then
local val = (0.04 * lostEnemyUnits)
if (currentTemperament > 0) then
delta = delta - val
else
delta = delta + val
end
end
if lostEnemyBuilding > 0 then
delta = delta + (20 * lostEnemyBuilding)
end
if (builtEnemyBuilding > 0) then
local val = (50 * builtEnemyBuilding)
if (currentTemperament > 0) then
delta = delta - val
else
delta = delta + val
end
else
delta = delta - 0.5
end
if (rocketLaunched > 0) then
local val = (100 * rocketLaunched)
delta = delta + val
end
if (ionCannonBlasts > 0) then
local val = (50 * ionCannonBlasts)
delta = delta + val
end
if (artilleryBlasts > 0) then
local val = (50 * artilleryBlasts)
delta = delta + val
end
-- print(natives.activeNests, natives.activeRaidNests, natives.destroyPlayerBuildings, natives.lostEnemyUnits,
-- natives.lostEnemyBuilding, natives.rocketLaunched, natives.builtEnemyBuilding, natives.ionCannonBlasts,
-- natives.artilleryBlasts)
natives.destroyPlayerBuildings = 0
natives.lostEnemyUnits = 0
natives.lostEnemyBuilding = 0
natives.rocketLaunched = 0
natives.builtEnemyBuilding = 0
natives.ionCannonBlasts = 0
natives.artilleryBlasts = 0
natives.temperamentScore = mMin(10000, mMax(-10000, currentTemperament + (natives.evolutionLevel * delta)))
natives.temperament = ((natives.temperamentScore + 10000) * 0.00005)
-- print(natives.temperament, natives.temperamentScore)
-- print("--")
end
aiPlanningG = aiPlanning
return aiPlanning