Ejemplo n.º 1
0
    def generateMaze(self, playerIds, prevMaze=None):
        """ Generate a maze for this game. """

        self.maze = MazeAI(self.air, self.doId)
        self.air.createDistributedObject(distObj=self.maze,
                                         zoneId=self.objZone)

        # How many players are we basing this maze on?
        numPlayers = len(playerIds)
        mazeSize = max(numPlayers * Globals.MazeSquaresPerPlayer,
                       Globals.MazeMinSize)
        xsize = math.sqrt(mazeSize)

        # Expand or contract the width of the maze by up to 33%, so
        # it's not always square.
        if random.choice([True, False]):
            xsize += xsize * random.uniform(0, 0.33)
        else:
            xsize -= xsize * random.uniform(0, 0.33)

        xsize = int(math.floor(xsize + 0.5))
        ysize = int(math.floor(mazeSize / xsize + 0.5))

        self.mazeId = self.maze.doId

        self.maze.generateMaze(xsize, ysize, prevMaze=prevMaze)
Ejemplo n.º 2
0
    def generateMaze(self, playerIds, prevMaze = None):
        """ Generate a maze for this game. """

        self.maze = MazeAI(self.air, self.doId)
        self.air.createDistributedObject(
            distObj = self.maze, zoneId = self.objZone)

        # How many players are we basing this maze on?
        numPlayers = len(playerIds)
        mazeSize = max(numPlayers * Globals.MazeSquaresPerPlayer, Globals.MazeMinSize)
        xsize = math.sqrt(mazeSize)

        # Expand or contract the width of the maze by up to 33%, so
        # it's not always square.
        if random.choice([True, False]):
            xsize += xsize * random.uniform(0, 0.33)
        else:
            xsize -= xsize * random.uniform(0, 0.33)
            
        xsize = int(math.floor(xsize + 0.5))
        ysize = int(math.floor(mazeSize / xsize + 0.5))

        self.mazeId = self.maze.doId

        self.maze.generateMaze(xsize, ysize, prevMaze = prevMaze)
