World Scanning

Come in here to talk about your sky-net style world-destroying super bots!

Moderator: Defcon moderators

User avatar
roflamingo
level3
level3
Posts: 404
Joined: Fri Jan 19, 2007 10:25 am

World Scanning

Postby roflamingo » Sun Feb 14, 2010 4:02 pm

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
User avatar
xander
level5
level5
Posts: 16867
Joined: Thu Oct 21, 2004 11:41 pm
Location: Riverside, CA, USA
Contact:

Postby xander » Sun Feb 14, 2010 4:30 pm

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
User avatar
roflamingo
level3
level3
Posts: 404
Joined: Fri Jan 19, 2007 10:25 am

Postby roflamingo » Sun Feb 14, 2010 4:43 pm

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
User avatar
Ace Rimmer
level5
level5
Posts: 10803
Joined: Thu Dec 07, 2006 9:46 pm
Location: The Multiverse

Postby Ace Rimmer » Sun Feb 14, 2010 10:28 pm

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:

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.
User avatar
xander
level5
level5
Posts: 16867
Joined: Thu Oct 21, 2004 11:41 pm
Location: Riverside, CA, USA
Contact:

Postby xander » Mon Feb 15, 2010 12:43 am

Ace Rimmer wrote: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:

At a guess, I would say that math.ceil is the ceiling function, i.e. it rounds a number up to the nearest integer.

xander
User avatar
roflamingo
level3
level3
Posts: 404
Joined: Fri Jan 19, 2007 10:25 am

Postby roflamingo » Mon Feb 15, 2010 2:32 am

I am trying to understand how your code would determine all the possibe places to place your land units. Maybe I am reading it wrong but what I see is stuff pertaining to your cities. Help?
User avatar
Ace Rimmer
level5
level5
Posts: 10803
Joined: Thu Dec 07, 2006 9:46 pm
Location: The Multiverse

Postby Ace Rimmer » Mon Feb 15, 2010 5:00 am

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.
Smoke me a kipper, I'll be back for breakfast...
User avatar
roflamingo
level3
level3
Posts: 404
Joined: Fri Jan 19, 2007 10:25 am

Postby roflamingo » Mon Feb 15, 2010 6:17 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?
User avatar
Ace Rimmer
level5
level5
Posts: 10803
Joined: Thu Dec 07, 2006 9:46 pm
Location: The Multiverse

Postby Ace Rimmer » Mon Feb 15, 2010 4:01 pm

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. :P

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. :?:
User avatar
roflamingo
level3
level3
Posts: 404
Joined: Fri Jan 19, 2007 10:25 am

Postby roflamingo » Mon Feb 15, 2010 4:57 pm

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.
User avatar
Ace Rimmer
level5
level5
Posts: 10803
Joined: Thu Dec 07, 2006 9:46 pm
Location: The Multiverse

Postby Ace Rimmer » Mon Feb 15, 2010 5:03 pm

I'm a bit confused then.

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...
User avatar
roflamingo
level3
level3
Posts: 404
Joined: Fri Jan 19, 2007 10:25 am

Postby roflamingo » Mon Feb 15, 2010 5:29 pm

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?
User avatar
Ace Rimmer
level5
level5
Posts: 10803
Joined: Thu Dec 07, 2006 9:46 pm
Location: The Multiverse

Postby Ace Rimmer » Mon Feb 15, 2010 6:30 pm

Yep, a variable: myCities = {}
Smoke me a kipper, I'll be back for breakfast...
User avatar
roflamingo
level3
level3
Posts: 404
Joined: Fri Jan 19, 2007 10:25 am

Postby roflamingo » Mon Feb 15, 2010 6:45 pm

Thx Ace, you rock. :D

Is there anyway to allow bots to play each other? Or anything else besides the IV bot?
User avatar
Ace Rimmer
level5
level5
Posts: 10803
Joined: Thu Dec 07, 2006 9:46 pm
Location: The Multiverse

Postby Ace Rimmer » Mon Feb 15, 2010 6:48 pm

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.
Smoke me a kipper, I'll be back for breakfast...

Return to “AI Bots”

Who is online

Users browsing this forum: No registered users and 1 guest