Exemplo n.º 1
0
def scanRequest(d, msg, src):
    if d.bots[src]['health'] == 0:
        return {
            'type': 'Error',
            'result': "Can't process ScanRequest when health == 0"
        }
    else:
        distance = 0
        bot = d.bots[src]
        for src2, bot2 in d.bots.items():
            if src != src2 and bot2['health'] != 0:
                # don't detect bot2 if it's fully inside a jam Zone.
                jammed = False
                for jz in d.conf['jamZones']:
                    if nbmath.distance(
                            bot2['x'], bot2['y'], jz['x'],
                            jz['y']) + d.conf['botRadius'] < jz['radius']:
                        jammed = True

                if not jammed:
                    dis = nbmath.contains(bot['x'], bot['y'],
                                          msg['startRadians'],
                                          msg['endRadians'], bot2['x'],
                                          bot2['y'])
                    if dis != 0 and distance == 0:
                        distance = dis
                    elif dis != 0 and dis < distance:
                        distance = dis

        return {'type': "scanReply", 'distance': distance}
Exemplo n.º 2
0
def mkObstacles(d, n):
    '''
    Randomly lay out obstacles with so they are at least 2 and a bit bot diameters away from any wall or other obstacle.
    '''
    obstacles = []
    rad = d.conf['arenaSize'] * d.conf['obstacleRadius'] / 100.0

    for i in range(n):
        overlaps = True
        attempts = 0
        while overlaps:
            attempts += 1
            new = {
                'x': random.random() * (d.conf['arenaSize'] - rad * 8.1) + rad * 4.1,
                'y': random.random() * (d.conf['arenaSize'] - rad * 8.1) + rad * 4.1,
                'radius': rad
                }
            overlaps = False
            for o in obstacles:
                if nbmath.distance(o['x'], o['y'], new['x'], new['y']) < o['radius'] + \
                        new['radius'] + d.conf['botRadius'] * 4.1:
                    overlaps = True
                    break
            if overlaps == False:
                obstacles.append(new)
            else:
                log("Obstacle overlapped during random layout. Trying again.", "VERBOSE")
                if attempts > 999:
                    log("Could not layout obstacles without overlapping.", "FAILURE")
                    quit()

    return obstacles
Exemplo n.º 3
0
    def run(self):
        name = self.name
        botSocket = self.botSocket
        srvConf = self.srvConf
        mydata = self.mydata
        friendsData = self.friendsData

        log(name + ": Running!")

        self.stop = False  # when this becomes True the run method must return.
        while not self.stop:
            try:
                # Store my location in mydata so friend can see it.
                getLocationReply = botSocket.sendRecvMessage({'type': 'getLocationRequest'})
                mydata.x = getLocationReply['x']
                mydata.y = getLocationReply['y']

                # Compute distance to friend and set speed based on distance (slower as we get closer).
                distanceToFriend = nbmath.distance(mydata.x, mydata.y, friendsData.x, friendsData.y)
                botSocket.sendRecvMessage({'type': 'setSpeedRequest',
                                           'requestedSpeed': min(100, distanceToFriend / 1000 * 100)})

                # Compute angle to friend and go in that direction.
                angleToFriend = nbmath.angle(mydata.x, mydata.y, friendsData.x, friendsData.y)
                botSocket.sendRecvMessage({'type': 'setDirectionRequest', 'requestedDirection': angleToFriend})

                log(f"{name}: Distance to friend == {distanceToFriend:>4.2f}, Angle to friend == {angleToFriend:>4.2f},", "INFO")

            except nbipc.NetBotSocketException as e:
                log(name + ": " + str(e), "WARNING")
                continue
Exemplo n.º 4
0
    def shoot():
        nonlocal mousePos

        angle = nbmath.angle(getLocationReply["x"], getLocationReply["y"],
                             mousePos["x"], mousePos["y"])
        dist = nbmath.distance(getLocationReply["x"], getLocationReply["y"],
                               mousePos["x"], mousePos["y"])
        botSocket.sendMessage({
            "type": "fireCanonRequest",
            "direction": angle,
            "distance": dist
        })

        shell_time = time.perf_counter()
        firing_distance = dist