Ejemplo n.º 3
0
class TagGameAI(DistributedObjectAI):

    notify = directNotify.newCategory("TagGameAI")

    def __init__(self, air):
        DistributedObjectAI.__init__(self, air)
        self.gameActive = True
        self.winners = []
        self.artPaintings = []
        self.nextGameId = 0
        self.timeout = globalClock.getFrameTime() + Globals.GameLengthSeconds
        self.expireTask = taskMgr.doMethodLater(Globals.GameLengthSeconds,
                                                self.expireGame, 'expireGame')
        self.deleteGameTask = None

        # Get a unique zoneId to put game objects (like the players)
        # in.
        self.objZone = self.air.zoneAllocator.allocate()

        self.maxNumPlayers = 0

        # Player ID's in the game.
        self.playerIds = []

        # Player ID's about to join the game.
        self.waitingIds = []

        # Mapping of player url -> server url for player posters.
        self.playerPosterMap = {}

        self.accept('newPlayer', self.newPlayer)
        self.accept('deletePlayer', self.deletePlayer)

    def generateMaze(self, playerIds, prevMaze=None):
        """ Generate a maze for this game. """

        self.maze = MazeAI(self.air, self.doId)
        self.air.createDistributedObject(distObj=self.maze,
                                         zoneId=self.objZone)

        # How many players are we basing this maze on?
        numPlayers = len(playerIds)
        mazeSize = max(numPlayers * Globals.MazeSquaresPerPlayer,
                       Globals.MazeMinSize)
        xsize = math.sqrt(mazeSize)

        # Expand or contract the width of the maze by up to 33%, so
        # it's not always square.
        if random.choice([True, False]):
            xsize += xsize * random.uniform(0, 0.33)
        else:
            xsize -= xsize * random.uniform(0, 0.33)

        xsize = int(math.floor(xsize + 0.5))
        ysize = int(math.floor(mazeSize / xsize + 0.5))

        self.mazeId = self.maze.doId

        self.maze.generateMaze(xsize, ysize, prevMaze=prevMaze)

    def setupPlayerPoster(self, player, url, posterData):
        """ Copies the player's posterData to the posterData list to
        store in the maze, so we can distribute local poster images to
        the players in the game.  Returns the modified URL. """

        try:
            i = int(URLSpec(url).getPath()[1:])
        except ValueError:
            return None

        try:
            data = player.posterData[i]
        except IndexError:
            return None

        if data in posterData:
            i = posterData.index(data)
        else:
            i = len(posterData)
            posterData.append(data)
        newUrl = 'maze://%s/%s' % (self.maze.doId, i)
        self.playerPosterMap[url] = newUrl

        return newUrl

    def announceGenerate(self):
        DistributedObjectAI.announceGenerate(self)

    def delete(self):
        self.air.zoneAllocator.free(self.objZone)
        self.objZone = None

        for playerId in self.playerIds[:]:
            player = self.air.doId2do.get(playerId, None)
            if player:
                player.game = None
        self.air.timeManager.chooseSuggestedGame(self.doId)

        DistributedObjectAI.delete(self)

    def getNumPlayers(self):
        return len(self.playerIds)

    def getMazeId(self):
        return self.mazeId

    def newPlayer(self, player):
        """ A new player has just joined the world: is he in this
        game? """
        if player.gameId == self.doId and player.doId in self.waitingIds:
            player.game = self
            self.waitingIds.remove(player.doId)
            self.playerIds.append(player.doId)
            self.maxNumPlayers = max(self.maxNumPlayers, len(self.playerIds))
            self.sendUpdate('setNumPlayers', [len(self.playerIds)])

            self.notify.info("player %s joined game %s, %s in game" %
                             (player.name, self.doId, len(self.playerIds)))

            # Award any paint points for carried-forward art paintings.
            prevCells = self.maze.prevPlayers.get(player.color, [])
            if prevCells:
                del self.maze.prevPlayers[player.color]
                for cell, dir in prevCells:
                    cell.markPrevUser(player, dir)

            # Assign a cell for the poster.
            self.maze.chooseRandomPosterCell(player)

    def deletePlayer(self, player):
        """ A player has just left the world. """
        if player.doId in self.playerIds:
            self.playerIds.remove(player.doId)
            player.game = None
            self.sendUpdate('setNumPlayers', [len(self.playerIds)])

            self.notify.info("player %s left game %s, %s in game" %
                             (player.name, self.doId, len(self.playerIds)))

            if player.posterCell:
                player.posterCell.updatePosterData(('', 0))
                player.posterCell.posterPlayerId = None
                player.posterCell = None

            if not self.playerIds:
                # When the last player leaves a game, shut it down.
                self.__deleteGame()

    def getTimeout(self):
        return globalClockDelta.localToNetworkTime(self.timeout)

    def getObjZone(self):
        return self.objZone

    def expireGame(self, task):
        """ The game has expired.  End it now. """
        self.expireTask = None
        self.endGame()

    def endGame(self):
        if self.expireTask:
            taskMgr.remove(self.expireTask)
            self.expireTask = None

        if not self.gameActive:
            return

        self.gameActive = False

        self.maze.chooseArtPaintings(self)

        playerList = []
        for playerId in self.playerIds:
            player = self.air.doId2do[playerId]
            playerList.append(player)

        # First, randomize the list, so ties come out in random order.
        random.shuffle(playerList)

        # Then sort it in decreasing order by score.
        playerList.sort(key=lambda p: -p.score)
        self.winners = playerList[:5]

        self.nextGameId = 0
        if self.playerIds:
            self.notify.info(
                "%s winner is %s, %s" %
                (self.doId, self.winners[0].name, self.winners[0].score))

            # Immediately start up a new game.  Assume the players in this
            # game will be joining the next game.
            self.nextGameId = self.air.allocateDoId()
            taskMgr.add(self.air.makeGame,
                        'makeGame',
                        extraArgs=[self.nextGameId, self.playerIds, self.maze])

        else:
            self.notify.info("%s ended with no players" % (self.doId))

        self.sendUpdate('setWinners', [
            self.gameActive, self.winners, self.maze.artPaintings,
            self.nextGameId
        ])
        self.air.timeManager.chooseSuggestedGame(self.doId)

        # And, after a period of time, remove this game object.
        self.deleteGameTask = taskMgr.doMethodLater(
            Globals.GameAfterlifeSeconds, self.__deleteGame, 'deleteGame')

    def __deleteGame(self, task=None):
        if self.expireTask:
            taskMgr.remove(self.expireTask)
            self.expireTask = None
        if self.deleteGameTask:
            taskMgr.remove(self.deleteGameTask)
            self.deleteGameTask = None

        if self.isDeleted():
            return

        self.maze.deleteMaze()
        self.air.sendDeleteMsg(self.maze.doId)
        self.air.sendDeleteMsg(self.doId)
        self.air.games.remove(self)
        self.ignoreAll()

    def getWinners(self):
        return (self.gameActive, self.winners, self.artPaintings,
                self.nextGameId)

    def requestJoin(self):
        """ Called by a new client to join the game. """

        playerId = self.air.getAvatarIdFromSender()

        if not self.gameActive or len(self.playerIds) + len(
                self.waitingIds) >= Globals.MaxPlayersPerGame:
            # Not allowing more joiners right now.
            self.sendUpdateToAvatarId(playerId, 'setJoin', [False])
            self.air.timeManager.chooseSuggestedGame(self.doId)
            return

        self.waitingIds.append(playerId)
        self.sendUpdateToAvatarId(playerId, 'setJoin', [True])

        if len(self.playerIds) + len(
                self.waitingIds) >= Globals.WantedPlayersPerGame:
            # This should no longer be the suggested game.
            self.air.timeManager.chooseSuggestedGame(self.doId)

    def setPoster(self, posterData):
        """ Sent from the client to tell the AI its current poster
        data.  Normally this is sent only when starting a new game,
        since the poster data is normally sent through the web
        interface initially. """

        playerId = self.air.getAvatarIdFromSender()
        if playerId in self.playerIds:
            player = self.air.doId2do[playerId]
            player.setPoster(posterData)
