From 782eba376fae7bdb9a6a1066d829cbbef1293aaf Mon Sep 17 00:00:00 2001 From: "BESTIA\\pixel" Date: Wed, 7 Mar 2018 20:08:02 -0400 Subject: [PATCH 1/3] refactored all ant comm algorithms, separated function calls, clean the mix --- code/simulation.lua | 73 ++++++++++++++++++++++++++++++--------------- 1 file changed, 49 insertions(+), 24 deletions(-) diff --git a/code/simulation.lua b/code/simulation.lua index 384488f..7067d76 100644 --- a/code/simulation.lua +++ b/code/simulation.lua @@ -9,9 +9,18 @@ local vec = require('libs.vec2d_arr') local sim = {} +sim.interactionAlgorithm = {} + function sim.init() math.randomseed(os.time()) - map.init() + print(sim.algorithm2_oldChat) + print(sim.algorithm3_groupCells) + + sim.interactionAlgorithm[0] = sim.algorithm0_doNothing + sim.interactionAlgorithm[1] = sim.algorithm1_ZeroOptimization + sim.interactionAlgorithm[2] = sim.algorithm2_oldChat + sim.interactionAlgorithm[3] = sim.algorithm3_groupCells + map.init() local newSur @@ -89,45 +98,60 @@ function sim.collisionAntWithSurfaces(ant) end end -function sim.collisionDetection() - local ant - if cfg.antComAlgorithm ~= 3 then + +function sim.algorithm0_doNothing() for _,node in pairs(map.ants.array) do --ant bounces with limits - ant = node.obj + local ant = node.obj + sim.collisionAntWithLimits(ant) + end --for ant node +end + +-- **1) No optimizaiton, just test N*N all with all ants** no brain. +--if you are porting the code to other language or api start implementing this for simplicity and safety +function sim.algorithm1_ZeroOptimization() + for _,node in pairs(map.ants.array) do + --ant bounces with limits + local ant = node.obj if not sim.collisionAntWithLimits(ant) then --ants with surfaces - if not sim.collisionAntWithSurfaces(ant) then - - -- **1) No optimizaiton, just test N*N all with all ants**. - --if you are porting the code to other language or api start implementing this for simplicity and safety - if cfg.antComAlgorithm == 1 then - local otherAnt - local betterPathCount = 0 + if not sim.collisionAntWithSurfaces(ant) then + if (cfg.antComEveryFrame or ant.isComNeeded()) then ant.communicateWithAnts(map.ants.array) - end + end + end + end + end --for ant node +end + +-- **2) Old 2003 way, chat with neighbors** +function sim.algorithm2_oldChat() + + if cfg.antComAlgorithm ~= 3 then + for _,node in pairs(map.ants.array) do + --ant bounces with limits + local ant = node.obj + if not sim.collisionAntWithLimits(ant) then + --ants with surfaces + if not sim.collisionAntWithSurfaces(ant) then - -- **2) Old 2003 way, chat with neighbors** - elseif cfg.antComAlgorithm == 2 then if (cfg.antComEveryFrame or ant.isComNeeded()) then + local antLists = map.antsNearMe( ant ) ant.communicateWithAnts_grid( antLists ) + end - end + end end end --for ant node - else - -- **3) New 2018, go by cell and process a cell group at once.** - if cfg.antComAlgorithm == 3 then - sim.antCommunication3() - end - end --if cfg.antCom... ~= 3 + end + end -- 3) **New algorithm 2018 group info matters to all**, share it -function sim.antCommunication3() +function sim.algorithm3_groupCells() local centerCell --TQuickList local neiborCell --TQuickList @@ -187,7 +211,8 @@ function sim.antCommunication3() end function sim.update() - sim.collisionDetection() + + sim.interactionAlgorithm[cfg.antComAlgorithm]() for _,node in pairs(map.ants.array) do node.obj.update() From e24a69eb6ebe8c5d2730ccddeb33a3b632d4e159 Mon Sep 17 00:00:00 2001 From: "BESTIA\\pixel" Date: Thu, 8 Mar 2018 12:02:41 -0400 Subject: [PATCH 2/3] updateOnGrid cleaning --- code/map.lua | 23 ++++++++++------------- code/simulation.lua | 27 +++++++++++++++++++-------- 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/code/map.lua b/code/map.lua index 957b8b1..74b8a41 100644 --- a/code/map.lua +++ b/code/map.lua @@ -58,25 +58,24 @@ function map.updateOnGrid_firstTime(grid, actor ) --vector position inside grid, integer values x,y local idxX, idxY = math.floor(actor.position[1]/map.gridSize), math.floor(actor.position[2]/map.gridSize) actor.gridInfo = { - posi = { idxX, idxY }, - lastPosi = { idxX, idxY } + posi = { idxX, idxY } } -- insert my node on the bidimentional array grid grid[ actor.gridInfo.posi[1] ][ actor.gridInfo.posi[2] ].qlist.add( actor.nodeRefs.gridNode ) end function map.updateOnGrid(grid, actor) - actor.gridInfo.posi[1] = math.floor(actor.position[1]/map.gridSize) - actor.gridInfo.posi[2] = math.floor(actor.position[2]/map.gridSize) + local posiX = math.floor(actor.position[1]/map.gridSize) + local posiY = math.floor(actor.position[2]/map.gridSize) --comparing to know if actor is now in a new grid X,Y - if (actor.gridInfo.posi[1] ~= actor.gridInfo.lastPosi[1] ) or (actor.gridInfo.posi[2] ~= actor.gridInfo.lastPosi[2] ) then + if (posiX ~= actor.gridInfo.posi[1] ) or (posiY ~= actor.gridInfo.posi[2] ) then --move from old list to new list actor.nodeRefs.gridNode.selfRemove() - grid[ actor.gridInfo.posi[1] ][ actor.gridInfo.posi[2] ].qlist.add( actor.nodeRefs.gridNode ) - actor.gridInfo.lastPosi[1] = actor.gridInfo.posi[1] - actor.gridInfo.lastPosi[2] = actor.gridInfo.posi[2] - if cfg.debugGrid then actor.color = grid[ actor.gridInfo.posi[1] ][ actor.gridInfo.posi[2] ].dcolor end - end + grid[ posiX ][ posiY ].qlist.add( actor.nodeRefs.gridNode ) + actor.gridInfo.posi[1] = posiX + actor.gridInfo.posi[2] = posiY + --if cfg.debugGrid then actor.color = grid[ posiX ][ posiY ].dcolor end + end end function map.addAnt( ant ) @@ -123,9 +122,7 @@ function map.draw() end end if cfg.debugGrid then - map.gridForEachCell( - - ) + map.gridForEachCell( cellcount ) end end diff --git a/code/simulation.lua b/code/simulation.lua index 7067d76..2a5106e 100644 --- a/code/simulation.lua +++ b/code/simulation.lua @@ -127,27 +127,19 @@ end -- **2) Old 2003 way, chat with neighbors** function sim.algorithm2_oldChat() - - if cfg.antComAlgorithm ~= 3 then for _,node in pairs(map.ants.array) do --ant bounces with limits local ant = node.obj if not sim.collisionAntWithLimits(ant) then --ants with surfaces if not sim.collisionAntWithSurfaces(ant) then - if (cfg.antComEveryFrame or ant.isComNeeded()) then - local antLists = map.antsNearMe( ant ) ant.communicateWithAnts_grid( antLists ) - end - end end end --for ant node - end - end -- 3) **New algorithm 2018 group info matters to all**, share it @@ -210,6 +202,25 @@ function sim.algorithm3_groupCells() end --fori end +-- **4) Old algorithm 2 plus Pheromones inspiration**, store good info on the cells. +function sim.algorithm4_Pheromones() + for _,node in pairs(map.ants.array) do + --ant bounces with limits + local ant = node.obj + if not sim.collisionAntWithLimits(ant) then + --ants with surfaces + if not sim.collisionAntWithSurfaces(ant) then + if (cfg.antComEveryFrame or ant.isComNeeded()) then + + local antLists = map.antsNearMe( ant ) + ant.communicateWithAnts_grid( antLists ) + + end + end + end + end --for ant node +end + function sim.update() sim.interactionAlgorithm[cfg.antComAlgorithm]() From b997dfef413d1d09332759b46ba1658f3c1ede2a Mon Sep 17 00:00:00 2001 From: "BESTIA\\pixel" Date: Thu, 8 Mar 2018 16:38:03 -0400 Subject: [PATCH 3/3] Pheromones inspired "NEW" algorithm #4. Implemented and working. SPEED improved! 6,000ants at 30fps (from 20 fps alg #3) --- code/actor.lua | 2 +- code/ant.lua | 4 ++-- code/map.lua | 21 +++++++++++++++++---- code/simconfig.lua | 6 +++--- code/simulation.lua | 38 +++++++++++++++++++++++++++----------- main.lua | 8 +++++--- 6 files changed, 55 insertions(+), 24 deletions(-) diff --git a/code/actor.lua b/code/actor.lua index 96c2073..39c2680 100644 --- a/code/actor.lua +++ b/code/actor.lua @@ -25,7 +25,7 @@ function TActor.create() obj.position = {0, 0} obj.radius = 1 obj.nodeRefs = {} --keys=values, store nodes of TQuickLists where the actor may be referenced. To make a clean "destruction" of the actor. - obj.gridInfo = {} --store stuff useful for Grid + obj.gridInfo = {posi = {0,0}} --store stuff useful for Grid --PUBLIC functions obj.classType = TActor diff --git a/code/ant.lua b/code/ant.lua index a802bf2..0ce518d 100644 --- a/code/ant.lua +++ b/code/ant.lua @@ -42,10 +42,10 @@ function TAnt.create() obj.acceleration = 0.04 + math.random()*0.05 obj.erratic = cfg.antErratic --crazyness obj.maxSpeed = cfg.antMaxSpeed - obj.tasks = {'food','cave'} + obj.tasks = {'food','cave'} --TODO: no need for Array of task, they can only have to targets, use two variables and swap obj.lookingForTask = 1 obj.comingFromTask = 0 - obj.lookingFor = 'food' + --obj.lookingFor = 'food' obj.comingFrom = '' obj.lastTimeSeenFood = -1 obj.lastTimeSeenCave = -1 diff --git a/code/map.lua b/code/map.lua index 74b8a41..9784004 100644 --- a/code/map.lua +++ b/code/map.lua @@ -27,24 +27,37 @@ map.limitsColor = cfg.colorBkLimits local limitsRect = {} local gridBorder = 2 + +-- calculating grid map dimensions, -- extra border (fGridBorder) to get rid of validations map.minXg = math.floor(map.minX / map.gridSize) - gridBorder map.maxXg = math.floor(map.maxX / map.gridSize) + gridBorder map.minYg = math.floor(map.minY / map.gridSize) - gridBorder map.maxYg = math.floor(map.maxY / map.gridSize) + gridBorder function map.init() - -- calculating grid map dimensions - -- extra border (fGridBorder) to get rid of validations - + -- initializing all Grid data structure, avoiding future validations and mem allocation + for i = map.minXg, map.maxXg do map.grid[i]={} for j = map.minYg, map.maxYg do map.grid[i][j] = { qlist = TQuickList.create(), - dcolor = {math.random(160), math.random(160), math.random(250)} + dcolor = {math.random(160), math.random(160), math.random(250)}, + pheromInfo = { + seen = {} + } } + for k = 1, #cfg.antInterests do + map.grid[i][j].pheromInfo.seen[ cfg.antInterests[k] ] = { + time = -1, + where = {1,0} --last position remembered on the direction coming from + } + end + end end + + end --TODO: discard AddActor OR (AddAnt and addSurface) ... think... diff --git a/code/simconfig.lua b/code/simconfig.lua index 3379e47..3587f76 100644 --- a/code/simconfig.lua +++ b/code/simconfig.lua @@ -1,15 +1,15 @@ ---"Constants", defaults, globals........ local simconfig = { - numAnts = 4000, + numAnts = 6000, antMaxSpeed = 1.2, - antComAlgorithm = 2, -- 0 = Comm disabled; 1 = No optimizations; 2= Old 2003 gridmap way; 3 = New improved 2018 gridmap group-to-group comm. + antComAlgorithm = 4, -- 0 = Comm disabled; 1 = No optimizations; 2= Old 2003 gridmap way; 3 = New improved 2018 gridmap group-to-group comm. antComRadius = 40, -- Ants communications radious, ignored on algorithm >1 ... gridSize*3/2 is the equivalent antComEveryFrame = false, -- comunicate every frame? or use values of antComNeedFrameStep below antComNeedFrameStep = {5,15}, -- {a,b} ant would need for comunication with other ants every amount of frames form a to b. Greater values more speed less path quality. antComMaxBetterPaths = 3, -- During communicaitons, in a single frame each ant gets many better advices of new direction, how many are enough? antSightDistance = 40, -- Only bellow this distance the ant can identify and locate things, bettr if > than antComRadius - antPositionMemorySize = 25, -- How many past position they can remember + antPositionMemorySize = 15, -- How many past position they can remember antErratic = 0.1, antInterests = {'food','cave'}, diff --git a/code/simulation.lua b/code/simulation.lua index 2a5106e..1b73fd1 100644 --- a/code/simulation.lua +++ b/code/simulation.lua @@ -13,16 +13,15 @@ sim.interactionAlgorithm = {} function sim.init() math.randomseed(os.time()) - print(sim.algorithm2_oldChat) - print(sim.algorithm3_groupCells) sim.interactionAlgorithm[0] = sim.algorithm0_doNothing sim.interactionAlgorithm[1] = sim.algorithm1_ZeroOptimization sim.interactionAlgorithm[2] = sim.algorithm2_oldChat sim.interactionAlgorithm[3] = sim.algorithm3_groupCells + sim.interactionAlgorithm[4] = sim.algorithm4_pheromones + map.init() - local newSur for i=1,1 do newSur = TSurface.createCave(-250+200*(math.random()-0.5), 300*(math.random()-0.5), 20) @@ -61,8 +60,11 @@ function sim.init() if node.obj.classType == TAnt then numAnts = numAnts + 1 end if node.obj.classType == TSurface then numSurs = numSurs + 1 end end + print('numAnts: ',numAnts,' numSurs', numSurs) - print('Initial memory: '..math.floor( collectgarbage ('count'))..'kb') + print('Mem used: '..math.floor( collectgarbage ('count'))..'kb') + + end function sim.collisionAntWithLimits(ant) @@ -202,21 +204,35 @@ function sim.algorithm3_groupCells() end --fori end --- **4) Old algorithm 2 plus Pheromones inspiration**, store good info on the cells. -function sim.algorithm4_Pheromones() +-- **4) Old algorithm 2 plus Pheromones inspiration**, store bestSeen info on the cells. +-- this time they communicate indirectly using the Grid cells, equivalent to pheromones nature +function sim.algorithm4_pheromones() for _,node in pairs(map.ants.array) do --ant bounces with limits local ant = node.obj if not sim.collisionAntWithLimits(ant) then --ants with surfaces if not sim.collisionAntWithSurfaces(ant) then - if (cfg.antComEveryFrame or ant.isComNeeded()) then - - local antLists = map.antsNearMe( ant ) - ant.communicateWithAnts_grid( antLists ) + if (cfg.antComEveryFrame or ant.isComNeeded()) then + --get info on ant cell position, of time and position stored from other ants. + local pheromInfoSeen = map.grid[ ant.gridInfo.posi[1] ][ ant.gridInfo.posi[2] ].pheromInfo.seen + local myInterest = pheromInfoSeen[ ant.tasks[ant.lookingForTask] ] + if myInterest.time > ant.maxTimeSeen then + ant.maxTimeSeen = myInterest.time + ant.headTo( myInterest.where ) + end + -- share what i Know in the map... + for name,time in pairs(ant.lastTimeSeen) do + local interest = pheromInfoSeen[ name ] + if time > interest.time then + interest.time = time + interest.where[1] = ant.oldestPositionRemembered[1] + interest.where[2] = ant.oldestPositionRemembered[2] + end + end --for end - end + end --ifnot end end --for ant node end diff --git a/main.lua b/main.lua index 2f86900..6cec33a 100644 --- a/main.lua +++ b/main.lua @@ -17,7 +17,9 @@ if not g_isTesting then --- We init the application defining the load event function api.load() - if arg[#arg] == "-debug" then require("mobdebug").start() end + TIME_start = os.clock() + print('Initializing...') + --if arg[#arg] == "-debug" then require("mobdebug").start() end sim.init() apiG.setBackgroundColor(cfg.colorBk) @@ -29,7 +31,7 @@ if not g_isTesting then function api.draw() --gameworld - + if cfg.simFrameNumber == 1 then print( (os.clock() - TIME_start)..'secs' ) end apiG.push() apiG.translate( cam.translation.x, cam.translation.y ) @@ -55,7 +57,7 @@ if not g_isTesting then print('cfg.debugGrid =',cfg.debugGrid) elseif key=='4' then cfg.antComAlgorithm = cfg.antComAlgorithm + 1 - if cfg.antComAlgorithm > 3 then cfg.antComAlgorithm = 0 end + if cfg.antComAlgorithm > 4 then cfg.antComAlgorithm = 0 end print('cfg.antComAlgorithm = ', cfg.antComAlgorithm ) elseif key=='m' then print('Memory: '..math.floor( collectgarbage ('count'))..'kb')