1
0
mirror of https://github.com/veden/Rampant.git synced 2024-12-26 20:54:12 +02:00

FACTO-59: more partial work towards converting to base ais

This commit is contained in:
Aaron Veden 2022-02-27 18:45:42 -08:00
parent 597b20b9e5
commit 52139e1e3a
No known key found for this signature in database
GPG Key ID: FF5990B1C6DD3F84
10 changed files with 421 additions and 374 deletions

View File

@ -650,10 +650,10 @@ function upgrade.prepMap(universe, surface)
map.activatedMap = false
map.sentSiegeGroups = 0
map.maxSiegeGroups = 2
map.maxAggressiveGroups = 1
map.sentAggressiveGroups = 0
-- map.sentSiegeGroups = 0
-- map.maxSiegeGroups = 2
-- map.maxAggressiveGroups = 1
-- map.sentAggressiveGroups = 0
map.processedChunks = 0
map.processQueue = {}
map.processIndex = 1
@ -696,30 +696,31 @@ function upgrade.prepMap(universe, surface)
map.universe = universe
map.bases = {}
map.baseIndex = 1
-- map.baseIncrement = 0
-- map.points = 0
map.state = constants.AI_STATE_PEACEFUL
map.squads = nil
map.pendingAttack = nil
map.building = nil
map.evolutionLevel = game.forces.enemy.evolution_factor
map.canAttackTick = 0
map.drainPylons = {}
map.activeRaidNests = 0
map.activeNests = 0
map.destroyPlayerBuildings = 0
map.lostEnemyUnits = 0
map.lostEnemyBuilding = 0
map.rocketLaunched = 0
map.builtEnemyBuilding = 0
map.ionCannonBlasts = 0
map.artilleryBlasts = 0
-- map.baseIndex = 1
-- map.baseIncrement = 0
-- map.points = 0
-- map.state = constants.AI_STATE_PEACEFUL
map.temperament = 0.5
map.temperamentScore = 0
map.stateTick = 0
-- map.evolutionLevel = game.forces.enemy.evolution_factor
-- map.canAttackTick = 0
-- map.drainPylons = {}
-- map.activeRaidNests = 0
-- map.activeNests = 0
-- map.destroyPlayerBuildings = 0
-- map.lostEnemyUnits = 0
-- map.lostEnemyBuilding = 0
-- map.rocketLaunched = 0
-- map.builtEnemyBuilding = 0
-- map.ionCannonBlasts = 0
-- map.artilleryBlasts = 0
-- map.temperament = 0.5
-- map.temperamentScore = 0
-- map.stateTick = 0
map.random = universe.random

View File

