Пример #1
0
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()
Пример #2
0
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)
Пример #3
0
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)
Пример #4
0
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)
Пример #5
0
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)
Пример #6
0
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)
Пример #7
0
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)
Пример #8
0
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])
Пример #9
0
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)
                    
Пример #10
0
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])
Пример #11
0
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)