The new code stream is below. It doesn't place anything yet. All it does is draw REALLY COOL stuff on the whiteboard. To see how cool it is, start a luabot, make yourself one of the old world 4 and make the other 3 enemies.
Everything it plots on the whiteboard is a viable ground installation that is:
1. not ocean
2. on my own territory
3. is > 1.83 from a city
4. is > 20.1 away from enemy territory
...and it works pretty fast too!! all extra functions have been removed for brevity.
Code: Select all
function OnInit()
end
function OnTick()
OnFirstTick()
OnTick = OnTickReal
return OnTick()
end
--enumerate our cities, opponent cities, position, population
function OnFirstTick()
StartLongTask( function()
-- Put Cities and Territories in Tables
myCities ={} -- list of my cities
enemyCities = {} -- list of enemy cities
enemyTerritories = "" -- as we enumerate empty cities, find their territories and concatanate into this string.
local allCities = GetCityIDs() -- all cities in the world
local us = GetOwnTeamID() -- my team ID
for i, city in next, allCities do
if city:GetTeamID() == us then
table.insert(myCities, city)
myTerritoryName = GetTerritoryName(city:GetLongitude(), city:GetLatitude() )
else
table.insert(enemyCities, city)
enemyTerritories = enemyTerritories .. GetTerritoryName(city:GetLongitude(), city:GetLatitude() )
end
end
YieldLongTask()
-- find viable places to place ground stuff.
x = 1.83
while x < 20 do
for i, city in next, myCities do
DrawBurningRingofFire( myCities[i]:GetLongitude() , myCities[i]:GetLatitude(), x )
YieldLongTask()
end
-- x = x + 1
x = x + 1.2
end
end)
end
-- other functions here
function OnTickReal()
WorkOnLongTasks()
-- if GetGameTick() % 60 == 0 then
-- SendChat("Tick" .. GetGameTick())
-- end
end
function OnEvent(eventType, sourceID, targetID, unitType, longitude, latitude)
print(eventType, ",", tostring(sourceID), ",", tostring(targetID), ",", unitType, (", %.3f , %.3f"):format(longitude, latitude))
end
function OnShutdown()
end
-- Simple coroutine management functions
local co, pairs, assert = coroutine, pairs, assert
local long_tasks_in_progress = {}
function StartLongTask(f)
long_tasks_in_progress[co.create(f)] = true
end
function WorkOnLongTasks(...)
for c in pairs(long_tasks_in_progress) do
if co.status(c) == "dead" then
long_tasks_in_progress[c] = nil
else
assert(co.resume(c, ...))
end
end
end
YieldLongTask = co.yield
-- Extra whiteboard function
function DrawWhiteboardCross(x, y, size)
WhiteboardDraw(x - size, y - size, x + size, y + size)
WhiteboardDraw(x - size, y + size, x + size, y - size)
end
-- Proper Distance Calculation
function GetRealDistance(x1,y1,x2,y2)
dist = math.sqrt((x2-x1)^2 + (y2-y1)^2)
return dist
end
-- check for good ground installation site, mark on whiteboard.
function DrawBurningRingofFire(x, y, radius)
valtoocloseCity = 1.82
local segments = 24
local theta_step = math.pi * 2 / segments
local sin, cos = math.sin(theta_step), math.cos(theta_step)
dx = radius
dy = 0
for i = 1, segments do
local nx = cos * dx - sin * dy
local ny = sin * dx + cos * dy
drawflag = false
-- could we place here?
if IsValidPlacementLocation (x + dx, y+ dy, "RadarStation") then
drawflag = true
-- is it too close to one of our cities?
for j, city in ipairs(myCities) do
if GetRealDistance(x +dx, y+dy, myCities[j]:GetLongitude(), myCities[j]:GetLatitude() ) < valtoocloseCity then
drawflag = false
end
end
-- is it too close to one of our enemies?
DrawRadiatingSpokes(x +dx, y+dy,20.1)
end
-- if it isn't in the ocean, on someone else's land, too close to one of our cities
-- or too close to enemy territory, then it's a good spot!!!
if drawflag == true and drawflag1 == true then
DrawWhiteboardCross(x + dx, y + dy, 0.2)
end
dx, dy = nx, ny
end
YieldLongTask()
end
-- find if position is too close to enemy
function DrawRadiatingSpokes(x1, y1, radius)
local segments = 24
local theta_step = math.pi * 2 / segments
local sin, cos = math.sin(theta_step), math.cos(theta_step)
dx1 = radius
dy1 = 0
drawflag1 = true
for i1 = 1, segments do
local nx1 = cos * dx1 - sin * dy1
local ny1 = sin * dx1 + cos * dy1
-- DrawWhiteboardCross(x + dx, y + dy,0.2)
if GetTerritoryName(x1 + dx1, y1 + dy1) ~= nil and GetTerritoryName(x1 + dx1, y1 + dy1) ~= myTerritoryName then
if string.find(enemyTerritories, GetTerritoryName(x1 + dx1, y1 + dy1) ) ~= nil then
-- SendChat(GetTerritoryName(x1 + dx1, y1 + dy1))
drawflag1 = false
return drawflag1
end
end
dx1, dy1 = nx1, ny1
end
dx1 = 0
dy1 = 0
return drawflag1
end