class Bot: def __init__(self, config): self.config = config self.irc = Irc(config) self.game = Game() def run(self): last_start = time.time() while True: new_messages = self.irc.recv_messages(1024) if new_messages: for message in new_messages: button = message['message'].lower() username = message['username'] if not self.game.is_valid_button(button): continue if self.config['start_throttle']['enabled'] and button == 'start': if time.time() - last_start < self.config['start_throttle']['time']: continue pbutton(username, button) self.game.push_button(button) if button == 'start': last_start = time.time()
class Bot: def __init__(self): self.config = config self.irc = Irc(config) self.game = Game() self.stats = Stats() if self.config['features']['gui_stats']: self.GUI = GUI(self) def run(self): throttle_timers = { button: 0 for button in config['throttled_buttons'].keys() } while True: new_messages = self.irc.recv_messages(1024) if not new_messages: continue for message in new_messages: button = message['message'].lower() username = message['username'].lower() if not self.game.is_valid_button(button): continue if button in self.config['throttled_buttons']: if (time.time() - throttle_timers[button] < self.config['throttled_buttons'][button]): continue throttle_timers[button] = time.time() if not self.game.is_political(button): if (self.config['features']['play_game'] and not button in self.config['misc']['blocked_buttons']): self.game.push_button(button) self.stats.tally_message(username, message['message']) if self.config['features']['stats_on']: if self.config['features']['gui_stats']: self.GUI.run() if self.config['features']['console_stats']: pframe(self.stats) elif self.config['features']['pbutton_on']: pbutton(self.stats.message_buffer)
class Bot: def __init__(self): self.config = config self.irc = Irc(config) self.game = Game() self.stats = Stats() if self.config['features']['gui_stats']: self.GUI = GUI(self) def run(self): throttle_timers = {button:0 for button in config['throttled_buttons'].keys()} while True: new_messages = self.irc.recv_messages(1024) if not new_messages: continue for message in new_messages: button = message['message'].lower() username = message['username'].lower() if not self.game.is_valid_button(button): continue if button in self.config['throttled_buttons']: if (time.time() - throttle_timers[button] < self.config['throttled_buttons'][button]): continue throttle_timers[button] = time.time() if not self.game.is_political(button): if (self.config['features']['play_game'] and not button in self.config['misc']['blocked_buttons']): self.game.push_button(button) self.stats.tally_message(username, message['message']) if self.config['features']['stats_on']: if self.config['features']['gui_stats']: self.GUI.run() if self.config['features']['console_stats']: pframe(self.stats) elif self.config['features']['pbutton_on']: pbutton(self.stats.message_buffer)
class Bot: def __init__(self): self.config = config self.irc = Irc(config) self.game = Game() self.message_buffer = [{ 'username': '', 'button': '' }] * self.config['misc']['chat_height'] def set_message_buffer(self, message): self.message_buffer.insert(self.config['misc']['chat_height'] - 1, message) self.message_buffer.pop(0) def run(self): throttle_timers = { button: 0 for button in config['throttled_buttons'].keys() } while True: new_messages = self.irc.recv_messages(1024) if not new_messages: continue for message in new_messages: button = message['message'].lower() username = message['username'].lower() if not self.game.is_valid_button(button): continue if button in self.config['throttled_buttons']: if time.time() - throttle_timers[button] < self.config[ 'throttled_buttons'][button]: continue throttle_timers[button] = time.time() self.set_message_buffer({ 'username': username, 'button': button }) pbutton(self.message_buffer) self.game.push_button(button)
class Bot: def __init__(self): self.config = config self.irc = Irc(config) self.game = Game() self.message_buffer = [{'username': '', 'button': ''}] * 10 def set_message_buffer(self, message): chat_height = 10 self.message_buffer.insert(chat_height - 1, message) self.message_buffer.pop(0) def run(self): last_start = time.time() while True: new_messages = self.irc.recv_messages(1024) if not new_messages: continue for message in new_messages: button = message['message'].lower() username = message['username'].lower() if not self.game.is_valid_button(button): continue print button if self.config['start_throttle']['enabled'] and button == 'start': if time.time() - last_start < self.config['start_throttle']['time']: continue if button == 'start': last_start = time.time() self.set_message_buffer({'username': username, 'button': button}) pbutton(self.message_buffer) self.game.push_button(button)
class Bot: def __init__(self): self.config = config self.irc = Irc(config) self.game = Game() self.message_buffer = [{'username': '', 'button': ''}] * self.config['misc']['chat_height'] def set_message_buffer(self, message): self.message_buffer.insert(self.config['misc']['chat_height'] - 1, message) self.message_buffer.pop(0) def run(self): throttle_timers = {button:0 for button in config['throttled_buttons'].keys()} while True: new_messages = self.irc.recv_messages(1024) if not new_messages: continue for message in new_messages: button = message['message'].lower() username = message['username'].lower() if not self.game.is_valid_button(button): continue if button in self.config['throttled_buttons']: if time.time() - throttle_timers[button] < self.config['throttled_buttons'][button]: continue throttle_timers[button] = time.time() self.set_message_buffer({'username': username, 'button': button}) pbutton(self.message_buffer) self.game.push_button(button)
class Bot: def __init__(self): self.config = config self.game = Game() self.message_buffer = [{'button': ''}] * self.config['misc']['chat_height'] def set_message_buffer(self, message): self.message_buffer.insert(self.config['misc']['chat_height'] - 1, message) self.message_buffer.pop(0) def run(self): throttle_timers = {button:0 for button in config['throttled_buttons'].keys()} while True: button = choice(self.game.keymap) if button in self.config['throttled_buttons']: if time.time() - throttle_timers[button] < self.config['throttled_buttons'][button]: continue throttle_timers[button] = time.time() self.set_message_buffer({'username': username, 'button': button}) pbutton(self.message_buffer) self.game.push_button(button)
class Bot: voteLength = 5 #Number of votes to show bufferLength = 5 #Number of recent commands to show commandDisplayLength = 21 #max number of characters visible on command screen def __init__(self): self.config = config self.irc = Irc(config) self.game = Game() self.extConfig = configparser.ConfigParser() self.message_buffer = deque( ' ', self.bufferLength ) #deque happens to be marginally more convenient for this self.curQueue = comQueue( ) #Based on Queue object, and therefore threadsafe self.daQueue = demAnQueue( ) #Based on deque object, and therefore threadsafe self.queueStatus = "Nominal" self.lastButton = "" self.voteCount = {} self.lastPushed = "" self.voteItems = self.voteCount.items( ) #Dynamically changing list in python 3 that keeps up with voteCount self.democracy = False #Anarchy is default on. self.game.democracy = self.democracy #Command processor needs this information due to slightly different processing in democracy vs. anarchy self.lastConfigTime = time.time() #Timer on config file updates self.configUpdateFreq = 60 #config file updates every 60 seconds ###DEFAULT VALUES (should be overwritten by readConfigText() at the end### self.botConfig = {'votetime': 20, 'checktime': 0.1, 'votethresh': 75} ###END DEFAULT VALUES### self.readConfigText( ) #read in config file (after all possible object initializations) self.daQueue.updateQueue( ) #It's poor form that I have to do this, but it's cleanest def readConfigText( self ): #the operations performed are threadsafe (attributes changed are either only ever changed here, or changed in one atomic operation) try: self.extConfig.read( self.config['configPath'] ) #Note that nothing from extConfig is directly accessed by any other function. This function is paranoid about it anyway... except: return #In case of read fail of some sort. In principle, this should throw a warning, but for the stream I don't want errors going to stdout, and it will not matter unless I try to edit the .ini and it somehow causes a permanent failure of the read (i.e. I messed up the formatting). By design, the stream will continue to run based on the old configuration; hopefully I will notice that the changes are not taking effect. Best practice would be to output the causative error to a log file; that can be implemented later if necessary tempkeymap = dict(self.extConfig['Keymap']) for sub in tempkeymap.keys(): tempkeymap[sub] = int(tempkeymap[sub], 16) #convert from the hex to integer self.game.keymap = tempkeymap #Note that the operations above are performed separately before being placed in the self object; this is for threadsafeness. This is an atomic operation. self.game.macros = dict( self.extConfig['Macros'] ) #this is okay because it doesn't get changed after this. This is an atomic operation. tempbotconfig = self.extConfig['Bot'] self.botConfig = self.configInferType( tempbotconfig ) #Note that the operations above are performed separately before being placed in the self object; this is for threadsafeness. This is an atomic operation. tempgameconfig = self.extConfig['Game'] self.game.gameConfig = self.configInferType( tempgameconfig ) #Note that the operations above are performed separately before being placed in the self object; this is for threadsafeness. This is an atomic operation. tempdemanqueueconfig = self.extConfig['demAnQueue'] self.daQueue.demAnQueueConfig = self.configInferType( tempdemanqueueconfig ) #Note that the operations above are performed separately before being placed in the self object; this is for threadsafeness. This is an atomic operation. def configInferType( self, inconfig ): #convenience function for type conversion based on first character of variable name #indict is the source ConfigParser object, outdict is the output dictionary which will get keys that are stripped of the first character, which signals type outdict = {} for sub in inconfig.keys(): if sub.startswith( 'f' ): #Personal Note: I finally understand why the civ 5 XML files are the way there are.... outdict[sub[1:]] = inconfig.getfloat( sub) #in python, dictionaries are a mutable type elif sub.startswith('i'): outdict[sub[1:]] = inconfig.getint(sub) elif sub.startswith('b'): outdict[sub[1:]] = inconfig.getboolean(sub) return outdict def update_message_buffer(self, message): self.message_buffer.appendleft( message ) #deque maximum length now takes care of the below functionality #if len(self.message_buffer)>self.bufferLength: #self.message_buffer.pop(0) def update_message(self, timeleft): system('cls') demvoteper = round( self.daQueue.demVotePerc ) #minimizing the number of times this attribute gets read, in case it changes midway if self.democracy: votes = self.sortVote( ) #It's inefficient to do this every time, yes, but the alternative is to implement a custom sorted value hashmap, and I hope that's not necessary... print('\n\n') print('Democracy: ' + str(demvoteper) + '%\nAnarchy: ' + str(100 - demvoteper) + '%\n\nDemocracy!\nTime Remaining: ' + str(int(timeleft)) + ' s\nLast Pushed: ' + self.lastPushed + '\n') if votes: print('Top Votes:\n') for y in votes[0:min(len(votes), self.voteLength )]: #show at most 5 votes print(str(y[1]) + " " + y[0]) print('\n') for y in self.message_buffer: print(y) else: print('\n\n') print('Democracy: ' + str(demvoteper) + '%\nAnarchy: ' + str(100 - demvoteper) + '%\n\nAnarchy!\n') for y in self.message_buffer: print(y) def commandQueue(self): while True: #update config file if necessary...see readConfigText regarding threadsafeness if time.time() - self.lastConfigTime > self.configUpdateFreq: self.readConfigText() #Only place this should ever get called self.lastConfigTime = time.time() #Toggles Anarchy/Democracy state self.daQueue.updateQueue() demvoteper = self.daQueue.demVotePerc #minimizing the number of times this attribute gets read (though it should only ever get changed by updateQueue() anyway if self.democracy and demvoteper < 100 - self.botConfig[ 'votethresh']: #Note that the attribute changes here are all atomic operations and threadsafe self.democracy = False self.game.democracy = False elif not self.democracy and demvoteper > self.botConfig[ 'votethresh']: self.democracy = True self.game.democracy = True if self.democracy: #this is Democracy lastvotetime = time.time() self.queueStatus = "Adding Votes" while time.time() - lastvotetime < self.botConfig[ 'votetime']: #collect commands for votetime seconds self.daQueue.updateQueue() self.update_message(self.botConfig['votetime'] - time.time() + lastvotetime) comList, userList = self.curQueue.getCom() self.lastButton = comList timetaken = time.time() index = 0 for button in comList: username = userList[index] index += 1 self.queueStatus = "Adding Votes" self.addVote(button) userLength = self.commandDisplayLength - len( button) - 2 printusername = username if len(username) > userLength: printusername = username[0:userLength - 3] + '...' self.update_message_buffer(printusername + ': ' + button) #pbutton(self.message_buffer) if time.time() - timetaken < self.botConfig[ 'checktime']: #don't check more frequently than once every 0.1 self.queueStatus = "Sleeping" time.sleep(self.botConfig['checktime']) self.queueStatus = "Running Command" vote = self.topVote( ) #running the command after votetime seconds if vote: self.lastPushed = vote words = vote.split( "+" ) #input-time check should have already made sure it's a valid command for y in words: try: self.game.push_button(y) except: time.sleep( 0.01 ) #this is just to fill this catch block. It's bad, yes. time.sleep(.15) self.clearVote() self.update_message(0) else: #this is Anarchy self.queueStatus = "Pushing buttons" self.update_message(0) comList, userList = self.curQueue.getCom() self.lastButton = comList timetaken = time.time() index = 0 for button in comList: username = userList[index] index += 1 words = button.split( "+" ) #input-time check should have already made sure it's a valid command for y in words: if y in self.config['throttled_buttons']: if time.time() - throttle_timers[y] < self.config[ 'throttled_buttons'][y]: continue throttle_timers[y] = time.time() try: #Just in case of weird edge case self.game.push_button(y) except: time.sleep( 0.01 ) #this is just to fill this catch block. It's bad, yes. time.sleep( .05) #Anarchy is a bit more jumpy than Democracy userLength = self.commandDisplayLength - len(button) - 2 printusername = username if len(username) > userLength: printusername = username[0:userLength - 3] + '...' self.update_message_buffer(printusername + ': ' + button) if time.time() - timetaken < self.botConfig[ 'checktime']: #don't check more frequently than once every 0.1 self.queueStatus = "Sleeping" time.sleep(self.botConfig['checktime']) def addVote(self, vote): if vote in self.voteCount: self.voteCount[vote] = self.voteCount[vote] + 1 else: self.voteCount[vote] = 1 def topVote(self): #Gets top vote, applying rng to choose among ties top = [ k for k, v in self.voteItems if v == max(self.voteCount.values()) ] if not top: return None return random.choice(top) def sortVote(self): sortedItems = sorted( self.voteItems, key=lambda tup: tup[1], reverse=True) #sort using the values, biggest to smallest return sortedItems def clearVote(self): self.voteCount.clear() def run(self): #print("New Version!") throttle_timers = { button: 0 for button in config['throttled_buttons'].keys() } t = threading.Thread(target=self.commandQueue, args=()) t.daemon = True t.start() while True: #For threadsafeness see discussion at the top of this file #print(self.queueStatus) #print(self.lastButton) #print(self.curQueue.getStatus()) #print("Checking for new messages") new_messages = self.irc.recv_messages(1024) if not new_messages: continue for message in new_messages: button = message['message'].lower() username = message['username'].lower() words = button.split(" ") #basic input cleanup button = words[0] #Anarchy/Democracy vote if button == 'democracy': self.daQueue.addVote( 1) #No update to try to make this as fast as possible elif button == 'anarchy': self.daQueue.addVote(0) if not self.game.is_valid_command(button): continue #print("Adding command") self.curQueue.addCom([button, username])
class Bot: def __init__(self): self.config = config self.irc = Irc(config) self.game = Game() self.botOn = True self.message_buffer = [{'username': '', 'button': ''}] * self.config['misc']['chat_height'] def set_message_buffer(self, message): self.message_buffer.insert(self.config['misc']['chat_height'] - 1, message) self.message_buffer.pop(0) def run(self): throttle_timers = {button:0 for button in config['throttled_buttons'].keys()} while True: new_messages = self.irc.recv_messages(1024) if not new_messages: continue for message in new_messages: button = message['message'].lower() username = message['username'].lower() #Turns off the bot with one of your commands if username == 'YOUR USERNAME GOES HERE': if button == 'YOUR INPUT SHUTOFF MESSAGE HERE': self.botOn = False #Turns on the bot with one of your commands if username == 'YOUR USERNAME GOES HERE': if button == 'YOUR INPUT TURNON MESSAGE HERE': self.botOn = True #Helper for writing actionable data to csv if button in self.game.keymap.keys(): actionable = 1 else: actionable = 0 #Helper for writing is Bot Active data to csv if self.botOn == True: chatActionsOn = 1 else: chatActionsOn = 0 #Creates an array of data to write to csv chat_data_array = [username, time.time(), button, actionable , chatActionsOn] #Writes a message to the csv that tracks chat data with open('chat_data.csv', 'a+') as chatData: writer = csv.writer(chatData) writer.writerow(chat_data_array) #If the Bot is on, then it outputs the appropriate action. #If the Bot is off, continues to gen the input feed but does not execute an action if self.botOn == True: if not self.game.is_valid_button(button): continue if button in self.config['throttled_buttons']: if time.time() - throttle_timers[button] < self.config['throttled_buttons'][button]: continue throttle_timers[button] = time.time() self.set_message_buffer({'username': username, 'button': button}) pbutton(self.message_buffer) #This is a console output function. It outputs the log of inputs from chat self.game.push_button(button) else: self.set_message_buffer({'username': username, 'button': button}) pbutton(self.message_buffer)
class Bot: voteLength=5 #Number of votes to show bufferLength=5 #Number of recent commands to show commandDisplayLength=21 #max number of characters visible on command screen def __init__(self): self.config = config self.irc = Irc(config) self.game = Game() self.extConfig=configparser.ConfigParser() self.message_buffer = deque(' ',self.bufferLength) #deque happens to be marginally more convenient for this self.curQueue=comQueue() #Based on Queue object, and therefore threadsafe self.daQueue=demAnQueue() #Based on deque object, and therefore threadsafe self.queueStatus="Nominal" self.lastButton="" self.voteCount={} self.lastPushed="" self.voteItems=self.voteCount.items() #Dynamically changing list in python 3 that keeps up with voteCount self.democracy=False #Anarchy is default on. self.game.democracy=self.democracy #Command processor needs this information due to slightly different processing in democracy vs. anarchy self.lastConfigTime=time.time() #Timer on config file updates self.configUpdateFreq=60 #config file updates every 60 seconds ###DEFAULT VALUES (should be overwritten by readConfigText() at the end### self.botConfig={'votetime':20, 'checktime':0.1, 'votethresh':75} ###END DEFAULT VALUES### self.readConfigText() #read in config file (after all possible object initializations) self.daQueue.updateQueue() #It's poor form that I have to do this, but it's cleanest def readConfigText(self): #the operations performed are threadsafe (attributes changed are either only ever changed here, or changed in one atomic operation) try: self.extConfig.read(self.config['configPath']) #Note that nothing from extConfig is directly accessed by any other function. This function is paranoid about it anyway... except: return #In case of read fail of some sort. In principle, this should throw a warning, but for the stream I don't want errors going to stdout, and it will not matter unless I try to edit the .ini and it somehow causes a permanent failure of the read (i.e. I messed up the formatting). By design, the stream will continue to run based on the old configuration; hopefully I will notice that the changes are not taking effect. Best practice would be to output the causative error to a log file; that can be implemented later if necessary tempkeymap=dict(self.extConfig['Keymap']) for sub in tempkeymap.keys(): tempkeymap[sub] = int(tempkeymap[sub],16) #convert from the hex to integer self.game.keymap=tempkeymap #Note that the operations above are performed separately before being placed in the self object; this is for threadsafeness. This is an atomic operation. self.game.macros=dict(self.extConfig['Macros']) #this is okay because it doesn't get changed after this. This is an atomic operation. tempbotconfig=self.extConfig['Bot'] self.botConfig=self.configInferType(tempbotconfig) #Note that the operations above are performed separately before being placed in the self object; this is for threadsafeness. This is an atomic operation. tempgameconfig=self.extConfig['Game'] self.game.gameConfig=self.configInferType(tempgameconfig) #Note that the operations above are performed separately before being placed in the self object; this is for threadsafeness. This is an atomic operation. tempdemanqueueconfig=self.extConfig['demAnQueue'] self.daQueue.demAnQueueConfig=self.configInferType(tempdemanqueueconfig) #Note that the operations above are performed separately before being placed in the self object; this is for threadsafeness. This is an atomic operation. def configInferType(self,inconfig): #convenience function for type conversion based on first character of variable name #indict is the source ConfigParser object, outdict is the output dictionary which will get keys that are stripped of the first character, which signals type outdict={} for sub in inconfig.keys(): if sub.startswith('f'): #Personal Note: I finally understand why the civ 5 XML files are the way there are.... outdict[sub[1:]]=inconfig.getfloat(sub) #in python, dictionaries are a mutable type elif sub.startswith('i'): outdict[sub[1:]]=inconfig.getint(sub) elif sub.startswith('b'): outdict[sub[1:]]=inconfig.getboolean(sub) return outdict def update_message_buffer(self, message): self.message_buffer.appendleft(message) #deque maximum length now takes care of the below functionality #if len(self.message_buffer)>self.bufferLength: #self.message_buffer.pop(0) def update_message(self,timeleft): system('cls') demvoteper=round(self.daQueue.demVotePerc) #minimizing the number of times this attribute gets read, in case it changes midway if self.democracy: votes=self.sortVote() #It's inefficient to do this every time, yes, but the alternative is to implement a custom sorted value hashmap, and I hope that's not necessary... print ('\n\n') print ('Democracy: '+str(demvoteper)+'%\nAnarchy: '+str(100-demvoteper)+'%\n\nDemocracy!\nTime Remaining: '+str(int(timeleft))+' s\nLast Pushed: '+self.lastPushed+'\n') if votes: print ('Top Votes:\n') for y in votes[0:min(len(votes),self.voteLength)]: #show at most 5 votes print (str(y[1])+" "+y[0]) print ('\n') for y in self.message_buffer: print (y) else: print ('\n\n') print ('Democracy: '+str(demvoteper)+'%\nAnarchy: '+str(100-demvoteper)+'%\n\nAnarchy!\n') for y in self.message_buffer: print (y) def commandQueue(self): while True: #update config file if necessary...see readConfigText regarding threadsafeness if time.time()-self.lastConfigTime>self.configUpdateFreq: self.readConfigText() #Only place this should ever get called self.lastConfigTime=time.time() #Toggles Anarchy/Democracy state self.daQueue.updateQueue() demvoteper=self.daQueue.demVotePerc #minimizing the number of times this attribute gets read (though it should only ever get changed by updateQueue() anyway if self.democracy and demvoteper<100-self.botConfig['votethresh']: #Note that the attribute changes here are all atomic operations and threadsafe self.democracy=False self.game.democracy=False elif not self.democracy and demvoteper>self.botConfig['votethresh']: self.democracy=True self.game.democracy=True if self.democracy: #this is Democracy lastvotetime=time.time() self.queueStatus="Adding Votes" while time.time()-lastvotetime<self.botConfig['votetime']: #collect commands for votetime seconds self.daQueue.updateQueue() self.update_message(self.botConfig['votetime']-time.time()+lastvotetime) comList,userList=self.curQueue.getCom() self.lastButton=comList timetaken=time.time() index=0; for button in comList: username=userList[index] index +=1 self.queueStatus="Adding Votes" self.addVote(button) userLength=self.commandDisplayLength-len(button)-2 printusername=username if len(username)>userLength: printusername=username[0:userLength-3]+'...' self.update_message_buffer(printusername+': '+button) #pbutton(self.message_buffer) if time.time()-timetaken<self.botConfig['checktime']: #don't check more frequently than once every 0.1 self.queueStatus="Sleeping" time.sleep(self.botConfig['checktime']) self.queueStatus="Running Command" vote=self.topVote() #running the command after votetime seconds if vote: self.lastPushed=vote words=vote.split("+") #input-time check should have already made sure it's a valid command for y in words: try: self.game.push_button(y) except: time.sleep(0.01) #this is just to fill this catch block. It's bad, yes. time.sleep(.15) self.clearVote() self.update_message(0) else: #this is Anarchy self.queueStatus="Pushing buttons" self.update_message(0) comList,userList=self.curQueue.getCom() self.lastButton=comList timetaken=time.time() index=0; for button in comList: username=userList[index] index +=1 words=button.split("+") #input-time check should have already made sure it's a valid command for y in words: if y in self.config['throttled_buttons']: if time.time() - throttle_timers[y] < self.config['throttled_buttons'][y]: continue throttle_timers[y] = time.time() try: #Just in case of weird edge case self.game.push_button(y) except: time.sleep(0.01) #this is just to fill this catch block. It's bad, yes. time.sleep(.05) #Anarchy is a bit more jumpy than Democracy userLength=self.commandDisplayLength-len(button)-2 printusername=username if len(username)>userLength: printusername=username[0:userLength-3]+'...' self.update_message_buffer(printusername+': '+button) if time.time()-timetaken<self.botConfig['checktime']: #don't check more frequently than once every 0.1 self.queueStatus="Sleeping" time.sleep(self.botConfig['checktime']) def addVote(self,vote): if vote in self.voteCount: self.voteCount[vote]=self.voteCount[vote]+1 else: self.voteCount[vote]=1 def topVote(self): #Gets top vote, applying rng to choose among ties top=[k for k,v in self.voteItems if v == max(self.voteCount.values())] if not top: return None return random.choice(top) def sortVote(self): sortedItems=sorted(self.voteItems,key=lambda tup: tup[1], reverse=True) #sort using the values, biggest to smallest return sortedItems def clearVote(self): self.voteCount.clear() def run(self): #print("New Version!") throttle_timers = {button:0 for button in config['throttled_buttons'].keys()} t=threading.Thread(target=self.commandQueue, args=()) t.daemon=True t.start() while True: #For threadsafeness see discussion at the top of this file #print(self.queueStatus) #print(self.lastButton) #print(self.curQueue.getStatus()) #print("Checking for new messages") new_messages = self.irc.recv_messages(1024) if not new_messages: continue for message in new_messages: button = message['message'].lower() username = message['username'].lower() words = button.split(" ") #basic input cleanup button=words[0] #Anarchy/Democracy vote if button=='democracy': self.daQueue.addVote(1) #No update to try to make this as fast as possible elif button=='anarchy': self.daQueue.addVote(0) if not self.game.is_valid_command(button): continue #print("Adding command") self.curQueue.addCom([button,username])
class Bot: def __init__(self): self.config = config self.irc = Irc(config) self.message_buffer = [{'username': '', 'button': ''}] * 10 def set_message_buffer(self, message): chat_height = 10 self.message_buffer.insert(chat_height - 1, message) self.message_buffer.pop(0) def start_golden_timer(self, cc): has_alerted_golden = False has_alerted_reindeer = False while True: time.sleep(1) golden_life = cc.get_golden_life() reindeer_life = cc.get_reindeer_life() print str(golden_life) + str(has_alerted_golden) print str(reindeer_life) + str(has_alerted_reindeer) if golden_life == 0: has_alerted_golden = False elif golden_life > 0 and has_alerted_golden == False: self.irc.say('GOLDEN!!!') has_alerted_golden = True if reindeer_life == 0: has_alerted_reindeer = False elif reindeer_life > 0 and has_alerted_reindeer == False: self.irc.say('REINDEER!!!') has_alerted_reindeer = True def run(self, cc): self.game = Game(cc) last_start = time.time() reset_counter = 0 reset_counter_max = self.config['reset_bar']['max'] pledge_counter = 0 pledge_counter_max = config['pledge_bar']['max'] pop_counter = 0 pop_counter_max = config['pop_bar']['max'] next_golden = time.clock() + 5 while True: new_messages = self.irc.recv_messages(1024) if not new_messages: continue for message in new_messages: button = message['message'].lower() username = message['username'].lower() suffix = '' if button[:12] == 'info upgrade': if len(button) > 12: try: upgrade_ind = int(button[12])-1 except: upgrade_ind = -1 else: upgrade_ind = 0 upgrade_name = self.game.cc.get_upgrade_name(upgrade_ind) if upgrade_name == 'undefined': self.irc.say('Invalid Upgrade') else: numdivs = 0 upgrade_price = self.game.cc.get_upgrade_price(upgrade_ind) if upgrade_price > 1000000: upgrade_price = float(upgrade_price) / 1000000 numdivs += 1 while upgrade_price > 1000: upgrade_price = float(upgrade_price) / 1000 numdivs += 1 if numdivs == 0: pricesuffix = '' elif numdivs == 1: pricesuffix = ' M' elif numdivs == 2: pricesuffix = ' B' elif numdivs == 3: pricesuffix = ' T' elif numdivs == 4: pricesuffix = ' Qa' elif numdivs == 5: pricesuffix = ' Qi' elif numdivs == 6: pricesuffix = ' Sx' elif numdivs == 7: pricesuffix = ' Sp' elif numdivs == 8: pricesuffix = ' O' short_price = "%.3f%s" % (upgrade_price, pricesuffix) self.irc.say('UPGRADE' + str(upgrade_ind+1) + ': ' + upgrade_name + ' (' + short_price + ')') elif button == '!commands': self.irc.say('Clickclick..., Golden, Reindeer, Dungeon, Up, Down, Left, Right, Stay, Upgrade1 - Upgrade5, Info UpgradeX, NoPledge, Santa, Cursor, Grandma, Farm, Factory, Mine, Shipment, Lab, Portal, Time, Antimatter, Prism, View, Scrolldown, Scrollup, Expand, Collapse, Reset, Continue') elif self.game.is_valid_button(button): if button == 'pop' and config['pop_bar']['enable']: pop_counter += 1 if pop_counter >= pop_counter_max: pop_counter = 0 self.game.push_button('unwrinkle') set_pop_bar(pop_counter) elif button == 'reset' or button == 'continue': if button == 'reset': reset_counter += 5 if reset_counter >= reset_counter_max: reset_counter = 0 self.game.push_button('reset') pledge_counter = 0 set_pledge_bar(pledge_counter) else: reset_counter -= 5 if reset_counter < 0: reset_counter = 0 suffix = '({0}/{1})'.format(reset_counter,reset_counter_max) elif button[:7] == 'upgrade': reset_counter -= 1 if reset_counter < 0: reset_counter = 0 if len(button) == 7: upgrade_ind = 0 else: upgrade_ind = int(button[7])-1 name = self.game.cc.get_upgrade_name(upgrade_ind) if config['pledge_bar']['enable'] and (name == 'Elder Pledge' or name == 'Elder Covenant' or name == 'Revoke Elder Covenant'): # Throttle pledges if necessary pledge_counter += 1 if pledge_counter >= pledge_counter_max: self.game.push_button(button) pledge_counter = 0 set_pledge_bar(pledge_counter) button = 'pledge/cov' suffix = '({0}/{1})'.format(pledge_counter,pledge_counter_max) else: self.game.push_button(button) elif button == 'nopledge': reset_counter -= 1 if reset_counter < 0: reset_counter = 0 if pledge_counter > 0: pledge_counter -= 1 set_pledge_bar(pledge_counter) suffix = '({0}/{1})'.format(pledge_counter,pledge_counter_max) else: reset_counter -= 1 if reset_counter < 0: reset_counter = 0 print button self.set_message_buffer({'username': username, 'button': button}) self.game.push_button(button) command(username, button + suffix) set_reset_bar(reset_counter) else: numclicks = button.count("click") if numclicks > 0: if numclicks > 9: numclicks = 9 reset_counter -= 1 #numclicks? if reset_counter < 0: reset_counter = 0 self.game.push_button("click%d" % numclicks) command(username, "click(%d)" % numclicks) set_reset_bar(reset_counter)