FAQ  •  Register  •  Login

Now introducing A_bot!

<<

amgine

Posts: 1399

Joined: Thu Apr 19, 2012 2:57 pm

Post Mon May 07, 2012 10:51 am

Now introducing A_bot!

introducing A_bot

  Code:
--- from S_bot which is from quickBot v2, modified by amgine
--- works on all game modes, except this bot don't work on non-pickup soccer (Yet)

game = nil
difficulty = nil
speed = nil
directionThreshold = nil
averageIndex = nil
averageMax = nil
myOrbitalDirection = nil
agression = nil
defense = nil
myNum = nil
gameType = nil
goalPt = vec.new(0,0)
dirToGo = nil

pathTimer = nil
pathTimerMax = nil

prevtarget = nil

gotoPositionWasNil = true
 
o = vec.new(0,0)
 
botLoc = nil        -- Bot's location, will be updated when onTick() is run
 
botRadius = nil
 
function main()
    botRadius = bot:getRad()
    pathTimerMax = 250
    pathTimer = pathTimerMax
    dirToGo = 0
    game = GameInfo()
    difficulty = tonumber(arg[1]) or 1
    agression = tonumber(arg[2]) or 1
    defense = tonumber(arg[3]) or .25
    speed = tonumber(arg[4]) or 2
    directionThreshold = tonumber(arg[5]) or 1
 
    gameType = game:getGameType()
   
    averageIndex = 1
    averageMax = 20
    averageArray = {}
    for i = 1, averageMax do
        averageArray[i] = false
    end
    myOrbitalDirection = 1
    myNum = math.random(0,10)

    possibleHealthItems = bot:findGlobalItems(RepairItemType)

    possibleEnergyItems = bot:findGlobalItems(EnergyItemType)
end
 
function vectorX(dir, dist)
    return(dist * math.cos(dir))
end
function vectorY(dir, dist)
    return(-dist * math.sin(dir))  
end
 
function shieldSelf()
    local bullets = bot:findItems(BulletType,AsteroidType,MineType,SpyBugType)
    local distToShieldAt = bot:getRad()*2 + (1-difficulty)*100
    if (bullets ~= nil) then
        for i,bullet in ipairs(bullets) do
            local bulletLoc = bullet:getLoc()
            local bulletVel = bullet:getVel()
            local angleDiff = math.abs(angleDifference(vec.angleTo(o, bulletVel), vec.angleTo(bulletLoc, botLoc)))
            --logprint(angleDiff)
            if (vec.distanceTo(bulletLoc, botLoc) < distToShieldAt + bullet:getRad() + vec.distanceTo(o,bulletVel)*50 and angleDiff < math.pi/4) then
                bot:activateModule(ModuleShield)
                return(true)
            end
        end
    end
end

function angleDifference(angleA,angleB)
    return (math.mod(math.mod(angleA - angleB, math.pi*2) + math.pi*3, math.pi*2) - math.pi)
end

function fireAtObjects()
    local enemies = bot:findItems(RobotType, TurretType, ShipType, AsteroidType, ForceFieldProjectorType, SpyBugType, CoreType,SoccerBallItemType,MineType )
    for index,enemy in ipairs(enemies) do
        if(fireAtObject(enemy, WeaponPhaser)) then
            break
        end
    end
end
 
 
--Fires at the specified object with the specified weapon if the obj is a good target.
--Does not fire if object is on the same team or if there is something in the way.
--Returns whether it fired or not.
function fireAtObject(obj, weapon)
    if(obj:getClassID() == TurretType or obj:getClassID() == ForceFieldProjectorType) then
        if(obj:getHealth() < .1) then
            --logprint("It's dead.")
            return(false)
        end
    end
   
    if(obj:getClassID() == ShipType or
        obj:getClassID() == RobotType or
        obj:getClassID() == TurretType or
        obj:getClassID() == ForceFieldProjectorType or
        obj:getClassID() == CoreType) then
            if obj:getTeamIndx() == bot:getTeamIndx() and game:isTeamGame() or obj:getTeamIndx() == NeutralTeamIndx then
                --logprint("It's an ally.")
                return(false)
            end
    end

   
    local angle = getFiringSolution(obj)
    if angle ~= nil and bot:hasWeapon(weapon) then
        bot:setAngle(angle + math.rad((math.random()-0.5)*20*(1-difficulty)))
        bot:setWeapon(weapon)
        bot:fire()
        --logprint("bot:fire() called!");
        return(true)
    end
    --logprint("Firing solution not found.");
    return(false)
