1
0
mirror of https://github.com/veden/Rampant.git synced 2025-01-14 02:23:01 +02:00

see readme

This commit is contained in:
Aaron Veden 2017-05-06 02:03:28 -07:00
parent 82753933b0
commit 65aa977f1e
17 changed files with 405 additions and 222 deletions

View File

@ -48,8 +48,15 @@ Configure Options not in game menu:
# Version History # Version History
0.15.5 -
- Tweak: Increased ai refund from 2 to 3
- Fix: Signals, Chain Signals, and Train stops now correctly rebuild when the corresponding make safe is toggled
- Feature: Remote interfaces for adjusting wave size, thresholds, ai build points, ai state, player thresholds, and attack triggers
- Improvement: Added reactor, programmable speaker, radars, lights, and rocket silo to biter targets
- Improvement: Switched all configs to global runtime except Dumb projectiles and NE Unit Launcher Options
0.15.4 - 0.15.4 -
- Fixed: Changed setting name from "make buildings safe from biters" to "Enable building safety." This is to clarify what the setting does. - Fix: Changed setting name from "make buildings safe from biters" to "Enable building safety." This is to clarify what the setting does.
0.15.3 - 0.15.3 -
- Improvement: Added configuration for safe buildings. This will be improved after a bug fix in factorio - Improvement: Added configuration for safe buildings. This will be improved after a bug fix in factorio

View File

