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

RC3 build

This commit is contained in:
Aaron Veden 2020-05-24 16:41:12 -07:00
parent 7e837d8529
commit 9aa81d20d4
No known key found for this signature in database
GPG Key ID: FF5990B1C6DD3F84
17 changed files with 209 additions and 106 deletions

View File

@ -1,5 +1,5 @@
# Rampant Tactics
Factorio Mod - Improves the enemies tactics by using potential fields/pheromones allowing probing of defenses, retreats, reinforcements, counterattacking, breaching, raids, rallying death cry, and player hunting. Uses nonhoming blockable biter projectiles. Adds new Enemies (disabled by default). Can completely replace the vanilla AI. Difficulty setting in mod options menu.
Factorio Mod - Improves the enemies tactics by using potential fields/pheromones allowing probing of defenses, retreats, reinforcements, counterattacking, breaching, raids, rallying death cry, and player hunting. Uses nonhoming blockable biter projectiles. Adds new Enemies (disabled by default). Difficulty setting in mod options menu.
# Forum Post
@ -35,7 +35,6 @@ Configure Options not in game menu:
- Frenzy squads - When a unit group gets close to a player or start combat they switch to attacking everything in there path for a set radius or until there is nothing left
- Rabid squads - Is in a permanent frenzied state as soon as the group is formed
- Tactical Retreats - These will take place when a unit group is in a chunk that has reached a death threshold
- Unit Group Merging - If two squads occupy roughly the same area and are doing the same task then they will merge
- Unit Group Forming - Any chunks with spawners in it that is covered by a pollution or player clouds will form groups based on the evolution factor
- Probing Behavior Against Defenses - unit groups will attempt to avoid chunks that are soaked in death
- Player Hunting - Unit groups will track the player based on there emitted pheromone cloud

View File

@ -7,7 +7,9 @@ Date: 16. 4 2020
- Integrated vanilla AI into Rampant for pollution management
- Map processing sweep now does and forward and reverse pass
- Better handling of death pheromone and squad coordination
- Added support for script_raised_set_tiles
Tweaks:
- Reduced active raid nest contribution to AI state to 0.002
- Changed ai credits per rocket launched to 5000
- Refactored calculateKamikazeThreshold based on member count and current evolution
- Reduced enemy unit lost contribution to AI state to 0.001

View File