Exemplo n.º 5
0
def findOverlapingBotsAndObstacles(d, bots):
    """
    bots is a dict/list of bot locations: {key:{'x': x,'y': y}, ...}
    bots can also contain health: {key:{'x': x,'y': y, 'health': h}, ...}
    Return any pair (key,i) of (key,obstacle) that overlap, else return False
    """

    try:
        keys = list(bots.keys())
    except AttributeError:
        keys = range(len(bots))

    for k in keys:
        bot = bots[k]
        if 'health' not in bot or bot['health'] != 0:
            for obstacle in d.conf['obstacles']:
                if nbmath.distance(bot['x'], bot['y'], obstacle['x'], obstacle['y']) <= \
                        d.conf['botRadius'] + obstacle['radius']:
                    return [k, obstacle]

    return False
Exemplo n.º 6
0
def findOverlapingBots(d, bots):
    """
    bots is a dict/list of bot locations: {key:{'x': x,'y': y}, ...}
    bots can also contain health: {key:{'x': x,'y': y, 'health': h}, ...}
    Return any pair (key,key) of bots that overlap, else return False
    """
    try:
        keys = list(bots.keys())
    except AttributeError:
        keys = range(len(bots))

    for i in range(0, len(keys) - 1):
        boti = bots[keys[i]]
        if 'health' not in boti or boti['health'] != 0:
            for j in range(i + 1, len(keys)):
                botj = bots[keys[j]]
                if 'health' not in botj or botj['health'] != 0:
                    if nbmath.distance(boti['x'], boti['y'], botj['x'], botj['y']) <= d.conf['botRadius'] * 2:
                        return [keys[i], keys[j]]

    return False
Exemplo n.º 7
0
    def run(self):
        name = self.name
        botSocket = self.botSocket
        srvConf = self.srvConf
        mydata = self.mydata
        friendsData = self.friendsData

        log(name + ": Running!")

        self.stop = False  # when this becomes True the run method must return.
        while not self.stop:
            try:
                # Store my location in mydata so friend can see it.
                getLocationReply = botSocket.sendRecvMessage({'type': 'getLocationRequest'})
                mydata.x = getLocationReply['x']
                mydata.y = getLocationReply['y']

                # Compute distance to friend.
                distanceToFriend = nbmath.distance(mydata.x, mydata.y, friendsData.x, friendsData.y)
                log(f"{name}: Distance to friend == {distanceToFriend:>4.2f}", "INFO")

                if distanceToFriend > 300:
                    # wait for friend to catch up.
                    botSocket.sendRecvMessage({'type': 'setSpeedRequest', 'requestedSpeed': 0})
                    log(name + ": Waiting for friend to get closer.", "INFO")
                else:
                    getSpeedReply = botSocket.sendRecvMessage({'type': 'getSpeedRequest'})
                    if getSpeedReply['requestedSpeed'] == 0:
                        radians = random.random() * 2 * math.pi
                        botSocket.sendRecvMessage({'type': 'setDirectionRequest', 'requestedDirection': radians})
                        botSocket.sendRecvMessage({'type': 'setSpeedRequest', 'requestedSpeed': 100})
                        log(f"{name}: Requested to go {radians:>4.2f} radians at max speed.", "INFO")

            except nbipc.NetBotSocketException as e:
                log(name + ": " + str(e), "WARNING")
                continue