end
 
 
function getName()
     return("A_Bot")
end
 
function findEnemy()
    local enemies = bot:findItems(ShipType, RobotType)
    local target = nil
    local smallestDist = 999999
   
    for index,enemy in ipairs(enemies) do
        if (enemy:getTeamIndx() ~= bot:getTeamIndx() or not game:isTeamGame()) then     -- Put cheaper test first
            local d = vec.distSquared(botLoc, enemy:getLoc())  
            if( d < smallestDist ) then
                target = enemy
                smallestDist = d
            end
        end  
    end
   
    if(target ~= nil and bot:hasLosPt(target:getLoc())) then
        return(target)
    elseif(enemies[0] ~= nil) then
        return(enemies[0])
    end
   
    return(nil)
end
function getNearestEnemy()
    local enemies = bot:findItems(ShipType, RobotType)
    local target = nil
    local smallestDist = 99999999
   
    for index,enemy in ipairs(enemies) do
        if (enemy:getTeamIndx() ~= bot:getTeamIndx() or not game:isTeamGame()) then     -- Put cheaper test first
            local d = vec.distSquared(botLoc, enemy:getLoc())  
            if( d < smallestDist ) then
                target = enemy
                smallestDist = d
            end
        end  
    end
   
    return(target)
end
 
function shield()
    averageArray[averageIndex] = shieldSelf()
    averageIndex = math.mod(averageIndex,averageMax) + 1
    local shieldPercent = 0
    for i = 1, averageMax do
        if(averageArray[averageIndex]) then
            shieldPercent = shieldPercent + 1
        end
    end
    shieldPercent = shieldPercent / averageMax
    if(shieldPercent > directionThreshold) then
        myOrbitalDirection = -myOrbitalDirection
        for i = 1, averageMax do
            averageArray[i] = false
        end
    end
end
 
function orbitPoint(pt, dir, inputDist, inputStrictness)
    local distAway = bot:getRad()*7
    local strictness = 2
    local direction = 1
    if(dir ~= nil) then direction = dir end
    if(inputDist ~= nil) then distAway = inputDist end
    if(inputStrictness ~= nil) then strictness = inputStrictness end
    if(pt ~= nil) then
        local dist = vec.distanceTo(pt, botLoc)
        local deltaDistance = (dist - distAway) * strictness / distAway
        local sign = 1
        if(deltaDistance > 0) then
            sign = 1
        elseif(deltaDistance < 0) then
            sign = -1
        end
        local changeInAngle = (math.abs(deltaDistance)/(deltaDistance + sign))*math.pi/2
        local angleToPoint = vec.angleTo(pt, bot:getLoc())
        dirToGo = angleToPoint + (math.pi/2 + changeInAngle)*direction
        --bot:setThrust(speed,dirToGo)
    end
end

function gotoPosition(pt)
    if pt ~= nil then
        gotoPositionWasNil = false
        if pathTimer<.01 then
            goalPt=bot:getWaypoint(pt)
            if(goalPt ~= nil) then
                       dirToGo = vec.angleTo(botLoc,goalPt)
                    end
        end
    end
end

function gotoAndOrbitPosition(pt)
    if pt ~= nil then
        gotoPositionWasNil = false
        if not bot:hasLosPt(pt) then
            gotoPositionWasNil = false
            gotoPosition(pt)
        else
            gotoPositionWasNil = false
            orbitPoint(pt, myOrbitalDirection, botRadius * 5, 2)
        end
    end
end
 
