diff --git a/README.md b/README.md index d527ca0..2fd0bb4 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,8 @@ https://forums.factorio.com/viewtopic.php?f=94&t=31445 # Notes +The 0.14.4 factorio version fixed some issues with unit groups commands + There will be a slight pause the first time this is started up due to indexing all the chunks that have been generated. MP should be working @@ -30,10 +32,13 @@ Base Expansion # Version History -0.14.1 - fixed ai created bases not being counted in logic - Optimization to offset ai created bases scanning +0.14.2 - adjusted unit retreat group size threshold + adjusted squad attack pattern (https://forums.factorio.com/viewtopic.php?f=94&t=31445&start=20#p203861) __ -0.13.1 - backported 0.14 factorio version to 0.13 factorio version +0.14.1 - fixed ai created bases not being counted in logic + Optimization to offset ai created bases scanning + +0.13.1 - backported 0.14 factorio version to 0.13 factorio version 0.0.8 - fixed retreat oscillations (https://forums.factorio.com/viewtopic.php?f=94&t=31445&start=10#p198750) added scaling for kamikaze attack (https://forums.factorio.com/viewtopic.php?f=94&t=31445&start=10#p199401) diff --git a/info.json b/info.json index 86bf1d6..52572a2 100644 --- a/info.json +++ b/info.json @@ -1,7 +1,7 @@ { "name" : "Rampant", "factorio_version" : "0.14", - "version" : "0.14.1", + "version" : "0.14.2", "title" : "Rampant AI", "author" : "Veden", "homepage" : "https://forums.factorio.com/viewtopic.php?f=94&t=31445", diff --git a/libs/AIAttack.lua b/libs/AIAttack.lua index ae93748..4d91d9e 100644 --- a/libs/AIAttack.lua +++ b/libs/AIAttack.lua @@ -14,7 +14,7 @@ local PLAYER_PHEROMONE = constants.PLAYER_PHEROMONE local DEATH_PHEROMONE = constants.DEATH_PHEROMONE local ENEMY_BASE_PHEROMONE = constants.ENEMY_BASE_PHEROMONE local PLAYER_BASE_PHEROMONE = constants.PLAYER_BASE_PHEROMONE -local PLAYER_DEFENSE_PHEROMONE = constants.PLAYER_DEFENSE_PHEROMONE +--local PLAYER_DEFENSE_PHEROMONE = constants.PLAYER_DEFENSE_PHEROMONE local SQUAD_RAIDING = constants.SQUAD_RAIDING local SQUAD_SUICIDE_RAID = constants.SQUAD_SUICIDE_RAID @@ -22,11 +22,11 @@ local SQUAD_HUNTING = constants.SQUAD_HUNTING local SQUAD_GUARDING = constants.SQUAD_GUARDING local SQUAD_SUICIDE_HUNT = constants.SQUAD_SUICIDE_HUNT -local ENEMY_BASE_GENERATOR = constants.ENEMY_BASE_GENERATOR -local MAGIC_MAXIMUM_NUMBER = constants.MAGIC_MAXIMUM_NUMBER +--local ENEMY_BASE_GENERATOR = constants.ENEMY_BASE_GENERATOR +--local MAGIC_MAXIMUM_NUMBER = constants.MAGIC_MAXIMUM_NUMBER -local HALF_CHUNK_SIZE = constants.HALF_CHUNK_SIZE -local CHUNK_SIZE = constants.CHUNK_SIZE +--local HALF_CHUNK_SIZE = constants.HALF_CHUNK_SIZE +--local CHUNK_SIZE = constants.CHUNK_SIZE local PLAYER_BASE_GENERATOR = constants.PLAYER_BASE_GENERATOR local PLAYER_DEFENSE_GENERATOR = constants.PLAYER_DEFENSE_GENERATOR @@ -40,11 +40,13 @@ local addSquadMovementPenalty = unitGroupUtils.addSquadMovementPenalty local lookupSquadMovementPenalty = unitGroupUtils.lookupSquadMovementPenalty local positionFromDirectionAndChunkCardinal = mapUtils.positionFromDirectionAndChunkCardinal +local euclideanDistanceNamed = mapUtils.euclideanDistanceNamed + local playersWithinProximityToPosition = playerUtils.playersWithinProximityToPosition local scoreNeighborsWithDirection = neighborUtils.scoreNeighborsWithDirection -local mMax = math.max + -- module code @@ -66,8 +68,17 @@ local function scoreHuntPlayerLocation(position, squad, neighborChunk, surface) return damageScore - avoidScore - squadMovementPenalty end -function aiAttack.squadAttack(regionMap, surface, natives, temps) +function aiAttack.squadAttack(regionMap, surface, natives) local squads = natives.squads + local attackPosition + local attackCmd + if (#squads > 0) then + attackPosition = {x=0, y=0} + attackCmd = { type = defines.command.attack_area, + destination = attackPosition, + radius = 16, + distraction = defines.distraction.by_enemy } + end for i=1,#squads do local squad = squads[i] local group = squad.group @@ -82,10 +93,9 @@ function aiAttack.squadAttack(regionMap, surface, natives, temps) scoreLocation = scoreHuntPlayerLocation end if group.valid and (raiding or hunting) then - if (group.state == defines.group_state.finished) or (group.state == defines.group_state.gathering) then + if (group.state == defines.group_state.finished) or (group.state == defines.group_state.gathering) or ((group.state == defines.group_state.moving) and (squad.cycles == 0)) then local chunk = getChunkByPosition(regionMap, group.position.x, group.position.y) if (chunk ~= nil) then - local attackPosition = {x=0, y=0} addSquadMovementPenalty(squad, chunk.cX, chunk.cY) local attackChunk, attackDirection = scoreNeighborsWithDirection(chunk, getCardinalChunksWithDirection(regionMap, chunk.cX, chunk.cY), @@ -98,14 +108,29 @@ function aiAttack.squadAttack(regionMap, surface, natives, temps) if ((attackChunk[PLAYER_BASE_GENERATOR] == 0) and (attackChunk[PLAYER_DEFENSE_GENERATOR] == 0)) or ((group.state == defines.group_state.finished) or (group.state == defines.group_state.gathering)) then - positionFromDirectionAndChunkCardinal(attackDirection, attackChunk, attackPosition) - - group.set_command({ type = defines.command.attack_area, - destination = attackPosition, - radius = 32, - distraction = defines.distraction.by_anything }) + positionFromDirectionAndChunkCardinal(attackDirection, squad.group.position, attackPosition) + + squad.cycles = 3 + + if not squad.rabid and squad.frenzy and (euclideanDistanceNamed(squad.group.position, squad.frenzyPosition) > 100) then + squad.frenzy = false + end + + if squad.rabid or squad.frenzy then + attackCmd.distraction = defines.distraction.by_anything + else + attackCmd.distraction = defines.distraction.by_enemy + end + + group.set_command(attackCmd) group.start_moving() - end + elseif not squad.frenzy and not squad.rabid and + (((group.state == defines.group_state.attacking_distraction) or (group.state == defines.group_state.attacking_distraction)) or + (attackChunk[PLAYER_BASE_GENERATOR] ~= 0) or (attackChunk[PLAYER_DEFENSE_GENERATOR] ~= 0)) then + squad.frenzy = true + squad.frenzyPosition.x = squad.group.position.x + squad.frenzyPosition.y = squad.group.position.y + end end end end @@ -119,9 +144,16 @@ function aiAttack.squadBeginAttack(natives, players, evolution_factor) local squad = squads[i] if (squad.status == SQUAD_GUARDING) and squad.group.valid then local threshold = 0.05 + (evolution_factor * 0.20) + (#squad.group.members * 0.0033) - + + local playerNearby = playersWithinProximityToPosition(players, squad.group.position, 100) + if playerNearby then + squad.frenzy = true + squad.frenzyPosition.x = squad.group.position.x + squad.frenzyPosition.y = squad.group.position.y + end + -- check to hunt player - if (math.random() < 0.30) and playersWithinProximityToPosition(players, squad.group.position, 100) then + if (math.random() < 0.30) and playerNearby then if (math.random() < threshold) then squad.status = SQUAD_SUICIDE_HUNT else @@ -131,7 +163,7 @@ function aiAttack.squadBeginAttack(natives, players, evolution_factor) -- check to raid base if (squad.status == SQUAD_GUARDING) and (math.random() < 0.70) then - if (math.random() < threshold) then + if (math.random() < threshold) then squad.status = SQUAD_SUICIDE_RAID else squad.status = SQUAD_RAIDING diff --git a/libs/AIBuilding.lua b/libs/AIBuilding.lua index b47192d..720f6a8 100644 --- a/libs/AIBuilding.lua +++ b/libs/AIBuilding.lua @@ -128,12 +128,16 @@ function aiBuilding.formSquads(regionMap, surface, natives, chunk, evolution_fac squadPosition.y = squadPath.pY + HALF_CHUNK_SIZE local squad = createSquad(squadPosition, surface, natives) - + + if (math.random() < 0.05) then + squad.rabid = true + end + local foundUnits = surface.set_multi_command({ command = { type = defines.command.group, - group = squad.group, - distraction = defines.distraction.none }, + group = squad.group, + distraction = defines.distraction.none }, unit_count = evolution_factor * AI_MAX_SQUAD_SIZE, - unit_search_distance = (constants.CHUNK_SIZE * 2)}) + unit_search_distance = (CHUNK_SIZE * 2)}) if (foundUnits > 0) then natives.points = natives.points - AI_SQUAD_COST end diff --git a/libs/AIDefense.lua b/libs/AIDefense.lua index c5d9462..d2c464e 100644 --- a/libs/AIDefense.lua +++ b/libs/AIDefense.lua @@ -58,11 +58,11 @@ function aiDefense.retreatUnits(position, squad, regionMap, surface, natives) if (squad == nil) then enemiesToSquad = surface.find_enemy_units(position, 15) - if (#enemiesToSquad > 0) then + if (#enemiesToSquad > 1) then performRetreat = true end elseif squad.group.valid and (squad.status ~= SQUAD_RETREATING) and (squad.status ~= SQUAD_SUICIDE_HUNT) and (squad.status ~= SQUAD_SUICIDE_RAID) then - if (#squad.group.members ~= 0) then + if (#squad.group.members > 1) then performRetreat = true end end @@ -90,13 +90,16 @@ function aiDefense.retreatUnits(position, squad, regionMap, surface, natives) if (newSquad == nil) then newSquad = createSquad(retreatPosition, surface, natives) newSquad.status = SQUAD_RETREATING - newSquad.cycles = 4 + newSquad.cycles = 6 end if (enemiesToSquad ~= nil) then membersToSquad(newSquad, enemiesToSquad, false) else membersToSquad(newSquad, squad.group.members, true) + if squad.rabid then + newSquad.rabid = true + end end end end diff --git a/libs/Constants.lua b/libs/Constants.lua index 2d017a0..772c283 100644 --- a/libs/Constants.lua +++ b/libs/Constants.lua @@ -105,7 +105,7 @@ constants.BUILDING_PHEROMONES["offshore-pump"] = 8 -- constants.buildingPheromones["constant-combinator"] = 1 -- constants.buildingPheromones["train-stop"] = 2 -- constants.buildingPheromones["rail-signal"] = 1 -constants.BUILDING_PHEROMONES["electric-pole"] = 4 +-- constants.BUILDING_PHEROMONES["electric-pole"] = 4 constants.BUILDING_PHEROMONES["transport-belt"] = 4 constants.BUILDING_PHEROMONES["accumulator"] = 40 constants.BUILDING_PHEROMONES["solar-panel"] = 32 diff --git a/libs/MapUtils.lua b/libs/MapUtils.lua index 7190ea5..9f8555e 100644 --- a/libs/MapUtils.lua +++ b/libs/MapUtils.lua @@ -188,24 +188,43 @@ function mapUtils.canMoveChunkDirectionCardinal(direction, startChunk, endChunk) return canMove end -function mapUtils.positionFromDirectionAndChunkCardinal(direction, chunk, position) +function mapUtils.positionFromDirectionAndChunkCardinal(direction, startPosition, position) -- local position = {x=0,y=0} if (direction == 1) then - position.x = chunk.pX + HALF_CHUNK_SIZE - position.y = chunk.pY + position.x = startPosition.x + position.y = startPosition.y - CHUNK_SIZE elseif (direction == 2) then - position.x = chunk.pX - position.y = chunk.pY + HALF_CHUNK_SIZE + position.x = startPosition.x - CHUNK_SIZE + position.y = startPosition.y elseif (direction == 3) then - position.x = chunk.pX + CHUNK_SIZE - position.y = chunk.pY + HALF_CHUNK_SIZE + position.x = startPosition.x + CHUNK_SIZE + position.y = startPosition.y elseif (direction == 4) then - position.x = chunk.pX + HALF_CHUNK_SIZE - position.y = chunk.pY + CHUNK_SIZE + position.x = startPosition.x + position.y = startPosition.y + CHUNK_SIZE end -- return position end + +-- function mapUtils.positionFromDirectionAndChunkCardinal(direction, chunk, position) +-- -- local position = {x=0,y=0} +-- if (direction == 1) then +-- position.x = chunk.pX + HALF_CHUNK_SIZE +-- position.y = chunk.pY +-- elseif (direction == 2) then +-- position.x = chunk.pX +-- position.y = chunk.pY + HALF_CHUNK_SIZE +-- elseif (direction == 3) then +-- position.x = chunk.pX + CHUNK_SIZE +-- position.y = chunk.pY + HALF_CHUNK_SIZE +-- elseif (direction == 4) then +-- position.x = chunk.pX + HALF_CHUNK_SIZE +-- position.y = chunk.pY + CHUNK_SIZE +-- end +-- -- return position +-- end + function mapUtils.positionFromDirectionAndChunk(direction, chunk) local position = {x=0, y=0} if (direction == 1) then diff --git a/libs/UnitGroupUtils.lua b/libs/UnitGroupUtils.lua index d26f801..19c094a 100644 --- a/libs/UnitGroupUtils.lua +++ b/libs/UnitGroupUtils.lua @@ -41,6 +41,10 @@ function unitGroupUtils.createSquad(position, surface, natives) local squad = { group = unitGroup, status = SQUAD_GUARDING, penalties = {}, + rabid = false, + frenzy = false, + frenzyPosition = {x = 0, + y = 0}, cycles = 0 } natives.squads[#natives.squads+1] = squad return squad @@ -48,12 +52,13 @@ end function unitGroupUtils.membersToSquad(squad, members, overwriteGroup) if (members ~= nil) then + local cmd = { type = defines.command.group, + group = squad.group, + distraction = defines.distraction.none } for i=1,#members do local member = members[i] if member.valid and (overwriteGroup or (not overwriteGroup and (member.unit_group == nil))) then - member.set_command({ type = defines.command.group, - group = squad.group, - distraction = defines.distraction.none }) + member.set_command(cmd) end end end @@ -72,6 +77,10 @@ function unitGroupUtils.convertUnitGroupToSquad(natives, unitGroup) returnSquad = { group = unitGroup, status = SQUAD_GUARDING, penalties = {}, + rabid = false, + frenzy = false, + frenzyPosition = {x = 0, + y = 0}, cycles = 0 } squads[#squads+1] = returnSquad end @@ -134,9 +143,13 @@ function unitGroupUtils.regroupSquads(natives) squad.group.destroy() tableRemove(squads, i) else - if (squad.status == SQUAD_RETREATING) and ((squad.cycles == 0) or (squad.group.state == GROUP_STATE_FINISHED)) then + if (squad.status == SQUAD_RETREATING) and (squad.cycles == 0) then squad.status = SQUAD_GUARDING - squad.cycles = 0 + squad.frenzy = true + squad.frenzyPosition.x = squad.group.position.x + squad.frenzyPosition.y = squad.group.position.y + elseif (squad.group.state == GROUP_STATE_FINISHED) then + squad.status = SQUAD_GUARDING elseif (squad.cycles > 0) then squad.cycles = squad.cycles - 1 end diff --git a/make.rkt b/make.rkt index c1304cf..88d47fd 100644 --- a/make.rkt +++ b/make.rkt @@ -73,7 +73,7 @@ (copyDirectory "graphics" modFolder) (copyDirectory "prototypes" modFolder))) -; (copyFiles modFolder) + (copyFiles modFolder) ; (copyFiles zipModFolder) - (makeZip) +; (makeZip) )