@ -64,7 +64,7 @@ local nextMap = mapUtils.nextMap
local distortPosition = mathUtils.distortPosition
local prepMap = upgrade.prepMap
local processMapAIs = aiPlanning.processMapAIs
local processBaseAIs = aiPlanning.processBaseAIs
local registerEnemyBaseStructure = chunkUtils.registerEnemyBaseStructure
@ -180,7 +180,7 @@ local function onAbandonedRuins(event)
if not map then
return
end
accountPlayerEntity(entity, map, true, false)
accountPlayerEntity(entity, map, true)
end
end
@ -317,6 +317,12 @@ local function onConfigChanged()
end
end
addBasesToAllEnemyStructures(universe, game.tick)
if not universe.ranIncompatibleMessage and universe.newEnemies and
(game.active_mods["bobenemies"] or game.active_mods["Natural_Evolution_Enemies"]) then
universe.ranIncompatibleMessage = true
game.print({"description.rampant-bobs-nee-newEnemies"})
end
end
local function onBuild(event)
@ -329,7 +335,7 @@ local function onBuild(event)
if (entity.type == "resource") and (entity.force.name == "neutral") then
registerResource(entity, map)
else
accountPlayerEntity(entity, map, true, false)
accountPlayerEntity(entity, map, true)
if universe.safeEntities[entity.type] or universe.safeEntities[entity.name] then
entity.destructible = false
end
@ -344,7 +350,7 @@ local function onMine(event)
if not map then
return
end
accountPlayerEntity(entity, map, false, false)
accountPlayerEntity(entity, map, false)
end
end
@ -358,45 +364,64 @@ local function onDeath(event)
if not map then
return
end
if (entity.force.name == "neutral") then
local entityForceName = entity.force.name
if (entityForceName == "neutral") then
if (entity.name == "cliff") then
entityForPassScan(map, entity)
end
return
end
local entityPosition = entity.position
local chunk = getChunkByPosition(map, entityPosition)
local cause = event.cause
local causedByEnemyForce = event.force and (event.force.name == "enemy")
local tick = event.tick
local entityType = entity.type
if (entity.force.name == "enemy") then
local artilleryBlast = (cause and
((cause.type == "artillery-wagon") or (cause.type == "artillery-turret")))
local entityPosition = entity.position
local damageTypeName = event.damage_type and event.damage_type.name
local chunk = getChunkByPosition(map, entityPosition)
local base
if artilleryBlast then
map.artilleryBlasts = map.artilleryBlasts + 1
if entityForceName == "enemy" then
if entityType ~= "unit" then
if getDrainPylonPair(map, entity.unit_number) then
removeDrainPylons(map, entity.unit_number)
else
unregisterEnemyBaseStructure(map, entity, damageTypeName)
end
else
local group = entity.unit_group
if group then
local squad = universe.groupNumberToSquad[group.group_number]
if damageTypeName and squad then
base = squad.base
end
end
end
if (entityType == "unit") then
if (chunk ~= -1) and event.force and (event.force.name ~= "enemy") then
if (chunk ~= -1) then
deathScent(map, chunk)
local group = entity.unit_group
if group then
local damageType = event.damage_type
local squad = universe.groupNumberToSquad[group.group_number]
if damageType and squad then
local base = squad.base
if base then
local damageTypeName = damageType.name
base.damagedBy[damageTypeName] = (base.damagedBy[damageTypeName] or 0) + 0.01
base.deathEvents = base.deathEvents + 1
end
if not base then
base = findNearbyBase(map, chunk)
end
local artilleryBlast = (cause and ((cause.type == "artillery-wagon") or (cause.type == "artillery-turret")))
if entityType == "unit" then
if base then
base.lostEnemyUnits = base.lostEnemyUnits + 1
base.damagedBy[damageTypeName] = (base.damagedBy[damageTypeName] or 0) + 0.01
base.deathEvents = base.deathEvents + 1
-- base.points = base.points - UNIT_DEATH_POINT_COST
-- if universe.aiPointsPrintSpendingToChat then
-- game.print(map.surface.name .. ": Points: -" .. UNIT_DEATH_POINT_COST .. ". [Unit Lost] Total: " .. string.format("%.2f", base.points))
-- end
if (universe.random() < universe.rallyThreshold) and not surface.peaceful_mode then
rallyUnits(chunk, map, tick, base)
end
if artilleryBlast then
base.artilleryBlasts = base.artilleryBlasts + 1
end
end
-- drop death pheromone where unit died
deathScent(map, chunk)
if (getDeathGeneratorRating(map, chunk) < universe.retreatThreshold) and cause and cause.valid then
retreatUnits(chunk,
cause,
@ -404,67 +429,59 @@ local function onDeath(event)
tick,
(artilleryBlast and RETREAT_SPAWNER_GRAB_RADIUS) or RETREAT_GRAB_RADIUS)
end
map.lostEnemyUnits = map.lostEnemyUnits + 1
-- map.points = map.points - UNIT_DEATH_POINT_COST
-- if universe.aiPointsPrintSpendingToChat then
-- game.print(map.surface.name .. ": Points: -" .. UNIT_DEATH_POINT_COST .. ". [Unit Lost] Total: " .. string.format("%.2f", map.points))
-- end
if (universe.random() < universe.rallyThreshold) and not surface.peaceful_mode then
rallyUnits(chunk, map, tick)
end
end
elseif getDrainPylonPair(map, entity.unit_number) then
removeDrainPylons(map, entity.unit_number)
else
if event.force and (event.force.name ~= "enemy") then
local rally = false
if (chunk ~= -1) then
local base = findNearbyBase(map, chunk)
if (entityType == "unit-spawner") then
base.points = base.points + RECOVER_NEST_COST
if universe.aiPointsPrintGainsToChat then
game.print(map.surface.name .. ": Points: +" .. RECOVER_NEST_COST .. ". [Nest Lost] Total: " .. string.format("%.2f", base.points))
end
rally = true
elseif (entityType == "turret") then
base.points = base.points + RECOVER_WORM_COST
if universe.aiPointsPrintGainsToChat then
game.print(map.surface.name .. ": Points: +" .. RECOVER_WORM_COST .. ". [Worm Lost] Total: " .. string.format("%.2f", base.points))
end
rally = true
end
if rally then
rallyUnits(chunk, map, tick, base)
if cause and cause.valid then
retreatUnits(chunk,
cause,
map,
tick,
RETREAT_SPAWNER_GRAB_RADIUS)
end
end
end
end
if universe.buildingHiveTypeLookup[entity.name] or
elseif universe.buildingHiveTypeLookup[entity.name] or
(entityType == "unit-spawner") or
(entityType == "turret")
then
unregisterEnemyBaseStructure(map, entity, event.damage_type)
if base then
if (entityType == "unit-spawner") then
base.points = base.points + RECOVER_NEST_COST
if universe.aiPointsPrintGainsToChat then
game.print(map.surface.name .. ": Points: +" .. RECOVER_NEST_COST ..
". [Nest Lost] Total: " .. string.format("%.2f", base.points))
end
elseif (entityType == "turret") then
base.points = base.points + RECOVER_WORM_COST
if universe.aiPointsPrintGainsToChat then
game.print(map.surface.name .. ": Points: +" .. RECOVER_WORM_COST ..
". [Worm Lost] Total: " .. string.format("%.2f", base.points))
end
end
rallyUnits(chunk, map, tick, base)
if artilleryBlast then
base.artilleryBlasts = base.artilleryBlasts + 1
end
end
if cause and cause.valid then
retreatUnits(chunk,
cause,
map,
tick,
RETREAT_SPAWNER_GRAB_RADIUS)
end
end
end
else
local creditNatives = false
if (event.force ~= nil) and (event.force.name == "enemy") then
if causedByEnemyForce then
creditNatives = true
local drained = false
if (chunk ~= -1) then
if chunk ~= -1 then
victoryScent(map, chunk, entityType)
drained = (entityType == "electric-turret") and isDrained(map, chunk, tick)
if cause and cause.type == "unit" then
local group = cause.unit_group
if group and group.valid then
local squad = universe.groupNumberToSquad[group.group_number]
if squad then
base = squad.base
end
end
end
if not base then
base = findNearbyBase(map, chunk)
end
end
if cause or drained then
@ -475,7 +492,7 @@ local function onDeath(event)
then
makeImmortalEntity(surface, entity)
else
accountPlayerEntity(entity, map, false, creditNatives)
accountPlayerEntity(entity, map, false, base)
end
end
end
@ -730,16 +747,25 @@ local function onUnitGroupCreated(event)
return
end
map.activeSurface = true
local chunk = getChunkByPosition(map, group.position)
if (chunk == -1) then
return
end
local base = findNearbyBase(map, chunk)
if not base then
group.destroy()
return
end
if not universe.aiNocturnalMode then
local settler = canMigrate(map) and
local settler = canMigrate(map, base) and
(universe.builderCount < universe.AI_MAX_BUILDER_COUNT) and
(universe.random() < 0.25)
if not settler and (universe.squadCount > universe.AI_MAX_SQUAD_COUNT) then
group.destroy()
map.points = map.points + AI_SQUAD_COST
base.points = base.points + AI_SQUAD_COST
if universe.aiPointsPrintGainsToChat then
game.print(map.surface.name .. ": Points: +" .. AI_SQUAD_COST .. ". [Squad Refund] Total: " .. string.format("%.2f", map.points))
game.print(map.surface.name .. ": Points: +" .. AI_SQUAD_COST .. ". [Squad Refund] Total: " .. string.format("%.2f", base.points))
end
return
end
@ -747,10 +773,7 @@ local function onUnitGroupCreated(event)
squad = createSquad(nil, map, group, settler)
universe.groupNumberToSquad[group.group_number] = squad
local chunk = getChunkByPosition(map, group.position)
if (chunk ~= -1) then
squad.base = findNearbyBase(map, chunk)
end
squad.base = base
if settler then
universe.builderCount = universe.builderCount + 1
@ -763,15 +786,15 @@ local function onUnitGroupCreated(event)
return
end
local settler = canMigrate(map) and
local settler = canMigrate(map, base) and
(universe.builderCount < universe.AI_MAX_BUILDER_COUNT) and
(universe.random() < 0.25)
if not settler and (universe.squadCount > universe.AI_MAX_SQUAD_COUNT) then
group.destroy()
map.points = map.points + AI_SQUAD_COST
base.points = base.points + AI_SQUAD_COST
if universe.aiPointsPrintGainsToChat then
game.print(map.surface.name .. ": Points: +" .. AI_SQUAD_COST .. ". [Squad Refund] Total: " .. string.format("%.2f", map.points))
game.print(map.surface.name .. ": Points: +" .. AI_SQUAD_COST .. ". [Squad Refund] Total: " .. string.format("%.2f", base.points))
end
return
end
@ -779,10 +802,7 @@ local function onUnitGroupCreated(event)
squad = createSquad(nil, map, group, settler)
universe.groupNumberToSquad[group.group_number] = squad
local chunk = getChunkByPosition(map, group.position)
if (chunk ~= -1) then
squad.base = findNearbyBase(map, chunk)
end
squad.base = base
if settler then
universe.builderCount = universe.builderCount + 1
@ -804,14 +824,15 @@ local function onGroupFinishedGathering(event)
map.activeSurface = true
local squad = universe.groupNumberToSquad[group.group_number]
if squad then
local base = squad.base
if squad.settler then
if (universe.builderCount < universe.AI_MAX_BUILDER_COUNT) then
squadDispatch(map, squad, event.tick)
else
group.destroy()
map.points = map.points + AI_SETTLER_COST
base.points = base.points + AI_SETTLER_COST
if universe.aiPointsPrintGainsToChat then
game.print(map.surface.name .. ": Points: +" .. AI_SETTLER_COST .. ". [Settler Refund] Total: " .. string.format("%.2f", map.points))
game.print(map.surface.name .. ": Points: +" .. AI_SETTLER_COST .. ". [Settler Refund] Total: " .. string.format("%.2f", base.points))
end
end
else
@ -819,22 +840,24 @@ local function onGroupFinishedGathering(event)
squadDispatch(map, squad, event.tick)
else
group.destroy()
map.points = map.points + AI_SQUAD_COST
base.points = base.points + AI_SQUAD_COST
if universe.aiPointsPrintGainsToChat then
game.print(map.surface.name .. ": Points: +" .. AI_SQUAD_COST .. ". [Squad Refund] Total: " .. string.format("%.2f", map.points))
game.print(map.surface.name .. ": Points: +" .. AI_SQUAD_COST .. ". [Squad Refund] Total: " .. string.format("%.2f", base.points))
end
end
end
else
local settler = canMigrate(map) and
local chunk = getChunkByPosition(map, group.position)
local base = findNearbyBase(map, chunk)
local settler = canMigrate(map, base) and
(universe.builderCount < universe.AI_MAX_BUILDER_COUNT) and
(universe.random() < 0.25)
if not settler and (universe.squadCount > universe.AI_MAX_SQUAD_COUNT) then
group.destroy()
map.points = map.points + AI_SQUAD_COST
base.points = base.points + AI_SQUAD_COST
if universe.aiPointsPrintGainsToChat then
game.print(map.surface.name .. ": Points: +" .. AI_SQUAD_COST .. ". [Squad Refund] Total: " .. string.format("%.2f", map.points))
game.print(map.surface.name .. ": Points: +" .. AI_SQUAD_COST .. ". [Squad Refund] Total: " .. string.format("%.2f", base.points))
end
return
end
@ -928,7 +951,6 @@ script.on_event(defines.events.on_tick,
if (pick == 0) then
processPendingChunks(universe, tick)
processMapAIs(universe, gameRef.forces.enemy.evolution_factor, tick)
if map then
recycleBases(map)
end
@ -965,6 +987,7 @@ script.on_event(defines.events.on_tick,
processScanChunks(universe)
end
processBaseAIs(universe, gameRef.forces.enemy.evolution_factor, tick)
processActiveNests(universe, tick)
processPendingUpgrades(universe, tick)
processPendingUpgrades(universe, tick)
@ -1071,7 +1094,13 @@ local function rampantSetAIState(event)
return
end
if (target ~= constants.AI_STATE_PEACEFUL and target ~= constants.AI_STATE_AGGRESSIVE and target ~= constants.AI_STATE_RAIDING and target ~= constants.AI_STATE_MIGRATING and target ~= constants.AI_STATE_SIEGE and target ~= constants.AI_STATE_ONSLAUGHT) then
if target ~= constants.BASE_AI_STATE_PEACEFUL and
target ~= constants.BASE_AI_STATE_AGGRESSIVE and
target ~= constants.BASE_AI_STATE_RAIDING and
target ~= constants.BASE_AI_STATE_MIGRATING and
target ~= constants.BASE_AI_STATE_SIEGE and
target ~= constants.BASE_AI_STATE_ONSLAUGHT
then
game.print(target .. " is not a valid state")
return
else

View File

@ -38,7 +38,6 @@ local RESOURCE_PHEROMONE = constants.RESOURCE_PHEROMONE
local AI_SQUAD_COST = constants.AI_SQUAD_COST
local AI_SETTLER_COST = constants.AI_SETTLER_COST
local AI_VENGENCE_SQUAD_COST = constants.AI_VENGENCE_SQUAD_COST
local AI_STATE_AGGRESSIVE = constants.AI_STATE_AGGRESSIVE
local COOLDOWN_RALLY = constants.COOLDOWN_RALLY
@ -48,9 +47,10 @@ local CHUNK_SIZE = constants.CHUNK_SIZE
local RALLY_CRY_DISTANCE = constants.RALLY_CRY_DISTANCE
local AI_STATE_SIEGE = constants.AI_STATE_SIEGE
local AI_STATE_ONSLAUGHT = constants.AI_STATE_ONSLAUGHT
local AI_STATE_RAIDING = constants.AI_STATE_RAIDING
local BASE_AI_STATE_SIEGE = constants.BASE_AI_STATE_SIEGE
local BASE_AI_STATE_ONSLAUGHT = constants.BASE_AI_STATE_ONSLAUGHT
local BASE_AI_STATE_RAIDING = constants.BASE_AI_STATE_RAIDING
local BASE_AI_STATE_AGGRESSIVE = constants.BASE_AI_STATE_AGGRESSIVE
-- imported functions
@ -99,7 +99,7 @@ end
local function attackWaveValidCandidate(chunk, map, base)
local isValid = getNestActiveness(map, chunk)
if (base.state == AI_STATE_RAIDING) or (base.state == AI_STATE_SIEGE) or (base.state == AI_STATE_ONSLAUGHT) then
if (base.stateAI == BASE_AI_STATE_RAIDING) or (base.stateAI == BASE_AI_STATE_SIEGE) or (base.stateAI == BASE_AI_STATE_ONSLAUGHT) then
isValid = isValid + getRaidNestActiveness(map, chunk)
end
return (isValid > 0)
@ -216,7 +216,7 @@ function aiAttackWave.formSettlers(map, chunk, base)
then
local surface = map.surface
local squadPath, squadDirection
if (map.state == AI_STATE_SIEGE) then
if (map.state == BASE_AI_STATE_SIEGE) then
squadPath, squadDirection = scoreNeighborsForFormation(getNeighborChunks(map, chunk.x, chunk.y),
validSiegeSettlerLocation,
scoreSiegeSettlerLocation,
@ -245,13 +245,13 @@ function aiAttackWave.formSettlers(map, chunk, base)
universe.formCommand.unit_count = scaledWaveSize
local foundUnits = surface.set_multi_command(universe.formCommand)
if (foundUnits > 0) then
if (base.state == AI_STATE_SIEGE) then
if (base.stateAI == BASE_AI_STATE_SIEGE) then
base.sentSiegeGroups = base.sentSiegeGroups + 1
end
squad.base = base
local kamikazeThreshold = calculateKamikazeSettlerThreshold(foundUnits, universe)
if base.state == AI_STATE_SIEGE then
if base.stateAI == BASE_AI_STATE_SIEGE then
kamikazeThreshold = kamikazeThreshold * 2.5
end
squad.kamikaze = map.random() < kamikazeThreshold
@ -400,7 +400,7 @@ function aiAttackWave.formSquads(map, chunk, base)
universe.formCommand.unit_count = scaledWaveSize
local foundUnits = surface.set_multi_command(universe.formCommand)
if (foundUnits > 0) then
if (base.state == AI_STATE_SIEGE) then
if (base.stateAI == BASE_AI_STATE_SIEGE) then
base.sentSiegeGroups = 0
end
@ -409,7 +409,7 @@ function aiAttackWave.formSquads(map, chunk, base)
base.unitPoints = base.unitPoints - AI_SQUAD_COST
universe.squadCount = universe.squadCount + 1
universe.groupNumberToSquad[squad.groupNumber] = squad
if (base.state == AI_STATE_AGGRESSIVE) then
if (base.stateAI == BASE_AI_STATE_AGGRESSIVE) then
base.sentAggressiveGroups = base.sentAggressiveGroups + 1
end
if universe.aiPointsPrintSpendingToChat then

View File

@ -35,12 +35,12 @@ local ACTIVE_NESTS_PER_AGGRESSIVE_GROUPS = constants.ACTIVE_NESTS_PER_AGGRESSIVE
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 BASE_AI_STATE_PEACEFUL = constants.BASE_AI_STATE_PEACEFUL
local BASE_AI_STATE_AGGRESSIVE = constants.BASE_AI_STATE_AGGRESSIVE
local BASE_AI_STATE_RAIDING = constants.BASE_AI_STATE_RAIDING
local BASE_AI_STATE_MIGRATING = constants.BASE_AI_STATE_MIGRATING
local BASE_AI_STATE_ONSLAUGHT = constants.BASE_AI_STATE_ONSLAUGHT
local BASE_AI_STATE_SIEGE = constants.BASE_AI_STATE_SIEGE
local AI_UNIT_REFUND = constants.AI_UNIT_REFUND
@ -83,41 +83,31 @@ local function getTimeStringFromTick(tick)
end
local function planning(map, evolution_factor, tick)
local universe = map.universe
map.evolutionLevel = evolution_factor
universe.evolutionLevel = evolution_factor
local maxPoints = mMax(AI_MAX_POINTS * evolution_factor, MINIMUM_AI_POINTS)
local function planning(universe, base, evolutionLevel, tick)
local maxPoints = mMax(AI_MAX_POINTS * evolutionLevel, MINIMUM_AI_POINTS)
universe.maxPoints = maxPoints
if not universe.ranIncompatibleMessage and universe.newEnemies and
(game.active_mods["bobenemies"] or game.active_mods["Natural_Evolution_Enemies"]) then
universe.ranIncompatibleMessage = true
game.print({"description.rampant-bobs-nee-newEnemies"})
end
local maxOverflowPoints = maxPoints * 3
universe.maxOverflowPoints = maxOverflowPoints
local attackWaveMaxSize = universe.attackWaveMaxSize
universe.retreatThreshold = linearInterpolation(evolution_factor,
universe.retreatThreshold = linearInterpolation(evolutionLevel,
RETREAT_MOVEMENT_PHEROMONE_LEVEL_MIN,
RETREAT_MOVEMENT_PHEROMONE_LEVEL_MAX)
universe.rallyThreshold = BASE_RALLY_CHANCE + (evolution_factor * BONUS_RALLY_CHANCE)
universe.formSquadThreshold = mMax((0.35 * evolution_factor), 0.1)
universe.rallyThreshold = BASE_RALLY_CHANCE + (evolutionLevel * BONUS_RALLY_CHANCE)
universe.formSquadThreshold = mMax((0.35 * evolutionLevel), 0.1)
universe.attackWaveSize = attackWaveMaxSize * (evolution_factor ^ 1.4)
universe.attackWaveSize = attackWaveMaxSize * (evolutionLevel ^ 1.4)
universe.attackWaveDeviation = (universe.attackWaveSize * 0.333)
universe.attackWaveUpperBound = universe.attackWaveSize + (universe.attackWaveSize * 0.35)
if (map.canAttackTick < tick) then
map.maxAggressiveGroups = mCeil(map.activeNests / ACTIVE_NESTS_PER_AGGRESSIVE_GROUPS)
map.sentAggressiveGroups = 0
map.canAttackTick = randomTickEvent(map.random,
tick,
AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION,
AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION)
if (base.canAttackTick < tick) then
base.maxAggressiveGroups = mCeil(base.activeNests / ACTIVE_NESTS_PER_AGGRESSIVE_GROUPS)
base.sentAggressiveGroups = 0
base.canAttackTick = randomTickEvent(universe.random,
tick,
AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION,
AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION)
end
if (universe.attackWaveSize < 1) then
@ -126,54 +116,55 @@ local function planning(map, evolution_factor, tick)
universe.attackWaveUpperBound = 3
end
universe.settlerWaveSize = linearInterpolation(evolution_factor ^ 1.66667,
universe.settlerWaveSize = linearInterpolation(evolutionLevel ^ 1.66667,
universe.expansionMinSize,
universe.expansionMaxSize)
universe.settlerWaveDeviation = (universe.settlerWaveSize * 0.33)
universe.settlerCooldown = mFloor(linearInterpolation(evolution_factor ^ 1.66667,
universe.settlerCooldown = mFloor(linearInterpolation(evolutionLevel ^ 1.66667,
universe.expansionMaxTime,
universe.expansionMinTime))
universe.unitRefundAmount = AI_UNIT_REFUND * evolution_factor
universe.kamikazeThreshold = NO_RETREAT_BASE_PERCENT + (evolution_factor * NO_RETREAT_EVOLUTION_BONUS_MAX)
universe.unitRefundAmount = AI_UNIT_REFUND * evolutionLevel
universe.kamikazeThreshold = NO_RETREAT_BASE_PERCENT + (evolutionLevel * NO_RETREAT_EVOLUTION_BONUS_MAX)
local points = ((AI_POINT_GENERATOR_AMOUNT * universe.random()) + (map.activeNests * 0.003) +
(AI_POINT_GENERATOR_AMOUNT * mMax(evolution_factor ^ 2.5, 0.1)))
local points = ((AI_POINT_GENERATOR_AMOUNT * universe.random()) + (base.activeNests * 0.003) +
(AI_POINT_GENERATOR_AMOUNT * mMax(evolutionLevel ^ 2.5, 0.1)))
if (map.temperament == 0) or (map.temperament == 1) then
if (base.temperament == 0) or (base.temperament == 1) then
points = points + 0.5
elseif (map.temperament < 0.20) or (map.temperament > 0.80) then
elseif (base.temperament < 0.20) or (base.temperament > 0.80) then
points = points + 0.3
elseif (map.temperament < 0.35) or (map.temperament > 0.65) then
elseif (base.temperament < 0.35) or (base.temperament > 0.65) then
points = points + 0.2
elseif (map.temperament < 0.45) or (map.temperament > 0.55) then
elseif (base.temperament < 0.45) or (base.temperament > 0.55) then
points = points + 0.1
end
if (map.state == AI_STATE_ONSLAUGHT) then
if (base.stateAI == BASE_AI_STATE_ONSLAUGHT) then
points = points * 2
end
points = points * universe.aiPointsScaler
map.baseIncrement = points * 30
base.points = points * 30
base.unitPoints = points * 30
local currentPoints = map.points
local currentPoints = base.points
if (currentPoints <= 0) then
currentPoints = 0
end
if (currentPoints < maxPoints) then
map.points = currentPoints + points
base.points = currentPoints + points
end
if (currentPoints > maxOverflowPoints) then
map.points = maxOverflowPoints
base.points = maxOverflowPoints
end
if (map.stateTick > tick) or not universe.awake then
if (base.stateAITick > tick) or not universe.awake then
if (not universe.awake) and (tick >= universe.initialPeaceTime) then
universe.awake = true
if universe.printAwakenMessage then
@ -184,189 +175,191 @@ local function planning(map, evolution_factor, tick)
end
end
local roll = universe.random()
if (map.temperament < 0.05) then -- 0 - 0.05
if (base.temperament < 0.05) then -- 0 - 0.05
if universe.enabledMigration then
if (roll < 0.30) then
map.state = AI_STATE_MIGRATING
base.stateAI = BASE_AI_STATE_MIGRATING
elseif (roll < 0.50) and universe.raidAIToggle then
map.state = AI_STATE_RAIDING
base.stateAI = BASE_AI_STATE_RAIDING
elseif universe.siegeAIToggle then
map.state = AI_STATE_SIEGE
base.stateAI = BASE_AI_STATE_SIEGE
else
map.state = AI_STATE_MIGRATING
base.stateAI = BASE_AI_STATE_MIGRATING
end
else
if universe.raidAIToggle then
if (roll < 0.70) then
map.state = AI_STATE_RAIDING
base.stateAI = BASE_AI_STATE_RAIDING
else
map.state = AI_STATE_AGGRESSIVE
base.stateAI = BASE_AI_STATE_AGGRESSIVE
end
else
map.state = AI_STATE_AGGRESSIVE
base.stateAI = BASE_AI_STATE_AGGRESSIVE
end
end
elseif (map.temperament < 0.20) then -- 0.05 - 0.2
elseif (base.temperament < 0.20) then -- 0.05 - 0.2
if (universe.enabledMigration) then
if (roll < 0.4) then
map.state = AI_STATE_MIGRATING
base.stateAI = BASE_AI_STATE_MIGRATING
elseif (roll < 0.55) and universe.raidAIToggle then
map.state = AI_STATE_RAIDING
base.stateAI = BASE_AI_STATE_RAIDING
elseif universe.siegeAIToggle then
map.state = AI_STATE_SIEGE
base.stateAI = BASE_AI_STATE_SIEGE
else
map.state = AI_STATE_MIGRATING
base.stateAI = BASE_AI_STATE_MIGRATING
end
else
if universe.raidAIToggle then
if (roll < 0.40) then
map.state = AI_STATE_AGGRESSIVE
base.stateAI = BASE_AI_STATE_AGGRESSIVE
else
map.state = AI_STATE_RAIDING
base.stateAI = BASE_AI_STATE_RAIDING
end
else
map.state = AI_STATE_AGGRESSIVE
base.stateAI = BASE_AI_STATE_AGGRESSIVE
end
end
elseif (map.temperament < 0.4) then -- 0.2 - 0.4
elseif (base.temperament < 0.4) then -- 0.2 - 0.4
if (universe.enabledMigration) then
if (roll < 0.2) and universe.raidAIToggle then
map.state = AI_STATE_RAIDING
base.stateAI = BASE_AI_STATE_RAIDING
elseif (roll < 0.2) then
map.state = AI_STATE_AGGRESSIVE
base.stateAI = BASE_AI_STATE_AGGRESSIVE
elseif (roll < 0.8) then
map.state = AI_STATE_MIGRATING
base.stateAI = BASE_AI_STATE_MIGRATING
elseif universe.peacefulAIToggle then
map.state = AI_STATE_PEACEFUL
base.stateAI = BASE_AI_STATE_PEACEFUL
else
map.state = AI_STATE_MIGRATING
base.stateAI = BASE_AI_STATE_MIGRATING
end
else
if (roll < 0.3) then
map.state = AI_STATE_AGGRESSIVE
base.stateAI = BASE_AI_STATE_AGGRESSIVE
elseif (roll < 0.6) and universe.raidAIToggle then
map.state = AI_STATE_RAIDING
base.stateAI = BASE_AI_STATE_RAIDING
elseif (roll < 0.6) then
map.state = AI_STATE_AGGRESSIVE
base.stateAI = BASE_AI_STATE_AGGRESSIVE
elseif universe.peacefulAIToggle then
map.state = AI_STATE_PEACEFUL
base.stateAI = BASE_AI_STATE_PEACEFUL
else
map.state = AI_STATE_AGGRESSIVE
base.stateAI = BASE_AI_STATE_AGGRESSIVE
end
end
elseif (map.temperament < 0.6) then -- 0.4 - 0.6
elseif (base.temperament < 0.6) then -- 0.4 - 0.6
if (roll < 0.4) then
map.state = AI_STATE_AGGRESSIVE
base.stateAI = BASE_AI_STATE_AGGRESSIVE
elseif (roll < 0.5) and universe.raidAIToggle then
map.state = AI_STATE_RAIDING
base.stateAI = BASE_AI_STATE_RAIDING
elseif (roll < 0.75) and universe.peacefulAIToggle then
map.state = AI_STATE_PEACEFUL
base.stateAI = BASE_AI_STATE_PEACEFUL
else
if universe.enabledMigration then
map.state = AI_STATE_MIGRATING
base.stateAI = BASE_AI_STATE_MIGRATING
else
map.state = AI_STATE_AGGRESSIVE
base.stateAI = BASE_AI_STATE_AGGRESSIVE
end
end
elseif (map.temperament < 0.8) then -- 0.6 - 0.8
elseif (base.temperament < 0.8) then -- 0.6 - 0.8
if (roll < 0.4) then
map.state = AI_STATE_AGGRESSIVE
base.stateAI = BASE_AI_STATE_AGGRESSIVE
elseif (roll < 0.6) then
map.state = AI_STATE_ONSLAUGHT
base.stateAI = BASE_AI_STATE_ONSLAUGHT
elseif (roll < 0.8) then
map.state = AI_STATE_RAIDING
base.stateAI = BASE_AI_STATE_RAIDING
elseif universe.peacefulAIToggle then
map.state = AI_STATE_PEACEFUL
base.stateAI = BASE_AI_STATE_PEACEFUL
else
map.state = AI_STATE_AGGRESSIVE
base.stateAI = BASE_AI_STATE_AGGRESSIVE
end
elseif (map.temperament < 0.95) then -- 0.8 - 0.95
elseif (base.temperament < 0.95) then -- 0.8 - 0.95
if (universe.enabledMigration and universe.raidAIToggle) then
if (roll < 0.20) and universe.siegeAIToggle then
map.state = AI_STATE_SIEGE
base.stateAI = BASE_AI_STATE_SIEGE
elseif (roll < 0.45) then
map.state = AI_STATE_RAIDING
base.stateAI = BASE_AI_STATE_RAIDING
elseif (roll < 0.85) then
map.state = AI_STATE_ONSLAUGHT
base.stateAI = BASE_AI_STATE_ONSLAUGHT
else
map.state = AI_STATE_AGGRESSIVE
base.stateAI = BASE_AI_STATE_AGGRESSIVE
end
elseif (universe.enabledMigration) then
if (roll < 0.20) and universe.siegeAIToggle then
map.state = AI_STATE_SIEGE
base.stateAI = BASE_AI_STATE_SIEGE
elseif (roll < 0.75) then
map.state = AI_STATE_ONSLAUGHT
base.stateAI = BASE_AI_STATE_ONSLAUGHT
else
map.state = AI_STATE_AGGRESSIVE
base.stateAI = BASE_AI_STATE_AGGRESSIVE
end
elseif (universe.raidAIToggle) then
if (roll < 0.45) then
map.state = AI_STATE_ONSLAUGHT
base.stateAI = BASE_AI_STATE_ONSLAUGHT
elseif (roll < 0.75) then
map.state = AI_STATE_RAIDING
base.stateAI = BASE_AI_STATE_RAIDING
else
map.state = AI_STATE_AGGRESSIVE
base.stateAI = BASE_AI_STATE_AGGRESSIVE
end
else
if (roll < 0.65) then
map.state = AI_STATE_ONSLAUGHT
base.stateAI = BASE_AI_STATE_ONSLAUGHT
else
map.state = AI_STATE_AGGRESSIVE
base.stateAI = BASE_AI_STATE_AGGRESSIVE
end
end
else
if (universe.enabledMigration and universe.raidAIToggle) then
if (roll < 0.30) and universe.siegeAIToggle then
map.state = AI_STATE_SIEGE
base.stateAI = BASE_AI_STATE_SIEGE
elseif (roll < 0.65) then
map.state = AI_STATE_RAIDING
base.stateAI = BASE_AI_STATE_RAIDING
else
map.state = AI_STATE_ONSLAUGHT
base.stateAI = BASE_AI_STATE_ONSLAUGHT
end
elseif (universe.enabledMigration) then
if (roll < 0.30) and universe.siegeAIToggle then
map.state = AI_STATE_SIEGE
base.stateAI = BASE_AI_STATE_SIEGE
else
map.state = AI_STATE_ONSLAUGHT
base.stateAI = BASE_AI_STATE_ONSLAUGHT
end
elseif (universe.raidAIToggle) then
if (roll < 0.45) then
map.state = AI_STATE_ONSLAUGHT
base.stateAI = BASE_AI_STATE_ONSLAUGHT
else
map.state = AI_STATE_RAIDING
base.stateAI = BASE_AI_STATE_RAIDING
end
else
map.state = AI_STATE_ONSLAUGHT
base.stateAI = BASE_AI_STATE_ONSLAUGHT
end
end
map.destroyPlayerBuildings = 0
map.lostEnemyUnits = 0
map.lostEnemyBuilding = 0
map.rocketLaunched = 0
map.builtEnemyBuilding = 0
map.ionCannonBlasts = 0
map.artilleryBlasts = 0
base.destroyPlayerBuildings = 0
base.lostEnemyUnits = 0
base.lostEnemyBuilding = 0
base.rocketLaunched = 0
base.builtEnemyBuilding = 0
base.ionCannonBlasts = 0
base.artilleryBlasts = 0
map.stateTick = randomTickEvent(map.random, tick, AI_MIN_STATE_DURATION, AI_MAX_STATE_DURATION)
base.stateAITick = randomTickEvent(universe.random, tick, AI_MIN_STATE_DURATION, AI_MAX_STATE_DURATION)
if universe.printAIStateChanges then
game.print(map.surface.name .. ": AI is now: " .. constants.stateEnglish[map.state] .. ", Next state change is in " .. string.format("%.2f", (map.stateTick - tick) / (60*60)) .. " minutes @ " .. getTimeStringFromTick(map.stateTick) .. " playtime")
game.print(base.index .. ": AI is now: " .. constants.stateEnglish[base.stateAI] .. ", Next state change is in "
.. string.format("%.2f", (base.stateAITick - tick) / (60*60)) .. " minutes @ " ..
getTimeStringFromTick(base.stateAITick) .. " playtime")
end
end
local function temperamentPlanner(map)
local destroyPlayerBuildings = map.destroyPlayerBuildings
local lostEnemyUnits = map.lostEnemyUnits
local lostEnemyBuilding = map.lostEnemyBuilding
local rocketLaunched = map.rocketLaunched
local builtEnemyBuilding = map.builtEnemyBuilding
local ionCannonBlasts = map.ionCannonBlasts
local artilleryBlasts = map.artilleryBlasts
local activeNests = map.activeNests
local activeRaidNests = map.activeRaidNests
local function temperamentPlanner(base, evolutionLevel)
local destroyPlayerBuildings = base.destroyPlayerBuildings
local lostEnemyUnits = base.lostEnemyUnits
local lostEnemyBuilding = base.lostEnemyBuilding
local rocketLaunched = base.rocketLaunched
local builtEnemyBuilding = base.builtEnemyBuilding
local ionCannonBlasts = base.ionCannonBlasts
local artilleryBlasts = base.artilleryBlasts
local activeNests = base.activeNests
local activeRaidNests = base.activeRaidNests
local currentTemperament = map.temperamentScore
local currentTemperament = base.temperamentScore
local delta = 0
if activeNests > 0 then
@ -393,15 +386,15 @@ local function temperamentPlanner(map)
if lostEnemyUnits > 0 then
local multipler
if map.evolutionLevel < 0.3 then
if evolutionLevel < 0.3 then
multipler = 0.000217
elseif map.evolutionLevel < 0.5 then
elseif evolutionLevel < 0.5 then
multipler = 0.000108
elseif map.evolutionLevel < 0.7 then
elseif evolutionLevel < 0.7 then
multipler = 0.000054
elseif map.evolutionLevel < 0.9 then
elseif evolutionLevel < 0.9 then
multipler = 0.000027
elseif map.evolutionLevel < 0.9 then
elseif evolutionLevel < 0.9 then
multipler = 0.0000135
else
multipler = 0.00000675
@ -449,48 +442,46 @@ local function temperamentPlanner(map)
delta = delta + val
end
local universe = map.universe
local universe = base.universe
delta = delta * universe.temperamentRateModifier
map.temperamentScore = mMin(TEMPERAMENT_RANGE_MAX, mMax(TEMPERAMENT_RANGE_MIN, currentTemperament + delta))
map.temperament = ((map.temperamentScore + TEMPERAMENT_RANGE_MAX) * TEMPERAMENT_DIVIDER)
base.temperamentScore = mMin(TEMPERAMENT_RANGE_MAX, mMax(TEMPERAMENT_RANGE_MIN, currentTemperament + delta))
base.temperament = ((base.temperamentScore + TEMPERAMENT_RANGE_MAX) * TEMPERAMENT_DIVIDER)
if universe.debugTemperament then
if game.tick % 243 == 0 then
game.print("Rampant Stats:")
game.print("aN:" .. map.activeNests .. ", aRN:" .. map.activeRaidNests .. ", dPB:" .. map.destroyPlayerBuildings ..
", lEU:" .. map.lostEnemyUnits .. ", lEB:" .. map.lostEnemyBuilding .. ", rL:" .. map.rocketLaunched .. ", bEB:" .. map.builtEnemyBuilding ..
", iCB:" .. map.ionCannonBlasts .. ", aB:" .. map.artilleryBlasts)
game.print("temp: " .. map.temperament .. ", tempScore:" .. map.temperamentScore .. ", points:" .. map.points .. ", state:" .. constants.stateEnglish[map.state] .. ", surface:" .. map.surface.index .. " [" .. map.surface.name .. "]")
game.print("aN:" .. base.activeNests .. ", aRN:" .. base.activeRaidNests .. ", dPB:" .. base.destroyPlayerBuildings ..
", lEU:" .. base.lostEnemyUnits .. ", lEB:" .. base.lostEnemyBuilding .. ", rL:" .. base.rocketLaunched .. ", bEB:" .. base.builtEnemyBuilding ..
", iCB:" .. base.ionCannonBlasts .. ", aB:" .. base.artilleryBlasts)
game.print("temp: " .. base.temperament .. ", tempScore:" .. base.temperamentScore .. ", points:" .. base.points .. ", state:" .. constants.stateEnglish[base.state] .. ", surface:" .. base.surface.index .. " [" .. base.surface.name .. "]")
game.print("aS:" .. universe.squadCount .. ", aB:" .. universe.builderCount .. ", atkSize:" .. universe.attackWaveSize .. ", stlSize:" .. universe.settlerWaveSize .. ", formGroup:" .. universe.formSquadThreshold)
game.print("sAgg:".. map.sentAggressiveGroups .. ", mAgg:" .. map.maxAggressiveGroups)
game.print("sAgg:".. base.sentAggressiveGroups .. ", mAgg:" .. base.maxAggressiveGroups)
end
end
end
function aiPlanning.processMapAIs(universe, evo, tick)
for _ = 1, 15 do
local mapId = universe.processMapAIIterator
local map
if not mapId then
mapId, map = next(universe.maps, nil)
else
map = universe.maps[mapId]
end
if not mapId then
universe.processMapAIIterator = nil
function aiPlanning.processBaseAIs(universe, evo, tick)
local baseId = universe.processBaseAIIterator
local base
if not baseId then
baseId, base = next(universe.bases, nil)
else
base = universe.bases[baseId]
end
if not baseId then
universe.processBaseAIIterator = nil
return
else
universe.processBaseAIIterator = next(universe.bases, baseId)
universe.evolutionLevel = evo
planning(universe, base, evo, tick)
temperamentPlanner(base, evo)
if not universe.processBaseAIIterator then
return
else
universe.processMapAIIterator = next(universe.maps, mapId)
planning(map, evo, tick)
temperamentPlanner(map)
if not universe.processMapAIIterator then
return
end
end
end
end
aiPlanningG = aiPlanning
return aiPlanning

View File

@ -25,33 +25,33 @@ local constants = require("Constants")
-- constants
local AI_STATE_RAIDING = constants.AI_STATE_RAIDING
local AI_STATE_AGGRESSIVE = constants.AI_STATE_AGGRESSIVE
local AI_STATE_MIGRATING = constants.AI_STATE_MIGRATING
local AI_STATE_SIEGE = constants.AI_STATE_SIEGE
local AI_STATE_ONSLAUGHT = constants.AI_STATE_ONSLAUGHT
local BASE_AI_STATE_RAIDING = constants.BASE_AI_STATE_RAIDING
local BASE_AI_STATE_AGGRESSIVE = constants.BASE_AI_STATE_AGGRESSIVE
local BASE_AI_STATE_MIGRATING = constants.BASE_AI_STATE_MIGRATING
local BASE_AI_STATE_SIEGE = constants.BASE_AI_STATE_SIEGE
local BASE_AI_STATE_ONSLAUGHT = constants.BASE_AI_STATE_ONSLAUGHT
-- imported functions
-- module code
function aiPredicates.canAttack(map)
function aiPredicates.canAttack(map, base)
local surface = map.surface
local goodAI = (((map.state == AI_STATE_AGGRESSIVE) and (map.sentAggressiveGroups < map.maxAggressiveGroups)) or
(map.state == AI_STATE_RAIDING) or
(map.state == AI_STATE_ONSLAUGHT) or
(map.universe.raidAIToggle and (map.state == AI_STATE_SIEGE) and (map.sentSiegeGroups >= map.maxSiegeGroups)))
local goodAI = (((base.stateAI == BASE_AI_STATE_AGGRESSIVE) and (map.sentAggressiveGroups < map.maxAggressiveGroups)) or
(base.stateAI == BASE_AI_STATE_RAIDING) or
(base.stateAI == BASE_AI_STATE_ONSLAUGHT) or
(map.universe.raidAIToggle and (base.stateAI == BASE_AI_STATE_SIEGE) and (base.sentSiegeGroups >= base.maxSiegeGroups)))
local notPeaceful = not surface.peaceful_mode
local nocturalMode = map.universe.aiNocturnalMode
local noctural = (not nocturalMode) or (nocturalMode and surface.darkness > 0.65)
return goodAI and notPeaceful and noctural
end
function aiPredicates.canMigrate(map)
function aiPredicates.canMigrate(map, base)
local surface = map.surface
local universe = map.universe
local nocturalMode = universe.aiNocturnalMode
local goodAI = (map.state == AI_STATE_MIGRATING) or (map.state == AI_STATE_SIEGE)
local goodAI = (base.stateAI == BASE_AI_STATE_MIGRATING) or (base.stateAI == BASE_AI_STATE_SIEGE)
local noctural = (not nocturalMode) or (nocturalMode and surface.darkness > 0.65)
return goodAI and universe.expansion and not surface.peaceful_mode and noctural
end

View File

@ -36,13 +36,13 @@ local MAGIC_MAXIMUM_NUMBER = constants.MAGIC_MAXIMUM_NUMBER
local FACTIONS_BY_DAMAGE_TYPE = constants.FACTIONS_BY_DAMAGE_TYPE
local BASE_AI_STATE_ACTIVE = constants.BASE_AI_STATE_ACTIVE
local BASE_AI_STATE_DORMANT = constants.BASE_AI_STATE_DORMANT
local BASE_GENERATION_STATE_ACTIVE = constants.BASE_GENERATION_STATE_ACTIVE
local BASE_GENERATION_STATE_DORMANT = constants.BASE_GENERATION_STATE_DORMANT
local FACTION_SET = constants.FACTION_SET
local BASE_AI_MIN_STATE_DURATION = constants.BASE_AI_MIN_STATE_DURATION
local BASE_AI_MAX_STATE_DURATION = constants.BASE_AI_MAX_STATE_DURATION
local BASE_GENERATION_MIN_STATE_DURATION = constants.BASE_GENERATION_MIN_STATE_DURATION
local BASE_GENERATION_MAX_STATE_DURATION = constants.BASE_GENERATION_MAX_STATE_DURATION
local HIVE_BUILDINGS_COST = constants.HIVE_BUILDINGS_COST
@ -54,6 +54,8 @@ local CHUNK_SIZE = constants.CHUNK_SIZE
local BASE_PROCESS_INTERVAL = constants.BASE_PROCESS_INTERVAL
local BASE_AI_STATE_PEACEFUL = constants.BASE_AI_STATE_PEACEFUL
-- imported functions
local setPositionXYInQuery = queryUtils.setPositionXYInQuery
@ -121,7 +123,7 @@ end
local function findBaseMutation(map, targetEvolution)
local universe = map.universe
local tier = evoToTier(universe, targetEvolution or map.evolutionLevel, 2)
local tier = evoToTier(universe, targetEvolution or universe.evolutionLevel, 2)
local alignments = universe.evolutionTableAlignment[tier]
local roll = map.random()
@ -310,7 +312,7 @@ function baseUtils.upgradeEntity(entity, base, map, disPos, evolve, register)
local currentEvo = entity.prototype.build_base_evolution_requirement or 0
local distance = mMin(1, euclideanDistancePoints(position.x, position.y, 0, 0) * BASE_DISTANCE_TO_EVO_INDEX)
local evoIndex = mMax(distance, map.evolutionLevel)
local evoIndex = mMax(distance, map.universe.evolutionLevel)
local baseAlignment = base.alignment
local pickedBaseAlignment
@ -443,7 +445,7 @@ local function upgradeBaseBasedOnDamage(map, base)
end
function baseUtils.processBase(chunk, map, tick, base)
if ((tick - base.tick) <= BASE_PROCESS_INTERVAL) then
if ((tick - base.generationTick) <= BASE_PROCESS_INTERVAL) then
return
end
@ -458,7 +460,10 @@ function baseUtils.processBase(chunk, map, tick, base)
chunk.y + (CHUNK_SIZE * map.random()))
local upgradeRoll = map.random()
if (base.state == BASE_AI_STATE_ACTIVE) and (base.points >= MINIMUM_BUILDING_COST) and (upgradeRoll < 0.30) then
if (base.generationState == BASE_GENERATION_STATE_ACTIVE) and
(base.points >= MINIMUM_BUILDING_COST) and
(upgradeRoll < 0.30)
then
local entities = surface.find_entities_filtered(universe.pbFilteredEntitiesPointQueryLimited)
if #entities ~= 0 then
local entity = entities[1]
@ -478,11 +483,12 @@ function baseUtils.processBase(chunk, map, tick, base)
end
local deathThreshold
if (map.evolutionLevel < 0.5) then
local evolutionLevel = map.universe.evolutionLevel
if (evolutionLevel < 0.5) then
deathThreshold = 4500
elseif (map.evolutionLevel < 0.7) then
elseif (evolutionLevel < 0.7) then
deathThreshold = 7500
elseif (map.evolutionLevel < 0.9) then
elseif (evolutionLevel < 0.9) then
deathThreshold = 11000
else
deathThreshold = 16000
@ -528,20 +534,20 @@ function baseUtils.processBase(chunk, map, tick, base)
base.unitPoints = universe.unitPoints
end
if (base.stateTick <= tick) then
if (base.stateGenerationTick <= tick) then
local roll = map.random()
if (roll < 0.85) then
base.state = BASE_AI_STATE_ACTIVE
base.generationState = BASE_GENERATION_STATE_ACTIVE
else
base.state = BASE_AI_STATE_DORMANT
base.generationState = BASE_GENERATION_STATE_DORMANT
end
base.stateTick = randomTickEvent(map.random,
tick,
BASE_AI_MIN_STATE_DURATION,
BASE_AI_MAX_STATE_DURATION)
base.stateGenerationTick = randomTickEvent(map.random,
tick,
BASE_GENERATION_MIN_STATE_DURATION,
BASE_GENERATION_MAX_STATE_DURATION)
end
base.tick = tick
base.generationTick = tick
end
function baseUtils.createBase(map, chunk, tick)
@ -552,7 +558,7 @@ function baseUtils.createBase(map, chunk, tick)
local meanLevel = mFloor(distance * 0.005)
local distanceIndex = mMin(1, distance * BASE_DISTANCE_TO_EVO_INDEX)
local evoIndex = mMax(distanceIndex, map.evolutionLevel)
local evoIndex = mMax(distanceIndex, map.universe.evolutionLevel)
local baseTick = tick
@ -573,20 +579,36 @@ function baseUtils.createBase(map, chunk, tick)
distanceThreshold = distanceThreshold * map.universe.baseDistanceModifier,
tick = baseTick,
alignment = alignment,
state = BASE_AI_STATE_ACTIVE,
state = BASE_GENERATION_STATE_ACTIVE,
damagedBy = {},
deathEvents = 0,
mutations = 0,
stateTick = 0,
stateGenerationTick = 0,
chunkCount = 0,
createdTick = tick,
points = 0,
unitPoints = 0,
stateAI = BASE_AI_STATE_PEACEFUL,
canAttackTick = 0,
drainPylons = {},
activeRaidNests = 0,
activeNests = 0,
destroyPlayerBuildings = 0,
lostEnemyUnits = 0,
lostEnemyBuilding = 0,
rocketLaunched = 0,
builtEnemyBuilding = 0,
ionCannonBlasts = 0,
artilleryBlasts = 0,
temperament = 0.5,
temperamentScore = 0,
stateAITick = 0,
id = universe.baseId
}
universe.baseId = universe.baseId + 1
map.bases[base.id] = base
universe.bases[base.id] = base
return base
end

View File

@ -37,7 +37,7 @@ local DEFINES_WIRE_TYPE_GREEN = defines.wire_type.green
local CHUNK_PASS_THRESHOLD = constants.CHUNK_PASS_THRESHOLD
local AI_STATE_ONSLAUGHT = constants.AI_STATE_ONSLAUGHT
local BASE_AI_STATE_ONSLAUGHT = constants.BASE_AI_STATE_ONSLAUGHT
local BASE_PHEROMONE = constants.BASE_PHEROMONE
local PLAYER_PHEROMONE = constants.PLAYER_PHEROMONE
@ -529,7 +529,7 @@ function chunkUtils.registerEnemyBaseStructure(map, entity, tick, incomingBase,
end
end
function chunkUtils.unregisterEnemyBaseStructure(map, entity, damageType, skipCount)
function chunkUtils.unregisterEnemyBaseStructure(map, entity, damageTypeName, skipCount)
local entityType = entity.type
local removeFunc
@ -568,9 +568,8 @@ function chunkUtils.unregisterEnemyBaseStructure(map, entity, damageType, skipCo
if removeFunc(map, chunk, entityUnitNumber) then
removed = true
local base = getChunkBase(map, chunk)
if damageType and not usedBases[base.id] then
if damageTypeName and not usedBases[base.id] then
usedBases[base.id] = true
local damageTypeName = damageType.name
base.damagedBy[damageTypeName] = (base.damagedBy[damageTypeName] or 0) + 3
base.deathEvents = base.deathEvents + 3
end
@ -585,23 +584,23 @@ function chunkUtils.unregisterEnemyBaseStructure(map, entity, damageType, skipCo
end
end
function chunkUtils.accountPlayerEntity(entity, map, addObject, creditNatives)
function chunkUtils.accountPlayerEntity(entity, map, addObject, base)
if (BUILDING_PHEROMONES[entity.type] ~= nil) and (entity.force.name ~= "enemy") then
local universe = map.universe
local entityValue = BUILDING_PHEROMONES[entity.type]
local overlapArray = getEntityOverlapChunks(map, entity)
if not addObject then
if creditNatives then
map.destroyPlayerBuildings = map.destroyPlayerBuildings + 1
if (map.state == AI_STATE_ONSLAUGHT) then
map.points = map.points + entityValue
if base then
base.destroyPlayerBuildings = base.destroyPlayerBuildings + 1
if (base.state == BASE_AI_STATE_ONSLAUGHT) then
base.points = base.points + entityValue
if universe.aiPointsPrintGainsToChat then
game.print(map.surface.name .. ": Points: +" .. math.floor(entityValue) .. ". [Structure Kill] Total: " .. string.format("%.2f", map.points))
game.print(map.surface.name .. ": Points: +" .. math.floor(entityValue) .. ". [Structure Kill] Total: " .. string.format("%.2f", base.points))
end
else
map.points = map.points + (entityValue * 0.12)
base.points = base.points + (entityValue * 0.12)
if universe.aiPointsPrintGainsToChat then
game.print(map.surface.name .. ": Points: +" .. math.floor(entityValue * 0.12) .. ". [Structure Kill] Total: " .. string.format("%.2f", map.points))
game.print(map.surface.name .. ": Points: +" .. math.floor(entityValue * 0.12) .. ". [Structure Kill] Total: " .. string.format("%.2f", base.points))
end
end
end

View File

@ -139,38 +139,38 @@ constants.AI_SQUAD_MERGE_THRESHOLD = constants.AI_MAX_BITER_GROUP_SIZE * 0.75
constants.AI_MAX_SQUADS_PER_CYCLE = 7
constants.AI_STATE_PEACEFUL = 1
constants.AI_STATE_AGGRESSIVE = 2
constants.AI_STATE_RAIDING = 4
constants.AI_STATE_MIGRATING = 5
constants.AI_STATE_SIEGE = 6
constants.AI_STATE_ONSLAUGHT = 7
constants.BASE_AI_STATE_PEACEFUL = 1
constants.BASE_AI_STATE_AGGRESSIVE = 2
constants.BASE_AI_STATE_RAIDING = 4
constants.BASE_AI_STATE_MIGRATING = 5
constants.BASE_AI_STATE_SIEGE = 6
constants.BASE_AI_STATE_ONSLAUGHT = 7
constants.stateEnglish = {}
constants.stateEnglish[constants.AI_STATE_PEACEFUL] = "AI_STATE_PEACEFUL"
constants.stateEnglish[constants.AI_STATE_AGGRESSIVE] = "AI_STATE_AGGRESSIVE"
constants.stateEnglish[constants.AI_STATE_RAIDING] = "AI_STATE_RAIDING"
constants.stateEnglish[constants.AI_STATE_MIGRATING] = "AI_STATE_MIGRATING"
constants.stateEnglish[constants.AI_STATE_SIEGE] = "AI_STATE_SIEGE"
constants.stateEnglish[constants.AI_STATE_ONSLAUGHT] = "AI_STATE_ONSLAUGHT"
constants.stateEnglish[constants.BASE_AI_STATE_PEACEFUL] = "AI_STATE_PEACEFUL"
constants.stateEnglish[constants.BASE_AI_STATE_AGGRESSIVE] = "AI_STATE_AGGRESSIVE"
constants.stateEnglish[constants.BASE_AI_STATE_RAIDING] = "AI_STATE_RAIDING"
constants.stateEnglish[constants.BASE_AI_STATE_MIGRATING] = "AI_STATE_MIGRATING"
constants.stateEnglish[constants.BASE_AI_STATE_SIEGE] = "AI_STATE_SIEGE"
constants.stateEnglish[constants.BASE_AI_STATE_ONSLAUGHT] = "AI_STATE_ONSLAUGHT"
constants.BASE_AI_STATE_DORMANT = 0
constants.BASE_AI_STATE_ACTIVE = 1
constants.BASE_AI_STATE_OVERDRIVE = 2
constants.BASE_AI_STATE_MUTATE = 3
constants.BASE_GENERATION_STATE_DORMANT = 0
constants.BASE_GENERATION_STATE_ACTIVE = 1
-- constants.BASE_AI_STATE_OVERDRIVE = 2
-- constants.BASE_AI_STATE_MUTATE = 3
constants.ACTIVE_NESTS_PER_AGGRESSIVE_GROUPS = 30
constants.AGGRESSIVE_CAN_ATTACK_WAIT_MIN_DURATION = 0.5
constants.AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION = 3
constants.AI_MIN_STATE_DURATION = 10
constants.AI_MAX_STATE_DURATION = 25
constants.BASE_AI_MIN_STATE_DURATION = 10
constants.BASE_AI_MAX_STATE_DURATION = 25
constants.AI_MIN_TEMPERAMENT_DURATION = 25
constants.AI_MAX_TEMPERAMENT_DURATION = 32
-- constants.AI_MIN_TEMPERAMENT_DURATION = 25
-- constants.AI_MAX_TEMPERAMENT_DURATION = 32
constants.BASE_AI_MIN_STATE_DURATION = 12
constants.BASE_AI_MAX_STATE_DURATION = 20
constants.BASE_GENERATION_MIN_STATE_DURATION = 12
constants.BASE_GENERATION_MAX_STATE_DURATION = 20
-- ai base

View File

@ -49,10 +49,10 @@ local PROCESS_STATIC_QUEUE_SIZE = constants.PROCESS_STATIC_QUEUE_SIZE
local AI_VENGENCE_SQUAD_COST = constants.AI_VENGENCE_SQUAD_COST
local AI_STATE_AGGRESSIVE = constants.AI_STATE_AGGRESSIVE
local AI_STATE_SIEGE = constants.AI_STATE_SIEGE
local AI_STATE_PEACEFUL = constants.AI_STATE_PEACEFUL
local AI_STATE_MIGRATING = constants.AI_STATE_MIGRATING
local BASE_AI_STATE_AGGRESSIVE = constants.BASE_AI_STATE_AGGRESSIVE
local BASE_AI_STATE_SIEGE = constants.BASE_AI_STATE_SIEGE
local BASE_AI_STATE_PEACEFUL = constants.BASE_AI_STATE_PEACEFUL
local BASE_AI_STATE_MIGRATING = constants.BASE_AI_STATE_MIGRATING
local COOLDOWN_DRAIN = constants.COOLDOWN_DRAIN
local COOLDOWN_RALLY = constants.COOLDOWN_RALLY
@ -60,6 +60,8 @@ local COOLDOWN_RETREAT = constants.COOLDOWN_RETREAT
-- imported functions
local findNearbyBase = baseUtils.findNearbyBase
local removeChunkToNest = mapUtils.removeChunkToNest
local processStaticPheromone = pheromoneUtils.processStaticPheromone
@ -219,13 +221,13 @@ function mapProcessor.processPlayers(players, universe, tick)
local char = player.character
local map = universe.maps[char.surface.index]
if map then
local allowingAttacks = canAttack(map)
local allowingAttacks = canAttack(map, base)
local playerChunk = getChunkByPosition(map, char.position)
if (playerChunk ~= -1) then
local base = findNearbyBase(map, playerChunk)
local vengence = allowingAttacks and
(map.points >= AI_VENGENCE_SQUAD_COST) and
(base.points >= AI_VENGENCE_SQUAD_COST) and
((getEnemyStructureCount(map, playerChunk) > 0) or
(getDeathGeneratorRating(map, playerChunk) < universe.retreatThreshold))
@ -506,19 +508,19 @@ local function processSpawnersBody(universe, iterator, chunks)
return
end
local state = chunkPack.map.state
if base.state == AI_STATE_PEACEFUL then
if base.state == BASE_AI_STATE_PEACEFUL then
return
end
if iterator == "processMigrationIterator" then
if (base.state ~= AI_STATE_MIGRATING) and (state ~= AI_STATE_SIEGE) then
if (base.state ~= BASE_AI_STATE_MIGRATING) and (state ~= BASE_AI_STATE_SIEGE) then
return
end
elseif iterator == "processActiveRaidSpawnerIterator" then
if (base.state == AI_STATE_AGGRESSIVE) or (base.state == AI_STATE_MIGRATING) then
if (base.state == BASE_AI_STATE_AGGRESSIVE) or (base.state == BASE_AI_STATE_MIGRATING) then
return
end
elseif iterator == "processActiveSpawnerIterator" then
if (base.state == AI_STATE_MIGRATING) then
if (base.state == BASE_AI_STATE_MIGRATING) then
return
end
end

View File

@ -44,7 +44,7 @@ local SQUAD_SETTLING = constants.SQUAD_SETTLING
local SQUAD_GUARDING = constants.SQUAD_GUARDING
local SQUAD_RETREATING = constants.SQUAD_RETREATING
local AI_STATE_SIEGE = constants.AI_STATE_SIEGE
local BASE_AI_STATE_SIEGE = constants.BASE_AI_STATE_SIEGE
local PLAYER_PHEROMONE_MULTIPLER = constants.PLAYER_PHEROMONE_MULTIPLER
@ -129,7 +129,7 @@ local function settleMove(map, squad)
local x, y = positionToChunkXY(groupPosition)
local chunk = getChunkByXY(map, x, y)
local scoreFunction = scoreResourceLocation
if (map.state == AI_STATE_SIEGE) then
if (base.state == BASE_AI_STATE_SIEGE) then
if squad.kamikaze then
scoreFunction = scoreSiegeLocationKamikaze
else
@ -200,7 +200,7 @@ local function settleMove(map, squad)
local attackPlayerThreshold = universe.attackPlayerThreshold
if (nextAttackChunk ~= -1) then
if (getPlayerBaseGenerator(map,nextAttackChunk) == 0) or (map.state ~= AI_STATE_SIEGE) then
if (getPlayerBaseGenerator(map,nextAttackChunk) == 0) or (base.state ~= BASE_AI_STATE_SIEGE) then
attackChunk = nextAttackChunk
position = findMovementPosition(
surface,
@ -256,7 +256,10 @@ local function settleMove(map, squad)
return
end
if (nextAttackChunk ~= -1) and (map.state == AI_STATE_SIEGE) and (getPlayerBaseGenerator(map, nextAttackChunk) ~= 0) then
if (nextAttackChunk ~= -1) and
(base.state == BASE_AI_STATE_SIEGE) and
(getPlayerBaseGenerator(map, nextAttackChunk) ~= 0)
then
cmd = universe.settleCommand
squad.status = SQUAD_BUILDING
if squad.kamikaze then