--returns if it found an enemy to fight
function attackNearbyEnemies(agressionLevel)
    local target = findEnemy()
    if target ~= nil then
        local targetLoc = target:getLoc()
     
        local dist = vec.distanceTo(botLoc, targetLoc)
        local myPow = (bot:getEnergy() + bot:getHealth() )
        local enemies = bot:findItems(ShipType, RobotType)
     
        --for index, otherShip in ipairs(enemies) do
        -- otherPow = otherPow + target:getEnergy() + target:getHealth()
        --end
        -- Means this, right?
        local otherPow = target:getEnergy() + target:getHealth() * #enemies
     
        --advantage is between -1 and 1, -1 meaning an extreme disadvantage and 1 meaning an extreme advantage
        local advantage = (myPow-otherPow) / math.max(myPow,otherPow)
        if(advantage/2 + .5>agressionLevel) then
            --orbitPoint(targetLoc, myOrbitalDirection, botRadius * 9, 2)
            prevtarget = targetLoc
            return(false)      -- was true
        else
        end
    end
    return(false)
end



 
--Returns the objective for the bot based on myNum.  This makes bots choose different defending locations.
function getObjective(objType, team, onTeam)
    local items = bot:findGlobalItems(objType)
    local itemsOnMyTeam = {}
    local currentIndex = 1
    for ind, it in ipairs(items) do
        local itTeamIndex = it:getTeamIndx()

        if objType == FlagType and gameType == NexusGame then
            if not it:isOnShip() then
                itemsOnMyTeam[currentIndex] = it
                currentIndex = currentIndex + 1
            end
        elseif (objType == FlagType and (gameType == HTFGame or gameType == RetrieveGame) and it:isInCaptureZone()) then
                --logprint(it:getCaptureZone():getTeamIndx());
            if it:getCaptureZone():getTeamIndx() ~= bot:getTeamIndx() then
                itemsOnMyTeam[currentIndex] = it
                currentIndex = currentIndex + 1
            end
        elseif objType == GoalZoneType and (gameType == HTFGame or gameType == RetrieveGame) then
            if (itTeamIndex == team) == onTeam then
                if not it:hasFlag() then
                    itemsOnMyTeam[currentIndex] = it
                    currentIndex = currentIndex + 1
                end
            end
        else
            if (itTeamIndex == NeutralTeamIndx and (objType ~= GoalZoneType or gameType ~= ZoneControlGame)) then
                itTeamIndex = team   -- anything Neutral is on our team (except zone control neutral goal zone)
            end
            if (itTeamIndex == team) == onTeam then
                itemsOnMyTeam[currentIndex] = it
                currentIndex = currentIndex + 1
            end
        end
    end
    local listMax = 0
    --find max
    if itemsOnMyTeam[1] ~= nil then
        for index,item in ipairs(itemsOnMyTeam) do
            if(item ~= nil) then
                listMax = listMax + 1
            end
        end
        local targetNum = math.mod(myNum,listMax) + 1
        return(itemsOnMyTeam[targetNum])
    else
        return(nil)
    end

--  local closestitem = 0 --itemsOnMyTeam[1]
--  local cur = 1
--  local closestdist = 99999999
--  while itemsOnMyTeam[cur] ~= nil do
--      local item1 = itemsOnMyTeam[cur]
--      if item1 ~= nil then
--          local loc = item1.getLoc()
--          if loc ~= nil then
--              local dist = vec.distanceTo(botLoc, loc)
--              if dist < closestdist then
--                  closestdist = dist
--                  closesetitem = item1
--              end
--          end
--      end
--      cur=cur+1
--  end
--  return(closestitem)
end


