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

refactor chunk scoring, and optimized it

This commit is contained in:
Aaron Veden 2017-06-14 22:08:13 -07:00
parent ab1fe32be5
commit 1fbd91908c
5 changed files with 112 additions and 63 deletions

View File

@ -57,7 +57,7 @@ Configure Options not in game menu:
# Version History
0.15.16 -
- Optimization: Greatly reduced reindexing time
0.15.15 -
- Fixed: Desync when reindexing chunks (https://forums.factorio.com/viewtopic.php?f=94&t=31445&start=180#p287941)

View File

@ -7,6 +7,8 @@ local constants = require("Constants")
-- constants
local CHUNK_QUEUE_SIZE = constants.CHUNK_QUEUE_SIZE
local CHUNK_SIZE = constants.CHUNK_SIZE
-- imported functions
@ -15,6 +17,10 @@ local createChunk = chunkUtils.createChunk
local checkChunkPassability = chunkUtils.checkChunkPassability
local scoreChunk = chunkUtils.scoreChunk
local remakeChunk = chunkUtils.remakeChunk
local registerChunkEnemies = chunkUtils.registerChunkEnemies
-- module code
function chunkProcessor.processPendingChunks(natives, regionMap, surface, pendingStack, tick)
@ -27,6 +33,8 @@ function chunkProcessor.processPendingChunks(natives, regionMap, surface, pendin
local count = 0
local useCustomAI = natives.useCustomAI
local chunkTiles = regionMap.chunkTiles
local start = #pendingStack
@ -51,13 +59,16 @@ function chunkProcessor.processPendingChunks(natives, regionMap, surface, pendin
regionMap[chunkX][chunk.cY] = chunk
checkChunkPassability(chunkTiles, chunk, surface)
scoreChunk(regionMap, chunk, surface, natives, tick, query)
if not useCustomAI then
registerChunkEnemies(chunk, surface, query)
end
scoreChunk(chunk, surface, natives, query)
processQueue[#processQueue+1] = chunk
if (count >= 200) then
if (count >= CHUNK_QUEUE_SIZE) then
break
end
end
if (count >= 200) and (start > 0) then
if (count >= CHUNK_QUEUE_SIZE) and (start > 0) then
surface.print("Rampant - " .. (start - count) .. " Remaining chunks to process")
end
end

View File

@ -46,21 +46,24 @@ local addEnemyStructureToChunk = baseRegisterUtils.addEnemyStructureToChunk
-- module code
function chunkUtils.checkChunkPassability(chunkTiles, chunk, surface)
local x = chunk.x
local y = chunk.y
local function fullScan(chunkTiles, x, y, get_tile)
local endY = y + 31
local get_tile = surface.get_tile
local i = 0
local validTiles = 0
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
local tile = get_tile(xi, yi)
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
chunkTiles[i] = tile
@ -68,94 +71,127 @@ function chunkUtils.checkChunkPassability(chunkTiles, chunk, surface)
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
local tile = chunkTiles[yi + xi]
if not tile then
-- 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
break
end
end
return validTiles / 1024, passableNorthSouth, passableEastWest
end
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
local function spotCheck(x, y, get_tile)
local valid = 0
for offsetX = 0, 31, 5 do
for offsetY = 0, 31, 5 do
local tile = get_tile(x + offsetX,
y + offsetY)
if not tile.collides_with("player-layer") then
valid = valid + 1
end
end
end
if (pass ~= CHUNK_IMPASSABLE) then
local rating = validTiles / 1024
return valid
end
function chunkUtils.checkChunkPassability(chunkTiles, chunk, surface)
local x = chunk.x
local y = chunk.y
local get_tile = surface.get_tile
--[[
0 represents water chunk
1-48 chunk requires full scan
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
pass = CHUNK_IMPASSABLE
local rating, passableNorthSouth, passableEastWest = fullScan(chunkTiles, x, y, get_tile, surface)
if passableEastWest and passableNorthSouth then
pass = CHUNK_ALL_DIRECTIONS
elseif passableEastWest then
pass = CHUNK_EAST_WEST
elseif passableNorthSouth then
pass = CHUNK_NORTH_SOUTH
end
chunk[PATH_RATING] = rating
if (rating < 0.6) then
pass = CHUNK_IMPASSABLE
end
elseif (cleanSpotCheck == 0) then
pass = CHUNK_IMPASSABLE
end
chunk[PASSABLE] = pass
end
function chunkUtils.scoreChunk(regionMap, chunk, surface, natives, tick, tempQuery)
local useCustomAI = natives.useCustomAI
function chunkUtils.remakeChunk(regionMap, chunk, surface, natives, tick, tempQuery)
tempQuery.force = "enemy"
local enemies = surface.find_entities_filtered(tempQuery)
local nests = 0
local worms = 0
local biters = 0
local points = 0
for f=1, #enemies do
local enemy = enemies[f]
local entityType = enemies[f].type
if not ((enemy.name == "small-tendril-biter-rampant") or (enemy.name == "biter-spawner-hive")) then
if (entityType == "unit-spawner") then
points = points + 3
elseif (entityType == "turret") then
points = points + 2
elseif (entityType == "unit") then
points = points + 1
end
enemy.destroy()
end
end
local foundBase = findNearbyBase(natives, chunk) or createBase(regionMap, natives, chunk, surface, tick)
if foundBase then
foundBase.upgradePoints = foundBase.upgradePoints + points
end
end
function chunkUtils.registerChunkEnemies(chunk, surface, tempQuery)
tempQuery.force = "enemy"
local enemies = surface.find_entities_filtered(tempQuery)
for i=1, #enemies do
local entityType = enemies[i].type
if (entityType == "unit-spawner") then
nests = nests + 1
elseif (entityType == "turret") then
worms = worms + 1
elseif useCustomAI and (entityType == "unit") then
biters = biters + 1
end
end
if useCustomAI then
if (nests > 0) or (worms > 0) or (biters > 0) then
for f=1, #enemies do
local enemy = enemies[f]
if (enemy.name == "small-tendril-biter-rampant") then
biters = biters - 1
elseif (enemy.name == "biter-spawner-hive") then
nests = nests - 1
else
enemy.destroy()
end
end
local foundBase = findNearbyBase(natives, chunk) or createBase(regionMap, natives, chunk, surface, tick)
if foundBase then
foundBase.upgradePoints = foundBase.upgradePoints + (nests*3) + (worms*2) + biters
end
end
else
for i=1, #enemies do
local enemy = enemies[i]
local enemyType = enemy.type
if (enemyType == "unit-spawner") or (enemyType == "turret") then
addEnemyStructureToChunk(chunk, enemy, nil)
end
local enemy = enemies[i]
local enemyType = enemy.type
if (enemyType == "unit-spawner") or (enemyType == "turret") then
addEnemyStructureToChunk(chunk, enemy, nil)
end
end
end
function chunkUtils.scoreChunk(chunk, surface, natives, tempQuery)
tempQuery.force = nil
tempQuery.type = "resource"
chunk[RESOURCE_GENERATOR] = surface.count_entities_filtered(tempQuery)
tempQuery.type = nil

View File

@ -20,6 +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.PROCESS_QUEUE_SIZE = 450
constants.SCAN_QUEUE_SIZE = 6
constants.BASE_QUEUE_SIZE = 1
@ -34,7 +35,7 @@ constants.INTERVAL_LOGIC = 38
constants.PLAYER_PHEROMONE_MULTIPLER = 100
constants.DEV_CUSTOM_AI = true
constants.DEV_CUSTOM_AI = false
-- chunk properties

View File

@ -6,6 +6,7 @@ local constants = require("Constants")
local mapUtils = require("MapUtils")
local baseRegisterUtils = require("BaseRegisterUtils")
local neighborsUtils = require("NeighborUtils")
local mathUtils = require("MathUtils")
local buildUtils = require("BuildUtils")
@ -82,7 +83,7 @@ local function buildTendrilPath(regionMap, tendril, surface, base, tick, natives
return
elseif tendrilPath then
positionFromDirectionAndChunk(tendrilDirection, tendrilPosition, tendrilPosition, 0.5)
mapUtils.distortPosition(tendrilPosition)
mathUtils.distortPosition(tendrilPosition)
-- tendril.path[#tendril.path] = chunk
local position = surface.find_non_colliding_position("spitter-spawner",
tendrilPosition,