Exemplo n.º 1
0
    def __init__(self, getStatisticForBeast=None):
        """
        constructor --> initialising Variables
        @param getStatisticForBeast List: insert a tupel of chars ('a','b')
        """
        threading.Thread.__init__(self)
        self.server = None
        self.gui = None
        self.beastObjectMap = {}
        self.rankingList = []
        self.worldMap = None
        self.foodCounter = 0
        self.enableUrwidVisualisation = Config.__getUseUrwidVisualisation__()
        self.useNetworking = Config.__getUseNetworking__()
        self.startTimeMillis = time.time() + Config.__getStartInSeconds__()
        self.startTime = time.ctime(self.startTimeMillis)
        self.roundCounter = 0
        self.getStatisticForBeast = getStatisticForBeast
        self.useBeastAnalytics = True if(getStatisticForBeast) else False
        self.deadBeasts = 0
        self.urwidRoundDelay = Config.__getUrwidRoundDelay__() / 1000.0
        self.gameStarted = False
        self.gameFinished = False
        self.running = False
        self.log = logging.getLogger('beast-arena-logging')

        if self.enableUrwidVisualisation:
            self.useBeastAnalytics = True
            self.getStatisticForBeast = ''
        self.beastAnalytics = BeastAnalytics() if(self.useBeastAnalytics) else False
