From 75eb3a29d44cd76c3b0bf561102fa58cb69c9bf3 Mon Sep 17 00:00:00 2001 From: Aaron Veden Date: Sat, 10 Jun 2017 01:38:20 -0700 Subject: [PATCH] see readme, base work not done --- README.md | 23 ++++++++++++++- Upgrade.lua | 2 -- control.lua | 10 +++---- libs/AIAttack.lua | 35 +++++++++++++---------- libs/AIBuilding.lua | 26 +++++++++++------ libs/AIDefense.lua | 18 ++++++++---- libs/AIPlanning.lua | 2 +- libs/BaseProcessor.lua | 4 +-- libs/ChunkUtils.lua | 52 +++++++++++++++++----------------- libs/Constants.lua | 53 ++++++++++++++++++----------------- libs/MapProcessor.lua | 16 ++++------- libs/MapUtils.lua | 62 +++++++++++++---------------------------- libs/PheromoneUtils.lua | 22 ++++++++++----- libs/TendrilUtils.lua | 9 +++--- libs/UnitGroupUtils.lua | 22 +++++++++++++-- make.rkt | 4 +-- settings.lua | 2 +- 17 files changed, 196 insertions(+), 166 deletions(-) diff --git a/README.md b/README.md index e1ad265..ed415a9 100644 --- a/README.md +++ b/README.md @@ -57,8 +57,29 @@ Configure Options not in game menu: # Version History 0.15.14 - -- Improvement: Made form squads aware of orientation changes when building squads +- Tweak: Increased pheromone output of: + - ammo-turret 2.5 -> 10 + - wall 0.25 -> 0.5 + - electric-turret 7 -> 20 + - fluid-turret 9 -> 28 + - turret 2.5 -> 10 + - mining-drill 15 -> 35 +- Tweak: Increased attack radius of squads from 28 to 32 tiles +- Tweak: Decreased movement(death) pheromone persistance from 0.98 to 0.9 +- Tweak: Increased impassable terrain generator pheromone amount from -30 to -0.1 +- Tweak: Reduced number of remembered past chunks for a squad from 10 to 7 +- Tweak: Increased unit group count for "ground shake" message from 11 to 14 +- Fixed: Pheromone is no longer placed on impassable chunks +- Improvement: Removed pollution from ai attack chunk scoring, pollution travels over water and creates weird pockets groups get stuck in +- Improvement: Made create squads aware of orientation changes when building squads +- Improvement: Recycling unit groups that are stuck +- Improvement: Allow movement from an impassable chunk to a all cardinals passable chunk +- Improvement: When creating squads base pheromone or player pheromone must be present. Prevents squad spawns when they can't reach the player(s) or player(s) structures. - Improvement: Made retreats aware of orientation changes with retreating squads +- Improvement: Path finding check for invalid destination before making command +- Improvement: Added path rating to each chunk to reduce the scores on chunks that may be passable but are easy to invalidate the unit group by making a command to an invalid location(water, entity) +- Optimization: Collapsed chunk attributes *_PASSABLE into single attribute PASSABLE +- Optimization: Preallocated neighbors and cardinal neighbors array 0.15.13 - - Improvement: Added lamps to make safe options (https://forums.factorio.com/viewtopic.php?f=94&t=31445&start=160#p284736) diff --git a/Upgrade.lua b/Upgrade.lua index 302be66..c5e6a43 100644 --- a/Upgrade.lua +++ b/Upgrade.lua @@ -143,8 +143,6 @@ function upgrade.attempt(natives, regionMap) global.version = constants.VERSION_23 end if (global.version < constants.VERSION_24) then - - game.surfaces[1].print("Rampant - Version 0.15.14") global.version = constants.VERSION_24 diff --git a/control.lua b/control.lua index 1a1bed7..9abd6a2 100644 --- a/control.lua +++ b/control.lua @@ -98,6 +98,8 @@ local function rebuildRegionMap() regionMap.processQueue = {} regionMap.processPointer = 1 regionMap.scanPointer = 1 + regionMap.neighbors = { nil, nil, nil, nil, nil, nil, nil, nil } + regionMap.cardinalNeighbors = { nil, nil, nil, nil } -- switched over to tick event regionMap.logicTick = roundToNearest(game.tick + INTERVAL_LOGIC, INTERVAL_LOGIC) @@ -234,13 +236,11 @@ local function onIonCannonFired(event) end local chunk = getChunkByPosition(regionMap, event.position.x, event.position.y) if chunk then - local tempNeighbors = {nil, nil, nil, nil, nil, nil, nil, nil} rallyUnits(chunk, regionMap, surface, natives, - event.tick, - tempNeighbors) + event.tick) end end end @@ -270,13 +270,11 @@ local function onDeath(event) natives, tick) if (math.random() < natives.rallyThreshold) and not surface.peaceful_mode then - local tempNeighbors = {nil, nil, nil, nil, nil, nil, nil, nil} rallyUnits(deathChunk, regionMap, surface, natives, - tick, - tempNeighbors) + tick) end end end diff --git a/libs/AIAttack.lua b/libs/AIAttack.lua index 0c0ed4c..9d72fdd 100644 --- a/libs/AIAttack.lua +++ b/libs/AIAttack.lua @@ -19,8 +19,6 @@ local SQUAD_GUARDING = constants.SQUAD_GUARDING local PLAYER_BASE_GENERATOR = constants.PLAYER_BASE_GENERATOR -local NEST_COUNT = constants.NEST_COUNT - local DEFINES_COMMAND_ATTACK_AREA = defines.command.attack_area local DEFINES_GROUP_FINISHED = defines.group_state.finished local DEFINES_GROUP_GATHERING = defines.group_state.gathering @@ -63,14 +61,12 @@ function aiAttack.squadAttack(regionMap, surface, natives) local squads = natives.squads local attackPosition local attackCmd - local tempNeighbors if (#squads > 0) then - tempNeighbors = {nil, nil, nil, nil, nil, nil, nil, nil} attackPosition = {x=0, y=0} attackCmd = { type = DEFINES_COMMAND_ATTACK_AREA, destination = attackPosition, - radius = 28, + radius = 32, distraction = DEFINES_DISTRACTION_BY_ENEMY } end @@ -86,19 +82,18 @@ function aiAttack.squadAttack(regionMap, surface, natives) local attackChunk, attackDirection = scoreNeighborsWithDirection(chunk, getNeighborChunks(regionMap, chunk.cX, - chunk.cY, - tempNeighbors), + chunk.cY), validLocation, scoreAttackLocation, squad, surface, true) - addSquadMovementPenalty(squad, chunk.cX, chunk.cY) - if attackChunk then + addSquadMovementPenalty(natives, squad, chunk.cX, chunk.cY) + if group.valid and attackChunk then if (attackChunk[PLAYER_BASE_GENERATOR] == 0) or ((groupState == DEFINES_GROUP_FINISHED) or (groupState == DEFINES_GROUP_GATHERING)) then - - positionFromDirectionAndChunk(attackDirection, groupPosition, attackPosition, 1.25) + + positionFromDirectionAndChunk(attackDirection, groupPosition, attackPosition, 1.35) if (#squad.group.members > 80) then squad.cycles = 6 @@ -114,9 +109,21 @@ function aiAttack.squadAttack(regionMap, surface, natives) else attackCmd.distraction = DEFINES_DISTRACTION_BY_ENEMY end - - group.set_command(attackCmd) - group.start_moving() + + if surface.can_place_entity({name="behemoth-biter", position=attackPosition}) then + group.set_command(attackCmd) + group.start_moving() + else + local newAttackPosition = surface.find_non_colliding_position("behemoth-biter", attackPosition, 5, 2) + if newAttackPosition then + attackPosition.x = newAttackPosition.x + attackPosition.y = newAttackPosition.y + group.set_command(attackCmd) + group.start_moving() + else + addSquadMovementPenalty(natives, squad, attackChunk.cX, attackChunk.cY) + end + end elseif not squad.frenzy and not squad.rabid and ((groupState == DEFINES_GROUP_ATTACKING_DISTRACTION) or (groupState == DEFINES_GROUP_ATTACKING_TARGET) or (attackChunk[PLAYER_BASE_GENERATOR] ~= 0)) then diff --git a/libs/AIBuilding.lua b/libs/AIBuilding.lua index f2aa0b9..1d3a77a 100644 --- a/libs/AIBuilding.lua +++ b/libs/AIBuilding.lua @@ -22,8 +22,8 @@ local RALLY_TRIGGERED = constants.RALLY_TRIGGERED local INTERVAL_LOGIC = constants.INTERVAL_LOGIC local TRIPLE_CHUNK_SIZE = constants.TRIPLE_CHUNK_SIZE -local NORTH_SOUTH_PASSABLE = constants.NORTH_SOUTH_PASSABLE -local EAST_WEST_PASSABLE = constants.EAST_WEST_PASSABLE +local PASSABLE = constants.PASSABLE +local CHUNK_ALL_DIRECTIONS = constants.CHUNK_ALL_DIRECTIONS local RALLY_CRY_DISTANCE = constants.RALLY_CRY_DISTANCE @@ -47,17 +47,25 @@ local attackWaveScaling = config.attackWaveScaling 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 end + local hasBasePheromone = false + if (chunk[BASE_PHEROMONE] > 0) then + hasBasePheromone = true + end if natives.attackUsePollution then total = total + surface.get_pollution(chunk) end - return total > natives.attackWaveThreshold + return (total > natives.attackWaveThreshold) and hasBasePheromone and hasPlayerPheromone end local function scoreUnitGroupLocation(squad, neighborChunk, surface) @@ -65,10 +73,10 @@ local function scoreUnitGroupLocation(squad, neighborChunk, surface) end local function validUnitGroupLocation(x, chunk, neighborChunk) - return neighborChunk[NORTH_SOUTH_PASSABLE] and neighborChunk[EAST_WEST_PASSABLE] and (neighborChunk[NEST_COUNT] ~= 0) + return (neighborChunk[PASSABLE] == CHUNK_ALL_DIRECTIONS) and (neighborChunk[NEST_COUNT] ~= 0) end -function aiBuilding.rallyUnits(chunk, regionMap, surface, natives, tick, tempNeighbors) +function aiBuilding.rallyUnits(chunk, regionMap, surface, natives, tick) if (tick - chunk[RALLY_TRIGGERED] > INTERVAL_LOGIC) and (natives.points >= AI_VENGENCE_SQUAD_COST) then chunk[RALLY_TRIGGERED] = tick local cX = chunk.cX @@ -77,7 +85,7 @@ function aiBuilding.rallyUnits(chunk, regionMap, surface, natives, tick, tempNei for y=cY - RALLY_CRY_DISTANCE, cY + RALLY_CRY_DISTANCE do local rallyChunk = getChunkByIndex(regionMap, x, y) if rallyChunk and (rallyChunk[NEST_COUNT] ~= 0) and (x ~= cX) and (y ~= cY) then - aiBuilding.formSquads(regionMap, surface, natives, rallyChunk, AI_VENGENCE_SQUAD_COST, tempNeighbors) + aiBuilding.formSquads(regionMap, surface, natives, rallyChunk, AI_VENGENCE_SQUAD_COST) if (natives.points < AI_VENGENCE_SQUAD_COST) then return end @@ -87,14 +95,14 @@ function aiBuilding.rallyUnits(chunk, regionMap, surface, natives, tick, tempNei end end -function aiBuilding.formSquads(regionMap, surface, natives, chunk, cost, tempNeighbors) +function aiBuilding.formSquads(regionMap, surface, natives, chunk, cost) local valid = ((cost == AI_VENGENCE_SQUAD_COST) or ((cost == AI_SQUAD_COST) and attackWaveValidCandidate(chunk, natives, surface))) if valid and (math.random() < natives.formSquadThreshold) then local squadPath, squadDirection = scoreNeighborsWithDirection(chunk, - getNeighborChunks(regionMap, chunk.cX, chunk.cY, tempNeighbors), + getNeighborChunks(regionMap, chunk.cX, chunk.cY), validUnitGroupLocation, scoreUnitGroupLocation, nil, @@ -103,7 +111,7 @@ function aiBuilding.formSquads(regionMap, surface, natives, chunk, cost, tempNei if squadPath then local squadPosition = positionFromDirectionAndChunk(squadDirection, chunk, {x=0,y=0}, 0.98) - squadPosition = surface.find_non_colliding_position("biter-spawner", + squadPosition = surface.find_non_colliding_position("biter-spawner-hive", squadPosition, 32, 4) diff --git a/libs/AIDefense.lua b/libs/AIDefense.lua index 1cd96cd..bf02704 100644 --- a/libs/AIDefense.lua +++ b/libs/AIDefense.lua @@ -65,12 +65,10 @@ function aiDefense.retreatUnits(chunk, position, squad, regionMap, surface, nati if performRetreat then chunk[RETREAT_TRIGGERED] = tick - local tempNeighbors = {nil, nil, nil, nil, nil, nil, nil, nil} local exitPath,exitDirection = scoreNeighborsWithDirection(chunk, getNeighborChunks(regionMap, chunk.cX, - chunk.cY, - tempNeighbors), + chunk.cY), validRetreatLocation, scoreRetreatLocation, nil, @@ -78,7 +76,17 @@ function aiDefense.retreatUnits(chunk, position, squad, regionMap, surface, nati false) if exitPath then local retreatPosition = positionFromDirectionAndChunk(exitDirection, position, {x=0,y=0}, 0.98) - + + 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 + 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 @@ -99,7 +107,7 @@ function aiDefense.retreatUnits(chunk, position, squad, regionMap, surface, nati newSquad.rabid = true end end - addSquadMovementPenalty(newSquad, chunk.cX, chunk.cY) + addSquadMovementPenalty(natives, newSquad, chunk.cX, chunk.cY) end end end diff --git a/libs/AIPlanning.lua b/libs/AIPlanning.lua index fe7e442..9ba06fc 100644 --- a/libs/AIPlanning.lua +++ b/libs/AIPlanning.lua @@ -49,7 +49,7 @@ local function isShockwaveReady(evolution_factor, natives, surface, tick, maxPoi (tick - natives.lastShakeMessage > TICKS_A_MINUTE * 5) and ((evolution_factor > 0.7) and (natives.points > maxPoints * 0.85) and - (#natives.squads > AI_MAX_SQUAD_COUNT * 0.35)) + (#natives.squads > AI_MAX_SQUAD_COUNT * 0.45)) end function aiPlanning.planning(natives, evolution_factor, tick, surface) diff --git a/libs/BaseProcessor.lua b/libs/BaseProcessor.lua index 2618948..cc763ef 100644 --- a/libs/BaseProcessor.lua +++ b/libs/BaseProcessor.lua @@ -23,14 +23,12 @@ function baseProcessor.processBases(regionMap, surface, natives, tick) local baseIndex = natives.baseIndex local bases = natives.bases - local tempNeighbors = {nil, nil, nil, nil, nil, nil, nil, nil} - local endIndex = mMin(baseIndex+BASE_QUEUE_SIZE, #bases) for index = baseIndex, endIndex do local base = bases[index] buildOrder(regionMap, natives, base, surface, tick) - advanceTendrils(regionMap, base, surface, tempNeighbors) + advanceTendrils(regionMap, base, surface, tick) end if (endIndex == #bases) then diff --git a/libs/ChunkUtils.lua b/libs/ChunkUtils.lua index a42ae7d..eaea2f1 100644 --- a/libs/ChunkUtils.lua +++ b/libs/ChunkUtils.lua @@ -23,11 +23,13 @@ local WORM_COUNT = constants.WORM_COUNT local PLAYER_BASE_GENERATOR = constants.PLAYER_BASE_GENERATOR local RESOURCE_GENERATOR = constants.RESOURCE_GENERATOR -local NORTH_SOUTH = constants.NORTH_SOUTH -local EAST_WEST = constants.EAST_WEST +local CHUNK_NORTH_SOUTH = constants.CHUNK_NORTH_SOUTH +local CHUNK_EAST_WEST = constants.CHUNK_EAST_WEST -local EAST_WEST_PASSABLE = constants.EAST_WEST_PASSABLE -local NORTH_SOUTH_PASSABLE = constants.NORTH_SOUTH_PASSABLE +local PASSABLE = constants.PASSABLE + +local CHUNK_ALL_DIRECTIONS = constants.CHUNK_ALL_DIRECTIONS +local CHUNK_IMPASSABLE = constants.CHUNK_IMPASSABLE local CHUNK_TICK = constants.CHUNK_TICK @@ -48,7 +50,7 @@ local function checkForDeadendTiles(constantCoordinate, iteratingCoordinate, dir local tile for x=iteratingCoordinate, iteratingCoordinate + 31 do - if (direction == NORTH_SOUTH) then + if (direction == CHUNK_NORTH_SOUTH) then tile = get_tile(constantCoordinate, x) else tile = get_tile(x, constantCoordinate) @@ -80,37 +82,33 @@ function chunkUtils.checkChunkPassability(chunk, surface) local passableNorthSouth = false local passableEastWest = false for xi=x, x + 31 do - if not checkForDeadendTiles(xi, y, NORTH_SOUTH, get_tile) then + if not checkForDeadendTiles(xi, y, CHUNK_NORTH_SOUTH, get_tile) then passableNorthSouth = true break end end for yi=y, y + 31 do - if not checkForDeadendTiles(yi, x, EAST_WEST, get_tile) then + if not checkForDeadendTiles(yi, x, CHUNK_EAST_WEST, get_tile) then passableEastWest = true break end end - if passableEastWest or passableNorthSouth then - if (checkForValidTiles(x, y, get_tile) < 0.6) then - passableEastWest = false - passableNorthSouth = false + + local pass = CHUNK_IMPASSABLE + if passableEastWest and passableNorthSouth then + pass = CHUNK_ALL_DIRECTIONS + elseif passableEastWest then + pass = CHUNK_EAST_WEST + elseif passableNorthSouth then + pass = CHUNK_NORTH_SOUTH + end + if (pass ~= CHUNK_IMPASSABLE) then + chunk[PATH_RATING] = checkForValidTiles(x, y, get_tile) + if (chunk[PATH_RATING] < 0.6) then + pass = CHUNK_IMPASSABLE end end - - -- if passableEastWest or passableNorthSouth then - -- chunk[PATH_RATING] = checkForValidTiles(x, y, get_tile) - -- end - chunk[PATH_RATING] = checkForValidTiles(x, y, get_tile) - if (chunk[PATH_RATING] < 0.99) then - chunk[EAST_WEST_PASSABLE] = false - chunk[NORTH_SOUTH_PASSABLE] = false - else - chunk[EAST_WEST_PASSABLE] = true - chunk[NORTH_SOUTH_PASSABLE] = true - end - -- chunk[EAST_WEST_PASSABLE] = passableEastWest - -- chunk[NORTH_SOUTH_PASSABLE] = passableNorthSouth + chunk[PASSABLE] = pass end function chunkUtils.scoreChunk(regionMap, chunk, surface, natives, tick, tempQuery) @@ -201,8 +199,8 @@ function chunkUtils.createChunk(topX, topY) chunk[PLAYER_PHEROMONE] = 0 chunk[RESOURCE_PHEROMONE] = 0 chunk[PLAYER_BASE_GENERATOR] = 0 - chunk[NORTH_SOUTH_PASSABLE] = false - chunk[EAST_WEST_PASSABLE] = false + chunk[RESOURCE_GENERATOR] = 0 + chunk[PASSABLE] = 0 chunk[CHUNK_TICK] = 0 chunk[RETREAT_TRIGGERED] = 0 chunk[RALLY_TRIGGERED] = 0 diff --git a/libs/Constants.lua b/libs/Constants.lua index 3379103..7d389c0 100644 --- a/libs/Constants.lua +++ b/libs/Constants.lua @@ -39,8 +39,10 @@ constants.TRIPLE_CHUNK_SIZE = constants.CHUNK_SIZE * 3 constants.HALF_CHUNK_SIZE = constants.CHUNK_SIZE / 2 constants.QUARTER_CHUNK_SIZE = constants.HALF_CHUNK_SIZE / 2 -constants.NORTH_SOUTH = 1 -constants.EAST_WEST = 2 +constants.CHUNK_IMPASSABLE = 0 +constants.CHUNK_NORTH_SOUTH = 1 +constants.CHUNK_EAST_WEST = 2 +constants.CHUNK_ALL_DIRECTIONS = 3 -- ai @@ -93,15 +95,14 @@ constants.NO_RETREAT_SQUAD_SIZE_BONUS_MAX = 0.40 -- pheromone amounts constants.MOVEMENT_PHEROMONE_GENERATOR_AMOUNT = 500 ---constants.ENEMY_BASE_PHEROMONE_GENERATOR_AMOUNT = 30 constants.DEATH_PHEROMONE_GENERATOR_AMOUNT = 500 constants.PLAYER_PHEROMONE_GENERATOR_AMOUNT = 150 -constants.IMPASSABLE_TERRAIN_GENERATOR_AMOUNT = -1 +constants.IMPASSABLE_TERRAIN_GENERATOR_AMOUNT = -0.1 -- pheromone diffusion amounts -constants.MOVEMENT_PHEROMONE_PERSISTANCE = 0.98 +constants.MOVEMENT_PHEROMONE_PERSISTANCE = 0.9 constants.BASE_PHEROMONE_PERSISTANCE = 0.99 constants.PLAYER_PHEROMONE_PERSISTANCE = 0.98 constants.RESOURCE_PHEROMONE_PERSISTANCE = 0.85 @@ -116,17 +117,16 @@ constants.RESOURCE_PHEROMONE = 4 constants.PLAYER_BASE_GENERATOR = 5 constants.RESOURCE_GENERATOR = 6 -constants.NORTH_SOUTH_PASSABLE = 7 -constants.EAST_WEST_PASSABLE = 8 +constants.PASSABLE = 7 -constants.CHUNK_TICK = 9 -constants.RETREAT_TRIGGERED = 10 -constants.RALLY_TRIGGERED = 11 -constants.NEST_BASE = 12 -constants.WORM_BASE = 13 -constants.NEST_COUNT = 14 -constants.WORM_COUNT = 15 -constants.PATH_RATING = 16 +constants.CHUNK_TICK = 8 +constants.RETREAT_TRIGGERED = 9 +constants.RALLY_TRIGGERED = 10 +constants.NEST_BASE = 11 +constants.WORM_BASE = 12 +constants.NEST_COUNT = 13 +constants.WORM_COUNT = 14 +constants.PATH_RATING = 15 -- Squad status @@ -142,11 +142,12 @@ constants.RETREAT_GRAB_RADIUS = 24 constants.BASE_RALLY_CHANCE = 0.02 constants.BONUS_RALLY_CHANCE = 0.06 -constants.MAX_RALLY_CRIES = 2 constants.RALLY_CRY_DISTANCE = 3 constants.GROUP_MERGE_DISTANCE = 28 +constants.MAX_PENALTY_BEFORE_PURGE = 8000 + -- player building pheromones constants.BUILDING_PHEROMONES = {} @@ -163,18 +164,18 @@ constants.BUILDING_PHEROMONES["roboport"] = 10 constants.BUILDING_PHEROMONES["beacon"] = 10 constants.BUILDING_PHEROMONES["furnace"] = 12 constants.BUILDING_PHEROMONES["programmable-speaker"] = 8 -constants.BUILDING_PHEROMONES["mining-drill"] = 15 +constants.BUILDING_PHEROMONES["mining-drill"] = 35 constants.BUILDING_PHEROMONES["rocket-silo"] = 18 constants.BUILDING_PHEROMONES["lamp"] = 4 -constants.BUILDING_PHEROMONES["radar"] = 10 +constants.BUILDING_PHEROMONES["radar"] = 20 -- player defense pheromones -constants.BUILDING_PHEROMONES["ammo-turret"] = 2.5 -constants.BUILDING_PHEROMONES["wall"] = 0.25 -constants.BUILDING_PHEROMONES["electric-turret"] = 7 -constants.BUILDING_PHEROMONES["fluid-turret"] = 9 -constants.BUILDING_PHEROMONES["turret"] = 2.5 +constants.BUILDING_PHEROMONES["ammo-turret"] = 10 +constants.BUILDING_PHEROMONES["wall"] = 0.5 +constants.BUILDING_PHEROMONES["electric-turret"] = 20 +constants.BUILDING_PHEROMONES["fluid-turret"] = 28 +constants.BUILDING_PHEROMONES["turret"] = 10 constants.retreatFilter = {} constants.retreatFilter[constants.SQUAD_RETREATING] = true @@ -184,14 +185,14 @@ constants.retreatFilter[constants.SQUAD_RETREATING] = true constants.PATH_FINDER_SHORT_REQUEST_RATIO = 0.8 constants.PATH_FINDER_SHORT_CACHE_SIZE = 25 constants.PATH_FINDER_LONG_REQUEST_RATIO = 5 -constants.PATH_FINDER_MIN_STEPS_TO_CHECK_PATH = 500 +constants.PATH_FINDER_MIN_STEPS_TO_CHECK_PATH = 100 -constants.MAX_FAILED_BEHAVIORS = 100 +constants.MAX_FAILED_BEHAVIORS = 6 constants.UNIT_GROUP_DISOWN_DISTANCE = 10 constants.UNIT_GROUP_TICK_TOLERANCE = 360 -constants.UNIT_GROUP_MAX_RADIUS = 12 +constants.UNIT_GROUP_MAX_RADIUS = 20 constants.UNIT_GROUP_MAX_SPEED_UP = 1.1 constants.UNIT_GROUP_MAX_SLOWDOWN = 1.0 constants.UNIT_GROUP_SLOWDOWN_FACTOR = 0.9 diff --git a/libs/MapProcessor.lua b/libs/MapProcessor.lua index 3ebb70a..f5344d3 100644 --- a/libs/MapProcessor.lua +++ b/libs/MapProcessor.lua @@ -85,9 +85,6 @@ function mapProcessor.processMap(regionMap, surface, natives, tick) roll = math.random() regionMap.processRoll = roll end - - local tempNeighbors = {nil, nil, nil, nil} - local tempNeighborsAll = {nil, nil, nil, nil, nil, nil, nil, nil} local squads = canAttack(natives, surface) and (0.11 <= roll) and (roll <= 0.35) and (natives.points >= AI_SQUAD_COST) @@ -99,10 +96,10 @@ function mapProcessor.processMap(regionMap, surface, natives, tick) if (chunk[CHUNK_TICK] ~= tick) then chunk[CHUNK_TICK] = tick - processPheromone(regionMap, chunk, tempNeighbors) + processPheromone(regionMap, chunk) if squads and (chunk[NEST_COUNT] ~= 0) then - formSquads(regionMap, surface, natives, chunk, AI_SQUAD_COST, tempNeighborsAll) + formSquads(regionMap, surface, natives, chunk, AI_SQUAD_COST) squads = natives.points >= AI_SQUAD_COST end @@ -134,9 +131,6 @@ function mapProcessor.processPlayers(players, regionMap, surface, natives, tick) local squads = allowingAttacks and (0.11 <= roll) and (roll <= 0.20) and (natives.points >= AI_SQUAD_COST) - local tempNeighbors = {nil, nil, nil, nil} - local tempNeighborsAll = {nil, nil, nil, nil, nil, nil, nil, nil} - for i=1,#playerOrdering do local player = players[playerOrdering[i]] if validPlayer(player) then @@ -163,14 +157,14 @@ function mapProcessor.processPlayers(players, regionMap, surface, natives, tick) if chunk and (chunk[CHUNK_TICK] ~= tick) then chunk[CHUNK_TICK] = tick - processPheromone(regionMap, chunk, tempNeighbors) + processPheromone(regionMap, chunk) if squads then - formSquads(regionMap, surface, natives, chunk, AI_SQUAD_COST, tempNeighborsAll) + formSquads(regionMap, surface, natives, chunk, AI_SQUAD_COST) squads = natives.points >= AI_SQUAD_COST end if vengence then - formSquads(regionMap, surface, natives, chunk, AI_VENGENCE_SQUAD_COST, tempNeighborsAll) + formSquads(regionMap, surface, natives, chunk, AI_VENGENCE_SQUAD_COST) vengence = natives.points >= AI_VENGENCE_SQUAD_COST end diff --git a/libs/MapUtils.lua b/libs/MapUtils.lua index 376691c..c05d815 100644 --- a/libs/MapUtils.lua +++ b/libs/MapUtils.lua @@ -8,8 +8,14 @@ local mathUtils = require("MathUtils") -- constants -local NORTH_SOUTH_PASSABLE = constants.NORTH_SOUTH_PASSABLE -local EAST_WEST_PASSABLE = constants.EAST_WEST_PASSABLE +local CHUNK_NORTH_SOUTH = constants.CHUNK_NORTH_SOUTH +local CHUNK_EAST_WEST = constants.CHUNK_EAST_WEST + +local CHUNK_ALL_DIRECTIONS = constants.CHUNK_ALL_DIRECTIONS + +local PASSABLE = constants.PASSABLE + +local CHUNK_IMPASSABLE = constants.CHUNK_IMPASSABLE local CHUNK_SIZE = constants.CHUNK_SIZE @@ -48,9 +54,10 @@ end /|\ 6 7 8 ]]-- -function mapUtils.getNeighborChunks(regionMap, chunkX, chunkY, neighbors) +function mapUtils.getNeighborChunks(regionMap, chunkX, chunkY) local chunkYRow1 = chunkY - 1 local chunkYRow3 = chunkY + 1 + local neighbors = regionMap.neighbors local xChunks = regionMap[chunkX-1] if xChunks then neighbors[1] = xChunks[chunkYRow1] @@ -75,19 +82,23 @@ end function mapUtils.canMoveChunkDirection(direction, startChunk, endChunk) local canMove = false - if ((direction == 2) or (direction == 7)) and startChunk[NORTH_SOUTH_PASSABLE] and endChunk[NORTH_SOUTH_PASSABLE] then + local startPassable = startChunk[PASSABLE] + local endPassable = endChunk[PASSABLE] + if ((direction == 2) or (direction == 7)) and (startPassable == CHUNK_NORTH_SOUTH) and (endPassable == CHUNK_NORTH_SOUTH) then canMove = true - elseif ((direction == 4) or (direction == 5)) and startChunk[EAST_WEST_PASSABLE] and endChunk[EAST_WEST_PASSABLE] then + elseif ((direction == 4) or (direction == 5)) and (startPassable == CHUNK_EAST_WEST) and (endPassable == CHUNK_EAST_WEST) then canMove = true - elseif (startChunk[NORTH_SOUTH_PASSABLE] and startChunk[EAST_WEST_PASSABLE] and endChunk[NORTH_SOUTH_PASSABLE] and - endChunk[EAST_WEST_PASSABLE]) then + elseif (startPassable == CHUNK_ALL_DIRECTIONS) and (endPassable == CHUNK_ALL_DIRECTIONS) then + canMove = true + elseif (startPassable ~= CHUNK_IMPASSABLE) and (endPassable == CHUNK_ALL_DIRECTIONS) then canMove = true end return canMove end -function mapUtils.getCardinalChunks(regionMap, chunkX, chunkY, neighbors) +function mapUtils.getCardinalChunks(regionMap, chunkX, chunkY) local xChunks = regionMap[chunkX] + local neighbors = regionMap.cardinalNeighbors if xChunks then neighbors[1] = xChunks[chunkY-1] neighbors[4] = xChunks[chunkY+1] @@ -123,41 +134,6 @@ function mapUtils.euclideanDistanceArray(p1, p2) return ((xs * xs) + (ys * ys)) ^ 0.5 end ---[[ - 1 - | - 2- -3 - | - 4 -]]-- -function mapUtils.canMoveChunkDirectionCardinal(direction, startChunk, endChunk) - local canMove = false - if ((direction == 1) or (direction == 4)) and startChunk[NORTH_SOUTH_PASSABLE] and endChunk[NORTH_SOUTH_PASSABLE] then - canMove = true - elseif ((direction == 2) or (direction == 3)) and startChunk[EAST_WEST_PASSABLE] and endChunk[EAST_WEST_PASSABLE] then - canMove = true - end - return canMove -end - -function mapUtils.positionFromDirectionAndChunkCardinal(direction, startPosition, position) - -- local position = {x=0,y=0} - if (direction == 1) then - position.x = startPosition.x - position.y = startPosition.y - CHUNK_SIZE - elseif (direction == 2) then - position.x = startPosition.x - CHUNK_SIZE - position.y = startPosition.y - elseif (direction == 3) then - position.x = startPosition.x + CHUNK_SIZE - position.y = startPosition.y - elseif (direction == 4) then - position.x = startPosition.x - position.y = startPosition.y + CHUNK_SIZE - end - -- return position -end - function mapUtils.distortPosition(position) local xDistort = gaussianRandomRange(1, 0.5, 0, 2) - 1 local yDistort = gaussianRandomRange(1, 0.5, 0, 2) - 1 diff --git a/libs/PheromoneUtils.lua b/libs/PheromoneUtils.lua index d607d86..f013a7c 100644 --- a/libs/PheromoneUtils.lua +++ b/libs/PheromoneUtils.lua @@ -27,6 +27,10 @@ local RESOURCE_PHEROMONE_PERSISTANCE = constants.RESOURCE_PHEROMONE_PERSISTANCE local NORTH_SOUTH_PASSABLE = constants.NORTH_SOUTH_PASSABLE local EAST_WEST_PASSABLE = constants.EAST_WEST_PASSABLE +local CHUNK_IMPASSABLE = constants.CHUNK_IMPASSABLE +local CHUNK_ALL_DIRECTIONS = constants.CHUNK_ALL_DIRECTIONS + +local PASSABLE = constants.PASSABLE local NEST_COUNT = constants.NEST_COUNT @@ -42,7 +46,7 @@ local getCardinalChunks = mapUtils.getCardinalChunks function pheromoneUtils.scents(chunk) - if not chunk[NORTH_SOUTH_PASSABLE] and not chunk[EAST_WEST_PASSABLE] then + if (chunk[PASSABLE] == CHUNK_IMPASSABLE) then chunk[BASE_PHEROMONE] = IMPASSABLE_TERRAIN_GENERATOR_AMOUNT; else chunk[BASE_PHEROMONE] = chunk[BASE_PHEROMONE] + chunk[PLAYER_BASE_GENERATOR] @@ -55,26 +59,30 @@ end function pheromoneUtils.victoryScent(chunk, entityType) local value = BUILDING_PHEROMONES[entityType] - if (value ~= nil) then + if (value ~= nil) and (chunk[PASSABLE] ~= CHUNK_IMPASSABLE) then chunk[MOVEMENT_PHEROMONE] = chunk[MOVEMENT_PHEROMONE] + (value * 10000) end end function pheromoneUtils.deathScent(chunk) - chunk[MOVEMENT_PHEROMONE] = chunk[MOVEMENT_PHEROMONE] - DEATH_PHEROMONE_GENERATOR_AMOUNT + if (chunk[PASSABLE] ~= CHUNK_IMPASSABLE) then + chunk[MOVEMENT_PHEROMONE] = chunk[MOVEMENT_PHEROMONE] - DEATH_PHEROMONE_GENERATOR_AMOUNT + end end function pheromoneUtils.playerScent(playerChunk) - playerChunk[PLAYER_PHEROMONE] = playerChunk[PLAYER_PHEROMONE] + PLAYER_PHEROMONE_GENERATOR_AMOUNT + if (playerChunk[PASSABLE] ~= CHUNK_IMPASSABLE) then + playerChunk[PLAYER_PHEROMONE] = playerChunk[PLAYER_PHEROMONE] + PLAYER_PHEROMONE_GENERATOR_AMOUNT + end end -function pheromoneUtils.processPheromone(regionMap, chunk, tempNeighbors) +function pheromoneUtils.processPheromone(regionMap, chunk) - if not chunk[NORTH_SOUTH_PASSABLE] and not chunk[EAST_WEST_PASSABLE] then + if (chunk[PASSABLE] == CHUNK_IMPASSABLE) then return end - getCardinalChunks(regionMap, chunk.cX, chunk.cY, tempNeighbors) + local tempNeighbors = getCardinalChunks(regionMap, chunk.cX, chunk.cY) local chunkMovement = chunk[MOVEMENT_PHEROMONE] local chunkBase = chunk[BASE_PHEROMONE] diff --git a/libs/TendrilUtils.lua b/libs/TendrilUtils.lua index cd01257..f6e29b0 100644 --- a/libs/TendrilUtils.lua +++ b/libs/TendrilUtils.lua @@ -58,14 +58,13 @@ local function removeTendril(base, tendril) end end -local function buildTendrilPath(regionMap, tendril, surface, base, tempNeighbors) +local function buildTendrilPath(regionMap, tendril, surface, base, tick) local chunk = getChunkByPosition(regionMap, tendril.x, tendril.y) if chunk then local tendrilPath,tendrilDirection = scoreNeighborsWithDirection(chunk, getNeighborChunks(regionMap, chunk.cX, - chunk.cY, - tempNeighbors), + chunk.cY), validTendrilChunk, scoreTendrilChunk, nil, @@ -98,9 +97,9 @@ local function buildTendrilPath(regionMap, tendril, surface, base, tempNeighbors end end -function tendrilUtils.advanceTendrils(regionMap, base, surface, tempNeighbors) +function tendrilUtils.advanceTendrils(regionMap, base, surface, tick) for i=1, #base.tendrils do - buildTendrilPath(regionMap, base.tendrils[i], surface, base, tempNeighbors) + buildTendrilPath(regionMap, base.tendrils[i], surface, base, tick) end end diff --git a/libs/UnitGroupUtils.lua b/libs/UnitGroupUtils.lua index aa4c436..c21aff1 100644 --- a/libs/UnitGroupUtils.lua +++ b/libs/UnitGroupUtils.lua @@ -17,6 +17,8 @@ local DEFINES_GROUP_STATE_ATTACKING_DISTRACTION = defines.group_state.attacking_ local DEFINES_COMMAND_GROUP = defines.command.group local DEFINES_DISTRACTION_NONE = defines.distraction.none +local MAX_PENALTY_BEFORE_PURGE = constants.MAX_PENALTY_BEFORE_PURGE + local SQUAD_RETREATING = constants.SQUAD_RETREATING local SQUAD_GUARDING = constants.SQUAD_GUARDING local GROUP_MERGE_DISTANCE = constants.GROUP_MERGE_DISTANCE @@ -108,17 +110,31 @@ function unitGroupUtils.convertUnitGroupToSquad(natives, unitGroup) return returnSquad end -function unitGroupUtils.addSquadMovementPenalty(squad, chunkX, chunkY) +function unitGroupUtils.addSquadMovementPenalty(natives, squad, chunkX, chunkY) local penalties = squad.penalties for i=1,#penalties do local penalty = penalties[i] if (penalty.x == chunkX) and (penalty.y == chunkY) then penalty.v = penalty.v + MOVEMENT_PHEROMONE_GENERATOR_AMOUNT + if (penalty.v > MAX_PENALTY_BEFORE_PURGE) then + local group = squad.group + local members = group.members + for x=1,#members do + members[x].destroy() + end + natives.points = natives.points + (#members * natives.unitRefundAmount) + + if (natives.points > AI_MAX_OVERFLOW_POINTS) then + natives.points = AI_MAX_OVERFLOW_POINTS + end + + group.destroy() + end return end end - if (#penalties == 10) then - tableRemove(penalties, 10) + if (#penalties == 7) then + tableRemove(penalties, 7) end tableInsert(penalties, 1, { v = MOVEMENT_PHEROMONE_GENERATOR_AMOUNT, x = chunkX, diff --git a/make.rkt b/make.rkt index 488ee09..e91b0c1 100644 --- a/make.rkt +++ b/make.rkt @@ -77,8 +77,8 @@ (copyDirectory "prototypes" modFolder))) (define (run) - (copyFiles modFolder) + ;; (copyFiles modFolder) ;; (copyFiles zipModFolder) - ;; (makeZip modFolder) + (makeZip modFolder) ) ) diff --git a/settings.lua b/settings.lua index db6d11f..3a98d01 100644 --- a/settings.lua +++ b/settings.lua @@ -188,7 +188,7 @@ data:extend({ name = "rampant-useCustomAI", description = "rampant-useCustomAI", setting_type = 'startup', - default_value = true, + default_value = false, order = "h[total]-a[ai]", per_user = false }