@ -41,11 +41,10 @@ local INTERVAL_PASS_SCAN = constants.INTERVAL_PASS_SCAN
local INTERVAL_NEST = constants.INTERVAL_NEST
local INTERVAL_CLEANUP = constants.INTERVAL_CLEANUP
local INTERVAL_MAP_STATIC_PROCESS = constants.INTERVAL_MAP_STATIC_PROCESS
local INTERVAL_VICTORY = constants.INTERVAL_VICTORY
local HIVE_BUILDINGS = constants.HIVE_BUILDINGS
local AI_MAX_BUILDER_COUNT = constants.AI_MAX_BUILDER_COUNT
local AI_MAX_SQUAD_COUNT = constants.AI_MAX_SQUAD_COUNT
local AI_SQUAD_COST = constants.AI_SQUAD_COST
local AI_SETTLER_COST = constants.AI_SETTLER_COST
@ -113,6 +112,8 @@ local processStaticMap = mapProcessor.processStaticMap
local getPlayerBaseGenerator = chunkPropertyUtils.getPlayerBaseGenerator
local disperseVictoryScent = pheromoneUtils.disperseVictoryScent
local getChunkByPosition = mapUtils.getChunkByPosition
local entityForPassScan = chunkUtils.entityForPassScan
@ -259,6 +260,7 @@ local function rebuildMap()
map.chunkToPathRating = {}
map.chunkToDeathGenerator = {}
map.chunkToDrained = {}
map.chunkToVictory = {}
map.chunkToActiveNest = {}
map.chunkToActiveRaidNest = {}
@ -273,6 +275,7 @@ local function rebuildMap()
map.processActiveRaidSpawnerIterator = nil
map.processMigrationIterator = nil
map.processNestIterator = nil
map.victoryScentIterator = nil
-- preallocating memory to be used in code, making it fast by reducing garbage generated.
map.neighbors = {
@ -442,8 +445,7 @@ local function rebuildMap()
map.moveCommand = {
type = DEFINES_COMMAND_GO_TO_LOCATION,
destination = map.position,
radius = 2,
pathfind_flags = { prefer_straight_paths = true, cache = true },
pathfind_flags = { cache = false },
distraction = DEFINES_DISTRACTION_BY_ENEMY
}
@ -539,11 +541,11 @@ local function rebuildMap()
unit_search_distance = TRIPLE_CHUNK_SIZE }
map.formLocalCommand = { command = map.formLocalGroupCommand,
unit_count = AI_MAX_BITER_GROUP_SIZE,
unit_count = natives.attackWaveMaxSize,
unit_search_distance = CHUNK_SIZE }
map.formRetreatCommand = { command = map.compoundRetreatGroupCommand,
unit_count = AI_MAX_BITER_GROUP_SIZE,
unit_count = natives.attackWaveMaxSize,
unit_search_distance = CHUNK_SIZE }
end
@ -597,6 +599,8 @@ local function onModSettingsChange(event)
natives.enabledMigration = natives.expansion and settings.global["rampant-enableMigration"].value
upgrade.compareTable(natives, "ENEMY_VARIATIONS", settings.startup["rampant-newEnemyVariations"].value)
upgrade.compareTable(natives, "AI_MAX_SQUAD_COUNT", settings.global["rampant-maxNumberOfSquads"].value)
upgrade.compareTable(natives, "AI_MAX_BUILDER_COUNT", settings.global["rampant-maxNumberOfBuilders"].value)
return true
end
@ -864,7 +868,7 @@ local function onSurfaceTileChange(event)
if (surface.index == surfaceIndex) then
local chunks = {}
local tiles = event.tiles
if (event.tile.name == "landfill") or sFind(event.tile.name, "water") then
if event.tile and ((event.tile.name == "landfill") or sFind(event.tile.name, "water")) then
for i=1,#tiles do
local position = tiles[i].position
local chunk = getChunkByPosition(map, position)
@ -889,6 +893,34 @@ local function onSurfaceTileChange(event)
end
end
end
else
for i=1,#tiles do
local tile = tiles[i]
if (tile.name == "landfill") or sFind(tile.name, "water") then
local position = tile.position
local chunk = getChunkByPosition(map, position)
if (chunk ~= -1) then
map.chunkToPassScan[chunk] = true
else
local x,y = positionToChunkXY(position)
local addMe = true
for ci=1,#chunks do
local c = chunks[ci]
if (c.x == x) and (c.y == y) then
addMe = false
break
end
end
if addMe then
local chunkXY = {x=x,y=y}
chunks[#chunks+1] = chunkXY
onChunkGenerated({area = { left_top = chunkXY },
surface = surface})
end
end
end
end
end
end
end
@ -994,11 +1026,18 @@ local function onUnitGroupCreated(event)
local group = event.group
local surface = group.surface
if (surface.name == natives.activeSurface) and (group.force.name == "enemy") then
print("fuck", event.tick, natives.squadCount, natives.squadCount > natives.AI_MAX_SQUAD_COUNT, natives.builderCount, natives.builderCount > natives.AI_MAX_BUILDER_COUNT)
if not group.is_script_driven then
if not natives.aiNocturnalMode then
local settler = mRandom() < 0.25 and
canMigrate(natives, group.surface) and
(natives.builderCount < AI_MAX_BUILDER_COUNT)
(natives.builderCount < natives.AI_MAX_BUILDER_COUNT)
if not settler and natives.squadCount > natives.AI_MAX_SQUAD_COUNT then
group.destroy()
natives.points = natives.points + AI_SQUAD_COST
return
end
squad = createSquad(nil, nil, group, settler)
natives.groupNumberToSquad[group.group_number] = squad
@ -1008,13 +1047,22 @@ local function onUnitGroupCreated(event)
else
natives.squadCount = natives.squadCount + 1
end
elseif not (surface.darkness > 0.65) then
natives.points = natives.points + AI_SQUAD_COST
group.destroy()
else
if not (surface.darkness > 0.65) then
natives.points = natives.points + AI_SQUAD_COST
group.destroy()
return
end
local settler = mRandom() < 0.25 and
canMigrate(natives, group.surface) and
(natives.builderCount < AI_MAX_BUILDER_COUNT)
(natives.builderCount < natives.AI_MAX_BUILDER_COUNT)
if not settler and natives.squadCount > natives.AI_MAX_SQUAD_COUNT then
group.destroy()
natives.points = natives.points + AI_SQUAD_COST
return
end
squad = createSquad(nil, nil, group, settler)
natives.groupNumberToSquad[group.group_number] = squad
@ -1055,21 +1103,17 @@ local function onGroupFinishedGathering(event)
if (group.surface.name == natives.activeSurface) then
local squad = natives.groupNumberToSquad[unitNumber]
if squad.settler then
if (natives.builderCount < AI_MAX_BUILDER_COUNT) then
if (natives.builderCount < natives.AI_MAX_BUILDER_COUNT) then
squadDispatch(map, group.surface, squad, unitNumber)
else
-- game.players[1].teleport(group.position, game.surfaces[1])
group.destroy()
-- print("destroying settlers", event.tick)
natives.points = natives.points + AI_SETTLER_COST
end
else
if (natives.squadCount < AI_MAX_SQUAD_COUNT) then
if (natives.squadCount < natives.AI_MAX_SQUAD_COUNT) then
squadDispatch(map, group.surface, squad, unitNumber)
else
-- game.players[1].teleport(group.position, game.surfaces[1])
group.destroy()
-- print("destroying squad", event.tick)
natives.points = natives.points + AI_SQUAD_COST
end
end
@ -1157,8 +1201,6 @@ script.on_nth_tick(INTERVAL_LOGIC,
game.forces.enemy.evolution_factor,
tick)
cleanSquads(natives, map.squadIterator)
if natives.newEnemies then
recycleBases(natives, tick)
end
@ -1185,6 +1227,11 @@ script.on_nth_tick(INTERVAL_SPAWNER,
event.tick)
end)
script.on_nth_tick(INTERVAL_VICTORY,
function (event)
disperseVictoryScent(map)
end)
script.on_nth_tick(INTERVAL_SQUAD,
function (event)
processVengence(map,
@ -1222,7 +1269,7 @@ script.on_event(defines.events.on_tick,
scanPlayerMap(map, surface, tick)
end
cleanSquads(natives, map.squadIterator)
processActiveNests(map, surface, tick)
end)
@ -1237,7 +1284,8 @@ script.on_configuration_changed(onConfigChanged)
script.on_event(defines.events.on_resource_depleted, onResourceDepleted)
script.on_event({defines.events.on_player_built_tile,
defines.events.on_robot_built_tile}, onSurfaceTileChange)
defines.events.on_robot_built_tile,
defines.events.script_raised_set_tiles}, onSurfaceTileChange)
script.on_event(defines.events.on_player_used_capsule, onUsedCapsule)