function doObjective()
    gotoPositionWasNil = true
    if(gameType == BitmatchGame) then
        --Nothing to do here.          
    elseif(gameType == NexusGame) then
        --Grab any flags that is found, and go to nexus when it opens
        local otherFlag = getObjective(FlagType,-100,false)
        if otherFlag ~= nil then gotoPosition(otherFlag:getLoc()) end
        -- logprint(bot:getFlagCount())  -- always 1
        if bot:getFlagCount() > 100 and (game:isNexusOpen() or game:getNexusTimeLeft() < 10000) then  --  Need to know if nexus is open
            local nexusOrFlag = getObjective(NexusType,-100,false)  -- unimplemented push function error.
            if nexusOrFlag ~= nil then gotoPosition(nexusOrFlag:getLoc()) end
        end
    elseif(gameType == RabbitGame) then
        --Grab a flag, or go after the flag.            
        if not bot:hasFlag() then
            local otherFlag = getObjective(FlagType,bot:getTeamIndx(),true)
            gotoPosition(otherFlag:getLoc())
        end
    elseif(gameType == HTFGame or gameType == RetrieveGame) then
        -- Grab the flag and put it into goal zones
        -- Robot keeps trying to pick up the flags that is already in the goalZones
        if bot:hasFlag() then
            local otherFlag = getObjective(GoalZoneType,bot:getTeamIndx(),true)
            if otherFlag ~= nil then gotoPosition(otherFlag:getLoc()) end
        else
            local otherFlag = getObjective(FlagType,bot:getTeamIndx(),true)
            if otherFlag ~= nil then gotoPosition(otherFlag:getLoc()) end
        end
    elseif(gameType == CTFGame) then
        --defend the flag
        local myFlag = getObjective(FlagType,bot:getTeamIndx(),true)
        local otherFlag = getObjective(FlagType,bot:getTeamIndx(),false)
        if(defense<.5) then
            if bot:hasFlag() then
                if not myFlag:isOnShip() then
                    gotoPosition(myFlag:getLoc())
                else
                    gotoAndOrbitPosition(myFlag:getLoc())
                end
                --gotoPosition(myFlag:getLoc())
            elseif(otherFlag ~= nil) then
                if myFlag:isOnShip() then
                    gotoPosition(myFlag:getLoc())
                elseif not otherFlag:isOnShip() then
                    gotoPosition(otherFlag:getLoc())
                else
                    gotoAndOrbitPosition(otherFlag:getLoc())
                end
            end
        else
            if bot:hasFlag() then
                gotoPosition(myFlag:getLoc())
            elseif myFlag:isInInitLoc() then
                gotoAndOrbitPosition(myFlag:getLoc())
            else
                if myFlag:isOnShip() then
                    gotoAndOrbitPosition(myFlag:getLoc())
                else
                    gotoPosition(myFlag:getLoc())
                end
            end
        end
    elseif(gameType == SoccerGame) then
        --grab soccer and put into enemy goal
        -- How do we know if we are holding soccer ? (not supported when cannot pickup soccer (016)
        if bot:getMountedItems(SoccerBallItemType)[1] ~= nil then
            local otherFlag = getObjective(GoalZoneType,bot:getTeamIndx(),false)
            if otherFlag ~= nil then gotoPosition(otherFlag:getLoc()) end          
        else
            local otherFlag = getObjective(SoccerBallItemType,-100,false)
            if otherFlag ~= nil then gotoPosition(otherFlag:getLoc()) end
        end
    elseif(gameType == ZoneControlGame) then
        -- Grab flag, then go after zones that is not ours.
        if not bot:hasFlag() then
            local otherFlag = getObjective(FlagType,bot:getTeamIndx(),true)
            if otherFlag ~= nil then
                if otherFlag:isOnShip() then
                    gotoAndOrbitPosition(otherFlag:getLoc())
                else
                    gotoPosition(otherFlag:getLoc())
                end
            end
        else
            local otherFlag = getObjective(GoalZoneType,bot:getTeamIndx(),false)
            gotoPosition(otherFlag:getLoc())
        end

    elseif(gameType == CoreGame) then
        local obj = getObjective(CoreType,bot:getTeamIndx(),false)
        if obj ~= nil then
            gotoAndOrbitPosition(obj:getLoc())
        end

    end

    -- If we have no where to go, go to nearest enemy.
    if gotoPositionWasNil then
        local target = getNearestEnemy()
        if(target ~= nil) then
            prevtarget = target:getLoc()
        end
        if(prevtarget ~= nil) then gotoAndOrbitPosition(prevtarget) end
    end
end
 
function goInDirection()
    bot:setThrust(speed,dirToGo)
end
 
function onTick()
    botLoc = bot:getLoc()
    pathTimer=pathTimer-bot:getTime()
    assert(bot:getLoc() ~= nil)
   
    if not attackNearbyEnemies(1-agression) then
        doObjective()
    end
    doObjective()
    goInDirection()
    fireAtObjects()
    shield()
    if(pathTimer<0)then
        pathTimer=pathTimerMax+math.random(0,pathTimerMax)
    end
end

-- Helper function to return the closest friendly or neutral item to the bot
-- Returns the closest item
function findClosestFriendly(items)
    if items == nil then
        return nil
    end

    local closestItem = nil
    local smallestDist = signedIntMax
    local distance
    for index, item in ipairs(items) do
        if (item:getTeamIndx() == bot:getTeamIndx() or item:getTeamIndx() == NeutralTeamIndx) then
            distance = vec.distSquared(bot:getLoc(), item:getLoc())  

            if( distance < smallestDist ) then
                closestItem = item
                smallestDist = distance
            end
        end
    end

    return closestItem
end


function goToHealthItem()
    local repairItem = findClosestFriendly(possibleHealthItems)

    if repairItem ~= nil then
        bot:setThrustToPt(repairItem:getLoc())
    end
end


function checkHealth()
    local currentHealth = bot:getHealth()

    if(currentHealth < 1)
     then   goToHealthItem()
    end

end

-- Helper function to return the closest friendly or neutral item to the bot
-- Returns the closest item
function findClosestFriendly(items)
    if items == nil then
        return nil
    end

    local closestItem = nil
    local smallestDist = signedIntMax
    local distance
    for index, item in ipairs(items) do
        if (item:getTeamIndx() == bot:getTeamIndx() or item:getTeamIndx() == NeutralTeamIndx) then
            distance = vec.distSquared(bot:getLoc(), item:getLoc())  

            if( distance < smallestDist ) then
                closestItem = item
                smallestDist = distance
            end
        end
    end

    return closestItem
end


function goToEnergyItem()
    local repairItem = findClosestFriendly(possibleEnergyItems)

    if EnergyItem ~= nil then
        bot:setThrustToPt(repairItem:getLoc())
    end
end


function checkEnergy()
    local currentEnergy = bot:getEnergy()

    if(currentEnergy < 1)
     then   goToEnergyItem()
    end

end

 
Last edited by amgine on Wed Sep 26, 2012 10:52 pm, edited 17 times in total.
<<

BlackBird

User avatar

Posts: 404

Joined: Wed Jun 15, 2011 7:25 pm

Location: Maryland USA

Post Mon May 07, 2012 11:39 am

Re: stronger bot

Try copy/pasteing the bot code into the post instead of uploading the file.
You cannot legislate the poor into prosperity by legislating the wealthy out of prosperity.
<<

raptor

Posts: 1046

Joined: Mon Oct 11, 2010 9:03 pm

Post Mon May 07, 2012 11:52 am

Re: stronger bot

@amgine

Yay for bots!

When posting bot code try clicking the 'Bot Code' button at the top of the post editing window. It will insert something like this:

[code=lua][/code]

Put the bot code in the middle of the tags and preview the post to make sure it worked OK.
<<

BlackBird

User avatar

Posts: 404

Joined: Wed Jun 15, 2011 7:25 pm

Location: Maryland USA

Post Mon May 07, 2012 2:48 pm

Re: stronger bot

raptor wrote:@amgine

Yay for bots!

When posting bot code try clicking the 'Bot Code' button at the top of the post editing window. It will insert something like this:

[code=lua][/code]

Put the bot code in the middle of the tags and preview the post to make sure it worked OK.

What he said.
You cannot legislate the poor into prosperity by legislating the wealthy out of prosperity.
<<

amgine

Posts: 1399

Joined: Thu Apr 19, 2012 2:57 pm

Post Fri Sep 21, 2012 9:45 pm

Re: stronger bot

amgine bot 1.0 released

please give feedback on the following.

1 what it does well
2. what could be improved
3. any problems or bugs enocountered
Bitfighter Forever.
<<

Lamp

User avatar

Posts: 426

Joined: Fri Jan 11, 2013 3:07 pm

Post Wed Jan 30, 2013 1:01 am

Re: Now introducing A_bot!

What does this bot do?
Image
<<

amgine

Posts: 1399

Joined: Thu Apr 19, 2012 2:57 pm

Post Wed Jan 30, 2013 10:15 pm

Re: Now introducing A_bot!

its a slight improvment of the 17b bot i will update it to make 18 bot impossible to beat!
Bitfighter Forever.

Return to Bots

Who is online

Users browsing this forum: No registered users and 18 guests