Exemplo n.º 8
0
def step(d):
    startTime = time.perf_counter()

    d.state['gameStep'] += 1
    d.state['serverSteps'] += 1

    # for each bot that is alive, copy health to so we know what it was at the start of the step.
    aliveBots = {}
    for src, bot in d.bots.items():
        if bot['health'] != 0:
            aliveBots[src] = bot['health']

    # for all bots that are alive
    for src, bot in d.bots.items():
        if src in aliveBots:
            # change speed if needed
            if bot['currentSpeed'] > bot['requestedSpeed']:
                bot['currentSpeed'] -= d.getClassValue('botAccRate', bot['class'])
                if bot['currentSpeed'] < bot['requestedSpeed']:
                    bot['currentSpeed'] = bot['requestedSpeed']
            elif bot['currentSpeed'] < bot['requestedSpeed']:
                bot['currentSpeed'] += d.getClassValue('botAccRate', bot['class'])
                if bot['currentSpeed'] > bot['requestedSpeed']:
                    bot['currentSpeed'] = bot['requestedSpeed']

            # change direction if needed
            if bot['currentDirection'] != bot['requestedDirection']:
                if bot['currentDirection'] != bot['requestedDirection'] and bot['currentSpeed'] == 0:
                    # turn instanly if bot is not moving
                    bot['currentDirection'] = bot['requestedDirection']
                else:
                    # how much can we turn at the speed we are going?
                    turnRate = d.getClassValue('botMinTurnRate', bot['class']) \
                        + (d.getClassValue('botMaxTurnRate', bot['class']) -
                           d.getClassValue('botMinTurnRate', bot['class'])) \
                        * (1 - bot['currentSpeed'] / 100)

                    # if turn is negative and does not pass over 0 radians
                    if bot['currentDirection'] > bot['requestedDirection'] and \
                            bot['currentDirection'] - bot['requestedDirection'] <= math.pi:
                        bot['currentDirection'] -= turnRate
                        if bot['currentDirection'] <= bot['requestedDirection']:
                            bot['currentDirection'] = bot['requestedDirection']

                    # if turn is negative and passes over 0 radians, so we may need to normalize angle
                    elif bot['requestedDirection'] > bot['currentDirection'] and \
                            bot['requestedDirection'] - bot['currentDirection'] >= math.pi:
                        bot['currentDirection'] = nbmath.normalizeAngle(bot['currentDirection'] - turnRate)
                        if bot['currentDirection'] <= bot['requestedDirection'] and bot['currentDirection'] >= bot['requestedDirection'] - math.pi:
                            bot['currentDirection'] = bot['requestedDirection']

                    # if turn is positive and does not pass over 0 radians
                    elif bot['requestedDirection'] > bot['currentDirection'] and \
                            bot['requestedDirection'] - bot['currentDirection'] <= math.pi:
                        bot['currentDirection'] += turnRate
                        if bot['requestedDirection'] <= bot['currentDirection']:
                            bot['currentDirection'] = bot['requestedDirection']

                    # if turn is positive and passes over 0 radians
                    elif bot['currentDirection'] > bot['requestedDirection'] and \
                            bot['currentDirection'] - bot['requestedDirection'] >= math.pi:
                        bot['currentDirection'] = nbmath.normalizeAngle(bot['currentDirection'] + turnRate)
                        if bot['currentDirection'] >= bot['requestedDirection'] and bot['currentDirection'] <= bot['requestedDirection'] + math.pi:
                            bot['currentDirection'] = bot['requestedDirection']
            # move bot
            if bot['currentSpeed'] != 0:
                bot['x'], bot['y'] = nbmath.project(bot['x'], bot['y'],
                                        bot['currentDirection'],
                                        bot['currentSpeed'] / 100.0 * d.getClassValue('botMaxSpeed', bot['class']))

    # set starting hitSeverity to 0 for all robots. hitSeverity == 0 means robot did not 
    # hit anything this step.
    for src, bot in d.bots.items():
        bot['hitSeverity'] = 0.0

    # do until we get one clean pass where no bot hitting wall, obstacle or other bot.
    foundOverlap = True
    while foundOverlap:
        foundOverlap = False

        # detect if bots hit walls. if they, did move them so they are just barely not touching,
        for src, bot in d.bots.items():
            hitSeverity = 0
            if bot['x'] - d.conf['botRadius'] < 0:
                # hit left side
                bot['x'] = d.conf['botRadius'] + 1
                hitSeverity = getHitSeverity(d, bot, math.pi)
            if bot['x'] + d.conf['botRadius'] > d.conf['arenaSize']:
                # hit right side
                bot['x'] = d.conf['arenaSize'] - d.conf['botRadius'] - 1
                hitSeverity = getHitSeverity(d, bot, 0)
            if bot['y'] - d.conf['botRadius'] < 0:
                # hit bottom side
                bot['y'] = d.conf['botRadius'] + 1
                hitSeverity = getHitSeverity(d, bot, math.pi * 3 / 2)
            if bot['y'] + d.conf['botRadius'] > d.conf['arenaSize']:
                # hit top side
                bot['y'] = d.conf['arenaSize'] - d.conf['botRadius'] - 1
                hitSeverity = getHitSeverity(d, bot, math.pi/2)
    
            if hitSeverity:
                foundOverlap = True
                bot['hitSeverity'] = max(bot['hitSeverity'], hitSeverity)

        # detect if bots hit obstacles, if the did move them so they are just barely not touching,
        overlap = findOverlapingBotsAndObstacles(d, d.bots)
        while overlap:
            foundOverlap = True
            b = d.bots[overlap[0]]
            o = overlap[1]
            # find angle to move bot directly away from obstacle
            a = nbmath.angle(o['x'], o['y'], b['x'], b['y'])
            # find min distance to move bot so it don't touch (plus 0.5 for safety).
            distance = d.conf['botRadius'] + o['radius'] + 0.5 - nbmath.distance(o['x'], o['y'], b['x'], b['y'])
            # move bot
            b['x'], b['y'] = nbmath.project(b['x'], b['y'], a, distance)
            # record damage
            hitSeverity = getHitSeverity(d, b, a + math.pi)
            b['hitSeverity'] = max(b['hitSeverity'], hitSeverity)
            # check for more bots overlapping
            overlap = findOverlapingBotsAndObstacles(d, d.bots)
                    
        # detect if bots hit other bots, if the did move them so they are just barely not touching,
        overlap = findOverlapingBots(d, d.bots)
        while overlap:
            foundOverlap = True
            b1 = d.bots[overlap[0]]
            b2 = d.bots[overlap[1]]
            # find angle to move bot directly away from each other
            a = nbmath.angle(b1['x'], b1['y'], b2['x'], b2['y'])
            # find min distance to move each bot so they don't touch (plus 0.5 for saftly).
            between = nbmath.distance(b1['x'], b1['y'], b2['x'], b2['y'])
            distance = between / 2 - (between - d.conf['botRadius']) + 0.5
            # move bots
            b1['x'], b1['y'] = nbmath.project(b1['x'], b1['y'], a + math.pi, distance)
            b2['x'], b2['y'] = nbmath.project(b2['x'], b2['y'], a, distance)
            # record damage
            hitSeverity = getHitSeverity(d, b1, a, b2)
            b1['hitSeverity'] = max(b1['hitSeverity'], hitSeverity)
            b2['hitSeverity'] = max(b2['hitSeverity'], hitSeverity)
            # check for more bots overlapping
            overlap = findOverlapingBots(d, d.bots)

    # give damage (only once this step) to bots that hit things. Also stop them.
    for src, bot in d.bots.items():
        if bot['hitSeverity']:
            if d.conf['simpleCollisions']:
                bot['hitSeverity'] = 1
            bot['health'] = max(0, bot['health'] - bot['hitSeverity'] * d.conf['hitDamage'] * d.getClassValue('botArmor', bot['class']))
            bot['currentSpeed'] = 0
            bot['requestedSpeed'] = 0
        del bot['hitSeverity']

    # for all shells
    for src in list(d.shells.keys()):
        shell = d.shells[src]

        # remember shells start point before moving
        oldx = shell['x']
        oldy = shell['y']

        # move shell
        distance = min(d.getClassValue('shellSpeed', d.bots[src]['class']), shell['distanceRemaining'])
        shell['x'], shell['y'] = nbmath.project(shell['x'], shell['y'], shell['direction'], distance)
        shell['distanceRemaining'] -= distance

        # did shell hit an obstacle?
        shellHitObstacle = False
        for o in d.conf['obstacles']:
            if nbmath.intersectLineCircle(oldx, oldy, shell['x'], shell['y'], o['x'], o['y'], o['radius']):
                shellHitObstacle = True

        # if did not hit an obstacle and shell's explosion would touch inside of arena
        if not shellHitObstacle and \
           (shell['x'] > d.getClassValue('explRadius', d.bots[src]['class']) * -1 and shell['x'] < d.conf['arenaSize'] + d.getClassValue('explRadius', d.bots[src]['class']) and
                shell['y'] > d.getClassValue('explRadius', d.bots[src]['class']) * -1 and shell['y'] < d.conf['arenaSize'] + d.getClassValue('explRadius', d.bots[src]['class'])):

            # if shell has reached it destination then explode.
            if shell['distanceRemaining'] <= 0:
                # apply damage to bots.
                for k, bot in d.bots.items():
                    if bot['health'] > 0:
                        distance = nbmath.distance(bot['x'], bot['y'], shell['x'], shell['y'])
                        if distance < d.getClassValue('explRadius', d.bots[src]['class']):
                            damage = d.getClassValue('explDamage', d.bots[src]['class']) * (1 - distance / d.getClassValue('explRadius', d.bots[src]['class']))
                            bot['health'] = max(0, bot['health'] - (damage * d.getClassValue('botArmor', bot['class'])))
                            # allow recording of inflicting damage that is greater than health of hit robot.
                            # also record damage to oneself.
                            d.bots[src]['shellDamage'] += damage

                # store the explosion so viewers can display it. we can't use src as index because it is possible for two explosions
                # from same bot to exist (but not likly).
                d.explosions[d.state['explIndex']] = {
                    'x': shell['x'],
                    'y': shell['y'],
                    'stepsAgo': 0,
                    'src': src  # this is needed by viewer to color this explosion based on the bot who fired it.
                    }
                d.state['explIndex'] += 1
                if d.state['explIndex'] > 65000:
                    d.state['explIndex'] = 0

                # this shell exploed so remove it
                del d.shells[src]
        else:
            # shell hit obstacle or left arena so remove it without exploding
            del d.shells[src]

    # Remove old explosions and add 1 to other explosions stepsAgo.
    # Note, We only keep these around so the viewer can do a nice animation
    # over a number of steps before they are removed.
    for key in list(d.explosions.keys()):
        expl = d.explosions[key]
        if expl['stepsAgo'] == d.conf['keepExplosionSteps']:
            del d.explosions[key]
        else:
            expl['stepsAgo'] += 1

    # find how many points bots that died this step will get. (Based on how many bots have died previouly)
    if len(aliveBots) == d.conf['botsInGame']:
        points = 0  # first to die
    elif len(aliveBots) > d.conf['botsInGame'] / 2:
        points = 2  # died in first half
    else:
        points = 5  # died in second half

    # Kill all bots if we have reached the max steps and there is still more than one bot alive.
    if d.state['gameStep'] == d.conf['stepMax'] and len(aliveBots) != 1:
        log("Game reached stepMax with more than one bot alive. Killing all bots.")
        for src in aliveBots:
            d.bots[src]['health'] = 0

    # Assign points to bots that died this turn
    for src in list(aliveBots.keys()):
        if d.bots[src]['health'] == 0:
            d.bots[src]['points'] += points
            del aliveBots[src]

    # If only one bot is left then end game.
    if len(aliveBots) == 1:
        src = list(aliveBots.keys())[0]
        d.bots[src]['winHealth'] += d.bots[src]['health']
        d.bots[src]['winCount'] += 1
        d.bots[src]['health'] = 0
        d.bots[src]['points'] += 10  # last robot (winner)
        del aliveBots[src]

    d.state['stepTime'] += time.perf_counter() - startTime