Ejemplo n.º 4
0
class TagGameAI(DistributedObjectAI):

    notify = directNotify.newCategory("TagGameAI")

    def __init__(self, air):
        DistributedObjectAI.__init__(self, air)
        self.gameActive = True
        self.winners = []
        self.artPaintings = []
        self.nextGameId = 0
        self.timeout = globalClock.getFrameTime() + Globals.GameLengthSeconds
        self.expireTask = taskMgr.doMethodLater(Globals.GameLengthSeconds, self.expireGame, 'expireGame')
        self.deleteGameTask = None

        # Get a unique zoneId to put game objects (like the players)
        # in.
        self.objZone = self.air.zoneAllocator.allocate()

        self.maxNumPlayers = 0

        # Player ID's in the game.
        self.playerIds = []

        # Player ID's about to join the game.
        self.waitingIds = []

        # Mapping of player url -> server url for player posters.
        self.playerPosterMap = {}

        self.accept('newPlayer', self.newPlayer)
        self.accept('deletePlayer', self.deletePlayer)

    def generateMaze(self, playerIds, prevMaze = None):
        """ Generate a maze for this game. """

        self.maze = MazeAI(self.air, self.doId)
        self.air.createDistributedObject(
            distObj = self.maze, zoneId = self.objZone)

        # How many players are we basing this maze on?
        numPlayers = len(playerIds)
        mazeSize = max(numPlayers * Globals.MazeSquaresPerPlayer, Globals.MazeMinSize)
        xsize = math.sqrt(mazeSize)

        # Expand or contract the width of the maze by up to 33%, so
        # it's not always square.
        if random.choice([True, False]):
            xsize += xsize * random.uniform(0, 0.33)
        else:
            xsize -= xsize * random.uniform(0, 0.33)
            
        xsize = int(math.floor(xsize + 0.5))
        ysize = int(math.floor(mazeSize / xsize + 0.5))

        self.mazeId = self.maze.doId

        self.maze.generateMaze(xsize, ysize, prevMaze = prevMaze)

    def setupPlayerPoster(self, player, url, posterData):
        """ Copies the player's posterData to the posterData list to
        store in the maze, so we can distribute local poster images to
        the players in the game.  Returns the modified URL. """

        try:
            i = int(URLSpec(url).getPath()[1:])
        except ValueError:
            return None

        try:
            data = player.posterData[i]
        except IndexError:
            return None

        if data in posterData:
            i = posterData.index(data)
        else:
            i = len(posterData)
            posterData.append(data)
        newUrl = 'maze://%s/%s' % (self.maze.doId, i)
        self.playerPosterMap[url] = newUrl

        return newUrl
        

    def announceGenerate(self):
        DistributedObjectAI.announceGenerate(self)

    def delete(self):
        self.air.zoneAllocator.free(self.objZone)
        self.objZone = None

        for playerId in self.playerIds[:]:
            player = self.air.doId2do.get(playerId, None)
            if player:
                player.game = None
        self.air.timeManager.chooseSuggestedGame(self.doId)

        DistributedObjectAI.delete(self)

    def getNumPlayers(self):
        return len(self.playerIds)

    def getMazeId(self):
        return self.mazeId

    def newPlayer(self, player):
        """ A new player has just joined the world: is he in this
        game? """
        if player.gameId == self.doId and player.doId in self.waitingIds:
            player.game = self
            self.waitingIds.remove(player.doId)
            self.playerIds.append(player.doId)
            self.maxNumPlayers = max(self.maxNumPlayers, len(self.playerIds))
            self.sendUpdate('setNumPlayers', [len(self.playerIds)])

            self.notify.info("player %s joined game %s, %s in game" % (player.name, self.doId, len(self.playerIds)))

            # Award any paint points for carried-forward art paintings.
            prevCells = self.maze.prevPlayers.get(player.color, [])
            if prevCells:
                del self.maze.prevPlayers[player.color]
                for cell, dir in prevCells:
                    cell.markPrevUser(player, dir)

            # Assign a cell for the poster.
            self.maze.chooseRandomPosterCell(player)
        

    def deletePlayer(self, player):
        """ A player has just left the world. """
        if player.doId in self.playerIds:
            self.playerIds.remove(player.doId)
            player.game = None
            self.sendUpdate('setNumPlayers', [len(self.playerIds)])

            self.notify.info("player %s left game %s, %s in game" % (player.name, self.doId, len(self.playerIds)))

            if player.posterCell:
                player.posterCell.updatePosterData(('', 0))
                player.posterCell.posterPlayerId = None
                player.posterCell = None

            if not self.playerIds:
                # When the last player leaves a game, shut it down.
                self.__deleteGame()

    def getTimeout(self):
        return globalClockDelta.localToNetworkTime(self.timeout)

    def getObjZone(self):
        return self.objZone

    def expireGame(self, task):
        """ The game has expired.  End it now. """
        self.expireTask = None
        self.endGame()

    def endGame(self):
        if self.expireTask:
            taskMgr.remove(self.expireTask)
            self.expireTask = None

        if not self.gameActive:
            return
        
        self.gameActive = False

        self.maze.chooseArtPaintings(self)

        playerList = []
        for playerId in self.playerIds:
            player = self.air.doId2do[playerId]
            playerList.append(player)

        # First, randomize the list, so ties come out in random order.
        random.shuffle(playerList)

        # Then sort it in decreasing order by score.
        playerList.sort(key = lambda p: -p.score)
        self.winners = playerList[:5]

        self.nextGameId = 0
        if self.playerIds:
            self.notify.info("%s winner is %s, %s" % (self.doId, self.winners[0].name, self.winners[0].score))

            # Immediately start up a new game.  Assume the players in this
            # game will be joining the next game.
            self.nextGameId = self.air.allocateDoId()
            taskMgr.add(self.air.makeGame, 'makeGame',
                        extraArgs = [self.nextGameId, self.playerIds, self.maze])
            
        else:
            self.notify.info("%s ended with no players" % (self.doId))

        self.sendUpdate('setWinners', [self.gameActive, self.winners, self.maze.artPaintings, self.nextGameId])
        self.air.timeManager.chooseSuggestedGame(self.doId)

        # And, after a period of time, remove this game object.
        self.deleteGameTask = taskMgr.doMethodLater(
            Globals.GameAfterlifeSeconds, self.__deleteGame,
            'deleteGame')

    def __deleteGame(self, task = None):
        if self.expireTask:
            taskMgr.remove(self.expireTask)
            self.expireTask = None
        if self.deleteGameTask:
            taskMgr.remove(self.deleteGameTask)
            self.deleteGameTask = None

        if self.isDeleted():
            return
            
        self.maze.deleteMaze()
        self.air.sendDeleteMsg(self.maze.doId)
        self.air.sendDeleteMsg(self.doId)
        self.air.games.remove(self)
        self.ignoreAll()

    def getWinners(self):
        return (self.gameActive, self.winners, self.artPaintings, self.nextGameId)

    def requestJoin(self):
        """ Called by a new client to join the game. """

        playerId = self.air.getAvatarIdFromSender()

        if not self.gameActive or len(self.playerIds) + len(self.waitingIds) >= Globals.MaxPlayersPerGame:
            # Not allowing more joiners right now.
            self.sendUpdateToAvatarId(playerId, 'setJoin', [False])
            self.air.timeManager.chooseSuggestedGame(self.doId)
            return

        self.waitingIds.append(playerId)
        self.sendUpdateToAvatarId(playerId, 'setJoin', [True])

        if len(self.playerIds) + len(self.waitingIds) >= Globals.WantedPlayersPerGame:
            # This should no longer be the suggested game.
            self.air.timeManager.chooseSuggestedGame(self.doId)
            
    def setPoster(self, posterData):
        """ Sent from the client to tell the AI its current poster
        data.  Normally this is sent only when starting a new game,
        since the poster data is normally sent through the web
        interface initially. """

        playerId = self.air.getAvatarIdFromSender()
        if playerId in self.playerIds:
            player = self.air.doId2do[playerId]
            player.setPoster(posterData)