Joshua LUA coroutine

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

Joshua LUA coroutine

Postby roflamingo » Wed Feb 24, 2010 4:43 pm

I tried to deploy this but it just hung instantly....educate me plz?

Step 1. Comment out existing co-routine stuff

Code: Select all

-- 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


Step 2 - paste in new Joshua coroutine code at top of main.lua (I only use 1 LUA for the moment)

Code: Select all

 local allottedTime
 local startTime
 local tasks = {}
 
 Multithreading = {}
 
 Multithreading.YieldLongTask = function()
         if (os.clock() - startTime >= allottedTime) then
                 coroutine.yield()
         end
         --coroutine.yield()
 end
 
 Multithreading.StartLongTask = function(f)
         tasks[coroutine.create(f)] = true
 end
 
 Multithreading.WorkOnLongTasks = function(allotted)
         allottedTime = allotted or 0.0005
                 
         for task, value in pairs(tasks) do
                 if coroutine.status(task) == "dead" then
                         tasks[task] = nil
                 else
                         startTime = os.clock()
                         assert(coroutine.resume(task))
                         allottedTime = allottedTime - (os.clock() - startTime)
                 end
         end
 end


Step 3. Excepting the coroutine code just recently pasted in, search and replace:
YieldLongTask -> Multithreading.YieldLongTask
StartLongTask -> Multithreading.StartLongTask
WorkonLongTasks -> Multithreading.WorkonLongTasks

Doing this, it just hangs instantly. The following block is how my main.lua starts:

Code: Select all

function OnInit()
  RequestGameSpeed(10)
  SendChat "/name [Bot]ROFLbot"
  SendChat("I am ROFLbot, a LUA Defcon API bot")
  SendChat("Author: ROFLamingo (scallbe1@hotmail.com) or IV forums")
end

function OnTickReal()
   Multithreading.WorkOnLongTasks()
end

function OnShutdown()
end

function OnTick()

   if (DefconLevel ~= GetDefconLevel()) then
      DefconLevel = GetDefconLevel()
      SendChat("Defcon " .. DefconLevel)
      if (DefconLevel == 5) then
         OnFirstTickD5()
      elseif (DefconLevel == 4) then
         OnFirstTickD4()
      elseif (DefconLevel == 3) then
         OnFirstTickD3()
      elseif( DefconLevel == 2) then
         OnFirstTickD2()
      elseif (DefconLevel == 1) then
         OnFirstTickD1()
      end
   end
   
   if (DefconLevel == 5) then
      TickD5()
   elseif (DefconLevel == 4) then
      TickD4()
   elseif (DefconLevel == 3) then
      TickD3()
   elseif (DefconLevel == 2) then
      TickD2()
   elseif (DefconLevel == 1) then
      TickD1()
   end
   Multithreading.WorkOnLongTasks()
end

function OnFirstTickD5()

Multithreading.StartLongTask( function()
SendChat("Things to do at D5")
SendChat("DONE: Determine who are we, who are they, enumeration activities")
SendChat("DONE: Determine how many forward radar to place, and try to pick good places")
SendChat("Determine how many scout battleships to place, and place them")
SendChat("Determine how many aggressive subs to place, and send them on their way(?!)")


What am I doing wrong?
Montyphy
level5
level5
Posts: 6747
Joined: Tue Apr 19, 2005 2:28 pm
Location: Bristol, England

Postby Montyphy » Wed Feb 24, 2010 4:53 pm

Why do you have Multithreading.WorkOnLongTasks() twice?
Uplink help: Check out the Guide or FAQ.
Latest Uplink patch is v1.55.
User avatar
roflamingo
level3
level3
Posts: 404
Joined: Fri Jan 19, 2007 10:25 am

Postby roflamingo » Wed Feb 24, 2010 4:58 pm

Montyphy wrote:Why do you have Multithreading.WorkOnLongTasks() twice?


Not sure. My original code had it and it worked ok...and it was borrowed from other code...and so on.

What I am saying here is that I am not sure when to use that (WorkOnLongTasks) :( thus looking for guidance from the more learned 8)
User avatar
Ace Rimmer
level5
level5
Posts: 10803
Joined: Thu Dec 07, 2006 9:46 pm
Location: The Multiverse

Postby Ace Rimmer » Wed Feb 24, 2010 5:05 pm

On a side note, for easy commenting, use "--[[ <code> ]]" for multi-line comments (saves time). You just have to remember to remove the end double brackets when you un-comment.

Example:

Code: Select all

--[[ 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]]
Montyphy
level5
level5
Posts: 6747
Joined: Tue Apr 19, 2005 2:28 pm
Location: Bristol, England

Postby Montyphy » Wed Feb 24, 2010 5:08 pm

roflamingo wrote:
Montyphy wrote:Why do you have Multithreading.WorkOnLongTasks() twice?


Not sure. My original code had it and it worked ok...and it was borrowed from other code...and so on.

What I am saying here is that I am not sure when to use that (WorkOnLongTasks) :( thus looking for guidance from the more learned 8)


You only need to call it once per tick. Use the yieldfreq technique I mentioned in the other thread if you want to execute more code per tick.

Ace Rimmer wrote:On a side note, for easy commenting, use "--[[ <code> ]]" for multi-line comments (saves time). You just have to remember to remove the end double brackets when you un-comment.


Or even better:

Code: Select all

--[[
    Comment
    Comment
    Comment
--]]


Add a hyphen and you get:

Code: Select all

---[[
    Code
    Code
    Code
--]]


Makes it very easy to toggle code.
Uplink help: Check out the Guide or FAQ.

Latest Uplink patch is v1.55.
martin
level5
level5
Posts: 3210
Joined: Fri Nov 19, 2004 8:37 pm

Postby martin » Wed Feb 24, 2010 5:26 pm

Montyphy has identified the bug, the WorkOnLongTasks executes for almost enough time to make the game hang, calling it twice will be 2*almost enough, which will make the game hang. Try removing the call in OnTickReal, and see if it works a bit better :)

