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.irc = Irc(config) def run(self): throttle_timers = {button: 0 for button in config['throttled_buttons'].keys()} i = 0 while True: t1 = datetime.datetime.now() i += 1 new_messages = self.irc.recv_messages(1024) if not new_messages: continue text_list = [] for message in new_messages: button = message['message'].lower() username = message['username'].lower() d_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") if button in self.config['throttled_buttons']: if (time.time() - throttle_timers[button] < self.config['throttled_buttons'][button]): continue throttle_timers[button] = time.time() print d_time, username, button if i == 1000: output = open(t1.strftime("%Y%m%d%H%M%S") + ".log", "wb") for post in text_list: output.write("%s <%s> %s \n" % (post[0], post[1], post[2])) i = 0 text_list = [] output.close()
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.game = Game() self.message_buffer = [] self.scrolling_chat = [] self.chat_buffer = [] self.game_tracker = [0,0,0,0,0,0,0,0,0] self.windowSurface = pygame.display.set_mode((1300,800), 0, 32) self.BLACK = (0,0,0) self.WHITE = (255,255,255) self.start = time.clock() self.game_timer = 0 self.old_time = 0; self.xwins = 0 self.owins = 0 self.cats_games = 0 self.games = 0 self.who_starts = 0 self.whos_move = 0 self.suspend = 0 self.winner = False self.is_cats = False self.music = pygame.mixer.Sound('music_loop.wav') self.basicFont = pygame.font.SysFont(None, 36) def reset_message_buffer(self): self.message_buffer = [] def draw_x1(self): pygame.draw.line(self.windowSurface, self.WHITE, (180,180), (266,266), 4) pygame.draw.line(self.windowSurface, self.WHITE, (180,266), (266,180), 4) def draw_x2(self): pygame.draw.line(self.windowSurface, self.WHITE, (334,180), (420,266), 4) pygame.draw.line(self.windowSurface, self.WHITE, (334,266), (420,180), 4) def draw_x3(self): pygame.draw.line(self.windowSurface, self.WHITE, (488,180), (574,266), 4) pygame.draw.line(self.windowSurface, self.WHITE, (488,266), (574,180), 4) def draw_x4(self): pygame.draw.line(self.windowSurface, self.WHITE, (180,334), (266,420), 4) pygame.draw.line(self.windowSurface, self.WHITE, (180,420), (266,334), 4) def draw_x5(self): pygame.draw.line(self.windowSurface, self.WHITE, (334,334), (420,420), 4) pygame.draw.line(self.windowSurface, self.WHITE, (334,420), (420,334), 4) def draw_x6(self): pygame.draw.line(self.windowSurface, self.WHITE, (488,334), (574,420), 4) pygame.draw.line(self.windowSurface, self.WHITE, (488,420), (574,334), 4) def draw_x7(self): pygame.draw.line(self.windowSurface, self.WHITE, (180,488), (266,574), 4) pygame.draw.line(self.windowSurface, self.WHITE, (180,574), (266,488), 4) def draw_x8(self): pygame.draw.line(self.windowSurface, self.WHITE, (334,488), (420,574), 4) pygame.draw.line(self.windowSurface, self.WHITE, (334,574), (420,488), 4) def draw_x9(self): pygame.draw.line(self.windowSurface, self.WHITE, (488,488), (574,574), 4) pygame.draw.line(self.windowSurface, self.WHITE, (488,574), (574,488), 4) def draw_o1(self): pygame.draw.circle(self.windowSurface, self.WHITE,(223,223), 43, 4) def draw_o2(self): pygame.draw.circle(self.windowSurface, self.WHITE,(377,223), 43, 4) def draw_o3(self): pygame.draw.circle(self.windowSurface, self.WHITE,(531,223), 43, 4) def draw_o4(self): pygame.draw.circle(self.windowSurface, self.WHITE,(223,377), 43, 4) def draw_o5(self): pygame.draw.circle(self.windowSurface, self.WHITE,(377,377), 43, 4) def draw_o6(self): pygame.draw.circle(self.windowSurface, self.WHITE,(531,377), 43, 4) def draw_o7(self): pygame.draw.circle(self.windowSurface, self.WHITE,(223,531), 43, 4) def draw_o8(self): pygame.draw.circle(self.windowSurface, self.WHITE,(377,531), 43, 4) def draw_o9(self): pygame.draw.circle(self.windowSurface, self.WHITE,(531,531), 43, 4) #draws the tic tac toe board def draw_board(self): self.windowSurface.fill(self.BLACK) pygame.draw.line(self.windowSurface, self.WHITE, (300,150), (300,600), 4) pygame.draw.line(self.windowSurface, self.WHITE, (446,150), (446,600), 4) pygame.draw.line(self.windowSurface, self.WHITE, (150,296), (600,296), 4) pygame.draw.line(self.windowSurface, self.WHITE, (150,450), (600,450), 4) def draw_scores(self): xtext = self.basicFont.render("X WINS: %s" % str(self.xwins), True, self.WHITE, self.BLACK) xtextRect = xtext.get_rect() xtextRect = xtextRect.move(10,10) otext = self.basicFont.render("O WINS: %s" % str(self.owins), True, self.WHITE, self.BLACK) otextRect = otext.get_rect() otextRect = otextRect.move(250,10) catstext = self.basicFont.render("CATS GAMES: %s" % str(self.cats_games), True, self.WHITE, self.BLACK) catstextRect = catstext.get_rect() catstextRect = catstextRect.move(500,10) self.windowSurface.blit(xtext, xtextRect) self.windowSurface.blit(otext, otextRect) self.windowSurface.blit(catstext, catstextRect) #draws the symbols def draw_symbols(self): if self.game_tracker[0] == 1: self.draw_o1() if self.game_tracker[1] == 1: self.draw_o2() if self.game_tracker[2] == 1: self.draw_o3() if self.game_tracker[3] == 1: self.draw_o4() if self.game_tracker[4] == 1: self.draw_o5() if self.game_tracker[5] == 1: self.draw_o6() if self.game_tracker[6] == 1: self.draw_o7() if self.game_tracker[7] == 1: self.draw_o8() if self.game_tracker[8] == 1: self.draw_o9() if self.game_tracker[0] == 2: self.draw_x1() if self.game_tracker[1] == 2: self.draw_x2() if self.game_tracker[2] == 2: self.draw_x3() if self.game_tracker[3] == 2: self.draw_x4() if self.game_tracker[4] == 2: self.draw_x5() if self.game_tracker[5] == 2: self.draw_x6() if self.game_tracker[6] == 2: self.draw_x7() if self.game_tracker[7] == 2: self.draw_x8() if self.game_tracker[8] == 2: self.draw_x9() def get_scrolling_chat(self): if len(self.chat_buffer) > 0: if (len(self.scrolling_chat) + len(self.chat_buffer)) > 25: if len(self.chat_buffer) > 25: self.scrolling_chat = self.chat_buffer[(len(self.chat_buffer)-25):] else: del self.scrolling_chat[:len(self.chat_buffer)] for item in self.chat_buffer: self.scrolling_chat.append(item) else: for item in self.chat_buffer: self.scrolling_chat.append(item) self.chat_buffer = [] def draw_scrolling_chat(self): counter = 0 text = self.basicFont.render("CHAT COMMANDS", True, self.WHITE, self.BLACK) textRect = text.get_rect() textRect = textRect.move(870,10) self.windowSurface.blit(text, textRect) for item in self.scrolling_chat: text = self.basicFont.render(str(item), True, self.WHITE, self.BLACK) textRect = text.get_rect() textRect = textRect.move(870,(60+(25*counter))) self.windowSurface.blit(text, textRect) counter+=1 def draw_game(self): self.draw_board() self.draw_symbols() self.draw_scores() self.draw_scrolling_chat() pygame.display.update() def reset_game(self): self.game_tracker = [0,0,0,0,0,0,0,0,0] self.game_timer = time.clock() self.old_time = 0 self.suspend = 0 self.who_starts += 1 self.whos_move = self.who_starts%2 self.winner = False self.is_cats = False def choose_random_move(self): templist = [] counter = 0 for move in self.game_tracker: if move == 0: templist.append(counter) counter+=1 return choice(templist) def get_valid_moves(self): templist = [] counter = 0 for move in self.game_tracker: if move == 0: templist.append(counter+1) counter+=1 return templist #TODO fix allows user selected move to overwrite filled in spaces. def choose_user_move(self): valid_moves = self.get_valid_moves() print valid_moves templist = [0,0,0,0,0,0,0,0,0] for item in self.message_buffer: if int(item) in valid_moves: templist[int(item)-1]+=1 # print templist max_votes = 0 for item in templist: if item > max_votes: max_votes = item # print "max votes = %s" % max_votes moves_choices = [] counter = 0 for item in templist: if item == max_votes and max_votes>0: moves_choices.append(counter) counter+=1 self.reset_message_buffer() print moves_choices if len(moves_choices) == 0: return self.choose_random_move() else: return choice(moves_choices) def choose_move(self): if len(self.message_buffer) == 0: random_move = self.choose_random_move() print("random move") print random_move return random_move else: user_move = self.choose_user_move() # print user_move return user_move def make_move(self): if self.winner == True or self.is_cats == True: self.games+=1 self.reset_game() elif self.winner == False: count = 0 for move in self.game_tracker: if move == 0: count+=1 break if count > 0: self.game_tracker[self.choose_move()]=self.whos_move+1 if calculate_win_condition(self.game_tracker): self.winner = True if self.whos_move == 0: self.owins+=1 else: self.xwins+=1 elif calculate_win_condition(self.game_tracker): self.winner = True if self.whos_move == 0: self.owins+=1 else: self.xwins+=1 else: self.is_cats = True self.cats_games+=1 def alternate_turn(self): if self.whos_move == 0: self.whos_move = 1 else: self.whos_move = 0 def run(self): # created by Aidan Thomson #throttle_timers = {button:0 for button in config['throttled_buttons'].keys()} #get new messages from chat. Store valid messages only in the message buffer list #after 5-10 seconds calculate the move that was chosen. If no move was chosen automatically choose an open one. #update the board. #calculate an end game condition # self.reset_game() #self.music.play(-1) while True: # self.draw_game() timer = time.clock() - self.game_timer if((timer-self.old_time)>.90): self.old_time = timer timer = int(timer) # self.draw_game() # every 10 seconds make a move and check for a win if timer > 0 and timer%3 == 0: self.make_move() self.alternate_turn() new_messages = None new_messages = self.irc.recv_messages(1024) if new_messages != None: for message in new_messages: button = message['message'].lower() username = message['username'].lower() # print username + " " + button if self.game.is_valid_button(button): # print button self.message_buffer.append(button) self.chat_buffer.append(str(username + ': ' + button)) self.get_scrolling_chat() # self.reset_message_buffer() for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit()
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)