Exemplo n.º 9
0
def binarySearch(l, r):
    # Check base case
    if r >= l:
        global currentMode
        global savedDirection
        global smallestDistance
        global previousX
        global previousY
        global shotX
        global shotY
        global stepCount
        global shotCount
        mid = (l + r) / 2
        # If element is present at the middle itself
        if (mid >= r - 1):
            fireDirection = ((((mid + r) / 2) / 128) * 2 * math.pi)
            savedDirection = (mid + r) / 2
            currentMode = "wait"
            tempX = smallestDistance * math.cos(fireDirection)
            tempY = smallestDistance * math.sin(fireDirection)
            if (nbmath.distance(shotX, shotY, tempX, tempY) < 30
                    and shotX != -1):
                tempSteps = smallestDistance // 40
                tempAngle = nbmath.angle(shotX, shotY, tempX, tempY)
                v = nbmath.distance(tempX, tempY, shotX, shotY)
                newX = previousX + (math.cos(tempAngle) * tempSteps * v)
                newY = previousY + (math.sin(tempAngle) * tempSteps * v)
                newAngle = nbmath.angle(previousX, previousY, newX, newY)
                botSocket.sendRecvMessage({
                    'type': 'fireCanonRequest',
                    'direction': newAngle,
                    'distance': smallestDistance
                })
            else:
                botSocket.sendRecvMessage({
                    'type': 'fireCanonRequest',
                    'direction': fireDirection,
                    'distance': smallestDistance
                })
            stepCount += 1
            shotCount = stepCount
            shotX = tempX
            shotY = tempY
            return
        elif (mid <= l + 1):
            fireDirection = ((((mid + l) / 2) / 128) * 2 * math.pi)
            savedDirection = (mid + l) / 2
            currentMode = "wait"
            tempX = smallestDistance * math.cos(fireDirection)
            tempY = smallestDistance * math.sin(fireDirection)
            if (nbmath.distance(shotX, shotY, tempX, tempY) < 30
                    and shotX != -1):
                tempSteps = smallestDistance // 40
                tempAngle = nbmath.angle(shotX, shotY, tempX, tempY)
                v = nbmath.distance(tempX, tempY, shotX, shotY)
                newX = previousX + (math.cos(tempAngle) * tempSteps * v)
                newY = previousY + (math.sin(tempAngle) * tempSteps * v)
                newAngle = nbmath.angle(previousX, previousY, newX, newY)
                botSocket.sendRecvMessage({
                    'type': 'fireCanonRequest',
                    'direction': newAngle,
                    'distance': smallestDistance
                })
            else:
                botSocket.sendRecvMessage({
                    'type': 'fireCanonRequest',
                    'direction': fireDirection,
                    'distance': smallestDistance
                })
            stepCount += 1
            shotCount = stepCount
            shotX = tempX
            shotY = tempY
            return
        scanReply = botSocket.sendRecvMessage({
            'type':
            'scanRequest',
            'startRadians': (l / 128) * 2 * math.pi,
            'endRadians': (mid / 128) * 2 * math.pi
        })
        stepCount += 1
        #print("scan" + str((l/128) * 2 * math.pi) + " " + str((mid/128) * 2 * math.pi))
        if ((scanReply['distance'] >= smallestDistance - float(30))
                and (scanReply['distance'] <= smallestDistance + float(30))):
            smallestDistance = scanReply['distance']
            return binarySearch(l, mid)
            # Else the element can only be present
        # in right subarray
        else:
            return binarySearch(mid, r)
    else:
        # Element is not present in the array
        return -1
