mirror of
https://github.com/veden/Rampant.git
synced 2025-02-03 13:11:54 +02:00
see changelog
This commit is contained in:
parent
397da09fe7
commit
351293f16b
10
Upgrade.lua
10
Upgrade.lua
@ -117,7 +117,7 @@ function upgrade.attempt(natives)
|
||||
natives.attackWaveDeviation = 0
|
||||
natives.attackWaveUpperBound = 0
|
||||
natives.unitRefundAmount = 0
|
||||
natives.attackWaveThreshold = 0
|
||||
-- natives.attackWaveThreshold = 0
|
||||
|
||||
game.map_settings.unit_group.member_disown_distance = constants.UNIT_GROUP_DISOWN_DISTANCE
|
||||
game.map_settings.unit_group.tick_tolerance_when_member_arrives = constants.UNIT_GROUP_TICK_TOLERANCE
|
||||
@ -260,6 +260,14 @@ function upgrade.attempt(natives)
|
||||
game.surfaces[natives.activeSurface].print("Rampant - Version 0.16.41")
|
||||
global.version = constants.VERSION_76
|
||||
end
|
||||
if (global.version < constants.VERSION_77) then
|
||||
|
||||
natives.attackWaveThreshold = nil
|
||||
natives.attackWav = nil
|
||||
|
||||
game.surfaces[natives.activeSurface].print("Rampant - Version 0.16.42")
|
||||
global.version = constants.VERSION_77
|
||||
end
|
||||
|
||||
return starting ~= global.version, natives
|
||||
end
|
||||
|
@ -1,3 +1,17 @@
|
||||
---------------------------------------------------------------------------------------------------
|
||||
Version: 0.16.42
|
||||
Date: 2. 18. 2019
|
||||
Improvements:
|
||||
- Reworked how nests are activated by pollution, player, and base pheromone for better nest tracking
|
||||
- Removed use pollution map setting
|
||||
- Removed min and max attack threshold settings
|
||||
Tweaks:
|
||||
- Increased max squad count from 30 to 40
|
||||
Bugfixes:
|
||||
- Reverted pheromone projection
|
||||
- Reverted settings default player threshold to 7
|
||||
- Fixed radial pattern sort not being trigger on map rebuild
|
||||
|
||||
---------------------------------------------------------------------------------------------------
|
||||
Version: 0.16.41
|
||||
Date: 2. 18. 2019
|
||||
@ -6,7 +20,7 @@ Date: 2. 18. 2019
|
||||
Tweaks:
|
||||
- Added energy thief crystal and pylon physical resistance 25%
|
||||
- Increased crystal pylon health from 150 to 750
|
||||
- Decreased electric faction damages (7->6, 15->10, 22.5->15, 35->20, 45->30, 60->45, 75->60, 90->75, 150->90, 200->150)
|
||||
- Decreased electric and energy thiefs faction damages (7->6, 15->10, 22.5->15, 35->20, 45->30, 60->45, 75->60, 90->75, 150->90, 200->150)
|
||||
- Decreased energy thief beam width (1.5->1, 1.5->1, 1.6->1.2, 1.6->1.2, 1.7->1.3, 1.7->1.3, 1.8->1.4, 1.8->1.4, 1.9->1.5, 1.9->1.5)
|
||||
- Decreased energy thief range (11->9, 11->9, 12->10, 12->10, 13->11, 13->11, 14->12, 14->12, 15->13, 15->13)
|
||||
- Decreased crystal pylon resistances for fire, electric, laser from 100, 100, 100 to 85, 95, 90
|
||||
|
11
control.lua
11
control.lua
@ -208,6 +208,8 @@ local function rebuildMap()
|
||||
map.chunkToPathRating = {}
|
||||
map.chunkToDeathGenerator = {}
|
||||
map.chunkToDrained = {}
|
||||
map.chunkToActiveNest = {}
|
||||
map.chunkToActiveRaidNest = {}
|
||||
|
||||
-- map.queueSpawners = {}
|
||||
|
||||
@ -304,16 +306,16 @@ local function onModSettingsChange(event)
|
||||
end
|
||||
|
||||
upgrade.compareTable(natives, "attackUsePlayer", settings.global["rampant-attackWaveGenerationUsePlayerProximity"].value)
|
||||
upgrade.compareTable(natives, "attackUsePollution", settings.global["rampant-attackWaveGenerationUsePollution"].value)
|
||||
-- upgrade.compareTable(natives, "attackUsePollution", settings.global["rampant-attackWaveGenerationUsePollution"].value)
|
||||
|
||||
upgrade.compareTable(natives, "deadZoneFrequency", settings.global["rampant-deadZoneFrequency"].value)
|
||||
upgrade.compareTable(natives, "raidAIToggle", settings.global["rampant-raidAIToggle"].value)
|
||||
upgrade.compareTable(natives, "siegeAIToggle", settings.global["rampant-siegeAIToggle"].value)
|
||||
upgrade.compareTable(natives, "onslaughtAIToggle", settings.global["rampant-onslaughtAIToggle"].value)
|
||||
|
||||
upgrade.compareTable(natives, "attackThresholdMin", settings.global["rampant-attackWaveGenerationThresholdMin"].value)
|
||||
upgrade.compareTable(natives, "attackThresholdMax", settings.global["rampant-attackWaveGenerationThresholdMax"].value)
|
||||
upgrade.compareTable(natives, "attackThresholdRange", natives.attackThresholdMax - natives.attackThresholdMin)
|
||||
-- upgrade.compareTable(natives, "attackThresholdMin", settings.global["rampant-attackWaveGenerationThresholdMin"].value)
|
||||
-- upgrade.compareTable(natives, "attackThresholdMax", settings.global["rampant-attackWaveGenerationThresholdMax"].value)
|
||||
-- upgrade.compareTable(natives, "attackThresholdRange", natives.attackThresholdMax - natives.attackThresholdMin)
|
||||
upgrade.compareTable(natives, "attackWaveMaxSize", settings.global["rampant-attackWaveMaxSize"].value)
|
||||
upgrade.compareTable(natives, "attackPlayerThreshold", settings.global["rampant-attackPlayerThreshold"].value)
|
||||
upgrade.compareTable(natives, "aiNocturnalMode", settings.global["rampant-permanentNocturnal"].value)
|
||||
@ -358,6 +360,7 @@ local function prepWorld(rebuild)
|
||||
-- queue all current chunks that wont be generated during play
|
||||
local surface = game.surfaces[natives.activeSurface]
|
||||
local tick = game.tick
|
||||
natives.nextChunkSort = 0
|
||||
for chunk in surface.get_chunks() do
|
||||
onChunkGenerated({ tick = tick,
|
||||
surface = surface,
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name" : "Rampant",
|
||||
"factorio_version" : "0.16",
|
||||
"version" : "0.16.41",
|
||||
"version" : "0.16.42",
|
||||
"title" : "Rampant",
|
||||
"author" : "Veden",
|
||||
"homepage" : "https://forums.factorio.com/viewtopic.php?f=94&t=31445",
|
||||
|
@ -22,6 +22,7 @@ local MOVEMENT_PHEROMONE = constants.MOVEMENT_PHEROMONE
|
||||
local RESOURCE_PHEROMONE = constants.RESOURCE_PHEROMONE
|
||||
|
||||
local AI_SQUAD_COST = constants.AI_SQUAD_COST
|
||||
local AI_SETTLER_COST = constants.AI_SETTLER_COST
|
||||
local AI_MAX_SQUAD_COUNT = constants.AI_MAX_SQUAD_COUNT
|
||||
local AI_VENGENCE_SQUAD_COST = constants.AI_VENGENCE_SQUAD_COST
|
||||
|
||||
@ -42,8 +43,6 @@ local AI_STATE_SIEGE = constants.AI_STATE_SIEGE
|
||||
local DEFINES_COMMAND_GROUP = defines.command.group
|
||||
local DEFINES_DISTRACTION_NONE = defines.distraction.none
|
||||
|
||||
local RAIDING_MINIMUM_BASE_THRESHOLD = constants.RAIDING_MINIMUM_BASE_THRESHOLD
|
||||
|
||||
local AI_STATE_RAIDING = constants.AI_STATE_RAIDING
|
||||
|
||||
local SENTINEL_IMPASSABLE_CHUNK = constants.SENTINEL_IMPASSABLE_CHUNK
|
||||
@ -59,6 +58,8 @@ local positionFromDirectionAndChunk = mapUtils.positionFromDirectionAndChunk
|
||||
local getPassable = chunkPropertyUtils.getPassable
|
||||
local getNestCount = chunkPropertyUtils.getNestCount
|
||||
local getChunkSettlerTick = chunkPropertyUtils.getChunkSettlerTick
|
||||
local getRaidNestActiveness = chunkPropertyUtils.getRaidNestActiveness
|
||||
local getNestActiveness = chunkPropertyUtils.getNestActiveness
|
||||
local setChunkSettlerTick = chunkPropertyUtils.setChunkSettlerTick
|
||||
local getRallyTick = chunkPropertyUtils.getRallyTick
|
||||
local setRallyTick = chunkPropertyUtils.setRallyTick
|
||||
@ -75,34 +76,12 @@ local settlerWaveScaling = config.settlerWaveScaling
|
||||
|
||||
-- module code
|
||||
|
||||
local function attackWaveValidCandidate(chunk, natives, surface)
|
||||
local total = 0;
|
||||
|
||||
local hasPlayerPheromone = false
|
||||
if natives.attackUsePlayer then
|
||||
local playerPheromone = chunk[PLAYER_PHEROMONE]
|
||||
if (playerPheromone > natives.attackPlayerThreshold) then
|
||||
total = total + chunk[PLAYER_PHEROMONE]
|
||||
hasPlayerPheromone = true
|
||||
elseif (playerPheromone > 0) then
|
||||
hasPlayerPheromone = true
|
||||
end
|
||||
local function attackWaveValidCandidate(chunk, natives, map)
|
||||
local isValid = getNestActiveness(map, chunk)
|
||||
if natives.state == AI_STATE_RAIDING then
|
||||
isValid = isValid + getRaidNestActiveness(map, chunk)
|
||||
end
|
||||
local hasBasePheromone = false
|
||||
local basePheromone = chunk[BASE_PHEROMONE]
|
||||
if (basePheromone > 0) then
|
||||
hasBasePheromone = true
|
||||
if (natives.state == AI_STATE_RAIDING) then
|
||||
if (basePheromone > RAIDING_MINIMUM_BASE_THRESHOLD) then
|
||||
total = total + basePheromone
|
||||
end
|
||||
end
|
||||
end
|
||||
if natives.attackUsePollution then
|
||||
total = total + surface.get_pollution(chunk)
|
||||
end
|
||||
|
||||
return (total > natives.attackWaveThreshold) and (hasBasePheromone or hasPlayerPheromone)
|
||||
return (isValid > 0)
|
||||
end
|
||||
|
||||
local function scoreSettlerLocation(neighborChunk)
|
||||
@ -141,7 +120,7 @@ function aiAttackWave.rallyUnits(chunk, map, surface, natives, tick)
|
||||
if (x ~= cX) and (y ~= cY) then
|
||||
local rallyChunk = getChunkByXY(map, x, y)
|
||||
if (rallyChunk ~= SENTINEL_IMPASSABLE_CHUNK) and (getNestCount(map, rallyChunk) > 0) then
|
||||
if not aiAttackWave.formSquads(map, surface, natives, rallyChunk, AI_VENGENCE_SQUAD_COST) then
|
||||
if not aiAttackWave.formVengenceSquad(map, surface, natives, rallyChunk) then
|
||||
return
|
||||
end
|
||||
end
|
||||
@ -167,8 +146,7 @@ local function noNearbySettlers(map, chunk, tick)
|
||||
return true
|
||||
end
|
||||
|
||||
function aiAttackWave.formSettlers(map, surface, natives, chunk, cost, tick)
|
||||
|
||||
function aiAttackWave.formSettlers(map, surface, natives, chunk, tick)
|
||||
if (mRandom() < natives.formSquadThreshold) and (#natives.squads < AI_MAX_SQUAD_COUNT) then
|
||||
|
||||
local squadPath, squadDirection
|
||||
@ -211,19 +189,18 @@ function aiAttackWave.formSettlers(map, surface, natives, chunk, cost, tick)
|
||||
unit_search_distance = TRIPLE_CHUNK_SIZE })
|
||||
if (foundUnits > 0) then
|
||||
setChunkSettlerTick(map, squadPath, tick + natives.settlerCooldown)
|
||||
natives.points = natives.points - cost
|
||||
natives.points = natives.points - AI_SETTLER_COST
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return (natives.points - cost) > 0
|
||||
return (natives.points - AI_SETTLER_COST) > 0
|
||||
end
|
||||
|
||||
function aiAttackWave.formSquads(map, surface, natives, chunk, cost)
|
||||
local valid = (cost == AI_VENGENCE_SQUAD_COST) or ((cost == AI_SQUAD_COST) and attackWaveValidCandidate(chunk, natives, surface))
|
||||
|
||||
if valid and (mRandom() < natives.formSquadThreshold) and (#natives.squads < AI_MAX_SQUAD_COUNT) then
|
||||
function aiAttackWave.formVengenceSquad(map, surface, natives, chunk)
|
||||
if (mRandom() < natives.formSquadThreshold) and (#natives.squads < AI_MAX_SQUAD_COUNT)
|
||||
then
|
||||
|
||||
local squadPath, squadDirection = scoreNeighborsForFormation(getNeighborChunks(map, chunk.x, chunk.y),
|
||||
validUnitGroupLocation,
|
||||
@ -249,14 +226,53 @@ function aiAttackWave.formSquads(map, surface, natives, chunk, cost)
|
||||
unit_count = scaledWaveSize,
|
||||
unit_search_distance = TRIPLE_CHUNK_SIZE })
|
||||
if (foundUnits > 0) then
|
||||
natives.points = natives.points - cost
|
||||
natives.points = natives.points - AI_VENGENCE_SQUAD_COST
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return (natives.points - cost) > 0
|
||||
return (natives.points - AI_VENGENCE_SQUAD_COST) > 0
|
||||
end
|
||||
|
||||
function aiAttackWave.formSquads(map, surface, natives, chunk)
|
||||
if attackWaveValidCandidate(chunk, natives, map) and
|
||||
(mRandom() < natives.formSquadThreshold) and
|
||||
(#natives.squads < AI_MAX_SQUAD_COUNT)
|
||||
then
|
||||
local squadPath, squadDirection = scoreNeighborsForFormation(getNeighborChunks(map, chunk.x, chunk.y),
|
||||
validUnitGroupLocation,
|
||||
scoreUnitGroupLocation,
|
||||
map)
|
||||
if (squadPath ~= SENTINEL_IMPASSABLE_CHUNK) then
|
||||
local squadPosition = surface.find_non_colliding_position("chunk-scanner-squad-rampant",
|
||||
positionFromDirectionAndChunk(squadDirection,
|
||||
chunk,
|
||||
map.position,
|
||||
0.98),
|
||||
CHUNK_SIZE,
|
||||
4)
|
||||
if squadPosition then
|
||||
local squad = createSquad(squadPosition, surface, natives)
|
||||
|
||||
squad.rabid = mRandom() < 0.03
|
||||
|
||||
local scaledWaveSize = attackWaveScaling(natives)
|
||||
local foundUnits = surface.set_multi_command({ command = { type = DEFINES_COMMAND_GROUP,
|
||||
group = squad.group,
|
||||
distraction = DEFINES_DISTRACTION_NONE },
|
||||
unit_count = scaledWaveSize,
|
||||
unit_search_distance = TRIPLE_CHUNK_SIZE })
|
||||
if (foundUnits > 0) then
|
||||
natives.points = natives.points - AI_SQUAD_COST
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return (natives.points - AI_SQUAD_COST) > 0
|
||||
end
|
||||
|
||||
|
||||
aiAttackWaveG = aiAttackWave
|
||||
return aiAttackWave
|
||||
|
@ -89,8 +89,8 @@ function aiPlanning.planning(natives, evolution_factor, tick, surface, connected
|
||||
|
||||
natives.unitRefundAmount = AI_UNIT_REFUND * evolution_factor
|
||||
natives.kamikazeThreshold = NO_RETREAT_BASE_PERCENT + (evolution_factor * NO_RETREAT_EVOLUTION_BONUS_MAX)
|
||||
local threshold = natives.attackThresholdRange
|
||||
natives.attackWaveThreshold = (threshold - (threshold * evolution_factor)) + natives.attackThresholdMin
|
||||
-- local threshold = natives.attackThresholdRange
|
||||
-- natives.attackWaveThreshold = (threshold - (threshold * evolution_factor)) + natives.attackThresholdMin
|
||||
|
||||
local points = mFloor((AI_POINT_GENERATOR_AMOUNT * mRandom()) + ((AI_POINT_GENERATOR_AMOUNT * 0.7) * (evolution_factor ^ 2.5)) * natives.aiPointsScaler)
|
||||
|
||||
|
@ -92,7 +92,8 @@ function chunkProcessor.processPendingChunks(natives, map, surface, pendingStack
|
||||
end
|
||||
|
||||
if (#processQueue > natives.nextChunkSort) or
|
||||
(((tick - natives.nextChunkSortTick) > MAX_TICKS_BEFORE_SORT_CHUNKS) and ((natives.nextChunkSort - 75) ~= #processQueue)) then
|
||||
(((tick - natives.nextChunkSortTick) > MAX_TICKS_BEFORE_SORT_CHUNKS) and ((natives.nextChunkSort - 75) ~= #processQueue))
|
||||
then
|
||||
natives.nextChunkSort = #processQueue + 75
|
||||
natives.nextChunkSortTick = tick
|
||||
tSort(processQueue, sorter)
|
||||
|
@ -116,6 +116,31 @@ function chunkPropertyUtils.getPassable(map, chunk)
|
||||
return map.chunkToPassable[chunk] or CHUNK_ALL_DIRECTIONS
|
||||
end
|
||||
|
||||
|
||||
function chunkPropertyUtils.getRaidNestActiveness(map, chunk)
|
||||
return map.chunkToActiveRaidNest[chunk] or 0
|
||||
end
|
||||
|
||||
function chunkPropertyUtils.setRaidNestActiveness(map, chunk, value)
|
||||
if (value <= 0) then
|
||||
map.chunkToActiveRaidNest[chunk] = nil
|
||||
else
|
||||
map.chunkToActiveRaidNest[chunk] = value
|
||||
end
|
||||
end
|
||||
|
||||
function chunkPropertyUtils.getNestActiveness(map, chunk)
|
||||
return map.chunkToActiveNest[chunk] or 0
|
||||
end
|
||||
|
||||
function chunkPropertyUtils.setNestActiveness(map, chunk, value)
|
||||
if (value <= 0) then
|
||||
map.chunkToActiveNest[chunk] = nil
|
||||
else
|
||||
map.chunkToActiveNest[chunk] = value
|
||||
end
|
||||
end
|
||||
|
||||
function chunkPropertyUtils.setPassable(map, chunk, value)
|
||||
if (value == CHUNK_ALL_DIRECTIONS) then
|
||||
map.chunkToPassable[chunk] = nil
|
||||
|
@ -57,6 +57,8 @@ local addResourceGenerator = chunkPropertyUtils.addResourceGenerator
|
||||
local setWormCount = chunkPropertyUtils.setWormCount
|
||||
local getPlayerBaseGenerator = chunkPropertyUtils.getPlayerBaseGenerator
|
||||
local getNestCount = chunkPropertyUtils.getNestCount
|
||||
local setRaidNestActiveness = chunkPropertyUtils.setRaidNestActiveness
|
||||
local setNestActiveness = chunkPropertyUtils.setNestActiveness
|
||||
|
||||
local findNearbyBase = baseUtils.findNearbyBase
|
||||
local createBase = baseUtils.createBase
|
||||
@ -132,7 +134,8 @@ end
|
||||
|
||||
local function removeEnemyStructureFromChunk(map, chunk, entity)
|
||||
local lookup
|
||||
if (entity.type == "unit-spawner") then
|
||||
local entityType = entity.type
|
||||
if (entityType == "unit-spawner") then
|
||||
lookup = map.chunkToNests
|
||||
elseif (entity.type == "turret") then
|
||||
lookup = map.chunkToWorms
|
||||
@ -146,6 +149,10 @@ local function removeEnemyStructureFromChunk(map, chunk, entity)
|
||||
|
||||
if lookup[chunk] then
|
||||
if ((lookup[chunk] - 1) <= 0) then
|
||||
if (entityType == "unit-spawner") then
|
||||
setRaidNestActiveness(map, chunk, 0)
|
||||
setNestActiveness(map, chunk, 0)
|
||||
end
|
||||
lookup[chunk] = nil
|
||||
else
|
||||
lookup[chunk] = lookup[chunk] - 1
|
||||
|
@ -28,6 +28,7 @@ constants.VERSION_72 = 72
|
||||
constants.VERSION_73 = 73
|
||||
constants.VERSION_75 = 75
|
||||
constants.VERSION_76 = 76
|
||||
constants.VERSION_77 = 77
|
||||
|
||||
-- misc
|
||||
|
||||
@ -38,8 +39,8 @@ constants.MAGIC_MAXIMUM_BASE_NUMBER = 100000000
|
||||
constants.RETREAT_MOVEMENT_PHEROMONE_LEVEL_MIN = 10000
|
||||
constants.RETREAT_MOVEMENT_PHEROMONE_LEVEL_MAX = 170000
|
||||
|
||||
constants.PROCESS_QUEUE_SIZE = 300
|
||||
constants.SCAN_QUEUE_SIZE = 5
|
||||
constants.PROCESS_QUEUE_SIZE = 275
|
||||
constants.SCAN_QUEUE_SIZE = 10
|
||||
constants.BASE_QUEUE_SIZE = 1
|
||||
constants.SQUAD_QUEUE_SIZE = 2
|
||||
constants.PROCESS_PLAYER_BOUND = 128
|
||||
@ -101,7 +102,7 @@ constants.RAIDING_MINIMUM_BASE_THRESHOLD = 250
|
||||
|
||||
constants.AI_UNIT_REFUND = 3
|
||||
|
||||
constants.AI_MAX_SQUAD_COUNT = 30
|
||||
constants.AI_MAX_SQUAD_COUNT = 40
|
||||
constants.AI_MAX_BITER_GROUP_SIZE = 450
|
||||
|
||||
constants.AI_SQUAD_MERGE_THRESHOLD = constants.AI_MAX_BITER_GROUP_SIZE * 0.75
|
||||
|
@ -34,7 +34,11 @@ local AI_SQUAD_COST = constants.AI_SQUAD_COST
|
||||
local AI_VENGENCE_SQUAD_COST = constants.AI_VENGENCE_SQUAD_COST
|
||||
local AI_SETTLER_COST = constants.AI_SETTLER_COST
|
||||
|
||||
local RAIDING_MINIMUM_BASE_THRESHOLD = constants.RAIDING_MINIMUM_BASE_THRESHOLD
|
||||
|
||||
local MOVEMENT_PHEROMONE = constants.MOVEMENT_PHEROMONE
|
||||
local PLAYER_PHEROMONE = constants.PLAYER_PHEROMONE
|
||||
local BASE_PHEROMONE = constants.BASE_PHEROMONE
|
||||
|
||||
local INTERVAL_RALLY = constants.INTERVAL_RALLY
|
||||
local INTERVAL_RETREAT = constants.INTERVAL_RETREAT
|
||||
@ -51,6 +55,7 @@ local playerScent = pheromoneUtils.playerScent
|
||||
|
||||
local formSquads = aiAttackWave.formSquads
|
||||
local formSettlers = aiAttackWave.formSettlers
|
||||
local formVengenceSquad = aiAttackWave.formVengenceSquad
|
||||
|
||||
local getChunkByPosition = mapUtils.getChunkByPosition
|
||||
local getChunkByXY = mapUtils.getChunkByXY
|
||||
@ -63,6 +68,11 @@ local analyzeChunk = chunkUtils.analyzeChunk
|
||||
|
||||
local getNestCount = chunkPropertyUtils.getNestCount
|
||||
local getEnemyStructureCount = chunkPropertyUtils.getEnemyStructureCount
|
||||
local getNestActiveness = chunkPropertyUtils.getNestActiveness
|
||||
local setNestActiveness = chunkPropertyUtils.setNestActiveness
|
||||
local getRaidNestActiveness = chunkPropertyUtils.getRaidNestActiveness
|
||||
local setRaidNestActiveness = chunkPropertyUtils.setRaidNestActiveness
|
||||
|
||||
|
||||
local canAttack = aiPredicates.canAttack
|
||||
local canMigrate = aiPredicates.canMigrate
|
||||
@ -72,6 +82,7 @@ local findNearbySquad = unitGroupUtils.findNearbySquad
|
||||
local processBase = baseUtils.processBase
|
||||
|
||||
local mMin = math.min
|
||||
local mMax = math.max
|
||||
|
||||
local mRandom = math.random
|
||||
|
||||
@ -124,14 +135,12 @@ function mapProcessor.processMap(map, surface, natives, tick, evolutionFactor)
|
||||
if (chunk[CHUNK_TICK] ~= tick) then
|
||||
processPheromone(map, chunk, scentStaging[i])
|
||||
|
||||
if (getNestCount(map, chunk) > 0) then
|
||||
if squads then
|
||||
squads = formSquads(map, surface, natives, chunk, AI_SQUAD_COST)
|
||||
end
|
||||
if settlers then
|
||||
settlers = formSettlers(map, surface, natives, chunk, AI_SETTLER_COST, tick)
|
||||
end
|
||||
end
|
||||
if squads then
|
||||
squads = formSquads(map, surface, natives, chunk)
|
||||
end
|
||||
if settlers and (getNestCount(map, chunk) > 0) then
|
||||
settlers = formSettlers(map, surface, natives, chunk, tick)
|
||||
end
|
||||
|
||||
if newEnemies then
|
||||
local base = chunkToBase[chunk]
|
||||
@ -204,7 +213,7 @@ function mapProcessor.processPlayers(players, map, surface, natives, tick)
|
||||
if (playerChunk ~= SENTINEL_IMPASSABLE_CHUNK) then
|
||||
local vengence = (allowingAttacks and
|
||||
(natives.points >= AI_VENGENCE_SQUAD_COST) and
|
||||
((getEnemyStructureCount(map, playerChunk) > 0) or (playerChunk[MOVEMENT_PHEROMONE] < natives.retreatThreshold)))
|
||||
((getEnemyStructureCount(map, playerChunk) > 0) or (playerChunk[MOVEMENT_PHEROMONE] < -natives.retreatThreshold)))
|
||||
|
||||
for x=playerChunk.x - PROCESS_PLAYER_BOUND, playerChunk.x + PROCESS_PLAYER_BOUND, 32 do
|
||||
for y=playerChunk.y - PROCESS_PLAYER_BOUND, playerChunk.y + PROCESS_PLAYER_BOUND, 32 do
|
||||
@ -213,14 +222,38 @@ function mapProcessor.processPlayers(players, map, surface, natives, tick)
|
||||
if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) and (chunk[CHUNK_TICK] ~= tick) then
|
||||
processPheromone(map, chunk, scentStaging[i])
|
||||
|
||||
if (getNestCount(map, chunk) > 0) then
|
||||
if squads then
|
||||
squads = formSquads(map, surface, natives, chunk, AI_SQUAD_COST)
|
||||
end
|
||||
if vengence then
|
||||
vengence = formSquads(map, surface, natives, chunk, AI_VENGENCE_SQUAD_COST)
|
||||
end
|
||||
end
|
||||
local nests = getNestCount(map, chunk)
|
||||
if (nests > 0) then
|
||||
local activeness = getNestActiveness(map, chunk)
|
||||
local raidActiveness = getRaidNestActiveness(map, chunk)
|
||||
if natives.attackUsePlayer and (chunk[PLAYER_PHEROMONE] > natives.attackPlayerThreshold) then
|
||||
setNestActiveness(map, chunk, mMin((activeness or 0) + 5, 20))
|
||||
elseif (chunk[BASE_PHEROMONE] > 0) then
|
||||
if (surface.get_pollution(chunk) > 0) then
|
||||
setNestActiveness(map, chunk, mMin((activeness or 0) + 5, 20))
|
||||
else
|
||||
setNestActiveness(map, chunk, activeness - 2)
|
||||
if (chunk[BASE_PHEROMONE] > RAIDING_MINIMUM_BASE_THRESHOLD) then
|
||||
setRaidNestActiveness(map, chunk, mMin((raidActiveness or 0) + 3, 20))
|
||||
else
|
||||
setRaidNestActiveness(map, chunk, raidActiveness - 1)
|
||||
end
|
||||
end
|
||||
else
|
||||
setNestActiveness(map, chunk, activeness - 5)
|
||||
setRaidNestActiveness(map, chunk, raidActiveness - 5)
|
||||
end
|
||||
else
|
||||
setNestActiveness(map, chunk, 0)
|
||||
setRaidNestActiveness(map, chunk, 0)
|
||||
end
|
||||
|
||||
if squads then
|
||||
squads = formSquads(map, surface, natives, chunk)
|
||||
end
|
||||
if vengence and (getNestCount(map, chunk) > 0) then
|
||||
vengence = formVengenceSquad(map, surface, natives, chunk)
|
||||
end
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
@ -307,12 +340,38 @@ function mapProcessor.scanMap(map, surface, natives, tick)
|
||||
end
|
||||
|
||||
analyzeChunk(chunk, natives, surface, map)
|
||||
local nests = getNestCount(map, chunk)
|
||||
if (nests > 0) then
|
||||
local activeness = getNestActiveness(map, chunk)
|
||||
local raidActiveness = getRaidNestActiveness(map, chunk)
|
||||
if natives.attackUsePlayer and (chunk[PLAYER_PHEROMONE] > natives.attackPlayerThreshold) then
|
||||
setNestActiveness(map, chunk, mMin((activeness or 0) + 5, 20))
|
||||
elseif (chunk[BASE_PHEROMONE] > 0) then
|
||||
if (surface.get_pollution(chunk) > 0) then
|
||||
setNestActiveness(map, chunk, mMin((activeness or 0) + 5, 20))
|
||||
else
|
||||
setNestActiveness(map, chunk, activeness - 2)
|
||||
if (chunk[BASE_PHEROMONE] > RAIDING_MINIMUM_BASE_THRESHOLD) then
|
||||
setRaidNestActiveness(map, chunk, mMin((raidActiveness or 0) + 3, 20))
|
||||
else
|
||||
setRaidNestActiveness(map, chunk, raidActiveness - 1)
|
||||
end
|
||||
end
|
||||
else
|
||||
setNestActiveness(map, chunk, activeness - 5)
|
||||
setRaidNestActiveness(map, chunk, raidActiveness - 5)
|
||||
end
|
||||
else
|
||||
setNestActiveness(map, chunk, 0)
|
||||
setRaidNestActiveness(map, chunk, 0)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if (endIndex == #processQueue) then
|
||||
map.scanIndex = 1
|
||||
map.scanIndex = 1
|
||||
else
|
||||
map.scanIndex = endIndex + 1
|
||||
map.scanIndex = endIndex + 1
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -193,7 +193,7 @@ function pheromoneUtils.processPheromone(map, chunk, staging)
|
||||
if neighborCount == 0 then
|
||||
neighborDiv = 0
|
||||
else
|
||||
neighborDiv = ((1/neighborCount) * 1.20)
|
||||
neighborDiv = (1/neighborCount)
|
||||
end
|
||||
|
||||
staging[MOVEMENT_PHEROMONE] = (chunkMovement + (neighborDiv * movementTotal)) * MOVEMENT_PHEROMONE_PERSISTANCE * chunkPathRating
|
||||
|
@ -12418,7 +12418,7 @@ poison-worm-v20-t10-rampant=Poison worm: Juggernaut class
|
||||
[mod-setting-name]
|
||||
rampant-useDumbProjectiles=Projectiles: Use non-homing attack
|
||||
rampant-useNEUnitLaunchers=Projectiles: Use NE Unit Launchers (Needs NE)
|
||||
rampant-attackWaveGenerationUsePollution=Attack Wave: Use Pollution as attack trigger
|
||||
# rampant-attackWaveGenerationUsePollution=Attack Wave: Use Pollution as attack trigger
|
||||
rampant-attackWaveGenerationUsePlayerProximity=Attack Wave: Use Player Proximity as attack trigger
|
||||
rampant-attackWaveGenerationThresholdMax=Attack Wave: Starting chunk attack threshold
|
||||
rampant-attackWaveGenerationThresholdMin=Attack Wave: Ending chunk attack threshold
|
||||
@ -12500,7 +12500,7 @@ rampant-poisonEnemy=Poison Biter Faction
|
||||
[mod-setting-description]
|
||||
rampant-useDumbProjectiles=Turns off homing projectiles for worms and spitters
|
||||
rampant-useNEUnitLaunchers=ONLY FOR USE WITH NATURAL EVOLUTION ENEMIES use the NE unit launchers with medium and big worms. if set to false this will still allow the dumb projectiles but without the unit spawning. A side effect of the dumb projectiles cause the units to be spawned as if two shots were fired
|
||||
rampant-attackWaveGenerationUsePollution=Include pollution amount for threshold on chunks with biter nests that will generate a Rampant attack wave. DOES NOT affect vanilla biters waves
|
||||
# rampant-attackWaveGenerationUsePollution=Include pollution amount for threshold on chunks with biter nests that will generate a Rampant attack wave. DOES NOT affect vanilla biters waves
|
||||
rampant-attackWaveGenerationUsePlayerProximity=Include player pheromones amount for threshold on chunks with biter nests that will generate a Rampant attack wave. DOES NOT affect vanilla biters waves
|
||||
rampant-attackWaveGenerationThresholdMax=The total score that a chunk must reach in order for an attack wave to spawn. DOES NOT affect vanilla biters waves. Scaling linearly with evolution factor (starting threshold @ 0.0 evolution)
|
||||
rampant-attackWaveGenerationThresholdMin=The total score that a chunk must reach in order for an attack wave to spawn. DOES NOT affect vanilla biters waves. Scaling linearly with evolution factor (ending threshold @ 100.0 evolution)
|
||||
|
@ -31,7 +31,10 @@
|
||||
settleScore
|
||||
siegeScore
|
||||
retreatScore
|
||||
kamikazeScore)
|
||||
kamikazeScore
|
||||
pollution
|
||||
aNe
|
||||
aRNe)
|
||||
#:transparent)
|
||||
|
||||
(struct Chunk (kamikazeScore
|
||||
@ -54,7 +57,10 @@
|
||||
retreat
|
||||
resourceGen
|
||||
playerGen
|
||||
deathGen)
|
||||
deathGen
|
||||
pollution
|
||||
aNe
|
||||
aRNe)
|
||||
#:transparent)
|
||||
|
||||
(require threading)
|
||||
@ -66,7 +72,7 @@
|
||||
|
||||
(define (stringToChunk str)
|
||||
(match-let (((list movement base player resource passable tick rating x y nest
|
||||
worms rally retreat resourceGen playerGen deathGen) (string-split str ",")))
|
||||
worms rally retreat resourceGen playerGen deathGen pollution aNe aRNe) (string-split str ",")))
|
||||
(apply Chunk
|
||||
(cons (+ (string->number base)
|
||||
(* (string->number player) 2500))
|
||||
@ -81,15 +87,15 @@
|
||||
(cons (+ (string->number movement)
|
||||
(string->number resource))
|
||||
(cons (+ ;; (* 2 (string->number movement))
|
||||
(* (string->number base)
|
||||
(if (< (string->number movement) 0)
|
||||
(- 1 (/ (string->number movement)
|
||||
-100000))
|
||||
1))
|
||||
(* (string->number player) 2500))
|
||||
(* (string->number base)
|
||||
(if (< (string->number movement) 0)
|
||||
(- 1 (/ (string->number movement)
|
||||
-100000))
|
||||
1))
|
||||
(* (string->number player) 2500))
|
||||
(map string->number
|
||||
(list x y movement base player resource passable tick rating nest
|
||||
worms rally retreat resourceGen playerGen deathGen))))))))))
|
||||
worms rally retreat resourceGen playerGen deathGen pollution aNe aRNe))))))))))
|
||||
|
||||
(define (chunk->string chunk)
|
||||
(string-append "x: " (~v (Chunk-x chunk)) "\n"
|
||||
@ -113,7 +119,10 @@
|
||||
"aSco: " (~v (Chunk-attackScore chunk)) "\n"
|
||||
"sSco: " (~v (Chunk-settleScore chunk)) "\n"
|
||||
"sSei: " (~v (Chunk-siegeScore chunk)) "\n"
|
||||
"sRet: " (~v (Chunk-retreatScore chunk)) "\n"))
|
||||
"sRet: " (~v (Chunk-retreatScore chunk)) "\n"
|
||||
"pol: " (~v (Chunk-pollution chunk)) "\n"
|
||||
"aNe: " (~v (Chunk-aNe chunk)) "\n"
|
||||
"aRNe: " (~v (Chunk-aRNe chunk)) "\n"))
|
||||
|
||||
(define (normalizeRange xs)
|
||||
(let* ((sDev (stddev xs))
|
||||
@ -146,7 +155,10 @@
|
||||
(sSco (map Chunk-settleScore chunks))
|
||||
(sSei (map Chunk-siegeScore chunks))
|
||||
(sRet (map Chunk-retreatScore chunks))
|
||||
(sKam (map Chunk-kamikazeScore chunks)))
|
||||
(sKam (map Chunk-kamikazeScore chunks))
|
||||
(pol (map Chunk-pollution chunks))
|
||||
(aNe (map Chunk-aNe chunks))
|
||||
(aRNe (map Chunk-aRNe chunks)))
|
||||
|
||||
;; (ChunkRange (MinMax (apply min xs) (apply max xs))
|
||||
;; (MinMax (apply min ys) (apply max ys))
|
||||
@ -190,7 +202,10 @@
|
||||
(normalizeRange sSco)
|
||||
(normalizeRange sSei)
|
||||
(normalizeRange sRet)
|
||||
(normalizeRange sKam))
|
||||
(normalizeRange sKam)
|
||||
(normalizeRange pol)
|
||||
(MinMax (apply min aNe) (apply max aNe))
|
||||
(MinMax (apply min aRNe) (apply max aRNe)))
|
||||
|
||||
))
|
||||
|
||||
|
54
settings.lua
54
settings.lua
@ -28,14 +28,14 @@ data:extend({
|
||||
per_user = false
|
||||
},
|
||||
|
||||
{
|
||||
type = "bool-setting",
|
||||
name = "rampant-attackWaveGenerationUsePollution",
|
||||
setting_type = "runtime-global",
|
||||
default_value = true,
|
||||
order = "b[modifier]-a[trigger]",
|
||||
per_user = false
|
||||
},
|
||||
-- {
|
||||
-- type = "bool-setting",
|
||||
-- name = "rampant-attackWaveGenerationUsePollution",
|
||||
-- setting_type = "runtime-global",
|
||||
-- default_value = true,
|
||||
-- order = "b[modifier]-a[trigger]",
|
||||
-- per_user = false
|
||||
-- },
|
||||
|
||||
{
|
||||
type = "bool-setting",
|
||||
@ -51,30 +51,30 @@ data:extend({
|
||||
name = "rampant-attackPlayerThreshold",
|
||||
setting_type = "runtime-global",
|
||||
minimum_value = 0,
|
||||
default_value = 16,
|
||||
default_value = 7,
|
||||
order = "b[modifier]-c[threshold]",
|
||||
per_user = false
|
||||
},
|
||||
|
||||
{
|
||||
type = "double-setting",
|
||||
name = "rampant-attackWaveGenerationThresholdMax",
|
||||
setting_type = "runtime-global",
|
||||
minimum_value = 0,
|
||||
default_value = 20,
|
||||
order = "b[modifier]-d[threshold]",
|
||||
per_user = false
|
||||
},
|
||||
-- {
|
||||
-- type = "double-setting",
|
||||
-- name = "rampant-attackWaveGenerationThresholdMax",
|
||||
-- setting_type = "runtime-global",
|
||||
-- minimum_value = 0,
|
||||
-- default_value = 20,
|
||||
-- order = "b[modifier]-d[threshold]",
|
||||
-- per_user = false
|
||||
-- },
|
||||
|
||||
{
|
||||
type = "double-setting",
|
||||
name = "rampant-attackWaveGenerationThresholdMin",
|
||||
setting_type = "runtime-global",
|
||||
minimum_value = 0,
|
||||
default_value = 0,
|
||||
order = "b[modifier]-e[threshold]",
|
||||
per_user = false
|
||||
},
|
||||
-- {
|
||||
-- type = "double-setting",
|
||||
-- name = "rampant-attackWaveGenerationThresholdMin",
|
||||
-- setting_type = "runtime-global",
|
||||
-- minimum_value = 0,
|
||||
-- default_value = 0,
|
||||
-- order = "b[modifier]-e[threshold]",
|
||||
-- per_user = false
|
||||
-- },
|
||||
|
||||
{
|
||||
type = "int-setting",
|
||||
|
25
tests.lua
25
tests.lua
@ -8,7 +8,7 @@ local mapUtils = require("libs/MapUtils")
|
||||
local baseUtils = require("libs/BaseUtils")
|
||||
-- local tendrilUtils = require("libs/TendrilUtils")
|
||||
|
||||
function tests.pheromoneLevels(size)
|
||||
function tests.pheromoneLevels(size)
|
||||
local player = game.player.character
|
||||
local playerChunkX = math.floor(player.position.x / 32) * constants.CHUNK_SIZE
|
||||
local playerChunkY = math.floor(player.position.y / 32) * constants.CHUNK_SIZE
|
||||
@ -158,7 +158,7 @@ function tests.fillableDirtTest()
|
||||
game.surfaces[global.natives.activeSurface].set_tiles({{name="fillableDirt", position={chunkX-1, chunkY-1}},
|
||||
{name="fillableDirt", position={chunkX, chunkY-1}},
|
||||
{name="fillableDirt", position={chunkX-1, chunkY}},
|
||||
{name="fillableDirt", position={chunkX, chunkY}}},
|
||||
{name="fillableDirt", position={chunkX, chunkY}}},
|
||||
false)
|
||||
end
|
||||
|
||||
@ -284,7 +284,7 @@ function tests.clearBases()
|
||||
pos = pos + slice
|
||||
end
|
||||
else
|
||||
table.remove(global.natives.bases, x)
|
||||
table.remove(global.natives.bases, x)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -350,7 +350,7 @@ function tests.colorResourcePoints()
|
||||
color = "water-green"
|
||||
end
|
||||
chunkUtils.colorChunk(chunk.x, chunk.y, color, game.surfaces[global.natives.activeSurface])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function tests.entityStats(name, d)
|
||||
@ -372,7 +372,7 @@ function tests.exportAiState()
|
||||
local s = ""
|
||||
for i=1,#chunks do
|
||||
local chunk = chunks[i]
|
||||
|
||||
|
||||
s = s .. table.concat({chunk[constants.MOVEMENT_PHEROMONE],
|
||||
chunk[constants.BASE_PHEROMONE],
|
||||
chunk[constants.PLAYER_PHEROMONE],
|
||||
@ -388,11 +388,14 @@ function tests.exportAiState()
|
||||
chunkPropertyUtils.getRetreatTick(global.map, chunk),
|
||||
chunkPropertyUtils.getResourceGenerator(global.map, chunk),
|
||||
chunkPropertyUtils.getPlayerBaseGenerator(global.map, chunk),
|
||||
chunkPropertyUtils.getDeathGenerator(global.map, chunk)}, ",") .. "\n"
|
||||
chunkPropertyUtils.getDeathGenerator(global.map, chunk),
|
||||
game.surfaces[global.natives.activeSurface].get_pollution(chunk),
|
||||
chunkPropertyUtils.getNestActiveness(global.map, chunk),
|
||||
chunkPropertyUtils.getRaidNestActiveness(global.map, chunk)}, ",") .. "\n"
|
||||
end
|
||||
game.write_file("rampantState.txt", s, false)
|
||||
end
|
||||
|
||||
|
||||
return function(interval)
|
||||
if not interval then
|
||||
interval = 0
|
||||
@ -401,7 +404,7 @@ function tests.exportAiState()
|
||||
end
|
||||
|
||||
printState()
|
||||
|
||||
|
||||
if (interval > 0) then
|
||||
script.on_nth_tick(interval, printState)
|
||||
end
|
||||
@ -422,11 +425,11 @@ function tests.createEnergyTest(x)
|
||||
-- print(entities[i].name)
|
||||
-- end
|
||||
local wires
|
||||
|
||||
|
||||
if #entities > 0 then
|
||||
entity.connect_neighbour(entities[1])
|
||||
end
|
||||
|
||||
|
||||
-- if wires then
|
||||
-- for connectType,neighbourGroup in pairs(wires) do
|
||||
-- if connectType == "copper" then
|
||||
@ -441,7 +444,7 @@ end
|
||||
function tests.unitGroupBuild()
|
||||
local surface = game.surfaces[global.natives.activeSurface]
|
||||
local group = surface.create_unit_group({position={-32, -32}})
|
||||
|
||||
|
||||
for i=1,10 do
|
||||
group.add_member(surface.create_entity({name="small-biter", position={-32, -32}}))
|
||||
end
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
(define CHUNK_SIZE 32)
|
||||
|
||||
(define INVALID_CHUNK (Chunk -1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0))
|
||||
(define INVALID_CHUNK (Chunk -1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0))
|
||||
|
||||
(define windowX 500)
|
||||
(define windowY 0)
|
||||
@ -139,7 +139,10 @@
|
||||
settleScore
|
||||
siegeScore
|
||||
retreatScore
|
||||
kamikazeScore) chunkMinMaxes))
|
||||
kamikazeScore
|
||||
pollution
|
||||
aNe
|
||||
aRNe) chunkMinMaxes))
|
||||
|
||||
(set! activeChunkSet chunks)
|
||||
(set! activeChunkMinMaxSet chunkMinMaxes)
|
||||
@ -264,7 +267,7 @@
|
||||
|
||||
(new radio-box%
|
||||
[label "Show Layer"]
|
||||
[choices (list "movement" "base" "player" "resource" "passable" "tick" "rating" "nests" "worms" "rally" "retreat" "resourceGen" "playerGen" "deathGen" "attackScore" "settleScore" "siegeScore" "retreatScore" "kamikazeScore")]
|
||||
[choices (list "movement" "base" "player" "resource" "passable" "tick" "rating" "nests" "worms" "rally" "retreat" "resourceGen" "playerGen" "deathGen" "attackScore" "settleScore" "siegeScore" "retreatScore" "kamikazeScore" "pollution" "aNe" "aRNe")]
|
||||
[selection 0]
|
||||
[parent mainFrame]
|
||||
(callback (lambda (radioButton event)
|
||||
|
Loading…
x
Reference in New Issue
Block a user