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 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
def play(botSocket, srvConf): gameNumber = 0 # The last game number bot got from the server (0 == no game has been started) # Each scan will be this wide in radians (note, math.pi*2 radians is the same as 360 Degrees) scanSliceWidth = math.pi 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'])) # start every new game in scan mode. No point waiting if we know we have not fired our canon yet. currentMode = "scan" # The distance to the closest bot in each quadrant is stored in this list. quadrant = [0, 0, 0, 0] try: 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": scanRadStart = 0 scanRadEnd = math.pi while scanRadStart <= scanRadEnd: if scanRadEnd > 2 * math.pi: scanRadEnd = 2 * math.pi scanReply = botSocket.sendRecvMessage({ 'type': 'scanRequest', 'startRadians': scanRadStart, 'endRadians': scanRadEnd }) necWidth = math.pi / 32 if scanReply[ 'distance'] >= 500 else math.pi / 16 #log('distance: %s' % scanReply['distance'], 'INFO') if scanReply[ 'distance'] != 0 and scanSliceWidth <= necWidth: fireDirection = scanRadStart + scanSliceWidth / 2 fireDirection = nbmath.normalizeAngle(fireDirection) botSocket.sendRecvMessage({ 'type': 'fireCanonRequest', 'direction': fireDirection, 'distance': scanReply['distance'] }) currentMode = "wait" elif scanReply[ 'distance'] != 0 and scanSliceWidth >= necWidth: scanSliceWidth /= 2 scanRadEnd = (scanRadStart + scanRadEnd) / 2 else: scanRadStart = scanRadEnd scanRadEnd = scanRadStart + scanSliceWidth if scanReply[ 'distance'] == 0 and scanSliceWidth <= necWidth: scanSliceWidth *= 2 elif currentMode == "wait": break scanSliceWidth = math.pi 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 ''' pi/2 pi 0 3pi/2 ''' try: # turns around before hitting the edge, hopefully getLocationReply = botSocket.sendRecvMessage( {'type': 'getLocationRequest'}) xMin = math.pi / 2 + random.random() * math.pi - math.pi xR = xMin if xMin > 0 else 3 * math.pi / 2 + random.random( ) * math.pi / 2 x = getLocationReply['x'] y = getLocationReply['y'] if abs(x - 1000) < 300 or abs(y - 1000) < 300 or abs( x - 1000) > 700 or abs(y - 1000) > 300: botSocket.sendRecvMessage({ 'type': 'setSpeedRequest', 'requestedSpeed': 0 }) #lower x boundary if round(getLocationReply['x']) <= srvConf['botRadius'] + 500: botSocket.sendRecvMessage({ 'type': 'setDirectionRequest', 'requestedDirection': xR }) botSocket.sendMessage({ 'type': 'setSpeedRequest', 'requestedSpeed': 35 }) #upper x boundary elif round(getLocationReply['x'] ) >= srvConf['arenaSize'] - srvConf['botRadius'] - 500: botSocket.sendRecvMessage({ 'type': 'setDirectionRequest', 'requestedDirection': math.pi / 2 + random.random() * math.pi }) botSocket.sendMessage({ 'type': 'setSpeedRequest', 'requestedSpeed': 35 }) #lower y boundary elif round(getLocationReply['y']) <= srvConf['botRadius'] + 500: botSocket.sendRecvMessage({ 'type': 'setDirectionRequest', 'requestedDirection': random.random() * math.pi }) botSocket.sendMessage({ 'type': 'setSpeedRequest', 'requestedSpeed': 35 }) #upper y boundary elif round(getLocationReply['y'] ) >= srvConf['arenaSize'] - srvConf['botRadius'] - 500: botSocket.sendRecvMessage({ 'type': 'setDirectionRequest', 'requestedDirection': math.pi + random.random() * math.pi }) botSocket.sendMessage({ 'type': 'setSpeedRequest', 'requestedSpeed': 35 }) else: # variables that are iterated in the while loop x = 0 i = 0 # ScaredyCat scans all four quadrants and looks for the closest target while x < 2.0: # ScaredyCat scans the quadrant starting from x pi to 1/2 more than x. This is a quarter of a circle. # Then , it adds the server's response to the list scanReply = botSocket.sendRecvMessage({ 'type': 'scanRequest', 'startRadians': math.pi * x, 'endRadians': math.pi * (x + 1.0 / 2.0) }) quadrant[i] = scanReply['distance'] x += 1.0 / 2.0 i += 1 # finds how far the closest enemy is from us (can't be zero) minDistance = min(i for i in quadrant if i > 0) # finds which quadrant that enemy is in moveDirection = quadrant.index(minDistance) # move perpendicular to the enemy. # ie. if closest enemy is in quadrant 0, it will move in the direction 3pi/4 or 7pi/4 ''' pi/2 1 | 0 pi ----|---- 0 2 | 3 3pi/2 ''' move1 = 5 * math.pi / 4 + random.random() * math.pi move2 = 7 * math.pi / 4 + random.random() * math.pi move3 = move1 if move1 < 2 * math.pi else random.random( ) * math.pi / 4 move4 = move2 if move2 < 2 * math.pi else random.random( ) * 3 * math.pi / 4 if moveDirection == 0: moveDirection = math.pi * (3.0 / 4.0) + random.random() * math.pi elif moveDirection == 1: moveDirection = move3 elif moveDirection == 2: moveDirection = move4 elif moveDirection == 3: moveDirection = math.pi * (1.0 / 4.0) + random.random() * math.pi # Turn in a new direction botSocket.sendMessage({ 'type': 'setDirectionRequest', 'requestedDirection': moveDirection }) # Request we start accelerating to max speed botSocket.sendMessage({ 'type': 'setSpeedRequest', 'requestedSpeed': 20 }) 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 '''
def play(botSocket, srvConf, q): arenaSize = srvConf["arenaSize"] gameNumber = 0 # The last game number bot got from the server (0 == no game has been started) getLocationReply = {"x": 0, "y": 0} mouseDown = False mousePos = {"x": 0, "y": 0} waiting = True # whether to wait for shell to explode firing_distance = 0 shell_time = 0 global keysDown global steering 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 # log the keys being used log("The up key is " + str(upKey), "INFO") log("The down key is " + str(downKey), "INFO") log("The left key is " + str(leftKey), "INFO") log("The right key is " + str(rightKey), "INFO") # log the current movement mode if (steering): log( "Steering. Use left and right keys to steer, and up and down to " + "control speed.", "INFO") else: log("Directional movement. Bot will go in direction of keys pressed.", "INFO") 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'])) # Reset variables keysDown["Up"] = False keysDown["Down"] = False keysDown["Left"] = False keysDown["Right"] = False mouseDown = False waiting = True try: getLocationReply = botSocket.sendRecvMessage( {"type": "getLocationRequest"}) getSpeedReply = botSocket.sendRecvMessage( {"type": "getSpeedRequest"}) radians = 0 requestedSpeed = getSpeedReply["currentSpeed"] # will add to later # check for shots using a queue (good asynchronous/threading practice) # hey wait why is this a queue but key-presses aren't?? MARTIN! while not q.empty(): nextData = q.get() if ("mousePos" in nextData): mousePos = nextData["mousePos"] elif ("mouseDown" in nextData): mouseDown = nextData["mouseDown"] # force a shot on click to emulate old behaviour for # those who thoroughly enjoyed clicking to shoot if (mouseDown == True): shoot() waiting = True else: waiting = False else: # no I don't feel like ending the program today log("Unexpected index name in q: " + str(q), "WARNING") q.task_done() # bot steers left and right, and up and down control speed if (steering): currAngle = botSocket.sendRecvMessage( {"type": "getDirectionRequest"}) radians = currAngle["currentDirection"] # will add to later # steer if (keysDown["Left"]): radians += 1 # ~pi/3 radians or ~60 radians = nbmath.normalizeAngle(radians) elif (keysDown["Right"]): radians -= 1 radians = nbmath.normalizeAngle(radians) # speed up if (keysDown["Up"]): requestedSpeed = 100 # slow down elif (keysDown["Down"]): requestedSpeed = 0 # bot moves in direction of arrow keys else: xDir = 0 yDir = 0 if (keysDown["Left"]): xDir = -1 elif (keysDown["Right"]): xDir = 1 else: xDir = 0 if (keysDown["Up"]): yDir = 1 elif (keysDown["Down"]): yDir = -1 else: yDir = 0 if (xDir == 0 and yDir == 0): requestedSpeed = 0 else: radians = nbmath.normalizeAngle(math.atan2(yDir, xDir)) requestedSpeed = 50 botSocket.sendMessage({ "type": "setDirectionRequest", "requestedDirection": radians }) botSocket.sendMessage({ "type": "setSpeedRequest", "requestedSpeed": requestedSpeed }) # wait until shell explodes before shooting again, or if player clicks again if (mouseDown): if (waiting): if firing_distance - ( time.perf_counter() - shell_time ) / srvConf['stepSec'] * srvConf['shellSpeed'] <= 0: waiting = False if (not waiting): waiting = True shoot() 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