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