1
0
mirror of https://github.com/veden/Rampant.git synced 2025-02-03 13:11:54 +02:00

smoothing out

This commit is contained in:
Aaron Veden 2019-03-07 19:40:55 -08:00
parent 2921d04e43
commit 5cf3e498e8
9 changed files with 217 additions and 179 deletions

View File

@ -6,6 +6,7 @@ Date: 3. 5. 2019
- Increased chunk processing from 825 to 1020 chunks
- Settler groups now occasionally disregard everything to reach a spot to build a base, instead of attacking player or buildings
Tweaks:
- Reduced full chunk scan threshold for water from 0.4 to 0.25
- Removed old map path finder settings
- Added new find position centered flag to positions searches
- Adjusted new enemy worm ranges to vanilla levels
@ -15,6 +16,7 @@ Date: 3. 5. 2019
- Fixed player pheromone not having highest value on chunk player was on
- Fixed settlers not being able to see chunks with resources on them
- Fixed retreat command not disengaging biters
- Fixed Poison faction poison death cloud crash
---------------------------------------------------------------------------------------------------
Version: 0.17.3

View File

@ -48,11 +48,13 @@ local RETREAT_SPAWNER_GRAB_RADIUS = constants.RETREAT_SPAWNER_GRAB_RADIUS
local DEFINES_COMMAND_GROUP = defines.command.group
local DEFINES_COMMAND_BUILD_BASE = defines.command.build_base
local DEFINES_COMMAND_ATTACK_AREA = defines.command.attack_area
local DEFINES_COMMAND_GO_TO_LOCATION = defines.command.go_to_location
local CHUNK_SIZE = constants.CHUNK_SIZE
local DEFINES_DISTRACTION_NONE = defines.distraction.none
local DEFINES_DISTRACTION_BY_ENEMY = defines.distraction.by_enemy
local DEFINES_DISTRACTION_BY_ANYTHING = defines.distraction.by_anything
local DEFINES_WIRE_TYPE_RED = defines.wire_type.red
local DEFINES_WIRE_TYPE_GREEN = defines.wire_type.green
@ -255,10 +257,18 @@ local function rebuildMap()
map.canPlaceQuery = { name="", position={0,0} }
map.filteredTilesQuery = { name=WATER_TILE_NAMES, area=map.area }
map.attackAreaCommand = {
map.attackCommand = {
type = DEFINES_COMMAND_ATTACK_AREA,
destination = map.position,
radius = CHUNK_SIZE,
distraction = DEFINES_DISTRACTION_BY_ANYTHING
}
map.moveCommand = {
type = DEFINES_COMMAND_GO_TO_LOCATION,
destination = map.position,
radius = 2,
pathfind_flags = { prefer_straight_paths = true },
distraction = DEFINES_DISTRACTION_BY_ENEMY
}
@ -367,6 +377,8 @@ local function prepWorld(rebuild)
y = chunk.y * 32 }}})
end
game.forces.enemy.kill_all_units()
processPendingChunks(natives, map, surface, pendingChunks, tick, game.forces.enemy.evolution_factor, rebuild)
end
end
@ -436,14 +448,13 @@ end)
script.on_nth_tick(INTERVAL_SQUAD,
function (event)
local gameRef = game
squadsBeginAttack(natives)
squadsDispatch(map, gameRef.surfaces[natives.activeSurface], natives)
-- cleanSquads(natives, map)
regroupSquads(natives, map)
regroupSquads(natives, map)
cleanBuilders(natives)
squadsBeginAttack(natives, gameRef.players)
squadsDispatch(map, gameRef.surfaces[natives.activeSurface], natives)
end)
local function onBuild(event)

View File

