示例#1
0
def advanceLevel(game: Dungeon):
    """
    Advances the game (Dungeon) to the next level (increments game's current
    level, moves players to a random room of next level) and returns the
    updated game. If there are no levels remaining in the game to advance
    to, ends the game.
    :param game: Dungeon
    """
    nextLevelNum = game.currLevel + 1
    if nextLevelNum == len(game.levels):
        return endGame(game)

    game.currLevel = nextLevelNum
    nextLevel: Level = game.levels[nextLevelNum]
    numPlayers = len(game.players)
    forbidden = [nextLevel.keyLocation, nextLevel.exitLocation]
    playerLocs = []
    i = 0
    while i < numPlayers:  # Populate players in level
        playerName = game.players[i]
        randBoardNum, randBoard = getRandomRoomInLevel(nextLevel)
        loc = genXRandCoords(1, forbidden, randBoard.origin,
                             randBoard.dimensions).pop()
        if loc not in playerLocs:
            player = Player(playerName, loc)
            nextLevel.boards[randBoardNum] = addPlayersToBoard(
                randBoard, {playerName: player})
            playerLocs.append(loc)
            i += 1

    return game
示例#2
0
def initEnemies(game: Dungeon, initPlayerLocs: list):
    enemies = []  # LIST of dictionaries for each level
    forbiddenLocs = initPlayerLocs

    for i in range(len(game.levels)):
        numZombies = math.floor((i + 1) / 2) + 1
        numGhosts = math.floor(((i + 1) - 1) / 2)
        forbiddenLocs += [
            game.levels[i].keyLocation, game.levels[i].exitLocation
        ]
        levelEnemies = {}
        enemyLocs = []
        for ghost in range(numGhosts):
            randBoardNum, randBoard = getRandomRoomInLevel(game.levels[i])
            name = "ghost" + str((ghost + 1))
            loc = genXRandCoords(1, forbiddenLocs + enemyLocs,
                                 randBoard.origin, randBoard.dimensions)
            enemyLocs.append(loc)
            newGhost = Enemy(name, loc, "ghost")
            levelEnemies[name] = (randBoardNum, newGhost)

        forbiddenLocs += [
            board.doorLocations for board in game.levels[i].boards
        ]
        for zombie in range(numZombies):
            randBoardNum, randBoard = getRandomRoomInLevel(game.levels[i])
            name = "zombie" + str((zombie + 1))
            loc = genXRandCoords(1, forbiddenLocs + enemyLocs,
                                 randBoard.origin, randBoard.dimensions).pop()
            enemyLocs.append(loc)
            newZombie = Enemy(name, loc)
            levelEnemies[name] = (randBoardNum, newZombie)

        enemies.append(levelEnemies)
        populateEnemies(i, levelEnemies, game)
        forbiddenLocs = []
    return game
示例#3
0
def interactWithWall(enemyName: str, destination: tuple, game: Dungeon):
    """
    Only for ghosts, teleports the enemy to a random location in the level,
    or doesn't do anything if that's not possible. Returns an updated (or not)
    game.
    """
    currLevel = game.levels[game.currLevel]
    randBoardNum, randBoard = getRandomRoomInLevel(currLevel)
    enemy = getEnemy(currLevel, enemyName)
    while True:
        loc = genXRandCoords(1, [enemy.location], randBoard.origin,
                             randBoard.dimensions).pop()
        if not destHasWall(loc, currLevel) and not destHasPlayer(
                loc, randBoard):
            newDestForGhost = loc
            break
    # Move ghost to newDest, and delete from currBoard
    game = move(enemyName, newDestForGhost, game, isPlayer=False)
    return game
示例#4
0
def populatePlayers(level: Level, playerNames: list):
    numPlayers = len(playerNames)
    forbidden = [level.keyLocation, level.exitLocation]
    players = []
    playerLocs = []
    i = 0
    while i < numPlayers:  # Populate players in level
        playerName = playerNames[i]
        randBoardNum, randBoard = getRandomRoomInLevel(level)
        log("Rand board", str(randBoardNum), str(randBoard.dimensions))
        loc = genXRandCoords(1, forbidden, randBoard.origin,
                             randBoard.dimensions).pop()
        if loc not in playerLocs:
            player = Player(playerName, loc)
            players.append(player)
            level.boards[randBoardNum] = addPlayersToBoard(
                randBoard, {playerName: player})
            playerLocs.append(loc)
            i += 1
    return playerLocs, level
