Eh... might as well, I guess. It's going to take me a while to re-write the Infected AI, so I guess the interested folks can take a look at this in the mean time.
This has Infected AI version 1, which is not very good on dynamic maps like this one. So it won't be much challenge to beat it, I think. There also aren't any victory/loss conditions in this. Very much in development.. :P
Copy and paste this into a LUA file.
Feel free to play around with the code and change stuff or whatever, but please don't release any levels with any of the new functionalities in this, until I've made my own debut. :>
function LevelSetup()
-- ** None of these are strictly necessary for Gravity... change as you like. **
SetBackdropColour(0,0,0)
Globals.Agents.MaxSpeed=600
Globals.Agents.MinSpeed=200
Globals.Mines.MinSpeed=1200
Globals.Mines.MaxSpeed=1200
Globals.Mines.MinHealth=2000
Globals.Mines.MaxHealth=2000
Globals.Asteroids.MaxTrees=3
Globals.Asteroids.MinRadius=125
Globals.Asteroids.MaxRadius=725
Globals.Asteroids.RadiusPowerRule=1.5
Globals.Asteroids.MinCoreHealth=50
Globals.Asteroids.MaxCoreHealth=900
Globals.Asteroids.CoreHealthPower=1
Globals.Asteroids.MinSendDistance=60000
Globals.Asteroids.MaxSendDistance=60000
Globals.Asteroids.SendPowerRule=1.4
Globals.Asteroids.SpawnCap=40
Globals.Asteroids.SeedlingCap=1000
Globals.G.Asteroids=(0)
Globals.AI.GraceTimer=(9999999)
Globals.G.EnemyFactionsMin=(0)
Globals.G.EnemyFactionsMax=(0)
Globals.G.MinAsteroidSeparation=100
Globals.G.MaxAsteroidNeighbourDist=60000
Globals.G.GreysProbability=0
Globals.Structures.FlowerProbability=(0.1)
SetVignetteAlpha(0)
-- **
-- ** Initialise Gravity Variables. No need to change anything here.
AccelerationX = {}
AccelerationY = {}
MomentumX = {}
MomentumY = {}
density = {}
CoordX = {}
CoordY = {}
roidradius = {}
str = {}
ene = {}
spe = {}
collision = {}
collisiontimer = {}
Timer = 0
collidedbefore = {}
oldCoordX = {}
oldCoordY = {}
-- **
-- ** G is the gravitational constant. Affects how powerful gravity is in the entire map. Change this as you like. **
G = 0.01
-- **
-- ****************************************
-- **********Asteroid Creation*************
-- ****************************************
--
-- How To.
-- * First we declare the asteroid ID to the Gravity Engine.
-- EG:
-- roid = 0
-- * Next comes the Acceleration array slot init. These should always be set to 0.
-- EG:
-- AccelerationX[roid] = 0
-- AccelerationY[roid] = 0
-- * MomentumX and MomentumY declare the initial velocity of the asteroid.
-- EG:
-- MomentumX[roid] = 10
-- MomentumY[roid] = 0
-- This example would produce an asteroid that is drifting east when the game begins.
-- * Density governs how dense the asteroid is. An asteroid that was made of metal has a higher density than an asteroid made of gas. Higher density means stronger gravity per unit of radius.
-- EG:
-- density[roid] = 1
-- * The coordinates of the asteroid when the game begins.
-- EG:
-- CoordX[roid] = 12000
-- CoordY[roid] = -8000
-- * Finally, we set the radius of the asteroid. Bigger asteroids have more gravity, but also weigh more so move in a "heavier" fashion.
-- EG:
-- roidradius[roid] = 400
-- Now we have declared all necessary gravity variables for the new asteroid, we can create it.
-- EG:
-- a = AddAsteroidWithAttribs(CoordX[roid],CoordY[roid],0.5,0.5,1)
-- a.Owner = 1
-- a.TreeCap = 2
-- a:SetRadius(roidradius[roid])
-- a:Reveal(1)
-- a.Moveable = False
-- any other commands you would like to run on this asteroid...
-- There are 3 different possible gravity behaviours; well-only, and full gravity, and static.
-- The asteroids MUST be created in the correct sections.
-- Please see below examples of all three different classes of asteroids.
-- ***
-- 1. THE BELOW ASTEROIDS HAVE A GRAVITY WELL BUT DO NOT THEMSELVES MOVE
-- ***
-- Asteroid 0 - A Sun
-- gravity variables
roid = 0
AccelerationX[roid] = 0
AccelerationY[roid] = 0
MomentumX[roid] = 0
MomentumY[roid] = 0
density[roid] = 10
CoordX[roid] = 0
CoordY[roid] = 0
oldCoordX[roid] = 0
oldCoordY[roid] = 0
roidradius[roid] = 300
-- Creation
a = AddAsteroidWithAttribs(CoordX[roid],CoordY[roid],0.5,0.5,1)
a.Owner = 1
a.TreeCap = 6
a:SetRadius(roidradius[roid])
a:Reveal(1)
a.Moveable = False
a:AddSeedlings(60)
a:AddDysonTree()
-- ** counter for gravity behaviour divisions, do not remove **
wellonlythreshold = roid + 1
-- **
-- ***
-- 2. THE BELOW ASTEROIDS HAVE A GRAVITY WELL, AND MOVE
-- ***
-- Asteroid 1 - A moving asteroid
-- gravity variables
name = 0
for setcollide = 0, 25 do
collidedbefore[setcollide] = 0
end
for makeroids = 1,25 do
roid = makeroids
AccelerationX[roid] = 0
AccelerationY[roid] = 0
CoordX[roid] = math.random(-15000,15000)
CoordY[roid] = math.random(-15000,15000)
oldCoordX[roid] = CoordX[roid]
oldCoordY[roid] = CoordY[roid]
if CoordX[roid] < 0 then
MomentumY[roid] = math.random(1,5)
else
MomentumY[roid] = math.random(-5,1)
end
if CoordY[roid] < 0 then
MomentumX[roid] = math.random(-5,1)
else
MomentumX[roid] = math.random(1,5)
end
density[roid] = 1
roidradius[roid] = math.random(110,260)
str[roid] = (math.random(1,10) / 10) * (roidradius[roid] / 260)
ene[roid] = (math.random(1,10) / 10) * (roidradius[roid] / 260)
spe[roid] = (math.random(1,10) / 10) * (roidradius[roid] / 260)
-- Creation
a = AddAsteroidWithAttribs(CoordX[roid],CoordY[roid],str[roid],ene[roid],spe[roid])
a.Owner = 2
a.TreeCap = 4
a:SetRadius(roidradius[roid])
a:Reveal(1)
a.Moveable = False
name = name + 1
a.Name = name
end
GetAsteroid(2):AddSeedlings(250, 2, 0.1, 0.1, 1)
-- ** counter for gravity behaviour divisions, do not remove **
gravroidsthreshold = roid
-- **
-- 3. THE BELOW ASTEROIDS DO NOT MOVE AND DO NOT HAVE A GRAVITY WELL
-- spacer asteroid, used to make sure the level is big enough for asteroids to wander about on long, eliptical orbits. Change to taste.
a = AddAsteroidWithAttribs(55000,5000,0.5,0.5,0.5)
a.Owner = 0
a.TreeCap = 4
a:SetRadius(1)
a.Moveable = False
roidnumber = roid
-- END ASTEROID CREATION
-- START AI ENGINE INITIALISATION
rcolour = 0
endfinal = false
finality = false
dangertimer = {}
purgetimer = 0
for dset = 0,roidnumber do
dangertimer[dset] = GetGameTime() - 90
end
danger = {}
torchlit = {}
constructionmetric = {}
gathermetric = {}
gatherexists = 0
gatherpoint = GetAsteroid(33)
-- END AI ENGINE INITIALISATION
timeoff = false
end
function LevelDraw()
-- left line
Line1x1 = -18000
Line1y1 = -18000
Line1x2 = -18000
Line1y2 = 18000
-- bottom line
Line2x1 = -18000
Line2y1 = -18000
Line2x2 = 18000
Line2y2 = -18000
-- right line
Line3x1 = 18000
Line3y1 = -18000
Line3x2 = 18000
Line3y2 = 18000
-- top line
Line4x1 = -18000
Line4y1 = 18000
Line4x2 = 18000
Line4y2 = 18000
DrawLine(Line1x1,Line1y1,Line1x2,Line1y2,0,0,1,1,0,1,0,1,20)
DrawLine(Line2x1,Line2y1,Line2x2,Line2y2,0,0,1,1,0,1,0,1,20)
DrawLine(Line3x1,Line3y1,Line3x2,Line3y2,0,0,1,1,0,1,0,1,20)
DrawLine(Line4x1,Line4y1,Line4x2,Line4y2,0,0,1,1,0,1,0,1,20)
end
function LevelLogic()
-- Zoom the camera
SetCameraZoom(9)
-- *** Set the send distances you want for each asteroid here.
-- *** I know you normally do it in Level Setup but in gravityland we do it here.
GetAsteroid(0).SendDistance = 6000
for ii = 1,roidnumber do
GetAsteroid(ii).SendDistance = 500 + roidradius[ii] * 10
end
-- *** End setting of send distances
while GameRunning() do
-- *** YOUR LOOPED COMMANDS GO HERE *** --
for wrap = 0,roidnumber do
if CoordX[wrap] > 18000 then
CoordX[wrap] = -18000
end
if CoordY[wrap] > 18000 then
CoordY[wrap] = -18000
end
if CoordX[wrap] < -18000 then
CoordX[wrap] = 18000
end
if CoordY[wrap] < -18000 then
CoordY[wrap] = 18000
end
end
-- Make the asteroids appear, one by one...
-- for slow = 0,roidnumber do
-- if MomentumX[slow] > 15 or MomentumX[slow] < -15 then
-- MomentumX[slow] = MomentumX[slow] * 0.98
-- end
-- if MomentumY[slow] > 15 or MomentumY[slow] < -15 then
-- MomentumY[slow] = MomentumY[slow] * 0.98
-- end
-- end
-- *** YOUR LOOPED COMMANDS END HERE *** ---
-- START GRAVITY ENGINE
-- change things below this line at your own peril!!
-- Rate Limiter - necessary to pause gravity simulation if the game is paused.
if GetGameTime() > Timer + 0.0 then
Timer = GetGameTime()
-- Get values for the the array
for i = 0, gravroidsthreshold do
for j = i + 1, gravroidsthreshold do
-- calculate Fgx and Fgy between i and j, then...
Fgx = (G * ((roidradius[i] * roidradius[i]) * math.pi * density[i]) * ((roidradius[j] * roidradius[j]) * math.pi * density[j])) / ((CoordX[j] - CoordX[i])^2 + (CoordY[j] - CoordY[i])^2)
Fgy = (G * ((roidradius[i] * roidradius[i]) * math.pi * density[i]) * ((roidradius[j] * roidradius[j]) * math.pi * density[j])) / ((CoordX[j] - CoordX[i])^2 + (CoordY[j] - CoordY[i])^2)
-- now we have the force of gravity x and y, as a scalar. we must find the direction to point in:
xdiff = CoordX[j] - CoordX[i]
ydiff = CoordY[j] - CoordY[i]
-- find the length of the vector..
vectorlength = math.sqrt(xdiff^2 + ydiff^2)
-- divide the vectors by the length to normalise
NormalisedVectorX = xdiff / vectorlength
NormalisedVectorY = ydiff / vectorlength
-- these normalised vectors are values between 0 and 1 that give us a direction :>
-- check if there has been a collision
-- if collision = true then
comboradius = roidradius[i] + roidradius[j]
if collision[i] ~= true then
collision[i] = false
end
if collision[j] ~= true then
collision[j] = false
end
if math.sqrt(((CoordX[j] - CoordX[i])^2 + (CoordY[j] - CoordY[i])^2)) < comboradius then
-- a collision has occurred!
-- update the positions of the colliding (and overlapping) roids to the positions from the previous cycle (lazy method)
-- CoordX[i] = oldCoordX[i]
-- CoordY[i] = oldCoordY[i]
-- CoordX[j] = oldCoordX[j]
-- CoordY[j] = oldCoordY[j]
-- modify momentum for bounce values
collidedbefore[i] = collidedbefore[i] + 1
collidedbefore[j] = collidedbefore[j] + 1
collision[j] = true
collision[i] = true
-- first up, what's the total mass of these colliding objects?
imass = math.pi * roidradius[i] * roidradius[i]
jmass = math.pi * roidradius[j] * roidradius[j]
totalmass = imass + jmass
-- change the momentums of both roids for the bounce.
if collidedbefore[i] < 2 and collidedbefore[j] < 2 then
-- These asteroids are not stuck together - bounce them.
dx = MomentumX[i] - MomentumX[j]
dy = MomentumY[i] - MomentumY[j]
collision_angle = math.atan2(dx, dy)
magnitude_1 = math.sqrt((MomentumX[i] * MomentumX[i]) + (MomentumY[i] * MomentumY[i]))
magnitude_2 = math.sqrt((MomentumX[j] * MomentumX[j]) + (MomentumY[j] * MomentumY[j]))
direction_1 = math.atan2(MomentumY[i], MomentumX[i])
direction_2 = math.atan2(MomentumY[j], MomentumX[j])
new_xspeed_1 = 1.05 * magnitude_1 * math.cos(direction_1 - collision_angle)
new_yspeed_1 = 1.05 * magnitude_1 * math.sin(direction_1 - collision_angle)
new_xspeed_2 = 1.05 * magnitude_2 * math.cos(direction_2 - collision_angle)
new_yspeed_2 = 1.05 * magnitude_2 * math.sin(direction_2 - collision_angle)
final_xspeed_1 = ((imass - jmass) * new_xspeed_1 + (jmass + jmass) * new_xspeed_2) / totalmass
final_xspeed_2 = ((imass + imass) * new_xspeed_1 + (jmass - imass) * new_xspeed_2) / totalmass
final_yspeed_1 = new_yspeed_1
final_yspeed_2 = new_yspeed_2
MomentumX[i] = math.cos(collision_angle) * final_xspeed_1 + math.cos(collision_angle + math.pi / 2) * final_yspeed_1
MomentumY[i] = math.sin(collision_angle) * final_xspeed_1 + math.sin(collision_angle + math.pi / 2) * final_yspeed_1
MomentumX[j] = math.cos(collision_angle) * final_xspeed_2 + math.cos(collision_angle + math.pi / 2) * final_yspeed_2
MomentumY[j] = math.sin(collision_angle) * final_xspeed_2 + math.sin(collision_angle + math.pi / 2) * final_yspeed_2
else
-- These asteroids are stuck together - don't bounce.
end
-- ..Now add the appropriate amount of acceleration
AccelerationX[i] = AccelerationX[i] + (NormalisedVectorX * Fgx / ((roidradius[i] * roidradius[i]) * math.pi) * density[i])
AccelerationY[i] = AccelerationY[i] + (NormalisedVectorY * Fgy / ((roidradius[i] * roidradius[i]) * math.pi) * density[i])
xdiff = CoordX[i] - CoordX[j]
ydiff = CoordY[i] - CoordY[j]
NormalisedVectorX = xdiff / vectorlength
NormalisedVectorY = ydiff / vectorlength
AccelerationX[j] = AccelerationX[j] + (NormalisedVectorX * Fgx / ((roidradius[j] * roidradius[j]) * math.pi) * density[j])
AccelerationY[j] = AccelerationY[j] + (NormalisedVectorY * Fgy / ((roidradius[j] * roidradius[j]) * math.pi) * density[j])
else
collidedbefore[i] = 0
collidedbefore[j] = 0
-- else if there wasn't a collision then
-- ..add the appropriate amount of acceleration as normal
AccelerationX[i] = AccelerationX[i] + (NormalisedVectorX * Fgx / ((roidradius[i] * roidradius[i]) * math.pi) * density[i])
AccelerationY[i] = AccelerationY[i] + (NormalisedVectorY * Fgy / ((roidradius[i] * roidradius[i]) * math.pi) * density[i])
xdiff = CoordX[i] - CoordX[j]
ydiff = CoordY[i] - CoordY[j]
NormalisedVectorX = xdiff / vectorlength
NormalisedVectorY = ydiff / vectorlength
AccelerationX[j] = AccelerationX[j] + (NormalisedVectorX * Fgx / ((roidradius[j] * roidradius[j]) * math.pi) * density[j])
AccelerationY[j] = AccelerationY[j] + (NormalisedVectorY * Fgy / ((roidradius[j] * roidradius[j]) * math.pi) * density[j])
end
end
end
for pass = wellonlythreshold,gravroidsthreshold do
MomentumX[pass] = MomentumX[pass] + AccelerationX[pass]
MomentumY[pass] = MomentumY[pass] + AccelerationY[pass]
-- national speed limit
if math.sqrt(MomentumX[pass]^2 + MomentumY[pass]^2) > 160 then
MomentumX[pass] = MomentumX[pass] * 0.93
MomentumY[pass] = MomentumY[pass] * 0.93
end
if math.sqrt(MomentumX[pass]^2 + MomentumY[pass]^2) > 60 then
MomentumX[pass] = MomentumX[pass] * 0.98
MomentumY[pass] = MomentumY[pass] * 0.98
end
if math.sqrt(MomentumX[pass]^2 + MomentumY[pass]^2) > 10 then
MomentumX[pass] = MomentumX[pass] * 0.999
MomentumY[pass] = MomentumY[pass] * 0.999
end
-- MOVE GETASTEROID(PASS) by MomentumX and MomentumY
if collision[pass] == false then
oldCoordX[pass] = CoordX[pass]
oldCoordY[pass] = CoordX[pass]
end
CoordX[pass] = CoordX[pass] + MomentumX[pass]
CoordY[pass] = CoordY[pass] + MomentumY[pass]
GetAsteroid(pass):MoveTo(CoordX[pass], CoordY[pass])
AccelerationX[pass] = 0
AccelerationY[pass] = 0
end
end
-- END GRAVITY ENGINE
-- *** START INFECTED AI ENGINE *** --
if rcolour > 0 then
rcolour = rcolour - 1
end
--SetBackdropColour(rcolour,0,0)
--AI
for check = 0,roidnumber do
checkedroid = GetAsteroid(check)
if GetGameTime() > purgetimer + 35 then
purgetimer = 0
end
-- First, find out which asteroids are close enough to travel in 1 jump, and
traversable = {}
pathsavailable = 0
attackable = {}
attackpaths = 0
actiontaken = 0
increasemetricvote = 1
increasegathermetricvote = 1
confirmedzero = 0
confirmedgatherpoint = 0
if GetEmpire(2):OwnsAsteroidID(checkedroid.ID) then
-- MINE CHECK NOT REQUIRED IN THIS MAP
--if checkedroid:GetNumSeedlings(1) == 0 and checkedroid:GetNumSeedlings(2) > 5 then
-- for minecheck = 0,roidnumber do
-- if GetEmpire(2):OwnsAsteroidID(minecheck) == true and GetAsteroid(minecheck):GetNumMines(1) > 0 and checkedroid:GetNumMines(1) == 0 then
-- checkedroid:SendSeedlingsToTarget(2,checkedroid:GetNumSeedlings(2),GetAsteroid(minecheck))
-- end
-- end
--end
for u = 0,roidnumber do
if GetAsteroid(u) ~= checkedroid then
-- only learn about this asteroid if it's not the one being checked
-- can we send seeds to this roid from the checked one?
if (GetAsteroid(checkedroid.ID):GetSendDistance() + roidradius[u]) > math.sqrt(((CoordX[u] - CoordX[checkedroid.ID])^2) + ((CoordY[u] - CoordY[checkedroid.ID])^2)) then
-- we can ! Now is this a friendly path or an attackable path?
if GetEmpire(2):OwnsAsteroidID(u) == false then
attackable[attackpaths] = GetAsteroid(u)
attackpaths = attackpaths + 1
-- moar aggression ! advantage pressing, etc
if checkedroid:GetNumSeedlings(2) > 120 and GetAsteroid(u):GetNumSeedlings(1) < (checkedroid:GetNumSeedlings(2) / 2) and checkedroid:GetNumSeedlings(1) < 10 then
checkedroid:SendSeedlingsToTarget(2,checkedroid:GetNumSeedlings(2),GetAsteroid(u))
if rcolour < 105 then
rcolour = rcolour + 150
end
end
elseif GetAI(2):OwnsAsteroidID(u) == true then
traversable[pathsavailable] = GetAsteroid(u)
pathsavailable = pathsavailable + 1
if GetAsteroid(u):GetNumTrees() < GetAsteroid(u).TreeCap then
constructionmetric[u] = 0
end
else
end
end
-- ok, this roid is not in range for us.
end
-- ok, we were trying to check ourselves.
end
-- end of neighbour-checking sequence
-- end of metric checking sequence
else
torchlit[checkedroid.ID] = nil
constructionmetric[checkedroid.ID] = nil
if checkedroid.ID ~= 4 or checkedroid.ID ~= 5 then
gathermetric[checkedroid.ID] = nil
end
end
-- we have selected "checkedroid" for checking. We must find out all we can about the asteroid and it's surroundings, and act appropriately.
if GetAI(2):OwnsAsteroidID(checkedroid.ID) == true and checkedroid:GetNumMines(1) > 0 then
-- do buggerysquat.
elseif GetAI(2):OwnsAsteroidID(checkedroid.ID) == true then
-- this roid is ours ! :>
-- if pathsavailable == 0 then
-- Orphan Control
-- boltfriendly = GetEmpire(2):GetRandomAsteroid()
-- letsgo = 0
-- for iii = 0,attackpaths do
-- if attackable[iii] ~= nil then
-- letsgo = letsgo + (attackable[iii]:GetNumSeedlings(1))
-- end
-- end
-- if letsgo > checkedroid:GetNumSeedlings(2) and checkedroid:GetNumSeedlings(2) > 10 and checkedroid:GetNumSeedlings(2) < 39 then
-- checkedroid:SendSeedlingsToTarget(2,checkedroid:GetNumSeedlings(2),boltfriendly)
-- elseif letsgo < checkedroid:GetNumSeedlings(2) and checkedroid:GetNumSeedlings(2) > (39 + (attackable[0]:GetNumDysonTrees() * 5) + (attackable[0]:GetNumDefenseTrees() * 15)) then
-- checkedroid:SendSeedlingsToTarget(2,checkedroid:GetNumSeedlings(2),attackable[0])
-- if rcolour < 105 then
-- rcolour = rcolour + 150
-- end
-- elseif attackable[0]:GetNumSeedlings(2) > 5 then
-- checkedroid:SendSeedlingsToTarget(2,checkedroid:GetNumSeedlings(2),attackable[0])
-- end
-- end
-- how many player seedlings are here?
-- more than what we have, and enough to be dangerous. Also, we do have at least 1 tree here, right?
if checkedroid:GetNumSeedlings(2) < checkedroid:GetNumSeedlings(1) and checkedroid:GetNumSeedlings(1) > 10 and checkedroid:GetNumTrees() > 0 then
-- *** WE OWN THIS ASTEROID, THE ENEMY OUTNUMBER US. WE HAVE AT LEAST ONE TREE HERE. We are under attack. torchmetric 0! ***
torchlit[checkedroid.ID] = 0
-- ***
-- elseif checkedroid:GetNumSeedlings(2) < checkedroid:GetNumSeedlings(1) and checkedroid:GetNumSeedlings(1) > 10 and checkedroid:GetNumTrees() == 0 then
-- *** ITS A FALSE ALARM....but dont try to build here unless the player leaves. ***
--torchlit[checkedroid.ID] = nil
--constructionmetric[checkedroid.ID] = nil
-- but once we get a bit more powerful, we can have a crack at it :>
-- if purgetimer == 0 then
-- purgetimer = GetGameTime() + 30
-- end
-- if GetGameTime() > purgetimer then
-- torchlit[checkedroid.ID] = 0
--for purge = 0,roidnumber do
-- if GetEmpire(2):OwnsAsteroidID(purge) == true and torchlit[purge] == nil and GetGameTime() > purgetimer + 45 then
--GetAsteroid(purge):SendSeedlingsToTarget(2,checkedroid:GetNumSeedlings(1),checkedroid)
-- if rcolour < 105 then
-- rcolour = rcolour + 150
-- end
-- end
-- end
-- purgetimer = 0
-- end
-- ***
-- more than zero but less than what we have
elseif checkedroid:GetNumSeedlings(1) > 0 and checkedroid:GetNumSeedlings(2) > checkedroid:GetNumSeedlings(1) then
-- *** WE OWN THIS ASTEROID, THERE ARE ENEMIES BUT WE OUTNUMBER THEM. Not elligible for sending reinforcements to other asteroids, but not in serious danger either. ***
-- ***
-- No enemies here at all.
elseif checkedroid:GetNumSeedlings(1) < 1 then
-- how many of our seedlings are here?
if checkedroid:GetNumSeedlings(2) > 1 then
-- 1 or more
--how many trees are here?
if checkedroid:GetNumTrees() < checkedroid.TreeCap and checkedroid:GetNumSeedlings(2) > 9 then
-- less than four trees
-- *** WE OWN THIS ASTEROID, THERE ARE NO ENEMIES HERE. WE HAVE AT LEAST 10 SEEDLINGS AND LESS THAN 4 TREES. Plant a tree. ***
-- but... is the enemy building up a force nearby, ready to take our freshly built trees..?
danger[checkedroid.ID] = false
for ooo = 0,roidnumber do
if GetEmpire(1):OwnsAsteroidID(ooo) and GetAsteroid(ooo):GetSendDistance() > math.sqrt(((CoordX[ooo] - CoordX[checkedroid.ID])^2) + ((CoordY[ooo] - CoordY[checkedroid.ID])^2)) then
if GetAsteroid(ooo):GetNumSeedlings(1) > 150 then
danger[checkedroid.ID] = true
dangertimer[checkedroid.ID] = GetGameTime()
end
end
end
if danger[checkedroid.ID] == true and checkedroid:GetNumSeedlings(2) > 12 then
checkedroid:PlantDysonTree(2)
elseif danger[checkedroid.ID] == false and GetGameTime() > dangertimer[checkedroid.ID] + 5 then
checkedroid:PlantDysonTree(2)
end
-- ***
elseif checkedroid:GetNumTrees() == checkedroid.TreeCap then
-- max trees. ELLIGIBLE FOR SENDING REINFORCEMENTS!
if constructionmetric[checkedroid.ID] == 0 then
-- we just built the last tree. now we should stop advertising to neighbours that we need more seedlings for construction.
constructionmetric[checkedroid.ID] = nil
end
-- is my torch metric nil?
if torchlit[checkedroid.ID] ~= nil then
-- no, my torch metric is not Nil.
-- is my torch metric 0? Cause, like, I don't have any enemies orbiting me dudez...
if torchlit[checkedroid.ID] == 0 then
-- *** ok, so my torch metric is 0 but there are no enemies here. Switch all torches off....if other roids are under attack they will just switch theirs on again straight away. ***
-- *** this step is needed to prevent the rest of the torch metrics from spiralling upward out of control. ***
for g = 0,roidnumber do
torchlit[g] = nil
end
-- ***
else
-- so my torch IS lit, but it's value is NOT zero. checkedroid is not nil and not 0.
totm = true
for ooo = 0,pathsavailable do
if traversable[ooo] ~= nil then
trav = traversable[ooo]
hopIDint = trav.ID
if torchlit[hopIDint] == 0 and GetGameTime() < 180 then
for emerg = 0,roidnumber do
if GetEmpire(2):OwnsAsteroidID(emerg) == true then
GetAsteroid(emerg):SendSeedlingsToTarget(2,GetAsteroid(emerg):GetNumSeedlings(2),traversable[ooo])
end
end
totm = false
elseif torchlit[hopIDint] == 0 then
-- *** WE HAVE FOUND A NEIGHBOUR THAT HAS A ROUTE TO AN ASTEROID IN NEED OF DEFENCE. Send seedlings ***
if GetAsteroid(hopIDint):GetNumSeedlings(1) < 10 then
checkedroid:SendSeedlingsToTarget(2,checkedroid:GetNumSeedlings(2),traversable[ooo])
elseif GetAsteroid(hopIDint):GetNumSeedlings(2) > GetAsteroid(hopIDint):GetNumSeedlings(1) * 0.6 then
checkedroid:SendSeedlingsToTarget(2,checkedroid:GetNumSeedlings(2),traversable[ooo])
elseif checkedroid:GetNumSeedlings(2) > (GetEmpire(2).NumSeedlings / 20) then
checkedroid:SendSeedlingsToTarget(2,checkedroid:GetNumSeedlings(2),traversable[ooo])
end
totm = false
torchlit[checkedroid.ID] = 1
-- elseif torchlit[checkedroid.ID] == nil then
-- totm = false
-- torchlit[checkedroid.ID] = torchlit[hopIDint] + 1
-- shortestpath = hopIDint
elseif torchlit[hopIDint] == nil then
-- do nothing, maybe there's no more attack and the metric should be turned off.
-- my torch metric is already non-nil, so set mine to be his + 1 if he has a shorter path than me.
elseif torchlit[hopIDint] < torchlit[checkedroid.ID] - 1 then
totm = false
torchlit[checkedroid.ID] = torchlit[hopIDint] + 1
shortestpath = hopIDint
checkedroid:SendSeedlingsToTarget(2,checkedroid:GetNumSeedlings(2),traversable[ooo])
elseif torchlit[hopIDint] == torchlit[checkedroid.ID] - 1 then
totm = false
torchlit[checkedroid.ID] = torchlit[hopIDint] + 1
shortestpath = hopIDint
checkedroid:SendSeedlingsToTarget(2,checkedroid:GetNumSeedlings(2),traversable[ooo])
end
end
end
-- *** WE OWN THIS ASTEROID. THERE ARE NO ENEMIES HERE. WE HAVE AT LEAST 10 SEEDLINGS AND MAXIMUM TREES. OUR TORCH METRIC INDICATES ***
-- *** THAT A NEARBY ASTEROID REQUIRES SEEDLINGS FOR DEFENSE. Find a neighbour with the lower metric and send 10 seedlings there. ***
end
elseif torchlit[checkedroid.ID] == nil then
-- yes my torch metric is nil, now lets see if any neighbours have a torch metric of 0..
totm = true
for ooo = 0,pathsavailable do
if traversable[ooo] ~= nil then
trav = traversable[ooo]
hopIDint = trav.ID
if torchlit[hopIDint] == 0 then
-- *** WE HAVE FOUND A NEIGHBOUR THAT NEEDS MORE SEEDS TO DEFEND WITH. Send 10 seedlings, or more if we have them available. ***
checkedroid:SendSeedlingsToTarget(2,((checkedroid:GetNumSeedlings(2)/pathsavailable) + 10),traversable[ooo])
totm = false
torchlit[checkedroid.ID] = 1
elseif torchlit[hopIDint] ~= nil then
if torchlit[hopIDint] > 0 then
-- seedlings needed in this direction!
-- my torch metric is nil at the moment, so set it to his + 1.
if torchlit[checkedroid.ID] == nil then
totm = false
torchlit[checkedroid.ID] = torchlit[hopIDint] + 1
shortestpath = hopIDint
end
-- my torch metric is already non-nil, so set mine to be his + 1 if he has a shorter path than me.
if torchlit[hopIDint] < torchlit[checkedroid.ID] - 1 then
totm = false
torchlit[checkedroid.ID] = torchlit[hopIDint] + 1
shortestpath = hopIDint
end
end
end
end
end
-- send seeds along the shortest torch path
if torchlit[checkedroid.ID] ~= nil then
if torchlit[checkedroid.ID] > 1 then
checkedroid:SendSeedlingsToTarget(2,((checkedroid:GetNumSeedlings(2)/pathsavailable) + 10),GetAsteroid(shortestpath))
end
end
if totm == true and torchlit[checkedroid.ID] ~= nil then
torchlit[checkedroid.ID] = nil
end
-- check if we are still under attack on any asteroids
stillattacked = false
for o = 0,roidnumber do
if GetAsteroid(o):GetNumTrees() > 0 and GetAI(2):OwnsAsteroidID(o) and GetAsteroid(o):GetNumSeedlings(1) > 1 then
stillattacked = true
end
end
if stillattacked == false then
for l = 0,roidnumber do
torchlit[l] = nil
end
end
-- yes, my torch metric is Nil and so is all my neighbours' - check my construction metric next.
-- turn off construction metric
tocm = true
for cc = 0,pathsavailable do
if traversable[cc] ~= nil then
trav = traversable[cc]
hopIDint = trav.ID
if constructionmetric[hopIDint] == 0 and GetAsteroid(hopIDint):GetNumSeedlings(1) < 8 then
-- *** WE HAVE FOUND A NEIGHBOUR THAT NEEDS MORE SEEDS TO BUILD WITH. Send 10 seedlings, or more if we have them available. ***
checkedroid:SendSeedlingsToTarget(2,((checkedroid:GetNumSeedlings(2)/pathsavailable) + 10),traversable[cc])
tocm = false
constructionmetric[checkedroid.ID] = 1
elseif danger[checkedroid.ID] == true or GetGameTime() < (dangertimer[checkedroid.ID] + 90) then
-- *** WAIT A BIT... THERE'S STILL A BIG FORCE NEARBY ***
tocm = false
constructionmetric[checkedroid.ID] = 1
elseif constructionmetric[hopIDint] ~= nil then
if constructionmetric[hopIDint] >= 0 then
-- seedlings needed in this direction!
-- my construction metric is nil at the moment, so set it to his + 1.
if constructionmetric[checkedroid.ID] == nil then
tocm = false
constructionmetric[checkedroid.ID] = constructionmetric[hopIDint] + 1
shortestpath = hopIDint
end
-- my construction metric is already non-nil, so set mine to be his + 1 if he has a shorter path than me.
if constructionmetric[hopIDint] < constructionmetric[checkedroid.ID] - 1 then
tocm = false
constructionmetric[checkedroid.ID] = constructionmetric[hopIDint] + 1
shortestpath = hopIDint
end
end
end
end
end
-- send seeds along the shortest construction path
if constructionmetric[checkedroid.ID] ~= nil then
if constructionmetric[checkedroid.ID] > 1 then
checkedroid:SendSeedlingsToTarget(2,((checkedroid:GetNumSeedlings(2)/pathsavailable) + 10),GetAsteroid(shortestpath))
end
end
if tocm == true and constructionmetric[checkedroid.ID] ~= nil then
constructionmetric[checkedroid.ID] = nil
end
-- check if we are finished building trees on all asteroids
stillbuilding = false
for o = 0,roidnumber do
if GetAsteroid(o):GetNumTrees() < GetAsteroid(o).TreeCap and GetAI(2):OwnsAsteroidID(o) then
stillbuilding = true
end
end
if stillbuilding == false then
for l = 0,roidnumber do
constructionmetric[l] = nil
end
end
end
-- ok, we didn't hit on torch metric or construction metric. So lets do some gathering instead.
if torchlit[checkedroid.ID] == nil and constructionmetric[checkedroid.ID] == nil and GetGameTime() > 6 then
-- is there already a gather point?
-- gatherexists = 0
gathertrue = false
for h = 0,roidnumber do
if gathermetric[h] == 0 then
gatherexists = 1
gathertrue = true
end
end
if gathertrue == false then
gatherexists = 0
end
-- there's no gather point at the moment.
if gatherexists == 0 then
-- ok, is there at least one player-owned asteroid and one traversable asteroid within my send distance?
if pathsavailable > 0 and attackpaths > 0 then
-- yep.
-- *** THEN I'M THE NEW GATHER POINT!! Bringin all the seedlings to the yard, y0. ***
gathermetric[checkedroid.ID] = 0
gatherexists = 1
-- MessageBox("new gather point")
--MessageBox(checkedroid.ID)
else
-- nope.
-- *** I CAN'T BE THE GATHER POINT because I am totally surrounded by either all friendly neighbours or all enemy asteroids. ***
end
if gathermetric[checkedroid.ID] ~= nil then
-- no, my gather metric is not Nil.
-- so my torch IS lit, but it's value is NOT zero.
for ddd = 0,pathsavailable do
if traversable[ddd] ~= nil then
trav = traversable[ddd]
hopIDint = trav.ID
if gathermetric[hopIDint] == 0 then
-- *** WE HAVE FOUND A NEIGHBOUR THAT HAS A ROUTE TO AN ASTEROID IN NEED OF SEEDS. Send 10 seedlings, or more if we have them available. ***
checkedroid:SendSeedlingsToTarget(2,((checkedroid:GetNumSeedlings(2)/pathsavailable) + 10),traversable[ddd])
gathermetric[checkedroid.ID] = 1
electiontimer = GetGameTime()
elseif gathermetric[hopIDint] ~= nil then
if gathermetric[hopIDint] > 0 then
-- both checkedroid and the neighbour we are looking at have a gather metric set. Also, the neighbour has a metric of at least 1.
-- seedlings needed in this direction!
-- my gather metric is already non-nil, so set mine to be his + 1 if he has a shorter path than me.
if gathermetric[hopIDint] < gathermetric[checkedroid.ID] - 1 then
gathermetric[checkedroid.ID] = gathermetric[hopIDint] + 1
shortestpath = hopIDint
elseif gathermetric[hopIDint] == gathermetric[checkedroid.ID] - 1 then
if shortestpath == nil then
shortestpath = hopIDint
end
if gathermetric[shortestpath] ~= nil then
if gathermetric[hopIDint] < gathermetric[shortestpath] then
shortestpath = hopIDint
end
end
end
end
end
end
end
if gathermetric[checkedroid.ID] ~= nil and gathermetric[shortestpath] ~= nil then
if gathermetric[shortestpath] < gathermetric[checkedroid.ID] then
checkedroid:SendSeedlingsToTarget(2,((checkedroid:GetNumSeedlings(2)/pathsavailable) + 10),GetAsteroid(shortestpath))
end
end
-- *** WE OWN THIS ASTEROID. THERE ARE NO ENEMIES HERE. WE HAVE AT LEAST 10 SEEDLINGS AND MAXIMUM TREES. OUR TORCH METRIC INDICATES ***
-- *** THAT A NEARBY ASTEROID REQUIRES SEEDLINGS FOR DEFENSE. Find a neighbour with the lower metric and send 10 seedlings there. ***
elseif gathermetric[checkedroid.ID] == nil then
-- yes my gather metric is nil, now lets see if any neighbours have a gather metric of 0..
for ddd = 0,pathsavailable do
if traversable[ddd] ~= nil then
trav = traversable[ddd]
hopIDint = trav.ID
if gathermetric[hopIDint] == 0 then
-- *** WE HAVE FOUND A NEIGHBOUR THAT IS A GATHER POINT. Send 10 seedlings, or more if we have them available. ***
checkedroid:SendSeedlingsToTarget(2,((checkedroid:GetNumSeedlings(2)/pathsavailable) + 10),traversable[ddd])
gathermetric[checkedroid.ID] = 1
elseif gathermetric[hopIDint] ~= nil then
if gathermetric[hopIDint] > 0 then
-- seedlings needed in this direction!
-- my gather metric is nil at the moment, so set it to his + 1.
if shortestpath == nil then
shortestpath = hopIDint
end
gathermetric[checkedroid.ID] = gathermetric[hopIDint] + 1
end
end
end
end
end
-- a gather point already exists.
else
-- Am I the gather point?
if gathermetric[checkedroid.ID] == 0 then
-- I AM the gather point! :>
-- is there still at least 1 player asteroid and 1 friendly asteroid nearby?
--validpath = 0
--validattack = 0
--for i = 0,pathsavailable do
-- if traversable[i] ~= nil then
-- travv = traversable[i]
-- travvy = travv.ID
-- if GetAI(2):OwnsAsteroidID(travvy) == true then
-- there's at least one friendly asteroid nearby.
-- validpath = 1
-- end
-- if GetAI(2):OwnsAsteroidID(travvy) == false then
-- there's at least one player asteroid nearby.
-- validattack = 1
-- end
-- end
--end
if attackpaths > 0 and pathsavailable > 0 then
-- yes, there's at least 1 friendly and 1 enemy asteroid nearby.
-- add up all the player seedlings in the nearby enemy systems. Do I have at least that, plus 50?
totalseeds = 50
currentlowest = 9000
attackpaths = attackpaths - 1
for j = 0,attackpaths do
totalseeds = totalseeds + attackable[j]:GetNumSeedlings(1)
-- this bit checks which of the asteroids has the lowest number of seedlings.
if attackable[j]:GetNumSeedlings(1) < currentlowest then
currentlowest = attackable[j]:GetNumSeedlings(1)
RAPETARGET = attackable[j]
end
end
-- "if i have more seeds than the enemy does, then..."
if checkedroid:GetNumSeedlings(2) > totalseeds + (RAPETARGET:GetNumDysonTrees() * 5) + (RAPETARGET:GetNumDefenseTrees() * 23) then
if checkedroid:GetNumSeedlings(1) < 15 then
checkedroid:SendSeedlingsToTarget(2,checkedroid:GetNumSeedlings(2),RAPETARGET)
if rcolour < 105 then
rcolour = rcolour + 150
end
end
--MessageBox("Rape time!")
-- *** RAEP TIEM!!!"!"
elseif checkedroid:GetNumSeedlings(2) > 1000 and checkedroid:GetNumSeedlings(1) == 0 then
-- if i have silly numbers of seeds, just gogo anyway.
if checkedroid:GetNumSeedlings(1) < 15 then
checkedroid:SendSeedlingsToTarget(2,checkedroid:GetNumSeedlings(2),RAPETARGET)
if rcolour < 105 then
rcolour = rcolour + 150
end
end
else
-- *** Hold, precious... we have not enough seeds yet to launch an attack... ***
-- ***
end
-- this bit checks if we have a "Cold War" situation on our hands - if so, we'd be better off moving to a different gather point with less player defenses nearby.
-- if totalseeds > 300 and totalseeds > checkedroid:GetNumSeedlings(2) and GetEmpire(1):GetNumOwnedAsteroids() > attackpaths + 1 then
-- MessageBox("ColdWar Detected - reset gather point")
-- for gathreset = 0,roidnumber do
-- gathermetric[gathreset] = nil
-- end
-- gatherexists = 0
-- end
else
-- *** I AM NO LONGER A SUITABLE GATHER POINT. RESET ALL GATHER POINTS
for r = 6,roidnumber do
gathermetric[r] = nil
end
gatherexists = 0
-- ***
end
else
-- I am not the gather point. :<
-- so send some seedlings to whichever traversable asteroid has the lowest gather metric.
-- ADD SOEM CODE HERE DRUIDS
if gathermetric[checkedroid.ID] ~= nil then
-- no, my gather metric is not Nil.
-- so my torch IS lit, but it's value is NOT zero.
for ddd = 0,pathsavailable do
if traversable[ddd] ~= nil then
trav = traversable[ddd]
hopIDint = trav.ID
if gathermetric[hopIDint] == 0 then
-- *** WE HAVE FOUND A NEIGHBOUR THAT HAS A ROUTE TO AN ASTEROID IN NEED OF SEEDS. Send 10 seedlings, or more if we have them available. ***
checkedroid:SendSeedlingsToTarget(2,((checkedroid:GetNumSeedlings(2)/pathsavailable) + 10),traversable[ddd])
gathermetric[checkedroid.ID] = 1
electiontimer = GetGameTime()
elseif gathermetric[hopIDint] ~= nil then
if gathermetric[hopIDint] > 0 then
-- both checkedroid and the neighbour we are looking at have a gather metric set. Also, the neighbour has a metric of at least 1.
-- seedlings needed in this direction!
-- my gather metric is already non-nil, so set mine to be his + 1 if he has a shorter path than me.
if gathermetric[hopIDint] < gathermetric[checkedroid.ID] - 1 then
gathermetric[checkedroid.ID] = gathermetric[hopIDint] + 1
shortestpath = hopIDint
checkedroid:SendSeedlingsToTarget(2,((checkedroid:GetNumSeedlings(2)/pathsavailable) + 10),traversable[ddd])
elseif gathermetric[hopIDint] == gathermetric[checkedroid.ID] - 1 then
if shortestpath == nil then
shortestpath = hopIDint
end
if gathermetric[shortestpath] ~= nil then
if gathermetric[hopIDint] < gathermetric[shortestpath] then
shortestpath = hopIDint
end
end
checkedroid:SendSeedlingsToTarget(2,((checkedroid:GetNumSeedlings(2)/pathsavailable) + 10),traversable[ddd])
end
end
end
end
end
checkedroid:SendSeedlingsToTarget(2,((checkedroid:GetNumSeedlings(2)/pathsavailable) + 10),GetAsteroid(shortestpath))
-- *** WE OWN THIS ASTEROID. THERE ARE NO ENEMIES HERE. WE HAVE AT LEAST 10 SEEDLINGS AND MAXIMUM TREES. OUR TORCH METRIC INDICATES ***
-- *** THAT A NEARBY ASTEROID REQUIRES SEEDLINGS FOR DEFENSE. Find a neighbour with the lower metric and send 10 seedlings there. ***
elseif gathermetric[checkedroid.ID] == nil then
-- yes my gather metric is nil, now lets see if any neighbours have a gather metric of 0..
for ddd = 0,pathsavailable do
if traversable[ddd] ~= nil then
trav = traversable[ddd]
hopIDint = trav.ID
if gathermetric[hopIDint] == 0 then
-- *** WE HAVE FOUND A NEIGHBOUR THAT IS A GATHER POINT. Send 10 seedlings, or more if we have them available. ***
checkedroid:SendSeedlingsToTarget(2,((checkedroid:GetNumSeedlings(2)/pathsavailable) + 10),traversable[ddd])
gathermetric[checkedroid.ID] = 1
elseif gathermetric[hopIDint] ~= nil then
if gathermetric[hopIDint] > 0 then
-- seedlings needed in this direction!
-- my gather metric is nil at the moment, so set it to his + 1.
if shortestpath == nil then
shortestpath = hopIDint
end
gathermetric[checkedroid.ID] = gathermetric[hopIDint] + 1
end
end
end
end
end
end
end
end
end
end
-- how many of our seedlings are here?
if checkedroid:GetNumSeedlings(2) < 10 then
-- 9 or less
-- how many trees are here?
if checkedroid:GetNumTrees() < checkedroid.TreeCap then
-- less than four trees
-- *** WE OWN THIS ASTEROID, THERE ARE NO ENEMIES HERE. WE HAVE LESS THAN 10 SEEDLINGS AND LESS THAN 4 TREES. We need seedlings for more trees! Advertise to neighbours that we need some.
constructionmetric[checkedroid.ID] = 0
-- ***
end
end
end
else
-- *** THIS ROID IS NOT OURS, it's a PLAYER asteroid!! Do nothing with it. :> ***
-- ***
end
if GetEmpire(1):GetNumOwnedAsteroids() < 4 and GetEmpire(2).NumSeedlings > 800 and finality == false then
finality = true
for doom = 0,roidnumber do
if GetEmpire(2):OwnsAsteroidID(doom) then
GetAsteroid(doom):SendSeedlingsToTarget(2,GetAsteroid(doom):GetNumSeedlings(2),GetEmpire(1):GetRandomAsteroid())
end
end
end
if electiontimer ~= nil then
if GetGameTime() > electiontimer + 45 then
-- we haven't managed to send any seedlings to a gather point for 45 seconds now. Lets try resetting all the gather metrics to trigger a new gather point election.
for greset = 6,roidnumber do
gathermetric[greset] = nil
end
--MessageBox("Due to low activity a new gather point election was held")
-- lets see if this helps, and seeds now start moving towards the gather point. if it doesn't, hold a new gather point election in 15 seconds.
electiontimer = electiontimer + 45
gatherexists = 0
end
end
gatherzero = false
for gatherzerocheck = 0,roidnumber do
if gathermetric[gatherzerocheck] == 0 then
gatherzero = true
end
end
if gatherzero == false then
gatherexists = 0
end
if GetEmpire(2).NumSeedlings > 8000 and GetEmpire(2):GetNumOwnedAsteroids() > roidnumber / 2 and endfinal == false then
endfinal = true
for final = 0,roidnumber do
if GetEmpire(2):OwnsAsteroidID(final) then
GetAsteroid(final):SendSeedlingsToTarget(2,GetAsteroid(final):GetNumSeedlings(2),GetEmpire(1):GetRandomAsteroid())
end
end
end
end
-- *** END INFECTED AI ENGINE *** --
coroutine.yield()
end
end