@ -5,6 +5,8 @@ local chunkPropertyUtils = {}
local constants = require("Constants")
local tRemove = table.remove
-- imported functions
local MOVEMENT_GENERATOR_PERSISTANCE = constants.MOVEMENT_GENERATOR_PERSISTANCE
@ -189,10 +191,12 @@ function chunkPropertyUtils.addSquadToChunk(map, chunk, squad)
chunkPropertyUtils.removeSquadFromChunk(map, squad)
end
if not chunkToSquad[chunk] then
chunkToSquad[chunk] = {}
local squads = chunkToSquad[chunk]
if not squads then
squads = {}
chunkToSquad[chunk] = squads
end
chunkToSquad[chunk][squad] = squad
squads[#squads+1] = squad
squad.chunk = chunk
end
@ -203,13 +207,13 @@ function chunkPropertyUtils.removeSquadFromChunk(map, squad)
if chunk then
local squads = chunkToSquad[chunk]
if squads then
squads[squad] = nil
local i = 0
for _,_ in pairs(squads) do
i = i + 1
break
for i=1,#squads do
if (squads[i] == squad) then
tRemove(squads, i)
break
end
end
if (i == 0) then
if (#squads == 0) then
chunkToSquad[chunk] = nil
end
end

View File

@ -79,49 +79,6 @@ local mRandom = math.random
-- module code
function chunkUtils.fullScan(chunk,
count_entities_filtered,
count_tiles_filtered,
filteredEntitiesCliffQuery,
filteredTilesPathQuery)
local x = chunk.x
local y = chunk.y
local passableNorthSouth = false
local passableEastWest = false
local topPosition = filteredEntitiesCliffQuery.area[1]
local bottomPosition = filteredEntitiesCliffQuery.area[2]
topPosition[2] = y
bottomPosition[2] = y + 32
for xi=x, x + 32 do
topPosition[1] = xi
bottomPosition[1] = xi + 1
if (count_entities_filtered(filteredEntitiesCliffQuery) == 0) and
(count_tiles_filtered(filteredTilesPathQuery) == 0)
then
passableNorthSouth = true
break
end
end
topPosition[1] = x
bottomPosition[1] = x + 32
for yi=y, y + 32 do
topPosition[2] = yi
bottomPosition[2] = yi + 1
if (count_entities_filtered(filteredEntitiesCliffQuery) == 0) and
(count_tiles_filtered(filteredTilesPathQuery) == 0)
then
passableEastWest = true
break
end
end
return passableNorthSouth, passableEastWest
end
local function addEnemyStructureToChunk(map, chunk, entity, base)
local lookup
if (entity.type == "unit-spawner") then
@ -227,12 +184,48 @@ end
function chunkUtils.scanChunkPaths(chunk, surface, map)
local pass = CHUNK_IMPASSABLE
local passableNorthSouth, passableEastWest = chunkUtils.fullScan(chunk,
surface.count_entities_filtered,
surface.count_tiles_filtered,
map.filteredEntitiesCliffQuery,
map.filteredTilesPathQuery)
local x = chunk.x
local y = chunk.y
local filteredEntitiesCliffQuery = map.filteredEntitiesCliffQuery
local filteredTilesPathQuery = map.filteredTilesPathQuery
local count_entities_filtered = surface.count_entities_filtered
local count_tiles_filtered = surface.count_tiles_filtered
local passableNorthSouth = false
local passableEastWest = false
local topPosition = filteredEntitiesCliffQuery.area[1]
local bottomPosition = filteredEntitiesCliffQuery.area[2]
topPosition[2] = y
bottomPosition[2] = y + 32
for xi=x, x + 32 do
topPosition[1] = xi
bottomPosition[1] = xi + 1
if (count_entities_filtered(filteredEntitiesCliffQuery) == 0) and
(count_tiles_filtered(filteredTilesPathQuery) == 0)
then
passableNorthSouth = true
break
end
end
topPosition[1] = x
bottomPosition[1] = x + 32
for yi=y, y + 32 do
topPosition[2] = yi
bottomPosition[2] = yi + 1
if (count_entities_filtered(filteredEntitiesCliffQuery) == 0) and
(count_tiles_filtered(filteredTilesPathQuery) == 0)
then
passableEastWest = true
break
end
end
if passableEastWest and passableNorthSouth then
pass = CHUNK_ALL_DIRECTIONS
elseif passableEastWest then
@ -279,11 +272,11 @@ end
function chunkUtils.initialScan(chunk, natives, surface, map, tick, evolutionFactor, rebuilding)
local passScore = chunkUtils.calculatePassScore(surface, map)
if (passScore >= 0.40) then
if (passScore >= 0.25) then
local pass = chunkUtils.scanChunkPaths(chunk, surface, map)
local playerObjects = scorePlayerBuildings(surface, map, natives)
local nests = surface.find_entities_filtered(map.filteredEntitiesUnitSpawnereQuery)
local worms = surface.find_entities_filtered(map.filteredEntitiesWormQuery)
@ -363,7 +356,7 @@ end
function chunkUtils.chunkPassScan(chunk, surface, map)
local passScore = chunkUtils.calculatePassScore(surface, map)
if (passScore >= 0.40) then
if (passScore >= 0.25) then
local pass = chunkUtils.scanChunkPaths(chunk, surface, map)
local playerObjects = getPlayerBaseGenerator(map, chunk)
@ -403,9 +396,7 @@ function chunkUtils.createChunk(topX, topY)
chunk[BASE_PHEROMONE] = 0
chunk[PLAYER_PHEROMONE] = 0
chunk[RESOURCE_PHEROMONE] = 0
-- chunk[PASSABLE] = 0
chunk[CHUNK_TICK] = 0
-- chunk[PATH_RATING] = 0
return chunk
end

View File

@ -577,8 +577,9 @@ constants.POISON_LOOKUP = {}
for tier=1, unitTiers do
local t = ((unitTiers == 5) and constants.TIER_NAMING_SET_5[tier]) or constants.TIER_NAMING_SET_10[tier]
local ct = ((unitTiers == 5) and constants.TIER_UPGRADE_SET_5[tier]) or constants.TIER_UPGRADE_SET_10[tier]
for i=1,unitVariations do
constants.POISON_LOOKUP["poison-biter-v" .. i .. "-t" .. t .. "-rampant"] = "poison-cloud-v" .. i .. "-cloud-rampant"
constants.POISON_LOOKUP["poison-biter-v" .. i .. "-t" .. t .. "-rampant"] = "poison-cloud-v" .. ct .. "-cloud-rampant"
end
end

View File

@ -37,7 +37,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)
pos = surface.find_non_colliding_position("behemoth-biter", position, 5, 1, true)
end
return (distort and distortPosition(pos)) or pos
end
@ -95,9 +95,9 @@ function movementUtils.scoreNeighborsForAttack(map, natives, chunk, neighborDire
end
end
if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) and (scoreFunction(natives, squad, chunk) > highestScore) then
return SENTINEL_IMPASSABLE_CHUNK, -1
end
-- if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) and (scoreFunction(natives, squad, chunk) > highestScore) then
-- return SENTINEL_IMPASSABLE_CHUNK, -1
-- end
return highestChunk, highestDirection
end