Exemplo n.º 10
0
def play(botSocket, srvConf):
    gameNumber = 0  # The last game number bot got from the server (0 == no game has been started)

    while True:
        try:
            # Get information to determine if bot is alive (health > 0) and if a new game has started.
            getInfoReply = botSocket.sendRecvMessage(
                {'type': 'getInfoRequest'})
        except nbipc.NetBotSocketException as e:
            # We are always allowed to make getInfoRequests, even if our health == 0. Something serious has gone wrong.
            log(str(e), "FAILURE")
            log("Is netbot server still running?")
            quit()

        if getInfoReply['health'] == 0:
            # we are dead, there is nothing we can do until we are alive again.
            continue

        if getInfoReply['gameNumber'] != gameNumber:
            # A new game has started. Record new gameNumber and reset any variables back to their initial state
            gameNumber = getInfoReply['gameNumber']
            log("Game " + str(gameNumber) + " has started. Points so far = " +
                str(getInfoReply['points']))

            maxSpeed = 70
            reversing = False
            scanCounter = 0
            defensiveScan = False
            counter = 0
            direction = 0
            speed = 50
            startingDirection = True
            wall = ""
            currentMode = "scan"
            scanSlices = 32
            nextScanSlice = 0
            scanSliceWidth = math.pi * 2 / scanSlices
            maxScanSlice = 0
            minScanSlice = 0

            getLocationReply = botSocket.sendRecvMessage(
                {'type': 'getLocationRequest'})
            x = getLocationReply['x']
            y = getLocationReply['y']

            # run to nearest wall from starting location
            if x < 500 and y < 500:
                if x >= y:
                    direction = math.pi * 3 / 2
                    wall = "down"
                else:
                    direction = math.pi
                    wall = "left"
            elif x < 500 and y >= 500:
                if x >= 1000 - y:
                    direction = math.pi / 2
                    wall = "up"
                else:
                    direction = math.pi
                    wall = "left"
            elif x >= 500 and y < 500:
                if 1000 - x <= y:
                    direction = 0
                    wall = "right"
                else:
                    direction = math.pi * 3 / 2
                    wall = "down"
            elif x >= 500 and y >= 500:
                if x >= y:
                    direction = 0
                    wall = "right"
                else:
                    direction = math.pi / 2
                    wall = "up"

        try:

            getLocationReply = botSocket.sendRecvMessage(
                {'type': 'getLocationRequest'})
            x = getLocationReply['x']
            y = getLocationReply['y']
            getSpeedReply = botSocket.sendRecvMessage(
                {'type': 'getSpeedRequest'})

            if getSpeedReply['currentSpeed'] == 0:

                if not (startingDirection):
                    direction = reverseDirection(direction, wall)
                if counter >= 1:
                    startingDirection = False

                # Turn in a new direction
                botSocket.sendRecvMessage({
                    'type': 'setDirectionRequest',
                    'requestedDirection': direction
                })

                speed = maxSpeed

                # log some useful information.
                log(
                    "Requested to go " + str(direction / math.pi) +
                    " pi radians at speed: " + str(speed), "INFO")
                botSocket.sendRecvMessage({
                    'type': 'setSpeedRequest',
                    'requestedSpeed': speed
                })
                reversing = False

            elif not (reversing):

                if startingDirection:
                    if (x <= 100 and direction
                            == math.pi) or (x >= 900 and direction == 0) or (
                                y <= 100 and direction == math.pi * 3 / 2) or (
                                    y >= 900 and direction == math.pi / 2):
                        speed = 10
                else:
                    if (x <= 200 and direction
                            == math.pi) or (x >= 800 and direction == 0) or (
                                y <= 200 and direction == math.pi * 3 / 2) or (
                                    y >= 800 and direction == math.pi / 2):
                        speed = 0
                        reversing = True
                    else:
                        speed = maxSpeed

                botSocket.sendRecvMessage({
                    'type': 'setSpeedRequest',
                    'requestedSpeed': speed
                })

            if not (startingDirection):
                if currentMode == "wait":
                    # find out if we already have a shell in the air. We need to wait for it to explode before
                    # we fire another shell. If we don't then the first shell will never explode!
                    getCanonReply = botSocket.sendRecvMessage(
                        {'type': 'getCanonRequest'})
                    if not getCanonReply['shellInProgress']:
                        # we are ready to shoot again!
                        currentMode = "scan"

                if currentMode == "scan":

                    defensiveScan = True if scanCounter % 6 == 0 else False

                    # defensive scan
                    if defensiveScan:

                        scanSliceTemp = nextScanSlice

                        scanRadStart = direction - math.pi / 4
                        scanRadEnd = direction + math.pi / 4

                        scanRadStart = nbmath.normalizeAngle(scanRadStart)
                        scanRadEnd = nbmath.normalizeAngle(scanRadEnd)

                        if scan(scanRadStart, scanRadEnd):
                            reverseDirection(direction, wall)

                    else:

                        scanning(minScanSlice, maxScanSlice, 1)
                        getLocationReply = botSocket.sendRecvMessage(
                            {'type': 'getLocationRequest'})
                        x = getLocationReply['x']
                        y = getLocationReply['y']

                        botSocket.sendRecvMessage({
                            'type':
                            'fireCanonRequest',
                            'direction':
                            nbmath.angle(x, y, enemyX, enemyY),
                            'distance':
                            nbmath.distance(x, y, enemyX, enemyY)
                        })
                        currentMode = "wait"

                    scanCounter += 1

            # initialize starting scan slice
            else:
                if wall == "up":
                    minScanSlice = 16
                    maxScanSlice = 32
                elif wall == "left":
                    minScanSlice = 24
                    maxScanSlice = 8
                elif wall == "down":
                    minScanSlice = 0
                    maxScanSlice = 16
                elif wall == "right":
                    minScanSlice = 8
                    maxScanSlice = 24

            counter += 1

        except nbipc.NetBotSocketException as e:
            # Consider this a warning here. It may simply be that a request returned
            # an Error reply because our health == 0 since we last checked. We can
            # continue until the next game starts.
            log(str(e), "WARNING")
            continue