World Scanning
Moderator: Defcon moderators
- roflamingo
- level3
- Posts: 404
- Joined: Fri Jan 19, 2007 10:25 am
World Scanning
I was working on a routine to scan the entire world to see which territory belonged to the bot.
It works but it is terribly slow... is there another way?
Complete Code to date:
-- Make require look in this folder
package.path = [[AI\luabot\?.lua;"]] .. package.path
function OnInit()
SendChat "/name [Bot]ROFLbot"
SendChat("I am ROFLbot, written by ROFLamingo in lua version of defcon API")
SendChat("contact ROFLamingo via the forums or email (scallbe1@hotmail.com)")
function OnTick()
OnFirstTick()
OnTick = OnTickReal
return OnTick()
end
function OnFirstTick()
--enumerate our cities, opponent cities, position, population
StartLongTask(function()
-- we want to place radar as soon as possible in Defcon 5 in this example
local poslong, poslat
for poslong = -180, 175, 5 do
for poslat = -52, 80, 5 do
if IsValidPlacementLocation(poslong, poslat,"RadarStation") then
DrawWhiteboardCross(poslong,poslat, 1)
end
YieldLongTask()
end
--YieldLongTask()
end
-- figure out our territory
local cities = GetCityIDs()
local us = GetOwnTeamID()
for i, city in ipairs(cities) do
local long, lat, pop = city:GetLongitude(), city:GetLatitude(), city:GetCityPopulation()
if city:GetTeamID() == us then
DrawGoodWhiteboardCircle(long, lat, pop / 3000000)
SendChat("Mine:" .. math.ceil(lat*1000)/1000 .. " " .. math.ceil(long*1000)/1000 .. " " .. math.ceil(pop/100000))
else
DrawBadWhiteboardCircle(long, lat, pop / 3000000)
SendChat("Theirs:" .. math.ceil(lat*1000)/1000 .. " " .. math.ceil(long*1000)/1000 .. " " .. math.ceil(pop/100000))
end
YieldLongTask()
end
end)
-- loop to output Defcon Level as it changes
local DefconLevel
StartLongTask(function()
repeat
local Level = GetDefconLevel()
if Level ~= DefconLevel then
SendChat(("it's DEFCON %i already!"):format(Level), "public")
DefconLevel = Level
end
YieldLongTask()
YieldLongTask()
YieldLongTask()
YieldLongTask()
until Level == 1
SendChat("Prepare to feel the wrath of my nuclear weaponry!", "public")
end)
end
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
-- Redefine print to write to the alliance chat channel
function print(...)
local args = {...}
local n = select('#', ...)
local tostring = tostring
local txt = {}
for i = 1, n do
if i ~= 1 then
txt[#txt + 1] = " "
end
txt[#txt + 1] = tostring(args[i])
end
SendChat(table.concat(txt), "alliance")
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 functions
function DrawWhiteboardCross(x, y, size)
WhiteboardDraw(x - size, y - size, x + size, y + size)
WhiteboardDraw(x - size, y + size, x + size, y - size)
end
function DrawWhiteboardSquare(x, y, size)
WhiteboardDraw(x - size, y - size, x + size, y - size)
WhiteboardDraw(x + size, y - size, x + size, y + size)
WhiteboardDraw(x + size, y + size, x - size, y + size)
WhiteboardDraw(x - size, y + size, x - size, y - size)
end
function DrawBadWhiteboardCircle(x, y, radius)
local mrandom, msin, mcos, pi = math.random, math.sin, math.cos, math.pi
local segments = mrandom(7, 14)
local theta_step = pi * 2 / segments
local sin, cos = msin(theta_step), mcos(theta_step)
local irot = mrandom() * 2 * pi
local dx = mcos(irot) * radius
local dy = msin(irot) * radius
for i = 1, segments + mrandom(2, segments - 2) do
local nx = cos * dx - sin * dy + mrandom(-2, 2) / 10
local ny = sin * dx + cos * dy + mrandom(-2, 2) / 10
WhiteboardDraw(x + dx, y + dy, x + nx, y + ny)
dx, dy = nx, ny
end
end
function DrawGoodWhiteboardCircle(x, y, radius)
local segments = 20
local theta_step = math.pi * 2 / segments
local sin, cos = math.sin(theta_step), math.cos(theta_step)
local dx = radius
local dy = 0
for i = 1, segments do
local nx = cos * dx - sin * dy
local ny = sin * dx + cos * dy
WhiteboardDraw(x + dx, y + dy, x + nx, y + ny)
dx, dy = nx, ny
end
end
--final end
end
It works but it is terribly slow... is there another way?
Complete Code to date:
-- Make require look in this folder
package.path = [[AI\luabot\?.lua;"]] .. package.path
function OnInit()
SendChat "/name [Bot]ROFLbot"
SendChat("I am ROFLbot, written by ROFLamingo in lua version of defcon API")
SendChat("contact ROFLamingo via the forums or email (scallbe1@hotmail.com)")
function OnTick()
OnFirstTick()
OnTick = OnTickReal
return OnTick()
end
function OnFirstTick()
--enumerate our cities, opponent cities, position, population
StartLongTask(function()
-- we want to place radar as soon as possible in Defcon 5 in this example
local poslong, poslat
for poslong = -180, 175, 5 do
for poslat = -52, 80, 5 do
if IsValidPlacementLocation(poslong, poslat,"RadarStation") then
DrawWhiteboardCross(poslong,poslat, 1)
end
YieldLongTask()
end
--YieldLongTask()
end
-- figure out our territory
local cities = GetCityIDs()
local us = GetOwnTeamID()
for i, city in ipairs(cities) do
local long, lat, pop = city:GetLongitude(), city:GetLatitude(), city:GetCityPopulation()
if city:GetTeamID() == us then
DrawGoodWhiteboardCircle(long, lat, pop / 3000000)
SendChat("Mine:" .. math.ceil(lat*1000)/1000 .. " " .. math.ceil(long*1000)/1000 .. " " .. math.ceil(pop/100000))
else
DrawBadWhiteboardCircle(long, lat, pop / 3000000)
SendChat("Theirs:" .. math.ceil(lat*1000)/1000 .. " " .. math.ceil(long*1000)/1000 .. " " .. math.ceil(pop/100000))
end
YieldLongTask()
end
end)
-- loop to output Defcon Level as it changes
local DefconLevel
StartLongTask(function()
repeat
local Level = GetDefconLevel()
if Level ~= DefconLevel then
SendChat(("it's DEFCON %i already!"):format(Level), "public")
DefconLevel = Level
end
YieldLongTask()
YieldLongTask()
YieldLongTask()
YieldLongTask()
until Level == 1
SendChat("Prepare to feel the wrath of my nuclear weaponry!", "public")
end)
end
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
-- Redefine print to write to the alliance chat channel
function print(...)
local args = {...}
local n = select('#', ...)
local tostring = tostring
local txt = {}
for i = 1, n do
if i ~= 1 then
txt[#txt + 1] = " "
end
txt[#txt + 1] = tostring(args[i])
end
SendChat(table.concat(txt), "alliance")
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 functions
function DrawWhiteboardCross(x, y, size)
WhiteboardDraw(x - size, y - size, x + size, y + size)
WhiteboardDraw(x - size, y + size, x + size, y - size)
end
function DrawWhiteboardSquare(x, y, size)
WhiteboardDraw(x - size, y - size, x + size, y - size)
WhiteboardDraw(x + size, y - size, x + size, y + size)
WhiteboardDraw(x + size, y + size, x - size, y + size)
WhiteboardDraw(x - size, y + size, x - size, y - size)
end
function DrawBadWhiteboardCircle(x, y, radius)
local mrandom, msin, mcos, pi = math.random, math.sin, math.cos, math.pi
local segments = mrandom(7, 14)
local theta_step = pi * 2 / segments
local sin, cos = msin(theta_step), mcos(theta_step)
local irot = mrandom() * 2 * pi
local dx = mcos(irot) * radius
local dy = msin(irot) * radius
for i = 1, segments + mrandom(2, segments - 2) do
local nx = cos * dx - sin * dy + mrandom(-2, 2) / 10
local ny = sin * dx + cos * dy + mrandom(-2, 2) / 10
WhiteboardDraw(x + dx, y + dy, x + nx, y + ny)
dx, dy = nx, ny
end
end
function DrawGoodWhiteboardCircle(x, y, radius)
local segments = 20
local theta_step = math.pi * 2 / segments
local sin, cos = math.sin(theta_step), math.cos(theta_step)
local dx = radius
local dy = 0
for i = 1, segments do
local nx = cos * dx - sin * dy
local ny = sin * dx + cos * dy
WhiteboardDraw(x + dx, y + dy, x + nx, y + ny)
dx, dy = nx, ny
end
end
--final end
end
- roflamingo
- level3
- Posts: 404
- Joined: Fri Jan 19, 2007 10:25 am
xander wrote:Code is easier to read if you use [code] tags. Also, if you were to edit out the parts of the code that are not attempting to scan the world, that would make it easier to follow. For instance, the first block at the top is pretty unnecessary.
xander
Point taken. Here.
-- we want to place radar as soon as possible in Defcon 5 in this example
local poslong, poslat
for poslong = -180, 175, 5 do
for poslat = -52, 80, 5 do
if IsValidPlacementLocation(poslong, poslat,"RadarStation") then
DrawWhiteboardCross(poslong,poslat, 1)
end
YieldLongTask()
end
--YieldLongTask()
end
- Ace Rimmer
- level5
- Posts: 10803
- Joined: Thu Dec 07, 2006 9:46 pm
- Location: The Multiverse
I'm not familiar with the math.ceil, yet, but here's my territory discovery code, which works in a matter a couple of seconds:
I use an If Elseif to determine with placement code to go with. The entire process still needs to be streamlined and improved, but only takes 10 seconds (real time) regardless of game speed to determine the set-up and place every single unit. I'm guessing when I get 'done' improving it I can get it down to less than half that.
Code: Select all
local allCities = GetCityIDs()
local us = GetOwnTeamID()
local counter = 0
repeat
for i, city in next, allCities, 1 do
if city:GetTeamID() == us then
if # myCities == 0 then
table.insert(myCities, city)
end
else
if # enemyCities == 0 then
table.insert(enemyCities, city)
end
end
end
YieldLongTask()
counter = counter + 1
until counter == 1
I use an If Elseif to determine with placement code to go with. The entire process still needs to be streamlined and improved, but only takes 10 seconds (real time) regardless of game speed to determine the set-up and place every single unit. I'm guessing when I get 'done' improving it I can get it down to less than half that.
- roflamingo
- level3
- Posts: 404
- Joined: Fri Jan 19, 2007 10:25 am
- Ace Rimmer
- level5
- Posts: 10803
- Joined: Thu Dec 07, 2006 9:46 pm
- Location: The Multiverse
It doesn't determine that, it only looks to see which territory it is and which territory the enemy is. Then, there is another block of code (if statements) that are called based on the results of the above code.
If you're trying to look at a wide area to place units, that will significantly slow you down. That's why I have mine 'filtered' to only look at small areas within the appropriate territory (the bot's own), not all possible land (on the globe).
Your code is looking at a gigantic area, nearly the entire globe.
If you're trying to look at a wide area to place units, that will significantly slow you down. That's why I have mine 'filtered' to only look at small areas within the appropriate territory (the bot's own), not all possible land (on the globe).
Your code is looking at a gigantic area, nearly the entire globe.
Smoke me a kipper, I'll be back for breakfast...
- roflamingo
- level3
- Posts: 404
- Joined: Fri Jan 19, 2007 10:25 am
I guess you are using an array of possible positions based on the territory selected?
I was thinking of doing it this way (with a smaller step value), subtract out the cities, subtract out enemy radar range, and then start to do math to place radar/ silos / airbases based on an algorithm to attain best grouping with best protection while being out-of-radar.
How do you solve for this problem with your if statements?
I was thinking of doing it this way (with a smaller step value), subtract out the cities, subtract out enemy radar range, and then start to do math to place radar/ silos / airbases based on an algorithm to attain best grouping with best protection while being out-of-radar.
How do you solve for this problem with your if statements?
- Ace Rimmer
- level5
- Posts: 10803
- Joined: Thu Dec 07, 2006 9:46 pm
- Location: The Multiverse
roflamingo wrote:...
How do you solve for this problem with your if statements?
I give the bot specific pre-defined areas to start with, after it determines which territories are in play. Instead of trying to find valid placement locations right away, my bot checks one city of each territory, then looks for valid placement locations based on the city. That is, if it finds Moscow, it knows not to even try to place in Greenland, or Mexico, etc. This really speeds things up. Also, I consider the thousands of games I've played to be enough algorithm.
What my Bot will lack in placement flexibility it will replace with superior fighting skills (i.e. micromanagement).
I would imagine your code is scanning the globe until it stumbles upon a place to put something.
- roflamingo
- level3
- Posts: 404
- Joined: Fri Jan 19, 2007 10:25 am
Ace Rimmer wrote:..I would imagine your code is scanning the globe until it stumbles upon a place to put something.
No, it was going to use superior programming skills to find the best place to put silos. But you have given me an idea...like you said there is no need to scan the whole globe if you know where your own cities are, and know where enemy radar can be placed.
- Ace Rimmer
- level5
- Posts: 10803
- Joined: Thu Dec 07, 2006 9:46 pm
- Location: The Multiverse
I'm a bit confused then.
That appears to be scanning the entire globe in steps of five, starting from somewhere in the South Pacific moving to north Russia, looking for valid placement locations, correct?
Code: Select all
-- we want to place radar as soon as possible in Defcon 5 in this example
local poslong, poslat
for poslong = -180, 175, 5 do
for poslat = -52, 80, 5 do
if IsValidPlacementLocation(poslong, poslat,"RadarStation") then
DrawWhiteboardCross(poslong,poslat, 1)
end
YieldLongTask()
end
--YieldLongTask()
end
That appears to be scanning the entire globe in steps of five, starting from somewhere in the South Pacific moving to north Russia, looking for valid placement locations, correct?
Smoke me a kipper, I'll be back for breakfast...
- roflamingo
- level3
- Posts: 404
- Joined: Fri Jan 19, 2007 10:25 am
It was a great idea until I realized how slowly the world would be scanned. It wasn't actually just going to drop radar. The same code was going to be leveraged for a lot of other purposes but it's too slow. My step was originally 0.5 degrees instead of 5!
What I am going to do now is try to leverage your code, and scan area around my own cities to deploy installations. I will scan much smaller areas so it should go much more quickly.
I'm not that good with lua tables/arrays yet... when I dropped in your code I get an error in this line:
if # myCities == 0 then
do you define myCities earlier?
What I am going to do now is try to leverage your code, and scan area around my own cities to deploy installations. I will scan much smaller areas so it should go much more quickly.
I'm not that good with lua tables/arrays yet... when I dropped in your code I get an error in this line:
if # myCities == 0 then
do you define myCities earlier?
- Ace Rimmer
- level5
- Posts: 10803
- Joined: Thu Dec 07, 2006 9:46 pm
- Location: The Multiverse
- roflamingo
- level3
- Posts: 404
- Joined: Fri Jan 19, 2007 10:25 am
- Ace Rimmer
- level5
- Posts: 10803
- Joined: Thu Dec 07, 2006 9:46 pm
- Location: The Multiverse
Of course, you just need somebody with a Bot to join your server, or somebody with a Bot to create a server (bot-enabled) and you can join with your bot. Never tried it.
You can also pit two bots together on a server of your own. It's all in the documentation.
Edit: forgot to mention that I did a test of RadarStation coverage and it's 20+ lat/long. Well, actually it's more like 20.something, but Lua doesn't seem to like anything other than 0.5.
You can also pit two bots together on a server of your own. It's all in the documentation.
Edit: forgot to mention that I did a test of RadarStation coverage and it's 20+ lat/long. Well, actually it's more like 20.something, but Lua doesn't seem to like anything other than 0.5.
Smoke me a kipper, I'll be back for breakfast...
Who is online
Users browsing this forum: No registered users and 4 guests