@ -3,23 +3,13 @@ local config = {}
local mathUtils = require("libs/MathUtils") local mathUtils = require("libs/MathUtils")
local gaussianRandomRange = mathUtils.gaussianRandomRange local gaussianRandomRange = mathUtils.gaussianRandomRange
--[[
Causes buildings to regenerate and become untargetable after they are destroyed by biters
--]]
config.safeBuildings = settings.startup["rampant-safeBuildings"].value
config.safeEntities = {}
config.safeEntityName = {}
config.safeEntities["curved-rail"] = settings.startup["rampant-safeBuildings-curvedRail"].value
config.safeEntities["straight-rail"] = settings.startup["rampant-safeBuildings-straightRail"].value
config.safeEntityName["big-electric-pole"] = settings.startup["rampant-safeBuildings-bigElectricPole"].value
--[[ --[[
attackWaveScaling is used to calculate the attack wave size from the evolutionFactor attackWaveScaling is used to calculate the attack wave size from the evolutionFactor
default is config.attackWaveMaxSize * (evolutionFactor ^ 1.666667) default is natives.attackWaveMaxSize * (evolutionFactor ^ 1.666667)
DOES NOT affect vanilla biters waves DOES NOT affect vanilla biters waves
--]] --]]
config.attackWaveScaling = function (evolutionFactor) config.attackWaveScaling = function (evolutionFactor, natives)
local attackWaveMaxSize = settings.startup["rampant-attackWaveMaxSize"].value local attackWaveMaxSize = natives.attackWaveMaxSize
return math.ceil(gaussianRandomRange(attackWaveMaxSize * (evolutionFactor ^ 1.66667), return math.ceil(gaussianRandomRange(attackWaveMaxSize * (evolutionFactor ^ 1.66667),
(attackWaveMaxSize * 0.5) * 0.333, (attackWaveMaxSize * 0.5) * 0.333,
1, 1,

View File

@ -12,8 +12,8 @@ local aiAttack = require("libs/AIAttack")
local aiBuilding = require("libs/AIBuilding") local aiBuilding = require("libs/AIBuilding")
local aiPlanning = require("libs/AIPlanning") local aiPlanning = require("libs/AIPlanning")
local mathUtils = require("libs/MathUtils") local mathUtils = require("libs/MathUtils")
local interop = require("libs/Interop")
local tests = require("tests") local tests = require("tests")
local config = require("config")
-- constants -- constants
@ -21,7 +21,6 @@ local INTERVAL_LOGIC = constants.INTERVAL_LOGIC
local INTERVAL_PROCESS = constants.INTERVAL_PROCESS local INTERVAL_PROCESS = constants.INTERVAL_PROCESS
local MAX_RALLY_CRIES = constants.MAX_RALLY_CRIES local MAX_RALLY_CRIES = constants.MAX_RALLY_CRIES
local MAX_RETREATS = constants.MAX_RETREATS
local MOVEMENT_PHEROMONE = constants.MOVEMENT_PHEROMONE local MOVEMENT_PHEROMONE = constants.MOVEMENT_PHEROMONE
@ -43,8 +42,6 @@ local processPlayers = mapProcessor.processPlayers
local scanMap = mapProcessor.scanMap local scanMap = mapProcessor.scanMap
local planning = aiPlanning.planning local planning = aiPlanning.planning
-- local removeScout = aiBuilding.removeScout
-- local scouting = aiBuilding.scouting
local rallyUnits = aiBuilding.rallyUnits local rallyUnits = aiBuilding.rallyUnits
@ -60,7 +57,7 @@ local squadBeginAttack = aiAttack.squadBeginAttack
local retreatUnits = aiDefense.retreatUnits local retreatUnits = aiDefense.retreatUnits
local addRemoveEntity = entityUtils.addRemoveEntity local addRemoveEntity = entityUtils.addRemoveEntity
local makeImmortalEntity = entityUtils.makeImmortalEntity --local makeImmortalEntity = entityUtils.makeImmortalEntity
local roundToNearest = mathUtils.roundToNearest local roundToNearest = mathUtils.roundToNearest
@ -86,6 +83,32 @@ local function onChunkGenerated(event)
end end
end end
local function onModSettingsChange(event)
if event and (string.sub(event.setting, 1, 7) ~= "rampant") then
return
end
natives.safeBuildings = settings.global["rampant-safeBuildings"].value
natives.safeEntities["curved-rail"] = settings.global["rampant-safeBuildings-curvedRail"].value
natives.safeEntities["straight-rail"] = settings.global["rampant-safeBuildings-straightRail"].value
natives.safeEntities["rail-signal"] = settings.global["rampant-safeBuildings-railSignals"].value
natives.safeEntities["rail-chain-signal"] = settings.global["rampant-safeBuildings-railChainSignals"].value
natives.safeEntities["train-stop"] = settings.global["rampant-safeBuildings-trainStops"].value
natives.safeEntityName["big-electric-pole"] = settings.global["rampant-safeBuildings-bigElectricPole"].value
natives.attackUsePlayer = settings.global["rampant-attackWaveGenerationUsePlayerProximity"].value
natives.attackUsePollution = settings.global["rampant-attackWaveGenerationUsePollution"].value
natives.attackThresholdMin = settings.global["rampant-attackWaveGenerationThresholdMin"].value
natives.attackThresholdMax = settings.global["rampant-attackWaveGenerationThresholdMax"].value
natives.attackThresholdRange = natives.attackThresholdMax - natives.attackThresholdMin
natives.attackWaveMaxSize = settings.global["rampant-attackWaveMaxSize"].value
natives.attackPlayerThreshold = settings.global["rampant-attackPlayerThreshold"].value
end
local function onConfigChanged() local function onConfigChanged()
if (global.version == nil) then if (global.version == nil) then
@ -171,7 +194,12 @@ local function onConfigChanged()
game.surfaces[1].print("Rampant - Version 0.14.13") game.surfaces[1].print("Rampant - Version 0.14.13")
global.version = constants.VERSION_16 global.version = constants.VERSION_16
end end
if (global.version < constants.VERSION_17) then if (global.version < constants.VERSION_18) then
natives.safeEntities = {}
natives.safeEntityName = {}
onModSettingsChange(nil)
-- clear old regionMap processing Queue -- clear old regionMap processing Queue
-- prevents queue adding duplicate chunks -- prevents queue adding duplicate chunks
@ -182,7 +210,6 @@ local function onConfigChanged()
-- clear pending chunks, will be added when loop runs below -- clear pending chunks, will be added when loop runs below
pendingChunks = {} pendingChunks = {}
-- queue all current chunks that wont be generated during play -- queue all current chunks that wont be generated during play
local surface = game.surfaces[1] local surface = game.surfaces[1]
for chunk in surface.get_chunks() do for chunk in surface.get_chunks() do
@ -191,8 +218,8 @@ local function onConfigChanged()
y = chunk.y * 32 }}}) y = chunk.y * 32 }}})
end end
game.surfaces[1].print("Rampant - Version 0.15.1") game.surfaces[1].print("Rampant - Version 0.15.5")
global.version = constants.VERSION_17 global.version = constants.VERSION_18
end end
end end
@ -212,16 +239,12 @@ local function onTick(event)
natives.rallyCries = MAX_RALLY_CRIES natives.rallyCries = MAX_RALLY_CRIES
natives.retreats = MAX_RETREATS
planning(natives, evolutionFactor, tick, surface) planning(natives, evolutionFactor, tick, surface)
regroupSquads(natives, evolutionFactor) regroupSquads(natives, evolutionFactor)
processPlayers(players, regionMap, surface, natives, evolutionFactor, tick) processPlayers(players, regionMap, surface, natives, evolutionFactor, tick)
-- scouting(regionMap, natives)
squadBeginAttack(natives, players, evolutionFactor) squadBeginAttack(natives, players, evolutionFactor)
squadAttack(regionMap, surface, natives) squadAttack(regionMap, surface, natives)
end end
@ -287,7 +310,7 @@ local function onDeath(event)
local victoryChunk = getChunkByPosition(regionMap, entityPosition.x, entityPosition.y) local victoryChunk = getChunkByPosition(regionMap, entityPosition.x, entityPosition.y)
victoryScent(victoryChunk, entity.type) victoryScent(victoryChunk, entity.type)
end end
if creditNatives and config.safeBuildings and (config.safeEntities[entity.type] or config.safeEntityName[entity.name]) then if creditNatives and natives.safeBuildings and (natives.safeEntities[entity.type] or natives.safeEntityName[entity.name]) then
-- makeImmortalEntity(surface, entity) -- makeImmortalEntity(surface, entity)
-- patch (Needs to be removed) -- patch (Needs to be removed)
@ -337,6 +360,8 @@ end
script.on_init(onInit) script.on_init(onInit)
script.on_load(onLoad) script.on_load(onLoad)
script.on_event(defines.events.on_runtime_mod_setting_changed,
onModSettingsChange)
script.on_configuration_changed(onConfigChanged) script.on_configuration_changed(onConfigChanged)
script.on_event(defines.events.on_player_built_tile, onSurfaceTileChange) script.on_event(defines.events.on_player_built_tile, onSurfaceTileChange)
@ -352,7 +377,7 @@ script.on_event(defines.events.on_entity_died, onDeath)
script.on_event(defines.events.on_tick, onTick) script.on_event(defines.events.on_tick, onTick)
script.on_event(defines.events.on_chunk_generated, onChunkGenerated) script.on_event(defines.events.on_chunk_generated, onChunkGenerated)
remote.add_interface("rampant", { remote.add_interface("rampantTests", {
test1 = tests.test1, test1 = tests.test1,
test2 = tests.test2, test2 = tests.test2,
test3 = tests.test3, test3 = tests.test3,
@ -365,3 +390,5 @@ remote.add_interface("rampant", {
test10 = tests.test10, test10 = tests.test10,
test11 = tests.test11 test11 = tests.test11
}) })
remote.add_interface("rampant", interop)

View File

@ -7,4 +7,3 @@ require("prototypes/tile/fillableDirt")
require("prototypes/enemies/UnitSuicideBiters") require("prototypes/enemies/UnitSuicideBiters")
require("prototypes/enemies/UnitFireSpitters") require("prototypes/enemies/UnitFireSpitters")

View File

@ -1,7 +1,7 @@
{ {
"name" : "Rampant", "name" : "Rampant",
"factorio_version" : "0.15", "factorio_version" : "0.15",
"version" : "0.15.4", "version" : "0.15.5",
"title" : "Rampant AI", "title" : "Rampant AI",
"author" : "Veden", "author" : "Veden",
"homepage" : "https://forums.factorio.com/viewtopic.php?f=94&t=31445", "homepage" : "https://forums.factorio.com/viewtopic.php?f=94&t=31445",

View File

@ -118,7 +118,7 @@ function aiAttack.squadBeginAttack(natives, players, evolution_factor)
for i=1,#squads do for i=1,#squads do
local squad = squads[i] local squad = squads[i]
if (squad.status == SQUAD_GUARDING) and squad.group.valid then if (squad.status == SQUAD_GUARDING) and squad.group.valid then
local kamikazeThreshold = calculateKamikazeThreshold(squad, evolution_factor) local kamikazeThreshold = calculateKamikazeThreshold(squad, natives, evolution_factor)
local playerNearby = playersWithinProximityToPosition(players, squad.group.position, 100) local playerNearby = playersWithinProximityToPosition(players, squad.group.position, 100)
if playerNearby then if playerNearby then

View File

@ -27,20 +27,11 @@ local CHUNK_SIZE = constants.CHUNK_SIZE
local NORTH_SOUTH_PASSABLE = constants.NORTH_SOUTH_PASSABLE local NORTH_SOUTH_PASSABLE = constants.NORTH_SOUTH_PASSABLE
local EAST_WEST_PASSABLE = constants.EAST_WEST_PASSABLE local EAST_WEST_PASSABLE = constants.EAST_WEST_PASSABLE
local CONFIG_USE_PLAYER_PROXIMITY = settings.startup["rampant-attackWaveGenerationUsePlayerProximity"].value
local CONFIG_USE_POLLUTION_PROXIMITY = settings.startup["rampant-attackWaveGenerationUsePollution"].value
local CONFIG_USE_THRESHOLD_MIN = settings.startup["rampant-attackWaveGenerationThresholdMin"].value
local CONFIG_USE_THRESHOLD_MAX = settings.startup["rampant-attackWaveGenerationThresholdMax"].value
local CONFIG_USE_THRESHOLD_RANGE = CONFIG_USE_THRESHOLD_MAX - CONFIG_USE_THRESHOLD_MIN
local RETREAT_MOVEMENT_PHEROMONE_LEVEL = constants.RETREAT_MOVEMENT_PHEROMONE_LEVEL
local RALLY_CRY_DISTANCE = 3 local RALLY_CRY_DISTANCE = 3
-- imported functions -- imported functions
local getNeighborChunks = mapUtils.getNeighborChunks local getNeighborChunks = mapUtils.getNeighborChunks
local getChunkByPosition = mapUtils.getChunkByPosition
local getChunkByIndex = mapUtils.getChunkByIndex local getChunkByIndex = mapUtils.getChunkByIndex
local scoreNeighbors = neighborUtils.scoreNeighbors local scoreNeighbors = neighborUtils.scoreNeighbors
local createSquad = unitGroupUtils.createSquad local createSquad = unitGroupUtils.createSquad
@ -50,22 +41,23 @@ local mMax = math.max
-- module code -- module code
local function attackWaveValidCandidate(chunk, surface, evolutionFactor) local function attackWaveValidCandidate(chunk, natives, surface, evolutionFactor)
local total = 0; local total = 0;
if CONFIG_USE_PLAYER_PROXIMITY then if natives.attackUsePlayer then
local playerPheromone = chunk[PLAYER_PHEROMONE] local playerPheromone = chunk[PLAYER_PHEROMONE]
if (playerPheromone > 7) then if (playerPheromone > natives.attackPlayerThreshold) then
total = total + chunk[PLAYER_PHEROMONE] total = total + chunk[PLAYER_PHEROMONE]
end end
end end
if CONFIG_USE_POLLUTION_PROXIMITY then if natives.attackUsePollution then
total = total + surface.get_pollution({chunk.pX, chunk.pY}) total = total + surface.get_pollution({chunk.pX, chunk.pY})
end end
local delta = CONFIG_USE_THRESHOLD_RANGE * evolutionFactor local threshold = natives.attackThresholdRange
local delta = threshold * evolutionFactor
if (total > (CONFIG_USE_THRESHOLD_MAX - delta)) then if (total > ((threshold - delta) + natives.attackThresholdMin)) then
return true return true
else else
return false return false
@ -80,51 +72,51 @@ local function validUnitGroupLocation(x, chunk, neighborChunk)
return neighborChunk[NORTH_SOUTH_PASSABLE] and neighborChunk[EAST_WEST_PASSABLE] and neighborChunk[ENEMY_BASE_GENERATOR] == 0 return neighborChunk[NORTH_SOUTH_PASSABLE] and neighborChunk[EAST_WEST_PASSABLE] and neighborChunk[ENEMY_BASE_GENERATOR] == 0
end end
function aiBuilding.removeScout(entity, natives) -- function aiBuilding.removeScout(entity, natives)
--[[ -- --[[
local scouts = natives.scouts -- local scouts = natives.scouts
for i=1, #scouts do -- for i=1, #scouts do
local scout = scouts[i] -- local scout = scouts[i]
if (scout == entity) then -- if (scout == entity) then
tableRemove(scouts, i) -- tableRemove(scouts, i)
return -- return
end -- end
end -- end
--]] -- --]]
end -- end
function aiBuilding.makeScouts(surface, natives, chunk, evolution_factor) -- function aiBuilding.makeScouts(surface, natives, chunk, evolution_factor)
--[[ -- --[[
if (natives.points > AI_SCOUT_COST) then -- if (natives.points > AI_SCOUT_COST) then
if (#global.natives.scouts < 5) and (math.random() < 0.05) then -- TODO scaled with evolution factor -- if (#global.natives.scouts < 5) and (math.random() < 0.05) then -- TODO scaled with evolution factor
local enemy = surface.find_nearest_enemy({ position = { x = chunk.pX + HALF_CHUNK_SIZE, -- local enemy = surface.find_nearest_enemy({ position = { x = chunk.pX + HALF_CHUNK_SIZE,
y = chunk.pY + HALF_CHUNK_SIZE }, -- y = chunk.pY + HALF_CHUNK_SIZE },
max_distance = 100}) -- max_distance = 100})
if (enemy ~= nil) and enemy.valid and (enemy.type == "unit") then -- if (enemy ~= nil) and enemy.valid and (enemy.type == "unit") then
natives.points = natives.points - AI_SCOUT_COST -- natives.points = natives.points - AI_SCOUT_COST
global.natives.scouts[#global.natives.scouts+1] = enemy -- global.natives.scouts[#global.natives.scouts+1] = enemy
-- print(enemy, enemy.unit_number) -- -- print(enemy, enemy.unit_number)
end -- end
end -- end
end -- end
--]] -- --]]
end -- end
function aiBuilding.scouting(regionMap, natives) -- function aiBuilding.scouting(regionMap, natives)
--[[ -- --[[
local scouts = natives.scouts -- local scouts = natives.scouts
for i=1,#scouts do -- for i=1,#scouts do
local scout = scouts[i] -- local scout = scouts[i]
if scout.valid then -- if scout.valid then
scout.set_command({type=defines.command.attack_area, -- scout.set_command({type=defines.command.attack_area,
destination={0,0}, -- destination={0,0},
radius=32, -- radius=32,
distraction=defines.distraction.none}) -- distraction=defines.distraction.none})
end -- end
end -- end
--]] -- --]]
end -- end
function aiBuilding.rallyUnits(chunk, regionMap, surface, natives, evolutionFactor) function aiBuilding.rallyUnits(chunk, regionMap, surface, natives, evolutionFactor)
local cX = chunk.cX local cX = chunk.cX
@ -146,12 +138,12 @@ function aiBuilding.formSquads(regionMap, surface, natives, chunk, evolution_fac
if (cost == AI_VENGENCE_SQUAD_COST) then if (cost == AI_VENGENCE_SQUAD_COST) then
valid = true valid = true
elseif (cost == AI_SQUAD_COST) then elseif (cost == AI_SQUAD_COST) then
valid = attackWaveValidCandidate(chunk, surface, evolution_factor) valid = attackWaveValidCandidate(chunk, natives, surface, evolution_factor)
end end
end end
if valid and (math.random() < mMax((0.25 * evolution_factor), 0.10)) then if valid and (math.random() < mMax((0.25 * evolution_factor), 0.10)) then
local squadPosition = {x=0, y=0} local squadPosition = {x=0, y=0}
local squadPath, squadScore = scoreNeighbors(chunk, local squadPath, _ = scoreNeighbors(chunk,
getNeighborChunks(regionMap, chunk.cX, chunk.cY), getNeighborChunks(regionMap, chunk.cX, chunk.cY),
validUnitGroupLocation, validUnitGroupLocation,
scoreUnitGroupLocation, scoreUnitGroupLocation,
@ -169,7 +161,7 @@ function aiBuilding.formSquads(regionMap, surface, natives, chunk, evolution_fac
squad.rabid = true squad.rabid = true
end end
local scaledWaveSize = attackWaveScaling(evolution_factor) local scaledWaveSize = attackWaveScaling(evolution_factor, natives)
local foundUnits = surface.set_multi_command({ command = { type = defines.command.group, local foundUnits = surface.set_multi_command({ command = { type = defines.command.group,
group = squad.group, group = squad.group,
distraction = defines.distraction.none }, distraction = defines.distraction.none },

View File

@ -72,8 +72,10 @@ function chunkUtils.scoreChunk(chunk, surface)
local x = chunk.pX local x = chunk.pX
local y = chunk.pY local y = chunk.pY
local areaBoundingBox = {{x, y}, local areaBoundingBox = {
{x + 32, y + 32}} {x, y},
{x + 32, y + 32}
}
local enemyChunkQuery = {area=areaBoundingBox, local enemyChunkQuery = {area=areaBoundingBox,
type="unit-spawner", type="unit-spawner",
force="enemy"} force="enemy"}
@ -122,14 +124,14 @@ function chunkUtils.createChunk(topX, topY)
return chunk return chunk
end end
-- function chunkUtils.colorChunk(x, y, tileType, surface) function chunkUtils.colorChunk(x, y, tileType, surface)
-- local tiles = {} local tiles = {}
-- for xi=x+5, x + 27 do for xi=x+5, x + 27 do
-- for yi=y+5, y + 27 do for yi=y+5, y + 27 do
-- tiles[#tiles+1] = {name=tileType, position={xi, yi}} tiles[#tiles+1] = {name=tileType, position={xi, yi}}
-- end end
-- end end
-- surface.set_tiles(tiles, false) surface.set_tiles(tiles, false)
-- end end
return chunkUtils return chunkUtils

View File

@ -12,6 +12,7 @@ constants.VERSION_14 = 14
constants.VERSION_15 = 15 constants.VERSION_15 = 15
constants.VERSION_16 = 16 constants.VERSION_16 = 16
constants.VERSION_17 = 17 constants.VERSION_17 = 17
constants.VERSION_18 = 18
-- misc -- misc
@ -39,7 +40,7 @@ constants.AI_BASE_BUILDING_COST = 500
constants.AI_TUNNEL_COST = 100 constants.AI_TUNNEL_COST = 100
constants.AI_MAX_POINTS = 10000 constants.AI_MAX_POINTS = 10000
constants.AI_UNIT_REFUND = 2 constants.AI_UNIT_REFUND = 3
constants.AI_MAX_SQUAD_COUNT = 40 constants.AI_MAX_SQUAD_COUNT = 40
constants.AI_MAX_BITER_GROUP_SIZE = 450 constants.AI_MAX_BITER_GROUP_SIZE = 450
@ -110,8 +111,6 @@ constants.RETREAT_GRAB_RADIUS = 24
constants.BASE_RALLY_CHANCE = 0.01 constants.BASE_RALLY_CHANCE = 0.01
constants.BONUS_RALLY_CHANCE = 0.01 constants.BONUS_RALLY_CHANCE = 0.01
constants.MAX_RETREATS = 7
constants.MAX_RALLY_CRIES = 2 constants.MAX_RALLY_CRIES = 2
constants.RALLY_CRY_DISTANCE = 3 constants.RALLY_CRY_DISTANCE = 3
@ -122,6 +121,7 @@ constants.GROUP_MERGE_DISTANCE = 28
constants.BUILDING_PHEROMONES = {} constants.BUILDING_PHEROMONES = {}
constants.BUILDING_PHEROMONES["generator"] = 8 constants.BUILDING_PHEROMONES["generator"] = 8
constants.BUILDING_PHEROMONES["pump"] = 2 constants.BUILDING_PHEROMONES["pump"] = 2
constants.BUILDING_PHEROMONES["reactor"] = 16
constants.BUILDING_PHEROMONES["offshore-pump"] = 2 constants.BUILDING_PHEROMONES["offshore-pump"] = 2
constants.BUILDING_PHEROMONES["transport-belt"] = 1 constants.BUILDING_PHEROMONES["transport-belt"] = 1
constants.BUILDING_PHEROMONES["accumulator"] = 10 constants.BUILDING_PHEROMONES["accumulator"] = 10
@ -131,7 +131,11 @@ constants.BUILDING_PHEROMONES["assembling-machine"] = 10
constants.BUILDING_PHEROMONES["roboport"] = 10 constants.BUILDING_PHEROMONES["roboport"] = 10
constants.BUILDING_PHEROMONES["beacon"] = 10 constants.BUILDING_PHEROMONES["beacon"] = 10
constants.BUILDING_PHEROMONES["furnace"] = 12 constants.BUILDING_PHEROMONES["furnace"] = 12
constants.BUILDING_PHEROMONES["programmable-speaker"] = 8
constants.BUILDING_PHEROMONES["mining-drill"] = 15 constants.BUILDING_PHEROMONES["mining-drill"] = 15
constants.BUILDING_PHEROMONES["rocket-silo"] = 18
constants.BUILDING_PHEROMONES["lamp"] = 4
constants.BUILDING_PHEROMONES["radar"] = 10
-- player defense pheromones -- player defense pheromones
@ -146,69 +150,176 @@ constants.retreatFilter[constants.SQUAD_RETREATING] = true
return constants return constants
--[[ types --[[
inserter
loader
offshore-pump
accumulator
power-switch
generator
pump
boiler
solar-panel
constant-combinator
arithmetic-combinator
decider-combinator
player-port
rocket-silo
roboport
assembling-machine
mining-drill
lab
beacon
radar
furnace
unit-spawner
lamp
land-mine
ammo-turret
wall
gate
electric-turret
fluid-turret
turret
resource
logistic-robot
construction-robot
unit
player player
combat-robot furnace
transport-belt
fish
boiler
container
electric-pole
generator
offshore-pump
inserter
pipe
radar
lamp
pipe-to-ground
assembling-machine
wall
mining-drill
projectile
resource
turret
ammo-turret
unit
unit-spawner
tree
smart-container
underground-belt
loader
splitter
car
solar-panel
locomotive locomotive
cargo-wagon cargo-wagon
car fluid-wagon
gate
smart-container player-port
logistic-container
container
storage-tank
transport-belt
underground-belt
splitter
pipe-to-ground
electric-pole
curved-rail
straight-rail straight-rail
curved-rail
land-mine
train-stop train-stop
rail-signal rail-signal
rail-chain-signal rail-chain-signal
pipe lab
]]-- logistic-robot
construction-robot
logistic-container
rocket-silo
roboport
storage-tank
pump
market
accumulator
beacon
combat-robot
arithmetic-combinator
decider-combinator
constant-combinator
power-switch
programmable-speaker
electric-energy-interface
reactor
heat-pipe
electric-turret
fluid-turret
night-vision-equipment
energy-shield-equipment
battery-equipment
solar-panel-equipment
generator-equipment
active-defense-equipment
movement-bonus-equipment
roboport-equipment
belt-immunity-equipment
tutorial
rocket-defense
item-with-entity-data
rail-planner
tool
blueprint
deconstruction-item
blueprint-book
selection-tool
item-with-tags
module
technology
custom-input
sprite
font
noise-layer
gui-style
utility-constants
utility-sounds
utility-sprites
ambient-sound
character-corpse
explosion
smoke
item-entity
arrow
flying-text
corpse
entity-ghost
tile-ghost
deconstructible-tile-proxy
item-request-proxy
particle
particle-source
leaf-particle
rail-remnants
simple-entity
decorative
ammo
armor
gun
item
capsule
repair-tool
mining-tool
item-group
item-subgroup
recipe
fluid
virtual-signal
autoplace-control
map-settings
map-gen-presets
tile
optimized-decorative
simple-entity-with-force
simple-entity-with-owner
beam
fire
stream
damage-type
ammo-category
rail-category
fuel-category
recipe-category
resource-category
module-category
equipment-grid
equipment-category
build-entity-achievement
research-achievement
finish-the-game-achievement
group-attack-achievement
construct-with-robots-achievement
deconstruct-with-robots-achievement
deliver-by-robots-achievement
train-path-achievement
player-damaged-achievement
produce-achievement
produce-per-hour-achievement
dont-use-entity-in-energy-production-achievement
kill-achievement
combat-robot-count
dont-craft-manually-achievement
dont-build-entity-achievement
achievement
rocket-silo-rocket
rocket-silo-rocket-shadow
smoke-with-trigger
sticker
--]]--

View File

@ -14,8 +14,6 @@ local PLAYER_BASE_GENERATOR = constants.PLAYER_BASE_GENERATOR
local ENEMY_BASE_PHEROMONE_GENERATOR_AMOUNT = constants.ENEMY_BASE_PHEROMONE_GENERATOR_AMOUNT local ENEMY_BASE_PHEROMONE_GENERATOR_AMOUNT = constants.ENEMY_BASE_PHEROMONE_GENERATOR_AMOUNT
local CHUNK_SIZE = constants.CHUNK_SIZE
-- imported functions -- imported functions
local getChunkByIndex = mapUtils.getChunkByIndex local getChunkByIndex = mapUtils.getChunkByIndex

65
libs/Interop.lua Normal file
View File

@ -0,0 +1,65 @@
local interop = {}
function interop.addAIPoints(value)
global.natives.points = global.natives.points + value
end
function interop.getAIPoints()
return global.natives.points
end
function interop.changeState(aiState)
global.natives.state = aiState
end
function interop.getState()
return global.natives.state
end
function interop.getNextStateTick()
return global.natives.stateTick
end
function interop.getMaxWaveSize()
return global.natives.attackMaxWaveSize
end
function interop.getThresholds()
return global.natives.attackThresholdMin, global.natives.attackThresholdMax
end
function interop.changeMaxWaveSize(waveSize)
global.natives.attackMaxWaveSize = waveSize
end
function interop.changeThreshold(min, max)
global.natives.attackThresholdMin = min
global.natives.attackThresholdMax = max
global.natives.attackThresholdRange = max - min
end
function interop.changePlayerThreshold(value)
global.natives.attackPlayerThreshold = value
end
function interop.getPlayerThreshold()
return global.natives.attackPlayerThreshold
end
function interop.changeAttackUsePollution(bool)
global.natives.attackUsePollution = bool
end
function interop.changeAttackUsePlayer(bool)
global.natives.attackUsePlayer = bool
end
function interop.getAttackUsePollution()
return global.natives.attackUsePollution
end
function interop.getAttackUsePlayer()
return global.natives.attackUsePlayer
end
return interop

View File

@ -37,7 +37,6 @@ local BUILDING_PHEROMONES = constants.BUILDING_PHEROMONES
local scents = pheromoneUtils.scents local scents = pheromoneUtils.scents
local processPheromone = pheromoneUtils.processPheromone local processPheromone = pheromoneUtils.processPheromone
local makeScouts = aiBuilding.makeScouts
local formSquads = aiBuilding.formSquads local formSquads = aiBuilding.formSquads
local getChunkByIndex = mapUtils.getChunkByIndex local getChunkByIndex = mapUtils.getChunkByIndex
@ -73,7 +72,6 @@ end
function mapProcessor.processMap(regionMap, surface, natives, evolution_factor) function mapProcessor.processMap(regionMap, surface, natives, evolution_factor)
local roll = regionMap.processRoll local roll = regionMap.processRoll
local index = regionMap.processPointer local index = regionMap.processPointer
local scouts = false
local squads = false local squads = false
if (index == 1) then if (index == 1) then
@ -81,10 +79,6 @@ function mapProcessor.processMap(regionMap, surface, natives, evolution_factor)
regionMap.processRoll = roll regionMap.processRoll = roll
end end
if (0.05 <= roll) and (roll <= 0.10) then
scouts = true
end
if (natives.state == AI_STATE_AGGRESSIVE) and (0.11 <= roll) and (roll <= 0.35) then if (natives.state == AI_STATE_AGGRESSIVE) and (0.11 <= roll) and (roll <= 0.35) then
squads = true squads = true
end end
@ -96,9 +90,6 @@ function mapProcessor.processMap(regionMap, surface, natives, evolution_factor)
processPheromone(regionMap, chunk) processPheromone(regionMap, chunk)
if scouts then
makeScouts(surface, natives, chunk, evolution_factor)
end
if squads then if squads then
formSquads(regionMap, surface, natives, chunk, evolution_factor, AI_SQUAD_COST) formSquads(regionMap, surface, natives, chunk, evolution_factor, AI_SQUAD_COST)
end end
@ -124,15 +115,10 @@ function mapProcessor.processPlayers(players, regionMap, surface, natives, evolu
-- randomize player order to ensure a single player isn't singled out -- randomize player order to ensure a single player isn't singled out
local playerOrdering = nonRepeatingRandom(players) local playerOrdering = nonRepeatingRandom(players)
local scouts = false
local squads = false local squads = false
local vengenceThreshold = -(evolution_factor * RETREAT_MOVEMENT_PHEROMONE_LEVEL) local vengenceThreshold = -(evolution_factor * RETREAT_MOVEMENT_PHEROMONE_LEVEL)
local roll = math.random() local roll = math.random()
if (0.05 <= roll) and (roll <= 0.7) then
scouts = true
end
if (natives.state == AI_STATE_AGGRESSIVE) and (0.11 <= roll) and (roll <= 0.20) then if (natives.state == AI_STATE_AGGRESSIVE) and (0.11 <= roll) and (roll <= 0.20) then
squads = true squads = true
end end
@ -168,9 +154,6 @@ function mapProcessor.processPlayers(players, regionMap, surface, natives, evolu
processPheromone(regionMap, chunk) processPheromone(regionMap, chunk)
if scouts then
makeScouts(surface, natives, chunk, evolution_factor)
end
if squads then if squads then
formSquads(regionMap, surface, natives, chunk, evolution_factor, AI_SQUAD_COST) formSquads(regionMap, surface, natives, chunk, evolution_factor, AI_SQUAD_COST)
end end

View File

@ -9,7 +9,6 @@ local constants = require("Constants")
local NORTH_SOUTH_PASSABLE = constants.NORTH_SOUTH_PASSABLE local NORTH_SOUTH_PASSABLE = constants.NORTH_SOUTH_PASSABLE
local EAST_WEST_PASSABLE = constants.EAST_WEST_PASSABLE local EAST_WEST_PASSABLE = constants.EAST_WEST_PASSABLE
local HALF_CHUNK_SIZE = constants.HALF_CHUNK_SIZE
local CHUNK_SIZE = constants.CHUNK_SIZE local CHUNK_SIZE = constants.CHUNK_SIZE
-- imported functions -- imported functions
@ -38,7 +37,6 @@ function mapUtils.positionToChunkOffset(position)
return mFloor(position.x * 0.03125), mFloor(position.y * 0.03125) return mFloor(position.x * 0.03125), mFloor(position.y * 0.03125)
end end
--[[ --[[
1 2 3 1 2 3
\|/ \|/

View File

@ -38,7 +38,7 @@ function pheromoneUtils.scents(chunk)
if not chunk[NORTH_SOUTH_PASSABLE] and not chunk[EAST_WEST_PASSABLE] then if not chunk[NORTH_SOUTH_PASSABLE] and not chunk[EAST_WEST_PASSABLE] then
chunk[BASE_PHEROMONE] = IMPASSABLE_TERRAIN_GENERATOR_AMOUNT; chunk[BASE_PHEROMONE] = IMPASSABLE_TERRAIN_GENERATOR_AMOUNT;
else else
chunk[BASE_PHEROMONE] = chunk[BASE_PHEROMONE] + chunk[PLAYER_BASE_GENERATOR] -- chunk[ENEMY_BASE_GENERATOR] chunk[BASE_PHEROMONE] = chunk[BASE_PHEROMONE] + chunk[PLAYER_BASE_GENERATOR]
end end
end end

View File

@ -21,8 +21,6 @@ local NO_RETREAT_BASE_PERCENT = constants.NO_RETREAT_BASE_PERCENT
local NO_RETREAT_EVOLUTION_BONUS_MAX = constants.NO_RETREAT_EVOLUTION_BONUS_MAX local NO_RETREAT_EVOLUTION_BONUS_MAX = constants.NO_RETREAT_EVOLUTION_BONUS_MAX
local NO_RETREAT_SQUAD_SIZE_BONUS_MAX = constants.NO_RETREAT_SQUAD_SIZE_BONUS_MAX local NO_RETREAT_SQUAD_SIZE_BONUS_MAX = constants.NO_RETREAT_SQUAD_SIZE_BONUS_MAX
local CONFIG_ATTACK_WAVE_MAX_SIZE = settings.startup["rampant-attackWaveMaxSize"].value
local AI_MAX_BITER_GROUP_SIZE = constants.AI_MAX_BITER_GROUP_SIZE local AI_MAX_BITER_GROUP_SIZE = constants.AI_MAX_BITER_GROUP_SIZE
-- imported functions -- imported functions
@ -131,9 +129,10 @@ function unitGroupUtils.lookupSquadMovementPenalty(squad, chunkX, chunkY)
return 0 return 0
end end
function unitGroupUtils.calculateKamikazeThreshold(squad, evolution_factor) function unitGroupUtils.calculateKamikazeThreshold(squad, natives, evolution_factor)
local maxSize = natives.attackWaveMaxSize
local kamikazeThreshold = NO_RETREAT_BASE_PERCENT + (evolution_factor * NO_RETREAT_EVOLUTION_BONUS_MAX) local kamikazeThreshold = NO_RETREAT_BASE_PERCENT + (evolution_factor * NO_RETREAT_EVOLUTION_BONUS_MAX)
local squadSizeBonus = mLog((#squad.group.members / CONFIG_ATTACK_WAVE_MAX_SIZE) + 0.1) + 1 local squadSizeBonus = mLog((#squad.group.members / maxSize) + 0.1) + 1
return kamikazeThreshold + (NO_RETREAT_SQUAD_SIZE_BONUS_MAX * squadSizeBonus) return kamikazeThreshold + (NO_RETREAT_SQUAD_SIZE_BONUS_MAX * squadSizeBonus)
end end
@ -192,7 +191,7 @@ function unitGroupUtils.regroupSquads(natives, evolution_factor)
end end
end end
if mergedSquads and not squad.kamikaze then if mergedSquads and not squad.kamikaze then
local kamikazeThreshold = unitGroupUtils.calculateKamikazeThreshold(squad, evolution_factor) local kamikazeThreshold = unitGroupUtils.calculateKamikazeThreshold(squad, natives, evolution_factor)
if (math.random() < kamikazeThreshold) then if (math.random() < kamikazeThreshold) then
squad.kamikaze = true squad.kamikaze = true
end end

View File

@ -35,14 +35,15 @@ rampant-safeBuildings-bigElectricPole=Make big electric poles safe from biters
rampant-safeBuildings-railChainSignals=Make rail chain signals safe from biters rampant-safeBuildings-railChainSignals=Make rail chain signals safe from biters
rampant-safeBuildings-railSignals=Make rail signals safe from biters rampant-safeBuildings-railSignals=Make rail signals safe from biters
rampant-safeBuildings-trainStops=Make train stops safe from biters rampant-safeBuildings-trainStops=Make train stops safe from biters
rampant-attackPlayerThreshold=Player score contribution threshold
[mod-setting-description] [mod-setting-description]
rampant-useDumbProjectiles=Turns off homing projectiles for worms and spitters 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-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-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 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-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 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) 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)
rampant-attackWaveMaxSize=If you wish to change how the attack wave scales with evolution you will need to modify the config.lua in the zip file. rampant-attackWaveMaxSize=If you wish to change how the attack wave scales with evolution you will need to modify the config.lua in the zip file.
rampant-safeBuildings=This needs to be toggle for the safe building toggles to work. Understand this can cause weird behavior due to the fact that this is a stopgap until a bug is fixed in factorio. rampant-safeBuildings=This needs to be toggle for the safe building toggles to work. Understand this can cause weird behavior due to the fact that this is a stopgap until a bug is fixed in factorio.
rampant-safeBuildings-curvedRail=Make curved rails safe from biters rampant-safeBuildings-curvedRail=Make curved rails safe from biters
@ -51,3 +52,4 @@ rampant-safeBuildings-bigElectricPole=Make big electric poles safe from biters
rampant-safeBuildings-railChainSignals=Make rail chain signals safe from biters rampant-safeBuildings-railChainSignals=Make rail chain signals safe from biters
rampant-safeBuildings-railSignals=Make rail signals safe from biters rampant-safeBuildings-railSignals=Make rail signals safe from biters
rampant-safeBuildings-trainStops=Make train stops safe from biters rampant-safeBuildings-trainStops=Make train stops safe from biters
rampant-attackPlayerThreshold=The score that a chunk must reach for it to contribute to the attack threshold. Increasing reduces player pheromone cloud impact.

View File

@ -22,7 +22,7 @@ data:extend({
{ {
type = "bool-setting", type = "bool-setting",
name = "rampant-attackWaveGenerationUsePollution", name = "rampant-attackWaveGenerationUsePollution",
setting_type = "startup", setting_type = "runtime-global",
default_value = true, default_value = true,
order = "b[modifier]-a[trigger]", order = "b[modifier]-a[trigger]",
per_user = false per_user = false
@ -31,16 +31,26 @@ data:extend({
{ {
type = "bool-setting", type = "bool-setting",
name = "rampant-attackWaveGenerationUsePlayerProximity", name = "rampant-attackWaveGenerationUsePlayerProximity",
setting_type = "startup", setting_type = "runtime-global",
default_value = true, default_value = true,
order = "b[modifier]-b[trigger]", order = "b[modifier]-b[trigger]",
per_user = false per_user = false
}, },
{
type = "double-setting",
name = "rampant-attackPlayerThreshold",
setting_type = "runtime-global",
minimum_value = 0,
default_value = 7,
order = "c[modifier]-b[threshold]",
per_user = false
},
{ {
type = "double-setting", type = "double-setting",
name = "rampant-attackWaveGenerationThresholdMax", name = "rampant-attackWaveGenerationThresholdMax",
setting_type = "startup", setting_type = "runtime-global",
minimum_value = 0, minimum_value = 0,
default_value = 20, default_value = 20,
order = "c[modifier]-b[threshold]", order = "c[modifier]-b[threshold]",
@ -50,7 +60,7 @@ data:extend({
{ {
type = "double-setting", type = "double-setting",
name = "rampant-attackWaveGenerationThresholdMin", name = "rampant-attackWaveGenerationThresholdMin",
setting_type = "startup", setting_type = "runtime-global",
minimum_value = 0, minimum_value = 0,
default_value = 0, default_value = 0,
order = "c[modifier]-a[threshold]", order = "c[modifier]-a[threshold]",
@ -60,9 +70,9 @@ data:extend({
{ {
type = "int-setting", type = "int-setting",
name = "rampant-attackWaveMaxSize", name = "rampant-attackWaveMaxSize",
setting_type = "startup", setting_type = "runtime-global",
minimum_value = 20, minimum_value = 20,
maximum_value = 250, maximum_value = 400,
default_value = 150, default_value = 150,
order = "d[modifier]-a[wave]", order = "d[modifier]-a[wave]",
per_user = false per_user = false
@ -71,7 +81,7 @@ data:extend({
{ {
type = "bool-setting", type = "bool-setting",
name = "rampant-safeBuildings", name = "rampant-safeBuildings",
setting_type = "startup", setting_type = "runtime-global",
default_value = false, default_value = false,
order = "e[modifier]-a[safe]", order = "e[modifier]-a[safe]",
per_user = false per_user = false
@ -80,7 +90,7 @@ data:extend({
{ {
type = "bool-setting", type = "bool-setting",
name = "rampant-safeBuildings-curvedRail", name = "rampant-safeBuildings-curvedRail",
setting_type = "startup", setting_type = "runtime-global",
default_value = false, default_value = false,
order = "e[modifier]-b[safe]", order = "e[modifier]-b[safe]",
per_user = false per_user = false
@ -90,7 +100,7 @@ data:extend({
{ {
type = "bool-setting", type = "bool-setting",
name = "rampant-safeBuildings-straightRail", name = "rampant-safeBuildings-straightRail",
setting_type = "startup", setting_type = "runtime-global",
default_value = false, default_value = false,
order = "e[modifier]-c[safe]", order = "e[modifier]-c[safe]",
per_user = false per_user = false
@ -99,7 +109,7 @@ data:extend({
{ {
type = "bool-setting", type = "bool-setting",
name = "rampant-safeBuildings-bigElectricPole", name = "rampant-safeBuildings-bigElectricPole",
setting_type = "startup", setting_type = "runtime-global",
default_value = false, default_value = false,
order = "e[modifier]-d[safe]", order = "e[modifier]-d[safe]",
per_user = false per_user = false
@ -108,7 +118,7 @@ data:extend({
{ {
type = "bool-setting", type = "bool-setting",
name = "rampant-safeBuildings-railSignals", name = "rampant-safeBuildings-railSignals",
setting_type = "startup", setting_type = "runtime-global",
default_value = false, default_value = false,
order = "e[modifier]-e[safe]", order = "e[modifier]-e[safe]",
per_user = false per_user = false
@ -117,7 +127,7 @@ data:extend({
{ {
type = "bool-setting", type = "bool-setting",
name = "rampant-safeBuildings-railChainSignals", name = "rampant-safeBuildings-railChainSignals",
setting_type = "startup", setting_type = "runtime-global",
default_value = false, default_value = false,
order = "e[modifier]-f[safe]", order = "e[modifier]-f[safe]",
per_user = false per_user = false
@ -126,7 +136,7 @@ data:extend({
{ {
type = "bool-setting", type = "bool-setting",
name = "rampant-safeBuildings-trainStops", name = "rampant-safeBuildings-trainStops",
setting_type = "startup", setting_type = "runtime-global",
default_value = false, default_value = false,
order = "e[modifier]-g[safe]", order = "e[modifier]-g[safe]",
per_user = false per_user = false