View File

@ -6,5 +6,5 @@
"author" : "Veden",
"homepage" : "https://forums.factorio.com/viewtopic.php?f=94&t=31445",
"description" : "Improves the enemies tactics by using potential fields/pheromones allowing probing of defenses, retreats, reinforcements, counterattacking, breaching, raids, rallying death cry, and player hunting. Uses blockable biter projectiles. Adds new Enemies (disabled by default). Difficulty setting in mod options menu.",
"dependencies" : ["base >= 0.18.22", "? bobenemies", "? Natural_Evolution_Enemies >= 0.17.0", "? Clockwork", "? Orbital Ion Cannon", "? RampantArsenal", "? RampantResources", "? ArmouredBiters"]
"dependencies" : ["base >= 0.18.26", "? bobenemies", "? Natural_Evolution_Enemies >= 0.17.0", "? Clockwork", "? Orbital Ion Cannon", "? RampantArsenal", "? RampantResources", "? ArmouredBiters"]
}

View File

@ -23,11 +23,8 @@ local RESOURCE_PHEROMONE = constants.RESOURCE_PHEROMONE
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_MAX_BUILDER_COUNT = constants.AI_MAX_BUILDER_COUNT
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
local AI_STATE_AGGRESSIVE = constants.AI_STATE_AGGRESSIVE
@ -189,7 +186,7 @@ end
function aiAttackWave.formSettlers(map, surface, chunk, tick)
local natives = map.natives
if (natives.builderCount < AI_MAX_BUILDER_COUNT) and
if (natives.builderCount < natives.AI_MAX_BUILDER_COUNT) and
(mRandom() < natives.formSquadThreshold) and
((natives.points - AI_SETTLER_COST) > 0)
then
@ -247,7 +244,7 @@ end
function aiAttackWave.formVengenceSquad(map, surface, chunk)
local natives = map.natives
if (natives.squadCount < AI_MAX_SQUAD_COUNT) and
if (natives.squadCount < natives.AI_MAX_SQUAD_COUNT) and
(mRandom() < natives.formSquadThreshold) and
((natives.points - AI_VENGENCE_SQUAD_COST) > 0)
then
@ -277,6 +274,7 @@ function aiAttackWave.formVengenceSquad(map, surface, chunk)
if (foundUnits > 0) then
squad.kamikaze = mRandom() < calculateKamikazeThreshold(foundUnits, natives)
natives.groupNumberToSquad[squad.groupNumber] = squad
natives.squadCount = natives.squadCount + 1
natives.points = natives.points - AI_VENGENCE_SQUAD_COST
else
if (squad.group.valid) then
@ -290,7 +288,7 @@ end
function aiAttackWave.formSquads(map, surface, chunk, tick)
local natives = map.natives
if (natives.squadCount < AI_MAX_SQUAD_COUNT) and
if (natives.squadCount < natives.AI_MAX_SQUAD_COUNT) and
attackWaveValidCandidate(chunk, natives, map) and
(mRandom() < natives.formSquadThreshold) and
((natives.points - AI_SQUAD_COST) > 0)