edit:: When is OnTickReal called?
GENERATION 22:The first time you see this, copy it into your sig on any forum and add 1 to the generation. Social experiment.
User avatar
roflamingo
level3
level3
Posts: 404
Joined: Fri Jan 19, 2007 10:25 am

Postby roflamingo » Thu Feb 25, 2010 1:04 am

I think I fixed it and my code is executing much faster now... at least inside my OnFirstTickD5. Havent tried fixing D4...thanks to all 3 of you.

Question:

Can you detect if a given sea co-ordinate is both a valid location for you to place, as well as for an enemy to place sea units?
User avatar
Ace Rimmer
level5
level5
Posts: 10803
Joined: Thu Dec 07, 2006 9:46 pm
Location: The Multiverse

Postby Ace Rimmer » Thu Feb 25, 2010 2:27 am

roflamingo wrote:Can you detect if a given sea co-ordinate is both a valid location for you to place, as well as for an enemy to place sea units?

I thought about this earlier yesterday when I was trying to figure out a way to place according to overlapping sea territories. My answer is no, unless there's some way to 'log' each territories placement locations and extrapolate from that.

A secondary question to this is; is there an easy way to make use of cities.txt? For example, if Moscow is hit make some statement. e.g., "Not Moscow!", [Atlanta hit]"You killed my neighbors in Atalanta!" I say secondary because coastlines and cities etc are already there, but I don't know how to 'use' them.
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 » Thu Feb 25, 2010 2:41 am

I have an idea on what I can do. It won't be much more than 80% accurate but algorithmically it seems sound. I will shoot you guys the code when I am done.

Not sure why you would want to read cities.txt....is the bot able to enumerate the city names? or just long/lat/pop/owner?
User avatar
Ace Rimmer
level5
level5
Posts: 10803
Joined: Thu Dec 07, 2006 9:46 pm
Location: The Multiverse

Postby Ace Rimmer » Thu Feb 25, 2010 5:17 am

roflamingo wrote:...Not sure why you would want to read cities.txt....is the bot able to enumerate the city names? or just long/lat/pop/owner?

Well, I don't mean read the file itself, rather add the data that's in it to the bot. This way the bot could reference the appropriate cities in chat, that's about it.
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 » Thu Feb 25, 2010 5:56 am

Sorry Ace, my code for forward-radar placement isn't perfect...if it can't place 4 or 5 according to it's internal parameters it freaks out.

Also my ocean-finding code is obviously a bit CPU-intense... i.e brute forcish.

It will be more ready tomorrow, i will even drop in some boats. Just need to solve the hang(s) first.
User avatar
Ace Rimmer
level5
level5
Posts: 10803
Joined: Thu Dec 07, 2006 9:46 pm
Location: The Multiverse

Postby Ace Rimmer » Mon Mar 01, 2010 3:15 am

So, what did you do to fix your hang, cause I have the same issue... ?
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 Mar 01, 2010 3:24 am

I started a new main.lua, then gradually implemented my code blocks.

When I found a code block that would hang up, I would experiment with placement of YieldLongTask (usually in an outer code loop) until I got that part to stop hanging.

Believe me it's worth the effort - everything will go faster/be smoother, but the code transition to the new martin coroutine took me around 2-3 hours.
User avatar
Ace Rimmer
level5
level5
Posts: 10803
Joined: Thu Dec 07, 2006 9:46 pm
Location: The Multiverse

Postby Ace Rimmer » Mon Mar 01, 2010 3:27 am

Alright, I've made it six seconds in so far, even placed on silo and one ship. :P
Smoke me a kipper, I'll be back for breakfast...
User avatar
Ace Rimmer
level5
level5
Posts: 10803
Joined: Thu Dec 07, 2006 9:46 pm
Location: The Multiverse

Postby Ace Rimmer » Mon Mar 01, 2010 5:00 am

martin, your code is too fast. I can't get three ships to place and be in different fleets. The old co-routine was slow enough to make this work right:

Code: Select all

function PlaceScoutsNAvsEU ()
   StartLongTask(function()

      local counter = 1
      repeat
         if counter == 1 then
            PlaceFleet (-40, 54, "BattleShip")
         elseif counter == 2 then
            PlaceFleet (-29, 29, "BattleShip")
         else
            PlaceFleet (-30.34, 43.58, "BattleShip")
         end   
      
         local units = GetAllUnits ()
         local item = Set (BBs)
         for i, unit in ipairs(units) do
            if unit:GetTeamID() == GetOwnTeamID() then
               if unit:GetUnitType() == "BattleShip" then
                  if item[unit] == nil then
                     table.insert(BBs, unit)
                  end
               end
            end
         end
         YieldLongTask()
         counter = counter + 1         
      until # BBs == 3      
      
      BBs[1]:SetMovementTarget (-27, 65)
      BBs[2]:SetMovementTarget (-13, 34)
      BBs[3]:SetMovementTarget (-16, 51)
      
      YieldLongTask()
   end)
   
end


This places three ships in NA waters and sends them to EU (Iceland, UK-ish, Portugal). After converting to multithreading, all I can do is place three ships, which end up in the same fleet, so I can't issue separate orders (they all get sent to UK).

I've tried various methods and arrangements of the above (with your multithreading), but either it hangs, or just places three ships in one fleet. Help!

Return to “AI Bots”

Who is online

Users browsing this forum: No registered users and 5 guests