1
0
mirror of https://github.com/veden/Rampant.git synced 2025-03-17 20:58:35 +02:00

see readme, base work not done

This commit is contained in:
Aaron Veden 2017-06-10 01:38:20 -07:00
parent 41fb7d6db4
commit 75eb3a29d4
17 changed files with 196 additions and 166 deletions

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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]

View File

@ -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

View File

@ -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,

View File

@ -77,8 +77,8 @@
(copyDirectory "prototypes" modFolder)))
(define (run)
(copyFiles modFolder)
;; (copyFiles modFolder)
;; (copyFiles zipModFolder)
;; (makeZip modFolder)
(makeZip modFolder)
)
)

View File

@ -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
}