def getData(socket, callback): try: # compute the length of the message (4 byte, little-endian) recstr = socket.recv(4) while len(recstr) < 4: recstr += socket.recv(4 - len(recstr)) assert len(recstr) == 4 lenstr = ["{:02x}".format(ord(char)) for char in recstr] lenstr.reverse() length = int(''.join(lenstr), 16) # receive message into buffer data = socket.recv(length) received = len(data) buff = [] while received < length: buff.append(data) data = socket.recv(length - received) received += len(data) else: assert received == length if buff: buff.append(data) data = ''.join(buff) return data except sock.timeout: trap("Socket operation (receive) timed out") return None except sock.error as err: # fix this if err.errno == 10054: # The connection has been reset. callback.connectionLost(err) else: printrap("WARNING - socket error on receive: " + str(err)) # fix this raise err
def gameStatus(self, status, playerStatus, players, passengers): """ Called to send an update message to this A.I. We do NOT have to send a response. status -- The status message. playerStatus -- The player this status is about. THIS MAY NOT BE YOU. players -- The status of all players. passengers -- The status of all passengers. """ # bugbug - Framework.cs updates the object's in this object's Players, # Passengers, and Companies lists. This works fine as long as this app # is single threaded. However, if you create worker thread(s) or # respond to multiple status messages simultaneously then you need to # split these out and synchronize access to the saved list objects. try: # bugbug - we return if not us because the below code is only for # when we need a new path or our limo hits a bus stop. If you want # to act on other players arriving at bus stops, you need to # remove this. But make sure you use self.me, not playerStatus for # the Player you are updating (particularly to determine what tile # to start your path from). if playerStatus != self.me: return ptDest = None pickup = [] if status == "UPDATE": return elif ((status == "PASSENGER_NO_ACTION" or status == "NO_PATH") and playerStatus == self.me): if playerStatus.limo.passenger is None: pickup = self.allPickups(self.me, passengers, players) ptDest = pickup[0].lobby.busStop else: ptDest = playerStatus.limo.passenger.destination.busStop elif (status == "PASSENGER_DELIVERED" or status == "PASSENGER_ABANDONED"): pickup = self.allPickups(self.me, passengers, players) ptDest = pickup[0].lobby.busStop elif status == "PASSENGER_REFUSED": pickup = self.allPickups(self.me, passengers, players) ptDest = pickup[0].lobby elif (status == "PASSENGER_DELIVERED_AND_PICKED_UP" or status == "PASSENGER_PICKED_UP"): pickup = self.allPickups(self.me, passengers, players) ptDest = self.me.limo.passenger.destination.busStop else: raise TypeError("unknown status %r", status) # get the path from where we are to the dest. path = self.calculatePathPlus1(self.me, ptDest) sendOrders(self, "move", path, pickup) except Exception as e: traceback.print_exc() printrap ("somefin' bad, foo'!") raise e
def calc_path(self, status, playerStatus, players, passengers, data, **kwargs): try: # bugbug - we return if not us because the below code is only for # when we need a new path or our limo hits a bus stop. If you want # to act on other players arriving at bus stops, you need to # remove this. But make sure you use self.me, not playerStatus for # the Player you are updating (particularly to determine what tile # to start your path from). if playerStatus != self.me: return ptDest = None pickup = [] if status == "UPDATE": return elif (status == "PASSENGER_NO_ACTION" or status == "NO_PATH"): if playerStatus.limo.passenger is None: pickup = self.allPickups(playerStatus, passengers) ptDest = pickup[0].lobby.busStop else: ptDest = playerStatus.limo.passenger.destination.busStop elif (status == "PASSENGER_DELIVERED" or status == "PASSENGER_ABANDONED"): pickup = self.allPickups(playerStatus, passengers) ptDest = pickup[0].lobby.busStop elif status == "PASSENGER_REFUSED": ptDest = random.choice(filter(lambda c: c != playerStatus.limo.passenger.destination, self.companies)).busStop elif (status == "PASSENGER_DELIVERED_AND_PICKED_UP" or status == "PASSENGER_PICKED_UP"): pickup = self.allPickups(playerStatus, passengers) ptDest = playerStatus.limo.passenger.destination.busStop else: raise TypeError("unknown status %r", status) # get the path from where we are to the dest. path = self.calculatePathPlus1(playerStatus, ptDest) return ("move", path, pickup) except Exception as e: printrap ("somefin' bad, foo'!") raise e
def sendMessage(self, message): # compute the length of the message (4 byte, little-endian) length = len(message) hexlen = "{:08x}".format(length) assert len(hexlen) == 8 # length should not be more than 4 bytes chrstr = [chr(int(hexlen[i:i+2], 16)) for i in range(0, 8, 2)] chrstr.reverse() retlen = ''.join(chrstr) try: #send the length self.socket.send(retlen) # fix this # send the message ret = self.socket.send(message) while ret < length: ret += self.socket.send(message[ret:]) assert ret == length except sock.timeout: # fix this printrap("Socket operation (send) timed out") self.sendMessage(message)
def incomingMessage(self, message): try: startTime = time.clock() # get the XML - we assume we always get a valid message from the server. xml = ET.XML(message) name = xml.tag if name == 'start-position': players = api.player.playersFromXML(xml.find("players")) guid = xml.find("players").get("your-guid") start = self._brain.setup( api.board.GameMap(xml.find("map")), [p for p in players if p.guid == guid][0], players, _getPoints(xml.find("points")), xml.get("game-start").lower() == "true" ) print("Starting robot at: %s" % start) doc = ET.Element('start-position', start.getAttributes()) self.client.sendMessage(ET.tostring(doc)) elif name == 'turn': turnOn = int(xml.get('turn')) print("turn %i request starting" % turnOn) allPlayers = api.player.playersFromXML(xml.find('players')) guid = xml.find('players').get('your-guid') turn = self._brain.turn( api.board.GameMap(xml.find("map")), [p for p in allPlayers if p.guid == guid][0], allPlayers, api.player.cardsFromXML(xml.find('cards')) ) print("Turn: %i - %s" % (turnOn, turn)) docTurn = turn.getXML() docTurn.set("turn", str(turnOn)) print("turn %i replying" % turnOn) self.client.sendMessage(ET.tostring(docTurn)) else: printrap("ERROR: bad message (XML) from server - root node %r" % name) turnTime = time.clock() - startTime prefix = '' if turnTime < .8 else "WARNING - " prefix = "!DANGER! - " if turnTime >= 1 else prefix print(prefix + "turn took %r seconds" % turnTime) except Exception as e: traceback.print_exc() printrap("Error on incoming message. Exception: %r" % e)
def incomingMessage(self, message): try: startTime = time.clock() # get the XML - we assume we always get a valid message from the server. xml = ET.XML(message) name = xml.tag if name == "setup": print("Received setup message") # TODO: logging players = api.units.playersFromXml(xml.find("players")) companies = api.map.companiesFromXml(xml.find("companies")) passengers = api.units.passengersFromXml(xml.find("passengers"), companies) map = api.map.Map(xml.find("map"), companies) self.guid = xml.attrib["my-guid"] me2 = [p for p in players if p.guid == self.guid][0] self._brain.setup(map, me2, players, companies, passengers, self.client) ###self.client.sendMessage(ET.tostring(doc)) elif name == "status": # may be here because re-started and got this message before # the re-send of setup if self.guid is None or len(self.guid) == 0: trap() return status = xml.attrib["status"] attr = xml.attrib["player-guid"] guid = attr if attr is not None else self.guid brain = self._brain if self.lock.acquire(False): try: api.units.updatePlayersFromXml(brain.players, brain.passengers, xml.find("players")) api.units.updatePassengersFromXml(brain.passengers, brain.companies, xml.find("passengers")) # update my path & pick-up playerStatus = [p for p in brain.players if p.guid == guid][0] elem = xml.find("path") # bugprint('framework.py: path element ->', ET.tostring(elem)) if elem is not None and elem.text is not None: path = [item.strip() for item in elem.text.split(";") if len(item.strip()) > 0] del playerStatus.limo.path[:] for stepOn in path: pos = stepOn.index(",") playerStatus.limo.path.append((int(stepOn[:pos]), int(stepOn[pos + 1 :]))) elem = xml.find("pick-up") # bugprint('framework.py: pick-up element ->', ET.tostring(elem)) if elem is not None and elem.text is not None: names = [item.strip() for item in elem.text.split(";") if len(item) > 0] playerStatus.pickup = [p for p in brain.passengers if p.name in names] # pass in to generate new orders brain.gameStatus(status, playerStatus, brain.players, brain.passengers) # except Exception as e: # raise e finally: self.lock.release() else: # failed to acquire the lock - we're throwing this message away. trap() return elif name == "exit": print("Received exit message") # TODO: logging sys.exit(0) else: printrap("ERROR: bad message (XML) from server - root node %r" % name) turnTime = time.clock() - startTime prefix = "" if turnTime < 0.8 else "WARNING - " prefix = "!DANGER! - " if turnTime >= 1.2 else prefix print(prefix + "turn took %r seconds" % turnTime) # TODO: logging except Exception as e: traceback.print_exc() printrap("Error on incoming message. Exception: %r" % e)
avatar = self._brain.avatar if avatar is not None: av_el = ET.Element("avatar") av_el.text = base64.b64encode(avatar) root.append(av_el) self.client.sendMessage(ET.tostring(root)) def sendOrders(brain, order, path, pickup): """Used to communicate with the server. Do not change this method!""" xml = ET.Element(order) if len(path) > 0: brain.me.limo.path = path # update our saved Player to match new settings sb = [str(point[0]) + "," + str(point[1]) + ";" for point in path] elem = ET.Element("path") elem.text = "".join(sb) xml.append(elem) if len(pickup) > 0: brain.me.pickup = pickup # update our saved Player to match new settings sb = [psngr.name + ";" for psngr in pickup] elem = ET.Element("pick-up") elem.text = "".join(sb) xml.append(elem) brain.client.sendMessage(ET.tostring(xml)) if __name__ == "__main__": printrap(sys.argv[0], breakOn=not sys.argv[0].endswith("framework.py")) framework = Framework(sys.argv[1:]) framework._run()
def incomingMessage(self, message): try: startTime = time.clock() # get the XML - we assume we always get a valid message from the server. #print ET.tostring(xml,encoding='utf8', method='xml') xml = ET.XML(message) name = xml.tag printrap("Received message of type: " + name) self.guid = xml.get('my-guid') hotels = [lib.HotelChain(hotel) for hotel in xml.find('hotels')] map = lib.GameMap(element=xml.find('map'), hotelChains=hotels) # need to handle the actual column/rows players = [lib.Player(player) for player in xml.find('players')] #fix stock pointers to right place... #pdb.set_trace() me = None msgid = xml.get('msg-id') reply = None for player in players: if player.guid == self.guid: me = player print "found matching guid..." elif player.name == self.brain.name: me = player print "no matching guid, but found matching name... " if name == 'query-card': move = self.brain.QuerySpecialPowersBeforeTurn(map, me, hotels, players) reply = ET.Element('reply', {'cmd': name, 'msg-id': msgid, 'card': move}) elif name == 'query-tile-purchase': move = self.brain.QueryTileAndPurchase(map, me, hotels, players) reply = ET.Element('reply', {'cmd': name, 'msg-id': msgid}) if move is not None: if move.Tile is not None: reply.set("tile-x", str(move.Tile.x)) reply.set("tile-y", str(move.Tile.y)) if move.CreatedHotel is not None: reply.set("created-hotel",move.CreatedHotel.name) if move.MergeSurvivor is not None: reply.set("merge-survivor", move.MergeSurvivor.name) if move.Card is not None: reply.set("card", move.Card) trade_string = ''.join(["{}:{};".format(stock.Trade, stock.Get) for stock in move.Trade]) if len(trade_string) > 0: reply.set("trade", trade_string) buy_string = ''.join(["{}:{};".format(stock.chain.name, stock.num_shares) for stock in move.Buy]) if len(buy_string) > 0: reply.set("buy", buy_string) elif name == 'query-tile': move = self.brain.QueryTileOnly(map, me, hotels, players) reply = ET.Element('reply', {'cmd': name, 'msg-id': msgid}) if move is not None: if move.Tile is not None: reply.set("tile-x", str(move.Tile.x)) reply.set("tile-y", str(move.Tile.y)) if move.CreatedHotel is not None: reply.set("created-hotel",move.CreatedHotel.name) if move.MergeSurvivor is not None: reply.set("merge-survivor", move.MergeSurvivor.name) elif name == 'query-merge': defunct_name = xml.get('defunct') survivor_name = xml.get('survivor') defunct = next((hotel for hotel in hotels if hotel.name == defunct_name),None) survivor = next((hotel for hotel in hotels if hotel.name == survivor_name),None) move = self.brain.QueryMergeStock(map, me, hotels, players, survivor, defunct) reply = ET.Element('reply', {'cmd': name, 'msg-id': msgid}) if move is not None: reply.set( "keep", str(move.Keep)) reply.set( "sell", str(move.Sell)) reply.set( "trade", str(move.Trade)) elif name == 'setup': print "\n\n", "----------------------------------", "\n\n" self.brain.Setup(map, me, hotels, players) reply = ET.Element('ready') elif name == 'exit': print("Received exit message") sys.exit(0) else: printrap("ERROR: bad message (XML) from server - root node %r" % name) self.send_xml(reply) turnTime = time.clock() - startTime prefix = '' if turnTime < 0.8 else "WARNING - " print(prefix + "turn took %r seconds" % turnTime)#Enable this to see turn speed except Exception as e: traceback.print_exc() printrap("Error on incoming message. Exception: %r" % e)
def incomingMessage(self, message): try: startTime = time.clock() # get the XML - we assume we always get a valid message from the server. xml = ET.XML(message) name = xml.tag if name == 'setup': players = None companies = None passengers = None stores = None powerups = None map = None print ("Received setup message") players = api.units.playersFromXml(xml.find("players")) companies = api.map.companiesFromXml(xml.find("companies")) passengers = api.units.passengersFromXml(xml.find("passengers"), companies) stores = api.map.coffeeFromXml(xml.find("stores")) powerups = api.units.powerUpFromXml(xml.find("powerups"), companies, passengers) map = api.map.Map(xml.find("map"), companies) self.guid = xml.attrib["my-guid"] me2 = [p for p in players if p.guid == self.guid][0] self.brain.setup(map, me2, players, companies, passengers, self.client, stores, powerups, framework) ###self.client.sendMessage(ET.tostring(doc)) elif name == 'status': # may be here because re-started and got this message before # the re-send of setup if self.guid is None or len(self.guid) == 0: trap() return status = xml.attrib["status"] attr = xml.attrib["player-guid"] guid = attr if attr is not None else self.guid brain = self.brain if self.lock.acquire(False): try: api.units.updatePlayersFromXml(brain.companies, brain.players, brain.passengers, xml.find("players")) api.units.updatePassengersFromXml(brain.passengers, brain.players, brain.companies, xml.find("passengers")) # update my path & pick-up playerStatus = [p for p in brain.players if p.guid == guid][0] elem = xml.find("path") #bugprint('framework.py: path element ->', ET.tostring(elem)) if elem is not None and elem.text is not None: path = [item.strip() for item in elem.text.split(';') if len(item.strip()) > 0] del playerStatus.limo.path[:] for stepOn in path: pos = stepOn.index(',') playerStatus.limo.path.append((int(stepOn[:pos]), int(stepOn[pos + 1:]))) elem = xml.find("pick-up") #bugprint('framework.py: pick-up element ->', ET.tostring(elem)) if elem is not None and elem.text is not None: names = [item.strip() for item in elem.text.split(';') if len(item) > 0] playerStatus.pickup = [p for p in brain.passengers if p.name in names] # pass in to generate new orders brain.gameStatus(status, playerStatus) #except Exception as e: # raise e finally: self.lock.release() else: # failed to acquire the lock - we're throwing this message away. trap() return elif name == "powerup-status": brain = self.brain if self.guid is None: return if self.lock.acquire(False): try: puStatus = xml.attrib["status"] puGuid = xml.attrib["played-by"] if xml.attrib["played-by"] is not None else self.guid plyrPowerUp = next(g for g in brain.players if g.guid == puGuid) cardPlayed = api.units.powerUpGenerateFlyweight(xml.find("card"), brain.companies, brain.passengers, brain.players) # do we update the card deck? if (cardPlayed == cardLastPlayed or ( datetime.datetime.now() > cardLastSendTime + datetime.timedelta(seconds=1))): updateCards(brain, xml.find("cards-deck").findall("card"), brain.powerUpDeck, brain.powerUpHand) updateCards(brain, xml.find("cards-hand").findall("card"), brain.powerUpHand, None) brain.powerUpStatus(puStatus, plyrPowerUp, cardPlayed) finally: self.lock.release() else: # failed to acquire the lock - we're throwing this message away. trap() return elif name == 'exit': print("Received exit message") sys.exit(0) else: printrap("ERROR: bad message (XML) from server - root node %r" % name) turnTime = time.clock() - startTime prefix = '' if turnTime < 0.8 else "WARNING - " prefix = "!DANGER! - " if turnTime >= 1.2 else prefix # print(prefix + "turn took %r seconds" % turnTime) Enable this to see turn speed except Exception as e: traceback.print_exc() printrap("Error on incoming message. Exception: %r" % e)
def incomingMessage(self, message): try: startTime = time.clock() # get the XML - we assume we always get a valid message from the server. xml = ET.XML(message) name = xml.tag if name == 'setup': print("Received setup message") #TODO: logging players = api.units.playersFromXml(xml.find("players")) companies = api.map.companiesFromXml(xml.find("companies")) passengers = api.units.passengersFromXml( xml.find("passengers"), companies) map = api.map.Map(xml.find("map"), companies) self.guid = xml.attrib["my-guid"] me2 = [p for p in players if p.guid == self.guid][0] self._brain.setup(map, me2, players, companies, passengers, self.client) ###self.client.sendMessage(ET.tostring(doc)) elif name == 'status': # may be here because re-started and got this message before # the re-send of setup if self.guid is None or len(self.guid) == 0: trap() return status = xml.attrib["status"] attr = xml.attrib["player-guid"] guid = attr if attr is not None else self.guid brain = self._brain if self.lock.acquire(False): try: api.units.updatePlayersFromXml(brain.players, brain.passengers, xml.find("players")) api.units.updatePassengersFromXml( brain.passengers, brain.companies, xml.find("passengers")) # update my path & pick-up playerStatus = [ p for p in brain.players if p.guid == guid ][0] elem = xml.find("path") #bugprint('framework.py: path element ->', ET.tostring(elem)) if elem is not None and elem.text is not None: path = [ item.strip() for item in elem.text.split(';') if len(item.strip()) > 0 ] del playerStatus.limo.path[:] for stepOn in path: pos = stepOn.index(',') playerStatus.limo.path.append( (int(stepOn[:pos]), int(stepOn[pos + 1:]))) elem = xml.find("pick-up") #bugprint('framework.py: pick-up element ->', ET.tostring(elem)) if elem is not None and elem.text is not None: names = [ item.strip() for item in elem.text.split(';') if len(item) > 0 ] playerStatus.pickup = [ p for p in brain.passengers if p.name in names ] # pass in to generate new orders brain.gameStatus(status, playerStatus, brain.players, brain.passengers) #except Exception as e: # raise e finally: self.lock.release() else: # failed to acquire the lock - we're throwing this message away. trap() return elif name == 'exit': print("Received exit message") #TODO: logging sys.exit(0) else: printrap( "ERROR: bad message (XML) from server - root node %r" % name) turnTime = time.clock() - startTime prefix = '' if turnTime < 0.8 else "WARNING - " prefix = "!DANGER! - " if turnTime >= 1.2 else prefix print(prefix + "turn took %r seconds" % turnTime) #TODO: logging except Exception as e: traceback.print_exc() printrap("Error on incoming message. Exception: %r" % e)
avatar = self._brain.avatar if avatar is not None: av_el = ET.Element('avatar') av_el.text = base64.b64encode(avatar) root.append(av_el) self.client.sendMessage(ET.tostring(root)) def sendOrders(brain, order, path, pickup): """Used to communicate with the server. Do not change this method!""" xml = ET.Element(order) if len(path) > 0: brain.me.limo.path = path # update our saved Player to match new settings sb = [str(point[0]) + ',' + str(point[1]) + ';' for point in path] elem = ET.Element('path') elem.text = ''.join(sb) xml.append(elem) if len(pickup) > 0: brain.me.pickup = pickup # update our saved Player to match new settings sb = [psngr.name + ';' for psngr in pickup] elem = ET.Element('pick-up') elem.text = ''.join(sb) xml.append(elem) brain.client.sendMessage(ET.tostring(xml)) if __name__ == '__main__': printrap(sys.argv[0], breakOn=not sys.argv[0].endswith("framework.py")) framework = Framework(sys.argv[1:]) framework._run()