View File

@ -290,7 +290,7 @@ function aiPlanning.temperamentPlanner(natives)
end
if activeRaidNests > 0 then
local val = (0.008 * activeRaidNests)
local val = (0.002 * activeRaidNests)
delta = delta - val
else
delta = delta - 0.5

View File

@ -226,6 +226,10 @@ function chunkPropertyUtils.addDeathGenerator(map, chunk, value)
map.chunkToDeathGenerator[chunk] = (map.chunkToDeathGenerator[chunk] or 0) + value
end
function chunkPropertyUtils.addVictoryGenerator(map, chunk, value)
map.chunkToVictory[chunk] = (map.chunkToVictory[chunk] or 0) + value
end
function chunkPropertyUtils.decayDeathGenerator(map, chunk)
local gen = map.chunkToDeathGenerator[chunk]
if gen then

View File

@ -53,24 +53,26 @@ constants.ATTACK_QUEUE_SIZE = 18
constants.BASE_QUEUE_SIZE = 1
constants.PROCESS_STATIC_QUEUE_SIZE = 20
constants.PROCESS_PLAYER_BOUND = 128
constants.VICTORY_SCENT_BOUND = 128
constants.TICKS_A_SECOND = 60
constants.TICKS_A_MINUTE = constants.TICKS_A_SECOND * 60
constants.CHUNK_PASS_THRESHOLD = 0.25
constants.INTERVAL_PLAYER_PROCESS = 63
constants.INTERVAL_MAP_PROCESS = 5
constants.INTERVAL_MAP_STATIC_PROCESS = 11
constants.INTERVAL_SCAN = 19
-- constants.INTERVAL_PLAYER_PROCESS = 63
-- constants.INTERVAL_MAP_PROCESS = 5
-- constants.INTERVAL_MAP_STATIC_PROCESS = 11
-- constants.INTERVAL_SCAN = 19
constants.INTERVAL_CHUNK_PROCESS = 23
constants.INTERVAL_LOGIC = 59
constants.INTERVAL_TEMPERAMENT = 121
constants.INTERVAL_SQUAD = 14
constants.INTERVAL_NEST = 16
constants.INTERVAL_PASS_SCAN = 29
constants.INTERVAL_RESQUAD = 101
-- constants.INTERVAL_RESQUAD = 101
constants.INTERVAL_SPAWNER = 19
constants.INTERVAL_VICTORY = 10
constants.INTERVAL_CLEANUP = 34
constants.COOLDOWN_RALLY = constants.TICKS_A_SECOND * 10
@ -129,8 +131,6 @@ constants.RAIDING_MINIMUM_BASE_THRESHOLD = 550
constants.AI_UNIT_REFUND = 3
constants.AI_MAX_BUILDER_COUNT = 60
constants.AI_MAX_SQUAD_COUNT = 100
constants.AI_MAX_BITER_GROUP_SIZE = 600
constants.AI_SQUAD_MERGE_THRESHOLD = constants.AI_MAX_BITER_GROUP_SIZE * 0.75
@ -139,7 +139,6 @@ constants.AI_MAX_SQUADS_PER_CYCLE = 7
constants.AI_STATE_PEACEFUL = 1
constants.AI_STATE_AGGRESSIVE = 2
-- constants.AI_STATE_NOCTURNAL = 3
constants.AI_STATE_RAIDING = 4
constants.AI_STATE_MIGRATING = 5
constants.AI_STATE_SIEGE = 6
@ -147,8 +146,6 @@ constants.AI_STATE_ONSLAUGHT = 7
constants.BASE_AI_STATE_DORMANT = 0
constants.BASE_AI_STATE_ACTIVE = 1
-- constants.BASE_AI_STATE_WORMS = 2
-- constants.BASE_AI_STATE_NESTS = 3
constants.BASE_AI_STATE_OVERDRIVE = 2
constants.BASE_AI_STATE_MUTATE = 3
@ -158,8 +155,6 @@ constants.AGGRESSIVE_CAN_ATTACK_WAIT_MAX_DURATION = 3
constants.AI_MIN_STATE_DURATION = 7
constants.AI_MAX_STATE_DURATION = 17
-- constants.AI_MIN_STATE_DURATION = 0.2
-- constants.AI_MAX_STATE_DURATION = 0.2
constants.AI_MIN_TEMPERAMENT_DURATION = 25
constants.AI_MAX_TEMPERAMENT_DURATION = 32
@ -1190,7 +1185,7 @@ if settings.startup["rampant-poisonEnemy"].value then
majorResistances = {"poison"},
minorWeaknesses = {"electric", "explosion", "laser"},
attributes = {"poisonDeathCloud"},
acceptRate = {1, 10, 0.4, 0.6},
acceptRate = {1, 10, 0.4, 0.6},
drops = {"greenArtifact"},
buildSets = {
{"biter", 1, 10}
@ -1217,7 +1212,7 @@ if settings.startup["rampant-poisonEnemy"].value then
acceptRate = {2, 10, 0.001, 0.0175},
drops = {"greenArtifact"},
buildSets = {
{"biter-spawner", 1, 10, 0.15, 0.3},
{"biter-spawner", 1, 10, 0.15, 0.3},
{"turret", 1, 10, 0.8, 0.57},
{"hive", 2, 10, 0.002, 0.02}
}
@ -1491,6 +1486,29 @@ constants.HIVE_BUILDINGS_TYPES = {
"hive"
}
constants.VICTORY_SCENT_MULTIPLER = {}
for x=1,9 do
for y=1,9 do
local adjV
local v
if x <= 5 and y <= 5 then
v = math.min(x, y)
elseif x > 5 and y < 5 then
v = math.min((10-x), y)
elseif x < 5 and y > 5 then
v = math.min(x, (10-y))
else
v = math.min((10-x), (10-y))
end
if v < 5 then
adjV = v / 5
else
adjV = 1
end
constants.VICTORY_SCENT_MULTIPLER[#constants.VICTORY_SCENT_MULTIPLER+1] = adjV
end
end
constants.HIVE_BUILDINGS_COST = {}
constants.HIVE_BUILDINGS_COST["trap"] = constants.BASE_WORM_UPGRADE * 0.5
constants.HIVE_BUILDINGS_COST["turret"] = constants.BASE_WORM_UPGRADE

View File

@ -55,7 +55,7 @@ function movementUtils.addMovementPenalty(map, squad, chunk)
if (penalty.c == chunk) then
penalty.v = ((penaltyCount > 1) and penalty.v + 1) or penalty.v
if (penalty.v > 2) then
-- print("movementThreshold", #penalties, squad.group.group_number, penalty.v, squad.settlers, squad.kamikaze, squad.status)
print("movementThreshold", #penalties, squad.group.group_number, penalty.v, squad.settlers, squad.kamikaze, squad.status)
-- game.players[1].teleport(chunk, game.surfaces[1])
squad.kamikaze = true
end

View File

@ -11,6 +11,9 @@ local chunkPropertyUtils = require("ChunkPropertyUtils")
-- constants
local VICTORY_SCENT_MULTIPLER = constants.VICTORY_SCENT_MULTIPLER
local VICTORY_SCENT_BOUND = constants.VICTORY_SCENT_BOUND
local MAGIC_MAXIMUM_NUMBER = constants.MAGIC_MAXIMUM_NUMBER
local CHUNK_TICK = constants.CHUNK_TICK
@ -36,6 +39,8 @@ local DEATH_PHEROMONE_GENERATOR_AMOUNT = constants.DEATH_PHEROMONE_GENERATOR_AMO
-- imported functions
local addVictoryGenerator = chunkPropertyUtils.addVictoryGenerator
local getPlayersOnChunk = chunkPropertyUtils.getPlayersOnChunk
local getNeighborChunks = mapUtils.getNeighborChunks
@ -52,17 +57,48 @@ local decayDeathGenerator = chunkPropertyUtils.decayDeathGenerator
local linearInterpolation = mathUtils.linearInterpolation
local getChunkByXY = mapUtils.getChunkByXY
local mAbs = math.abs
local next = next
-- module code
function pheromoneUtils.victoryScent(map, chunk, entityType)
local value = VICTORY_SCENT[entityType]
if value then
addDeathGenerator(map, chunk, -value)
addVictoryGenerator(map, chunk, value)
end
end
function pheromoneUtils.disperseVictoryScent(map)
local iterator = map.victoryScentIterator
local chunkToVictory = map.chunkToVictory
local chunk,pheromone = next(chunkToVictory, iterator)
if chunk then
local chunkX = chunk.x
local chunkY = chunk.y
local i = 1
for x=chunkX - VICTORY_SCENT_BOUND, chunkX + VICTORY_SCENT_BOUND do
for y = chunkY - VICTORY_SCENT_BOUND, chunkY + VICTORY_SCENT_BOUND do
local c = getChunkByXY(map, x, y)
if (c ~= -1) then
addDeathGenerator(map, c, -pheromone * VICTORY_SCENT_MULTIPLER[i])
end
i = i + 1
end
end
local newChunk = next(chunkToVictory, chunk)
chunkToVictory[chunk] = nil
chunk = newChunk
end
map.victoryScentIterator = chunk
end
function pheromoneUtils.deathScent(map, chunk)
addDeathGenerator(map, chunk, DEATH_PHEROMONE_GENERATOR_AMOUNT)
end

View File

@ -93,10 +93,16 @@ function aiDefense.retreatUnits(chunk, cause, map, surface, tick, radius)
local newSquad = findNearbyRetreatingSquad(map, exitPath)
local created = false
local natives = map.natives
if not newSquad then
created = true
newSquad = createSquad(position, surface)
if (natives.squadCount < natives.AI_MAX_SQUAD_COUNT) then
created = true
newSquad = createSquad(position, surface)
else
print("cancelling retreat")
return
end
end
map.fleeCommand.from = cause
@ -113,8 +119,7 @@ function aiDefense.retreatUnits(chunk, cause, map, surface, tick, radius)
return
end
if created then
local natives = map.natives
if created then
natives.groupNumberToSquad[newSquad.groupNumber] = newSquad
natives.squadCount = natives.squadCount + 1
end

View File

@ -134,13 +134,10 @@ function unitGroupUtils.createSquad(position, surface, group, settlers)
end
function unitGroupUtils.cleanSquads(natives, iterator)
-- local profiler = game.create_profiler()
local squads = natives.groupNumberToSquad
local map = natives.map
local k, squad = next(squads, iterator)
local nextK
-- for i=1,2 do
if not k then
if (table_size(squads) == 0) then
-- this is needed as the next command remembers the max length a table has been
@ -159,53 +156,15 @@ function unitGroupUtils.cleanSquads(natives, iterator)
else
natives.squadCount = natives.squadCount - 1
end
local nextK
nextK,squad = next(squads, k)
squads[k] = nil
k = nextK
-- else
-- game.print({"", "3b", profiler})
-- profiler.restart()
-- local members = group.members
-- local memberCount = #members
-- if (memberCount == 0) then
-- game.print({"", "4a", profiler})
-- profiler.restart()
-- local deathGen = getDeathGenerator(map, squad.chunk)
-- local penalties = squad.penalties
-- for xc=1,mMin(#squad.penalties,5) do
-- addDeathGenerator(map,
-- penalties[xc].c,
-- deathGen * DIVISOR_DEATH_TRAIL_TABLE[xc])
-- end
-- removeSquadFromChunk(map, squad)
-- group.destroy()
-- game.print({"", "4ea", profiler})
-- profiler.restart()
-- elseif (memberCount > AI_MAX_BITER_GROUP_SIZE) then
-- game.print({"", "4b", profiler})
-- profiler.restart()
-- unitGroupUtils.recycleBiters(natives, members)
-- removeSquadFromChunk(map, squad)
-- group.destroy()
-- game.print({"", "4eb", profiler})
-- profiler.restart()
-- end
-- game.print({"", "3be", profiler})
end
end
-- end
map.squadIterator = k
end
-- function unitGroupUtils.membersToSquad(cmd, size, members, overwriteGroup)
-- for i=1,size do
-- local member = members[i]
-- if member.valid and (overwriteGroup or (not overwriteGroup and not member.unit_group)) then
-- member.set_command(cmd)
-- end
-- end
-- end
function unitGroupUtils.calculateKamikazeThreshold(memberCount, natives)
local threshold = (memberCount / natives.attackWaveMaxSize) * 0.2 + (natives.evolutionLevel * 0.2)
return threshold

View File

@ -18687,6 +18687,8 @@ rampant-useDumbProjectiles=Projectiles: Use blockable projectiles
rampant-attackWaveGenerationThresholdMax=Attack Wave: Starting chunk attack threshold
rampant-attackWaveGenerationThresholdMin=Attack Wave: Ending chunk attack threshold
rampant-attackWaveMaxSize=Attack Wave: Max biter group size that can be directly formed
rampant-maxNumberOfSquads=Attack Wave: Max number of attack groups that can be active at once
rampant-maxNumberOfBuilders=Attack Wave: Max number of building groups that can be active at once
rampant-safeBuildings=Safety: Enable building safety.
rampant-safeBuildings-curvedRail=Safety: Make curved rails safe from biters
rampant-safeBuildings-straightRail=Safety: Make straight rails safe from biters
@ -18870,6 +18872,9 @@ rampant-enableFullMapScan=This setting causes the game map to slowly be scanned
rampant-suppress-surface-change-warnings=Turn off the warnings you get when you change surfaces, warnings should only appear the first time you visit a new surface.
rampant-maxNumberOfBuilders=If you are not using many other script mods, I recommend putting this to 60.
rampant-maxNumberOfSquads=If you are not using many other script mods, I recommend putting this to 70.
[description]
rampant-set-surface=You are setting the Rampant AI active surface to\n__1__
rampant-error-set-surface=If you wish to change Rampants active surface run, \n/SetRampantAISurface SurfaceName\nwhere SurfaceName is the name of the surface you want to switch to.

View File

@ -39,7 +39,8 @@
baseCreated
hives
traps
utility)
utility
vg)
#:transparent)
(struct Chunk (kamikazeScore
@ -70,7 +71,8 @@
baseCreated
hives
traps
utility)
utility
vg)
#:transparent)
(require threading)
@ -83,7 +85,7 @@
(define (stringToChunk str)
(match-let (((list movement base player resource passable tick rating x y nest
worms rally retreat resourceGen playerGen deathGen pollution aNe aRNe squads
baseCreated hives traps utility) (string-split str ",")))
baseCreated hives traps utility vg) (string-split str ",")))
(apply Chunk
(cons (+ (string->number base)
(* (string->number player) 100))
@ -103,7 +105,7 @@
(map string->number
(list x y movement base player resource passable tick rating nest
worms rally retreat resourceGen playerGen deathGen pollution aNe
aRNe squads baseCreated hives traps utility))))))))))
aRNe squads baseCreated hives traps utility vg))))))))))
(define (chunk->string chunk)
(string-append "x: " (~v (Chunk-x chunk)) "\n"
@ -135,7 +137,8 @@
"bC: " (~v (Chunk-baseCreated chunk)) "\n"
"H: " (~v (Chunk-hives chunk)) "\n"
"T: " (~v (Chunk-traps chunk)) "\n"
"U: " (~v (Chunk-utility chunk)) "\n"))
"U: " (~v (Chunk-utility chunk)) "\n"
"vg: " (~v (Chunk-vg chunk)) "\n"))
(define (normalizeRange xs)
(let* ((sDev (stddev xs))
@ -176,7 +179,8 @@
(bC (map Chunk-baseCreated chunks))
(H (map Chunk-hives chunks))
(T (map Chunk-traps chunks))
(U (map Chunk-utility chunks)))
(U (map Chunk-utility chunks))
(vg (map Chunk-vg chunks)))
(ChunkRange (MinMax (apply min xs) (apply max xs))
(MinMax (apply min ys) (apply max ys))
@ -206,7 +210,8 @@
(MinMax (apply min bC) (apply max bC))
(MinMax (apply min H) (apply max H))
(MinMax (apply min T) (apply max T))
(MinMax (apply min U) (apply max U)))
(MinMax (apply min U) (apply max U))
(MinMax (apply min vg) (apply max vg)))
))
(define (readState filePath)

View File

@ -42,12 +42,34 @@ data:extend({
name = "rampant-attackWaveMaxSize",
setting_type = "runtime-global",
minimum_value = 20,
maximum_value = 400,
maximum_value = 600,
default_value = 150,
order = "b[modifier]-f[wave]",
per_user = false
},
{
type = "int-setting",
name = "rampant-maxNumberOfSquads",
setting_type = "runtime-global",
minimum_value = 1,
maximum_value = 300,
default_value = 50,
order = "b[modifier]-f[wave]",
per_user = false
},
{
type = "int-setting",
name = "rampant-maxNumberOfBuilders",
setting_type = "runtime-global",
minimum_value = 1,
maximum_value = 120,
default_value = 50,
order = "b[modifier]-f[wave]",
per_user = false
},
{
type = "bool-setting",
name = "rampant-permanentNocturnal",

View File

@ -435,7 +435,9 @@ function tests.exportAiState()
alignmentCount,
chunkPropertyUtils.getHiveCount(global.map, chunk),
chunkPropertyUtils.getTrapCount(global.map, chunk),
chunkPropertyUtils.getUtilityCount(global.map, chunk)}, ",") .. "\n"
chunkPropertyUtils.getUtilityCount(global.map, chunk),
global.map.chunkToVictory[chunk] or 0
}, ",") .. "\n"
end
game.write_file("rampantState.txt", s, false)
end

View File

@ -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 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 0 0 0 0 0 0))
(define windowX 500)
(define windowY 0)
@ -278,7 +278,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" "pollution" "aNe" "aRNe" "squads" "baseCreated" "hives" "traps" "utility")]
[choices (list "movement" "base" "player" "resource" "passable" "tick" "rating" "nests" "worms" "rally" "retreat" "resourceGen" "playerGen" "deathGen" "attackScore" "settleScore" "siegeScore" "retreatScore" "kamikazeScore" "pollution" "aNe" "aRNe" "squads" "baseCreated" "hives" "traps" "utility" "vg")]
[selection 0]
[parent mainFrame]
(callback (lambda (radioButton event)