mirror of
https://github.com/veden/Rampant.git
synced 2024-12-26 20:54:12 +02:00
Code clean, refactored modules, prepping for more custom ai work
This commit is contained in:
parent
1fbd91908c
commit
337951c548
@ -57,7 +57,12 @@ Configure Options not in game menu:
|
||||
# Version History
|
||||
|
||||
0.15.16 -
|
||||
- Optimization: Greatly reduced reindexing time
|
||||
- Tweak: Increased chunks processed at a time from 200 to 3000
|
||||
- Tweak: Increased failed unit behaviors from 6 to 10
|
||||
- Optimization: Preallocated a position for use in squad movement
|
||||
- Optimization: Greatly reduced reindexing time and chunk scoring
|
||||
- Framework: Split chunk scoring and custom ai chunk purging
|
||||
- Framework: Refactored code into more appropriate modules
|
||||
|
||||
0.15.15 -
|
||||
- Fixed: Desync when reindexing chunks (https://forums.factorio.com/viewtopic.php?f=94&t=31445&start=180#p287941)
|
||||
|
@ -94,8 +94,6 @@ function upgrade.attempt(natives)
|
||||
game.map_settings.path_finder.short_cache_size = constants.PATH_FINDER_SHORT_CACHE_SIZE
|
||||
game.map_settings.path_finder.long_cache_size = constants.PATH_FINDER_LONG_REQUEST_RATIO
|
||||
|
||||
game.map_settings.max_failed_behavior_count = constants.MAX_FAILED_BEHAVIORS
|
||||
|
||||
game.map_settings.unit_group.max_group_radius = constants.UNIT_GROUP_MAX_RADIUS
|
||||
game.map_settings.unit_group.max_member_speedup_when_behind = constants.UNIT_GROUP_MAX_SPEED_UP
|
||||
game.map_settings.unit_group.max_member_slowdown_when_ahead = constants.UNIT_GROUP_MAX_SLOWDOWN
|
||||
@ -149,6 +147,8 @@ function upgrade.attempt(natives)
|
||||
end
|
||||
if (global.version < constants.VERSION_26) then
|
||||
|
||||
game.map_settings.max_failed_behavior_count = constants.MAX_FAILED_BEHAVIORS
|
||||
|
||||
game.surfaces[1].print("Rampant - Version 0.15.16")
|
||||
global.version = constants.VERSION_26
|
||||
end
|
||||
|
@ -98,9 +98,12 @@ local function rebuildRegionMap()
|
||||
regionMap.processQueue = {}
|
||||
regionMap.processPointer = 1
|
||||
regionMap.scanPointer = 1
|
||||
-- preallocating memory to be used in code, making it fast by reducing garbage generated.
|
||||
regionMap.neighbors = { nil, nil, nil, nil, nil, nil, nil, nil }
|
||||
regionMap.cardinalNeighbors = { nil, nil, nil, nil }
|
||||
regionMap.chunkTiles = {}
|
||||
regionMap.position = {x=0,
|
||||
y=0}
|
||||
for i=1,1024 do
|
||||
regionMap.chunkTiles[i] = nil
|
||||
end
|
||||
|
@ -106,10 +106,11 @@ function aiAttackWave.formSquads(regionMap, surface, natives, chunk, cost)
|
||||
validUnitGroupLocation,
|
||||
scoreUnitGroupLocation)
|
||||
if squadPath then
|
||||
local squadPosition = positionFromDirectionAndChunk(squadDirection, chunk, {x=0,y=0}, 0.98)
|
||||
|
||||
squadPosition = surface.find_non_colliding_position("biter-spawner-hive",
|
||||
squadPosition,
|
||||
local squadPosition = surface.find_non_colliding_position("biter-spawner-hive",
|
||||
positionFromDirectionAndChunk(squadDirection,
|
||||
chunk,
|
||||
regionMap.position,
|
||||
0.98),
|
||||
32,
|
||||
4)
|
||||
if squadPosition then
|
||||
|
@ -40,6 +40,8 @@ local canAttack = aiPredicates.canAttack
|
||||
|
||||
local randomTickEvent = mathUtils.randomTickEvent
|
||||
|
||||
local mFloor = math.floor
|
||||
|
||||
local mMax = math.max
|
||||
|
||||
-- module code
|
||||
@ -74,7 +76,7 @@ function aiPlanning.planning(natives, evolution_factor, tick, surface)
|
||||
natives.attackWaveThreshold = (threshold - (threshold * evolution_factor)) + natives.attackThresholdMin
|
||||
|
||||
if (natives.points < maxPoints) then
|
||||
natives.points = natives.points + math.floor((AI_POINT_GENERATOR_AMOUNT * math.random()) +
|
||||
natives.points = natives.points + mFloor((AI_POINT_GENERATOR_AMOUNT * math.random()) +
|
||||
((AI_POINT_GENERATOR_AMOUNT * 0.7) * (evolution_factor ^ 2.5)) * natives.aiPointsScaler)
|
||||
end
|
||||
|
||||
|
@ -2,7 +2,7 @@ local baseUtils = {}
|
||||
|
||||
-- imports
|
||||
|
||||
local mapUtils = require("MapUtils")
|
||||
local mathUtils = require("MathUtils")
|
||||
local constants = require("Constants")
|
||||
|
||||
local tendrilUtils = require("TendrilUtils")
|
||||
@ -20,7 +20,7 @@ local MAGIC_MAXIMUM_BASE_NUMBER = constants.MAGIC_MAXIMUM_BASE_NUMBER
|
||||
|
||||
-- imported functions
|
||||
|
||||
local euclideanDistancePoints = mapUtils.euclideanDistancePoints
|
||||
local euclideanDistancePoints = mathUtils.euclideanDistancePoints
|
||||
|
||||
local buildHive = buildUtils.buildHive
|
||||
|
||||
|
@ -16,9 +16,6 @@ local CHUNK_SIZE = constants.CHUNK_SIZE
|
||||
local createChunk = chunkUtils.createChunk
|
||||
local checkChunkPassability = chunkUtils.checkChunkPassability
|
||||
local scoreChunk = chunkUtils.scoreChunk
|
||||
|
||||
local remakeChunk = chunkUtils.remakeChunk
|
||||
|
||||
local registerChunkEnemies = chunkUtils.registerChunkEnemies
|
||||
|
||||
-- module code
|
||||
@ -33,7 +30,7 @@ function chunkProcessor.processPendingChunks(natives, regionMap, surface, pendin
|
||||
|
||||
local count = 0
|
||||
|
||||
local useCustomAI = natives.useCustomAI
|
||||
local vanillaAI = not natives.useCustomAI
|
||||
|
||||
local chunkTiles = regionMap.chunkTiles
|
||||
|
||||
@ -59,7 +56,7 @@ function chunkProcessor.processPendingChunks(natives, regionMap, surface, pendin
|
||||
regionMap[chunkX][chunk.cY] = chunk
|
||||
|
||||
checkChunkPassability(chunkTiles, chunk, surface)
|
||||
if not useCustomAI then
|
||||
if vanillaAI then
|
||||
registerChunkEnemies(chunk, surface, query)
|
||||
end
|
||||
scoreChunk(chunk, surface, natives, query)
|
||||
|
@ -53,16 +53,10 @@ local function fullScan(chunkTiles, x, y, get_tile)
|
||||
|
||||
local passableNorthSouth = false
|
||||
local passableEastWest = false
|
||||
-- local skip = true
|
||||
for xi=x, x + 31 do
|
||||
local northSouth = true
|
||||
-- skip = not skip
|
||||
for yi=y, endY do
|
||||
i = i + 1
|
||||
-- if skip then
|
||||
-- skip = false
|
||||
-- else
|
||||
-- skip = true
|
||||
local tile = get_tile(xi, yi)
|
||||
if not tile.collides_with("player-layer") then
|
||||
validTiles = validTiles + 1
|
||||
@ -71,26 +65,18 @@ local function fullScan(chunkTiles, x, y, get_tile)
|
||||
northSouth = false
|
||||
chunkTiles[i] = nil
|
||||
end
|
||||
-- end
|
||||
end
|
||||
if northSouth then
|
||||
passableNorthSouth = true
|
||||
end
|
||||
end
|
||||
-- skip = true
|
||||
for yi=1, 32 do
|
||||
local westEast = true
|
||||
-- skip = not skip
|
||||
for xi=0, 992, 32 do
|
||||
-- if skip then
|
||||
-- skip = false
|
||||
-- else
|
||||
-- skip = true
|
||||
if not chunkTiles[yi + xi] then
|
||||
westEast = false
|
||||
break
|
||||
end
|
||||
-- end
|
||||
end
|
||||
if westEast then
|
||||
passableEastWest = true
|
||||
@ -122,16 +108,16 @@ function chunkUtils.checkChunkPassability(chunkTiles, chunk, surface)
|
||||
local get_tile = surface.get_tile
|
||||
|
||||
--[[
|
||||
0 represents water chunk
|
||||
1-48 chunk requires full scan
|
||||
49 assume chunk is passable in all directions
|
||||
0-4 represents water chunk
|
||||
5-46 chunk requires full scan
|
||||
47-49 assume chunk is passable in all directions
|
||||
--]]
|
||||
local cleanSpotCheck = spotCheck(x, y, get_tile)
|
||||
|
||||
local pass = CHUNK_ALL_DIRECTIONS
|
||||
if (cleanSpotCheck > 0) and (cleanSpotCheck < 49) then
|
||||
if (cleanSpotCheck > 5) and (cleanSpotCheck < 47) then
|
||||
pass = CHUNK_IMPASSABLE
|
||||
local rating, passableNorthSouth, passableEastWest = fullScan(chunkTiles, x, y, get_tile, surface)
|
||||
local rating, passableNorthSouth, passableEastWest = fullScan(chunkTiles, x, y, get_tile)
|
||||
|
||||
if passableEastWest and passableNorthSouth then
|
||||
pass = CHUNK_ALL_DIRECTIONS
|
||||
@ -145,8 +131,10 @@ function chunkUtils.checkChunkPassability(chunkTiles, chunk, surface)
|
||||
if (rating < 0.6) then
|
||||
pass = CHUNK_IMPASSABLE
|
||||
end
|
||||
elseif (cleanSpotCheck == 0) then
|
||||
elseif (cleanSpotCheck <= 4) then
|
||||
pass = CHUNK_IMPASSABLE
|
||||
else
|
||||
chunk[PATH_RATING] = 1
|
||||
end
|
||||
chunk[PASSABLE] = pass
|
||||
end
|
||||
|
@ -20,7 +20,7 @@ constants.MAGIC_MAXIMUM_NUMBER = 1e99 -- used in loops trying to find the lowest
|
||||
constants.MAGIC_MAXIMUM_BASE_NUMBER = 100000000
|
||||
constants.RETREAT_MOVEMENT_PHEROMONE_LEVEL = 10000
|
||||
|
||||
constants.CHUNK_QUEUE_SIZE = 1500
|
||||
constants.CHUNK_QUEUE_SIZE = 3000
|
||||
constants.PROCESS_QUEUE_SIZE = 450
|
||||
constants.SCAN_QUEUE_SIZE = 6
|
||||
constants.BASE_QUEUE_SIZE = 1
|
||||
@ -191,7 +191,7 @@ constants.PATH_FINDER_SHORT_CACHE_SIZE = 25
|
||||
constants.PATH_FINDER_LONG_REQUEST_RATIO = 5
|
||||
constants.PATH_FINDER_MIN_STEPS_TO_CHECK_PATH = 100
|
||||
|
||||
constants.MAX_FAILED_BEHAVIORS = 6
|
||||
constants.MAX_FAILED_BEHAVIORS = 10
|
||||
|
||||
constants.UNIT_GROUP_DISOWN_DISTANCE = 10
|
||||
constants.UNIT_GROUP_TICK_TOLERANCE = 360
|
||||
|
@ -11,6 +11,8 @@ local constants = require("Constants")
|
||||
local mapUtils = require("MapUtils")
|
||||
local playerUtils = require("PlayerUtils")
|
||||
|
||||
local mathUtils = require("MathUtils")
|
||||
|
||||
-- constants
|
||||
|
||||
local PROCESS_QUEUE_SIZE = constants.PROCESS_QUEUE_SIZE
|
||||
@ -51,7 +53,7 @@ local playerScent = pheromoneUtils.playerScent
|
||||
|
||||
local canAttack = aiPredicates.canAttack
|
||||
|
||||
local euclideanDistanceNamed = mapUtils.euclideanDistanceNamed
|
||||
local euclideanDistanceNamed = mathUtils.euclideanDistanceNamed
|
||||
|
||||
local mMin = math.min
|
||||
|
||||
|
@ -26,7 +26,7 @@ local distortPosition = mathUtils.distortPosition
|
||||
function movementUtils.findMovementPosition(surface, position, distort)
|
||||
local pos = position
|
||||
if not surface.can_place_entity({name="behemoth-biter", position=position}) then
|
||||
pos = surface.find_non_colliding_position("behemoth-biter", position, 5, 2) or position
|
||||
pos = surface.find_non_colliding_position("behemoth-biter", position, 5, 2)
|
||||
end
|
||||
return (distort and distortPosition(pos)) or pos
|
||||
end
|
||||
|
@ -2,11 +2,11 @@ local playerUtils = {}
|
||||
|
||||
-- imports
|
||||
|
||||
local mapUtils = require("MapUtils")
|
||||
local mathUtils = require("MathUtils")
|
||||
|
||||
-- imported functions
|
||||
|
||||
local euclideanDistanceNamed = mapUtils.euclideanDistanceNamed
|
||||
local euclideanDistanceNamed = mathUtils.euclideanDistanceNamed
|
||||
|
||||
-- module code
|
||||
|
||||
|
@ -8,6 +8,7 @@ local unitGroupUtils = require("UnitGroupUtils")
|
||||
local playerUtils = require("PlayerUtils")
|
||||
local neighborUtils = require("NeighborUtils")
|
||||
local movementUtils = require("MovementUtils")
|
||||
local mathUtils = require("MathUtils")
|
||||
|
||||
-- constants
|
||||
|
||||
@ -33,16 +34,16 @@ local DEFINES_DISTRACTION_BY_ANYTHING = defines.distraction.by_anything
|
||||
|
||||
-- imported functions
|
||||
|
||||
local findMovementPoint = movementUtils.findMovementPoint
|
||||
local findMovementPosition = movementUtils.findMovementPosition
|
||||
|
||||
local getNeighborChunks = mapUtils.getNeighborChunks
|
||||
local getChunkByPosition = mapUtils.getChunkByPosition
|
||||
local addMovementPenalty = unitGroupUtils.addMovementPenalty
|
||||
local lookupSquadMovementPenalty = unitGroupUtils.lookupSquadMovementPenalty
|
||||
local addMovementPenalty = movementUtils.addMovementPenalty
|
||||
local lookupMovementPenalty = movementUtils.lookupMovementPenalty
|
||||
local calculateKamikazeThreshold = unitGroupUtils.calculateKamikazeThreshold
|
||||
local positionFromDirectionAndChunk = mapUtils.positionFromDirectionAndChunk
|
||||
|
||||
local euclideanDistanceNamed = mapUtils.euclideanDistanceNamed
|
||||
local euclideanDistanceNamed = mathUtils.euclideanDistanceNamed
|
||||
|
||||
local playersWithinProximityToPosition = playerUtils.playersWithinProximityToPosition
|
||||
|
||||
@ -52,7 +53,7 @@ local scoreNeighborsForAttack = neighborUtils.scoreNeighborsForAttack
|
||||
|
||||
local function scoreAttackLocation(squad, neighborChunk)
|
||||
local damage = neighborChunk[MOVEMENT_PHEROMONE] + neighborChunk[BASE_PHEROMONE] + (neighborChunk[PLAYER_PHEROMONE] * PLAYER_PHEROMONE_MULTIPLER)
|
||||
return damage - lookupSquadMovementPenalty(squad, neighborChunk.cX, neighborChunk.cY)
|
||||
return damage - lookupMovementPenalty(squad, neighborChunk.cX, neighborChunk.cY)
|
||||
end
|
||||
|
||||
function squadAttack.squadsAttack(regionMap, surface, natives)
|
||||
@ -61,7 +62,7 @@ function squadAttack.squadsAttack(regionMap, surface, natives)
|
||||
local attackCmd
|
||||
|
||||
if (#squads > 0) then
|
||||
attackPosition = {x=0, y=0}
|
||||
attackPosition = regionMap.position
|
||||
attackCmd = { type = DEFINES_COMMAND_ATTACK_AREA,
|
||||
destination = attackPosition,
|
||||
radius = 32,
|
||||
@ -99,7 +100,7 @@ function squadAttack.squadsAttack(regionMap, surface, natives)
|
||||
attackCmd.distraction = DEFINES_DISTRACTION_BY_ENEMY
|
||||
end
|
||||
|
||||
local position = findMovementPoint(surface,
|
||||
local position = findMovementPosition(surface,
|
||||
positionFromDirectionAndChunk(attackDirection,
|
||||
groupPosition,
|
||||
attackPosition,
|
||||
|
@ -6,11 +6,13 @@ local constants = require("Constants")
|
||||
local mapUtils = require("MapUtils")
|
||||
local unitGroupUtils = require("UnitGroupUtils")
|
||||
local neighborUtils = require("NeighborUtils")
|
||||
local movementUtils = require("MovementUtils")
|
||||
|
||||
-- constants
|
||||
|
||||
local RETREAT_GRAB_RADIUS = constants.RETREAT_GRAB_RADIUS
|
||||
|
||||
local PLAYER_BASE_GENERATOR = constants.PLAYER_BASE_GENERATOR
|
||||
local MOVEMENT_PHEROMONE = constants.MOVEMENT_PHEROMONE
|
||||
local PLAYER_PHEROMONE = constants.PLAYER_PHEROMONE
|
||||
local BASE_PHEROMONE = constants.BASE_PHEROMONE
|
||||
@ -33,16 +35,16 @@ local WORM_COUNT = constants.WORM_COUNT
|
||||
local positionFromDirectionAndChunk = mapUtils.positionFromDirectionAndChunk
|
||||
local getNeighborChunks = mapUtils.getNeighborChunks
|
||||
local findNearBySquad = unitGroupUtils.findNearBySquad
|
||||
local addSquadMovementPenalty = unitGroupUtils.addSquadMovementPenalty
|
||||
local addMovementPenalty = movementUtils.addMovementPenalty
|
||||
local createSquad = unitGroupUtils.createSquad
|
||||
local membersToSquad = unitGroupUtils.membersToSquad
|
||||
local scoreNeighborsForRetreat = neighborUtils.scoreNeighborsForRetreat
|
||||
local findMovementPosition = movementUtils.findMovementPosition
|
||||
|
||||
-- module code
|
||||
|
||||
local function scoreRetreatLocation(neighborChunk)
|
||||
local danger = neighborChunk[BASE_PHEROMONE] + -neighborChunk[MOVEMENT_PHEROMONE] + (neighborChunk[PLAYER_PHEROMONE] * 100)
|
||||
return -danger
|
||||
return -(neighborChunk[BASE_PHEROMONE] + -neighborChunk[MOVEMENT_PHEROMONE] + (neighborChunk[PLAYER_PHEROMONE] * 100) + (neighborChunk[PLAYER_BASE_GENERATOR] * 20))
|
||||
end
|
||||
|
||||
function aiDefense.retreatUnits(chunk, position, squad, regionMap, surface, natives, tick)
|
||||
@ -65,18 +67,17 @@ function aiDefense.retreatUnits(chunk, position, squad, regionMap, surface, nati
|
||||
chunk.cY),
|
||||
scoreRetreatLocation)
|
||||
if exitPath then
|
||||
local retreatPosition = positionFromDirectionAndChunk(exitDirection, position, {x=0,y=0}, 0.98)
|
||||
local retreatPosition = findMovementPosition(surface,
|
||||
positionFromDirectionAndChunk(exitDirection,
|
||||
position,
|
||||
regionMap.position,
|
||||
0.98),
|
||||
false)
|
||||
|
||||
|
||||
if not surface.can_place_entity({name="behemoth-biter", position=retreatPosition}) then
|
||||
local newRetreatPosition = surface.find_non_colliding_position("behemoth-biter", retreatPosition, 5, 2)
|
||||
if newRetreatPosition then
|
||||
retreatPosition.x = newRetreatPosition.x
|
||||
retreatPosition.y = newRetreatPosition.y
|
||||
else
|
||||
if not retreatPosition then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- in order for units in a group attacking to retreat, we have to create a new group and give the command to join
|
||||
-- to each unit, this is the only way I have found to have snappy mid battle retreats even after 0.14.4
|
||||
@ -98,7 +99,7 @@ function aiDefense.retreatUnits(chunk, position, squad, regionMap, surface, nati
|
||||
newSquad.rabid = true
|
||||
end
|
||||
end
|
||||
addSquadMovementPenalty(natives, newSquad, chunk.cX, chunk.cY)
|
||||
addMovementPenalty(natives, newSquad, chunk.cX, chunk.cY)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -9,6 +9,7 @@ local neighborsUtils = require("NeighborUtils")
|
||||
local mathUtils = require("MathUtils")
|
||||
|
||||
local buildUtils = require("BuildUtils")
|
||||
local mathUtils = require("MathUtils")
|
||||
|
||||
-- constants
|
||||
|
||||
@ -30,7 +31,7 @@ local registerEnemyBaseStructure = baseRegisterUtils.registerEnemyBaseStructure
|
||||
|
||||
local buildOutpost = buildUtils.buildOutpost
|
||||
|
||||
local euclideanDistanceNamed = mapUtils.euclideanDistanceNamed
|
||||
local euclideanDistanceNamed = mathUtils.euclideanDistanceNamed
|
||||
|
||||
-- module code
|
||||
|
||||
|
@ -2,7 +2,7 @@ local unitGroupUtils = {}
|
||||
|
||||
-- imports
|
||||
|
||||
local mapUtils = require("MapUtils")
|
||||
local mathUtils = require("MathUtils")
|
||||
local constants = require("Constants")
|
||||
|
||||
-- constants
|
||||
@ -32,7 +32,7 @@ local mLog = math.log10
|
||||
|
||||
local mMin = math.min
|
||||
|
||||
local euclideanDistanceNamed = mapUtils.euclideanDistanceNamed
|
||||
local euclideanDistanceNamed = mathUtils.euclideanDistanceNamed
|
||||
|
||||
-- module code
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user