View File

@ -179,66 +179,71 @@ local function settleMove(map, attackPosition, attackCmd, settleCmd, squad, grou
end
local function attackMove(map, attackPosition, attackCmd, squad, group, natives, surface)
local groupState = group.state
local function attackMove(map, squad, natives, surface)
local attackPosition = map.position
local group = squad.group
if (groupState == DEFINES_GROUP_FINISHED) or (groupState == DEFINES_GROUP_GATHERING) or ((groupState == DEFINES_GROUP_MOVING) and (squad.cycles <= 0)) then
local groupPosition = group.position
local x, y = positionToChunkXY(groupPosition)
local chunk = getChunkByXY(map, x, y)
local attackScorer = scoreAttackLocation
if (squad.attackScoreFunction == ATTACK_SCORE_KAMIKAZE) then
attackScorer = scoreAttackKamikazeLocation
local groupPosition = group.position
local x, y = positionToChunkXY(groupPosition)
local chunk = getChunkByXY(map, x, y)
local attackScorer = scoreAttackLocation
if (squad.attackScoreFunction == ATTACK_SCORE_KAMIKAZE) then
attackScorer = scoreAttackKamikazeLocation
end
local attackChunk, attackDirection = scoreNeighborsForAttack(map,
natives,
chunk,
getNeighborChunks(map, x, y),
attackScorer,
squad)
if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) then
addSquadToChunk(map, chunk, squad)
addMovementPenalty(natives, squad, chunk)
end
if (attackChunk ~= SENTINEL_IMPASSABLE_CHUNK) then
local playerBaseGenerator = getPlayerBaseGenerator(map, attackChunk)
local playerPheromone = attackChunk[PLAYER_PHEROMONE]
local cmd
local position
if (playerBaseGenerator == 0) and (playerPheromone < natives.attackPlayerThreshold) then
squad.cycles = ((#squad.group.members > 80) and 6) or 4
squad.frenzy = (squad.frenzy and (euclideanDistanceNamed(groupPosition, squad.frenzyPosition) < 100))
cmd = map.moveCommand
if squad.rabid or squad.frenzy then
cmd.distraction = DEFINES_DISTRACTION_BY_ANYTHING
else
cmd.distraction = DEFINES_DISTRACTION_BY_ENEMY
end
else
squad.cycles = ((#squad.group.members > 80) and 6) or 4
cmd = map.attackCommand
if not squad.rabid then
squad.frenzy = true
squad.frenzyPosition.x = groupPosition.x
squad.frenzyPosition.y = groupPosition.y
end
end
local attackChunk, attackDirection = scoreNeighborsForAttack(map,
natives,
chunk,
getNeighborChunks(map, x, y),
attackScorer,
squad)
if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) then
addSquadToChunk(map, chunk, squad)
addMovementPenalty(natives, squad, chunk)
-- elseif (attackChunk ~= SENTINEL_IMPASSABLE_CHUNK) then
-- addSquadToChunk(map, attackChunk, squad)
-- addMovementPenalty(natives, squad, attackChunk)
end
if group.valid and (attackChunk ~= SENTINEL_IMPASSABLE_CHUNK) then
local playerBaseGenerator = getPlayerBaseGenerator(map, attackChunk)
-- local playerPheromone = attackChunk[PLAYER_PHEROMONE]
if (playerBaseGenerator == 0) or
((groupState == DEFINES_GROUP_FINISHED) or (groupState == DEFINES_GROUP_GATHERING))-- or
-- (playerPheromone < natives.attackPlayerThreshold)
then
squad.cycles = ((#squad.group.members > 80) and 6) or 4
local moreFrenzy = not squad.rabid and squad.frenzy and (euclideanDistanceNamed(groupPosition, squad.frenzyPosition) < 100)
squad.frenzy = moreFrenzy
position = findMovementPosition(surface,
positionFromDirectionAndChunk(attackDirection,
groupPosition,
attackPosition,
1.35))
if position then
attackPosition.x = position.x
attackPosition.y = position.y
if squad.rabid or squad.frenzy then
attackCmd.distraction = DEFINES_DISTRACTION_BY_ANYTHING
else
attackCmd.distraction = DEFINES_DISTRACTION_BY_ENEMY
end
local position = findMovementPosition(surface, positionFromDirectionAndChunk(attackDirection, groupPosition, attackPosition, 1.35))
if position then
attackPosition.x = position.x
attackPosition.y = position.y
group.set_command(attackCmd)
group.start_moving()
else
addMovementPenalty(natives, squad, attackChunk)
end
elseif not squad.frenzy and not squad.rabid and
((groupState == DEFINES_GROUP_ATTACKING_DISTRACTION) or (groupState == DEFINES_GROUP_ATTACKING_TARGET) or
(playerBaseGenerator ~= 0)) then
squad.frenzy = true
squad.frenzyPosition.x = groupPosition.x
squad.frenzyPosition.y = groupPosition.y
end
end
group.set_command(cmd)
group.start_moving()
else
addMovementPenalty(natives, squad, attackChunk)
end
else
print("attack: bad attack chunk", squad.group.group_number)
end
end
@ -267,9 +272,15 @@ function squadAttack.squadsDispatch(map, surface, natives)
else
local status = squad.status
local cycles = squad.cycles
local groupState = group.state
if (status == SQUAD_RAIDING) then
attackMove(map, attackPosition, attackCmd, squad, group, natives, surface)
if (groupState == DEFINES_GROUP_FINISHED) or
(groupState == DEFINES_GROUP_GATHERING) or
((groupState == DEFINES_GROUP_MOVING) and (cycles <= 0))
then
attackMove(map, squad, natives, surface)
end
elseif (status == SQUAD_SETTLING) then
settleMove(map, attackPosition, attackCmd, settleCmd, squad, group, natives, surface)
elseif (status == SQUAD_RETREATING) and (cycles == 0) then
@ -292,7 +303,7 @@ function squadAttack.squadsDispatch(map, surface, natives)
end
end
function squadAttack.squadsBeginAttack(natives, players)
function squadAttack.squadsBeginAttack(natives)
local squads = natives.pendingAttack
for i=1,#squads do
local squad = squads[i]
@ -303,25 +314,15 @@ function squadAttack.squadsBeginAttack(natives, players)
squad.kamikaze = (mRandom() < kamikazeThreshold)
end
if squad.settlers then
-- if (squad.status == SQUAD_GUARDING) then
squad.status = SQUAD_SETTLING
natives.squads[#natives.squads+1] = squad
else
-- if (squad.status == SQUAD_GUARDING) then
local groupPosition = group.position
if playersWithinProximityToPosition(players, groupPosition, 100, natives) then
squad.frenzy = true
squad.frenzyPosition.x = groupPosition.x
squad.frenzyPosition.y = groupPosition.y
end
else
if squad.kamikaze and (mRandom() < (kamikazeThreshold * 0.75)) then
squad.attackScoreFunction = ATTACK_SCORE_KAMIKAZE
end
squad.status = SQUAD_RAIDING
natives.squads[#natives.squads+1] = squad
end
-- end
end
end
natives.pendingAttack = {}

View File

@ -51,7 +51,10 @@ local getEnemyStructureCount = chunkPropetyUtils.getEnemyStructureCount
-- module code
local function scoreRetreatLocation(map, neighborChunk)
return -(neighborChunk[BASE_PHEROMONE] + neighborChunk[MOVEMENT_PHEROMONE] + -(neighborChunk[PLAYER_PHEROMONE] * PLAYER_PHEROMONE_MULTIPLER) + -(getPlayerBaseGenerator(map, neighborChunk)))
return -(neighborChunk[BASE_PHEROMONE] +
neighborChunk[MOVEMENT_PHEROMONE] +
-(neighborChunk[PLAYER_PHEROMONE] * PLAYER_PHEROMONE_MULTIPLER) +
-(getPlayerBaseGenerator(map, neighborChunk)))
end
function aiDefense.retreatUnits(chunk, position, squad, map, surface, natives, tick, radius, artilleryBlast, force)
@ -64,10 +67,10 @@ function aiDefense.retreatUnits(chunk, position, squad, map, surface, natives, t
performRetreat = #enemiesToSquad > 0
if (mRandom() < calculateKamikazeThreshold(#enemiesToSquad, natives)) then
setRetreatTick(map, chunk, tick)
performRetreat = false
return
end
elseif squad.group and squad.group.valid and (squad.status ~= SQUAD_RETREATING) and not squad.kamikaze then
performRetreat = #squad.group.members > 1
performRetreat = #squad.group.members > 3
end
if performRetreat then
@ -78,8 +81,7 @@ function aiDefense.retreatUnits(chunk, position, squad, map, surface, natives, t
map)
if (exitPath ~= SENTINEL_IMPASSABLE_CHUNK) then
local retreatPosition = findMovementPosition(surface,
positionFromDirectionAndChunk(exitDirection, position, map.position, 0.98),
false)
positionFromDirectionAndChunk(exitDirection, position, map.position, 0.98))
if not retreatPosition then
return
@ -88,7 +90,7 @@ function aiDefense.retreatUnits(chunk, position, squad, map, surface, natives, t
-- 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
local newSquad = findNearbySquadFiltered(map, exitPath, retreatPosition)
local newSquad = findNearbySquadFiltered(map, exitPath)
if not newSquad then
newSquad = createSquad(retreatPosition, surface)
@ -97,12 +99,7 @@ function aiDefense.retreatUnits(chunk, position, squad, map, surface, natives, t
if newSquad then
newSquad.status = SQUAD_RETREATING
newSquad.cycles = 4
squad.frenzy = true
local squadPosition = newSquad.group.position
squad.frenzyPosition.x = squadPosition.x
squad.frenzyPosition.y = squadPosition.y
newSquad.cycles = 4
local cmd = map.retreatCommand
cmd.group = newSquad.group
@ -115,6 +112,13 @@ function aiDefense.retreatUnits(chunk, position, squad, map, surface, natives, t
newSquad.rabid = true
end
end
if not newSquad.rapid then
newSquad.frenzy = true
local squadPosition = newSquad.group.position
newSquad.frenzyPosition.x = squadPosition.x
newSquad.frenzyPosition.y = squadPosition.y
end
addSquadToChunk(map, chunk, newSquad)
addMovementPenalty(natives, newSquad, chunk)
end

View File

@ -62,51 +62,75 @@ function tests.killActiveSquads()
end
function tests.activeSquads()
print("--")
print("-----")
print("Squads", #global.natives.squads)
for i=1, #global.natives.squads do
print("-")
local squad = global.natives.squads[i]
local squadHealth = 0
local squadMakeup = {}
local squadResistances = {}
if squad.group.valid then
for x=1,#squad.group.members do
local member = squad.group.members[x].prototype
if not squadMakeup[member.name] then
squadMakeup[member.name] = 0
end
local resistances = member.resistances
if resistances then
for key,resistance in pairs(resistances) do
local pack = squadResistances[key]
if not pack then
pack = {}
squadResistances[key] = pack
end
if resistance.percent then
if (pack.percent == nil) then
pack.percent = 0
end
pack.percent = pack.percent + resistance.percent
end
if resistance.decrease then
if (pack.decrease == nil) then
pack.decrease = 0
end
pack.decrease = pack.decrease + resistance.decrease
end
end
squadHealth = squadHealth + member.max_health
squadMakeup[member.name] = squadMakeup[member.name] + 1
end
print(math.floor(squad.group.position.x * 0.03125), math.floor(squad.group.position.y * 0.03125), squad.status, squad.group.state, #squad.group.members, squad.cycles, squadHealth)
-- print(serpent.dump(squadResistances))
print(serpent.dump(squadMakeup))
print(serpent.dump(squad))
end
end
print("---")
print("pending", #global.natives.pendingAttack)
for i=1, #global.natives.pendingAttack do
print("-")
local squad = global.natives.pendingAttack[i]
local squadHealth = 0
local squadMakeup = {}
if squad.group.valid then
for x=1,#squad.group.members do
local member = squad.group.members[x].prototype
if not squadMakeup[member.name] then
squadMakeup[member.name] = 0
end
squadHealth = squadHealth + member.max_health
squadMakeup[member.name] = squadMakeup[member.name] + 1
end
print(math.floor(squad.group.position.x * 0.03125), math.floor(squad.group.position.y * 0.03125), squad.status, squad.group.state, #squad.group.members, squadHealth)
print(serpent.dump(squadResistances))
print(math.floor(squad.group.position.x * 0.03125), math.floor(squad.group.position.y * 0.03125), squad.status, squad.group.state, #squad.group.members, squad.cycles, squadHealth)
-- print(serpent.dump(squadResistances))
print(serpent.dump(squadMakeup))
print(serpent.dump(squad))
end
end
print("---")
print("building", #global.natives.building)
for i=1, #global.natives.building do
print("-")
local squad = global.natives.pendingAttack[i]
local squadHealth = 0
local squadMakeup = {}
if squad.group.valid then
for x=1,#squad.group.members do
local member = squad.group.members[x].prototype
if not squadMakeup[member.name] then
squadMakeup[member.name] = 0
end
squadHealth = squadHealth + member.max_health
squadMakeup[member.name] = squadMakeup[member.name] + 1
end
print(math.floor(squad.group.position.x * 0.03125), math.floor(squad.group.position.y * 0.03125), squad.status, squad.group.state, #squad.group.members, squad.cycles, squadHealth)
-- print(serpent.dump(squadResistances))
print(serpent.dump(squadMakeup))
print(serpent.dump(squad))
end
end
end
function tests.entitiesOnPlayerChunk()