示例#5
0
def main():
    DEFAULT_LEVEL = './tests/snarl.levels'
    numPlayers = 1
    startLevel = 1
    jsonLevels = []
    isObserving = False
    numLevels = 0

    parser = argparse.ArgumentParser()  # initialize
    # this is how you add an optional argument
    parser.add_argument("--levels",
                        help="Enter the name of an input JSON Level file",
                        nargs='?',
                        const=DEFAULT_LEVEL, type=str)
    parser.add_argument("--players", help="Enter an amount of players 1-4",
                        nargs='?',
                        const=numPlayers, type=int)
    parser.add_argument("--start",
                        nargs='?',
                        help="Enter the number of the level to start the game from",
                        const=startLevel, type=int)
    parser.add_argument("--observe", help="Observe the game",
                        action="store_true")

    # this is called after you define your optional args
    args = parser.parse_args()

    # Parse level
    if args.levels:
        log('got levels flag', args.levels)
        with open(args.levels) as file:
            wholeFile = file.read()
            portions = wholeFile.split('\n\n')
            cleaned = list(filter(lambda port: port != '', portions))
            numLevels = cleaned[0]
            jsonLevels = cleaned[1:]
    else:
        log("using default level")
        with open(DEFAULT_LEVEL) as file:
            wholeFile = file.read()
            portions = wholeFile.split('\n\n')
            cleaned = list(filter(lambda port: port != '', portions))
            numLevels = cleaned[0]
            jsonLevels = cleaned[1:]

    if args.players:
        if 1 <= args.players <= 4:
            log('got players flag', str(args.players))
            numPlayers = args.players
        else:
            print("Players must be from 1-4")
            sys.exit(1)

    if args.start and 0 < args.start <= len(jsonLevels):
        log('got start flag', args.start)
        startLevel = args.start

    if args.observe:
        log('got observe')
        isObserving = True

    try:
        rawJsonGameLevels = jsonLevels[(startLevel - 1):]
        jsonGameLevels = [json.loads(rawJsonLevel) for rawJsonLevel in
                          rawJsonGameLevels]
        log("got+converted {} levels".format(len(jsonGameLevels)))

        # this has all the levels needed with the starting level as the first
        # element in the list
        levels = [convertJsonLevel(jsonLevel["rooms"], jsonLevel["hallways"],
                                   jsonLevel["objects"]) for jsonLevel in
                  jsonGameLevels]

        playerNames = [input("Player {}, enter your name > ".format(i + 1)) for
                       i in
                       range(numPlayers)]

        log("Using levels", str(levels))
        forbidden = [levels[0].keyLocation, levels[0].exitLocation]
        players = []
        playerLocs = []
        i = 0
        while i < numPlayers:  # Populate players in level
            playerName = playerNames[i]
            randBoardNum, randBoard = getRandomRoomInLevel(levels[0])
            log("Rand board", str(randBoardNum), str(randBoard.dimensions))
            loc = genXRandCoords(1, forbidden, randBoard.origin,
                                 randBoard.dimensions).pop()
            if loc not in playerLocs:
                player = Player(playerName, loc)
                players.append(player)
                levels[0].boards[randBoardNum] = addPlayersToBoard(randBoard, {
                    playerName: player})
                playerLocs.append(loc)
                i += 1

        game = Dungeon(levels, playerNames, startLevel - 1, False)

        enemies = []  # LIST of dictionaries for each level

        for i in range(len(game.levels)):
            numZombies = math.floor((i + 1) / 2) + 1
            numGhosts = math.floor(((i + 1) - 1) / 2)
            log("NUM ZOMBIES", str(numZombies), "NUM GHOSTS", str(numGhosts))
            levelEnemies = {}
            enemyLocs = []
            for zombie in range(numZombies):
                randBoardNum, randBoard = getRandomRoomInLevel(levels[i])
                name = "zombie" + str((zombie + 1))
                # log("BUILDIGN NEW ZOMBIEEE")
                # log("NAME: ", name)
                loc = genXRandCoords(1, playerLocs + forbidden + enemyLocs,
                                     randBoard.origin,
                                     randBoard.dimensions).pop()
                log("LOC", str(loc))
                enemyLocs.append(loc)
                newZombie = Enemy(name, loc)
                levelEnemies[name] = (randBoardNum, newZombie)
            for ghost in range(numGhosts):
                randBoardNum, randBoard = getRandomRoomInLevel(levels[i])
                name = "ghost" + str((ghost + 1))
                loc = genXRandCoords(1, playerLocs + forbidden + enemyLocs,
                                     randBoard.origin,
                                     randBoard.dimensions)
                # loc = getRandCoordInLevel(level, True)
                enemyLocs.append(loc)
                newGhost = Enemy(name, loc, "ghost")
                levelEnemies[name] = (randBoardNum, newGhost)

            enemies.append(levelEnemies)
            populateEnemies(i, levelEnemies, game)

        # Initialize screen
        pygame.init()
        clock = pygame.time.Clock()
        screen = pygame.display.set_mode(Globals.SCREEN_DIMENSIONS,
                                         flags=pygame.RESIZABLE)
        pygame.display.set_caption("Local Snarl Demo")

        # Fill background. Draw onto this
        gameDisplaySize = (
            Globals.GAME_DISPLAY_WIDTH, Globals.GAME_DISPLAY_HEIGHT)
        background = pygame.Surface(gameDisplaySize)
        statusBarSize = (Globals.STATUS_BAR_WIDTH, Globals.STATUS_BAR_HEIGHT)
        statusBar = pygame.Surface(statusBarSize)
        background = background.convert()  # converts Surface to single-pixel
        statusBar = statusBar.convert()  # converts Surface to single-pixel
        # format
        background.fill(Globals.BG_COLOR)
        statusBar.fill(Globals.BG_COLOR)

        currLevel0: Level = game.levels[game.currLevel]

        def getEnemies(enemiesDict: list):
            acc = []
            for enemiesInLevel in enemiesDict:
                for enemyName in enemiesInLevel.keys():
                    acc.append(enemiesInLevel[enemyName][1])
            return acc

        allEnemies = getEnemies(enemies)

        log("All enemies", str(allEnemies))
        log("Level has this many boards", str(len(currLevel0.boards)))

        def locationInTiles(location: tuple, tiles: dict):
            lrow, lcol = location
            for row in tiles.keys():
                if lrow == row:
                    for col in tiles[row].keys():
                        if lcol == col:
                            return True
            return False

        # if isObserving:
        #     log("OBSERVER VIEW")
        #     allTiles = getAllTiles(currLevel0)
        #     view = ObserverView("observer", allTiles, [currLevel0.keyLocation],
        #                         [currLevel0.exitLocation],
        #                         players, allEnemies)
        #     renderObserverView(background, view)
        # else:
        #     log("PLAYER VIEW")
        #     player: Player = getPlayer(currLevel0, playerNames[0])
        #     visibleTiles = getVisibleTiles(player, currLevel0)
        #     nearbyEnemies = [enemy for enemy in allEnemies if
        #                      locationInTiles(enemy.location, visibleTiles)]
        #     nearbyPlayers = [player for player in players if
        #                      locationInTiles(player.location, visibleTiles)]
        #     view = PlayerView(playerNames[0],
        #                       visibleTiles,
        #                       player.location,
        #                       [currLevel0.keyLocation],
        #                       [currLevel0.exitLocation],
        #                       nearbyPlayers, nearbyEnemies)
        #     # renderPlayerView(background, view)

        # Block events we don't care about and allow ones we do
        # (speeds processing)
        pygame.event.set_blocked(None)
        pygame.event.set_allowed([QUIT, MOUSEBUTTONDOWN, MOUSEBUTTONUP])

        hasMoved = {}
        for player in game.players:
            hasMoved[player] = 0

        while True:

            # pygame.time.wait(250)
            clock.tick(30)  # cap at 30fps

            currLevel: Level = game.levels[game.currLevel]

            if game.isGameOver:
                log("The game is over! If you won, congrats!")
                sys.exit(0)

            log("Player turn is ", str(currLevel.playerTurn))
            playerName = game.players[currLevel.playerTurn]
            player: Player = getPlayer(currLevel, playerName)

            log("Game players", str(game.players))
            log("Level players", str(getAllPlayers(currLevel)))

            # player not in level (ejected or exited)
            if not player:
                log("Skipping turn")
                hasMoved[playerName] = 1
                log("HASSSMOVVVEEEEDD POST ENEMIESS", str(hasMoved))
                if currLevel.playerTurn == len(game.players) - 1:
                    currLevel.playerTurn = 0
                else:
                    currLevel.playerTurn = currLevel.playerTurn + 1
                # currLevel.playerTurn = currLevel.playerTurn + 1
                # currLevel.enemyTurn = currLevel.enemyTurn + 1
                continue

            log("Player turn", str(currLevel.playerTurn))
            log("Enemy turn:", str(currLevel.enemyTurn))

            # Move all enemies at beginning of rounds (all players moved)
            numPlayersInGame = len(game.players) - 1
            # log("numPlayersInGame", str(numPlayersInGame))
            # if currLevel.enemyTurn == numPlayersInGame:
            if all(hasMoved.values()):
                for enemy in getEnemiesInLevel(currLevel):
                    nextMove = EnemyMove.enemyNextMove(enemy, game)
                    log("Next move is", str(nextMove))
                    GameManager.move(enemy.name, nextMove, game,
                                     isPlayer=False)
                # currLevel.enemyTurn = -1
                for moved in hasMoved.keys():
                    hasMoved[moved] = 0
                log("HASSSMOVVVEEEEDD POST ENEMIESS", str(hasMoved))

            board1: Board = currLevel.boards[
                whichBoardInLevel(currLevel,
                                  player.location)]

            # Render appropriate view
            if isObserving:
                allTiles = getAllTiles(currLevel)
                allPlayers = getAllPlayers(currLevel)
                allEnemies = getAllEnemies(currLevel)
                view = ObserverView("observer", allTiles,
                                    [currLevel.keyLocation],
                                    [currLevel.exitLocation],
                                    allPlayers, allEnemies)
                renderObserverView(background, view)
            else:
                visibleTiles = getVisibleTiles(player, currLevel)
                visiblePlayers = [board1.players[pname] for pname in
                                  board1.players.keys() if
                                  locationInTiles(
                                      # FIXME bug when player next to you
                                      board1.players[pname].location,
                                      visibleTiles)]
                visibleEnemies = [board1.enemies[ename] for ename in
                                  board1.enemies.keys() if
                                  locationInTiles(
                                      board1.enemies[ename].location,
                                      visibleTiles)]
                newView = PlayerView(playerName,
                                     visibleTiles,
                                     player.location,
                                     [currLevel.keyLocation],
                                     [currLevel.exitLocation],
                                     visiblePlayers,
                                     visibleEnemies)
                renderPlayerView(background, newView)

            # Everyone gets a status bar (yay)
            renderStatusBar(statusBar, game)

            # handle user events
            for event in pygame.event.get():
                if event.type == QUIT:
                    sys.exit(0)
                if event.type == MOUSEBUTTONDOWN:  # FIXME and not isObserving:
                    newLoc = translateScreenLocation(event.pos)
                    if not locationInLevelBounds(currLevel, newLoc):
                        continue
                    # log("Got click at", str(event.pos), "--->", str(newLoc))
                    GameManager.move(playerName, newLoc, game)
                    hasMoved[playerName] = 1
                    log("HASSSMOVVVEEEEDD", str(hasMoved))

            """
            gameCollection ---> {gameName: dungeon}
            observerCollection ---> {observerName: gameName}

            when observe requested/game state change
                Observer.send(observerName, gameCollection[observerCollection[observerName]])
            """

            # map of keys pressed

            # keys = pygame.key.get_pressed()
            screen.blit(background,
                        (0, Globals.STATUS_BAR_HEIGHT))  # render pixels to
            screen.blit(statusBar, (0, 0))
            pygame.display.update()  # update


    except FileNotFoundError:
        print("Couldn't find that level file. Try again")
        sys.exit(1)
    except json.JSONDecodeError:
        print("Malformed levels")
        sys.exit(1)
    except KeyboardInterrupt:
        print("\nExiting...")
        sys.exit(0)