Exemplo n.º 2
0
class Game(threading.Thread):
    """ 
    global Game class
    here will your beast be registered and seated on WorldMap after it has been 
    created (dependend on the number of beasts)
    """

    def __init__(self, getStatisticForBeast=None):
        """
        constructor --> initialising Variables
        @param getStatisticForBeast List: insert a tupel of chars ('a','b')
        """
        threading.Thread.__init__(self)
        self.server = None
        self.gui = None
        self.beastObjectMap = {}
        self.rankingList = []
        self.worldMap = None
        self.foodCounter = 0
        self.enableUrwidVisualisation = Config.__getUseUrwidVisualisation__()
        self.useNetworking = Config.__getUseNetworking__()
        self.startTimeMillis = time.time() + Config.__getStartInSeconds__()
        self.startTime = time.ctime(self.startTimeMillis)
        self.roundCounter = 0
        self.getStatisticForBeast = getStatisticForBeast
        self.useBeastAnalytics = True if(getStatisticForBeast) else False
        self.deadBeasts = 0
        self.urwidRoundDelay = Config.__getUrwidRoundDelay__() / 1000.0
        self.gameStarted = False
        self.gameFinished = False
        self.running = False
        self.log = logging.getLogger('beast-arena-logging')

        if self.enableUrwidVisualisation:
            self.useBeastAnalytics = True
            self.getStatisticForBeast = ''
        self.beastAnalytics = BeastAnalytics() if(self.useBeastAnalytics) else False


    def registerBeast(self, beast):
        """
        registers a Beast instance: give it a name, create a BeastObject 
        instance and store it in internal dictionary 'beastObjectMap'.
        This method is called when a new Beast joins.
        @param beast Beast: is the clients beast
        @return returns the beast's name
        """

        #recursive call for every beast in passed beast array
        if isinstance(beast,list):
            for b in beast:
                self.registerBeast(b)

        if self.gameSignOnPossible():
            name = string.ascii_letters[len(self.beastObjectMap)]
        else:
            self.log.warning('registered beast limit reached')
            return
            
        beastObject = BeastObject(beast, name, self.beastAnalytics)
        self.rankingList.append(None) # generates proper length of rankingList
        self.beastObjectMap[name] = beastObject
        
        self.log.info("beast " + name + " registered")
        return name
    
    def getStartInSeconds(self):
        return str(self.startTimeMillis-time.time())
    
    def run(self):
        """
        WorldMap creation, Beast and food positioning, game mechanics and final
        creation of ranking list
        also calling of the Visualisation and beastAnalytics
        """
        self.running = True
        if self.useNetworking:
            self.server.prepareGameStart()
                
        # ensure that at least configured minimum number of beasts are registered:
        availableBeasts = ['NikolaisBeast()', 'SamysBeast()', 'Team8Beast()']
        while (self.gameSignOnPossible() and len(self.beastObjectMap) < Config.__getMinimumBeasts__()):
            self.registerBeast(eval(random.choice(availableBeasts)))

        #final beastObjectMap gets passed to beastAnalytics
        if self.useBeastAnalytics:
            self.beastAnalytics.setBeastObjectMap(self.beastObjectMap)

        self.gameStarted = True
        
        #size = number of beast * value of fieldFactor(Config) * 25(beast-View)
        size = len(self.beastObjectMap) * Config.__getFieldFactor__() * 25
        self.worldMap = WorldMap(size, self)
        self.worldMap.placeBeasts()
        self.worldMap.placeStartFood()
        
        #calls outsourced round mechanic
        self.doRounds()
        self.gameFinished = True
        
        for beastObject in self.beastObjectMap.values():
            #this sends the last ten rounds to client after game is finished
            beastObject.beast.bewege(str(beastObject.energy) + ';' + 'Ende' + ';' + self.worldMap.getLastTenRoundsAsString() + ';')
          
        self.log.info(self.getRankingList())
        #BeastAnalytics
        if self.useBeastAnalytics and self.enableUrwidVisualisation == False:
            for i in range(len(self.getStatisticForBeast)):
                self.log.info(self.beastAnalytics.getStatistic(self.getStatisticForBeast[i]))
                self.beastAnalytics.getStatisticFile(self.getStatisticForBeast[i])

        # Added to stop Thread
        self.stop()
        
    def doRounds(self):
        """
        round mechanic -runs until maxRounds are reached or only 1 beast remains
        random food positioning and calling of move() for every beast
        """
        while (self.roundCounter < Config.__getMaxRounds__() and \
                    self.deadBeasts < len(self.beastObjectMap) - 1 and self.running):
            #Generate/Save WorldMap state of last round

            self.foodCounter = 0 #needed for food arrangement
            for beastObject in self.beastObjectMap.values():
                self.arrangeFoodEveryRound()
                
                #calls move() for every beast, also if it's already dead    
                beastObject.move(self.worldMap)                
                if self.enableUrwidVisualisation and beastObject.energy > 0:
                    time.sleep(self.urwidRoundDelay)
                    
            self.arrangeFoodEveryRound(whileRoundState=False)
            self.worldMap.insertWorldToLastTenRoundsAsString()
            self.roundCounter += 1                             

            #BeastAnalytics
            if self.useBeastAnalytics:
                self.beastAnalytics.nextRound()
        
    def arrangeFoodEveryRound(self, whileRoundState=True):
        """
        arranges the correct number of food items every round
        @param whileRoundState (default=True) marks if this method is called 
        while or at the end of a round
        """
        if whileRoundState:
            #calls placeFoodItem once per per 3/5 beast
            rnd = random.randint(1, len(self.beastObjectMap))
            if rnd in range(len(self.beastObjectMap) * 3 / 5) and \
                            self.foodCounter < len(self.beastObjectMap) * 3 / 5:
                self.worldMap.placeFoodItem()
                self.foodCounter += 1  
        else:
            # is called if not enough food has been rained
            if self.foodCounter < len(self.beastObjectMap) * 3 / 5:
                
                counter = 0
                while counter in range(len(self.beastObjectMap) * 3 / 5 - self.foodCounter):
                    self.worldMap.placeFoodItem()
                    counter += 1
                    
    def getBeastByName(self, name):
        """
        @param name String: beast name
        @return socket, srcAddr: Returns client-socket, client-source-address of given beast-name from BeastObjectMap
        """
        beast = self.beastObjectMap.get(name)
        return beast.socket, beast.srcAddr
    
    def gameSignOnPossible(self):
        """
        Checks if game is full or has already started
        @return Boolean 
        """
        if not(self.gameStarted) and (len(self.beastObjectMap) < len(string.ascii_letters)):
            return True
        return False

    def getRankingList(self):
        """
        calculates the ranking of the beasts depending on their time of death or
        their remaining energy
        @return String: the ranking list of the beasts
        """
        survivedBeasts = []
        for beast in self.beastObjectMap.values():
            if beast.alive:
                survivedBeasts.append(beast)
        tmp = sorted(survivedBeasts, key=lambda BeastObject:BeastObject.energy, reverse=True)
        for i in range(len(tmp)):
            self.rankingList[i] = tmp[i]
   
        #Create return string
        dots=lambda x: x>=9 and'.'*12 or'.'*13
        returnString = 'Ranking:\n'
        for i in range(len(self.rankingList)):
            returnString += str(i + 1) + str(dots(i)) + str(
                self.rankingList[i]) + ' with ' + str(
                    self.rankingList[i].energy) + ' energy\n'          
        return returnString
            
    def markDeadBeast(self, name):
        """
        marks beasts who died in a fight as dead and writes them in the 
        rankingList (LIFO)
        @param name String: puts in the name of the dead beast
        """
        self.rankingList[len(self.rankingList) - 1 - self.deadBeasts] = self.beastObjectMap[name]
        self.deadBeasts += 1

    def setupUrwid(self):
        """
        checks if urwid should be used and starts its loops
        """
        if self.enableUrwidVisualisation: 
            #update content Loop:
            self.gui.start()            
            #main urwid loop:
            self.gui.runLoop()
            
    def stop(self):
        """
        stops game thread
        """
        self.running = False