New Code Stream for ROFLbot
Posted: Sat Feb 20, 2010 4:54 pm
I basically started over because my placement code was getting messy
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.
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