Beispiel #1
0
def enemyPossibleMoves(enemy: Enemy, game: Dungeon):
    """
    Gets a list of the possible moves a given enemy can feasibly make.
    In essence, gets all the moves are traversable within each enemy's
    walkable distance.
    :params enemy: Enemy
    :params game: Dungeon
    """
    possibleMoves = []
    enemyBoardNum = whichBoardInLevel(game.levels[game.currLevel],
                                      enemy.location)
    enemyBoard: Board = game.levels[game.currLevel].boards[enemyBoardNum]
    if enemy.enemyType == "zombie":
        tilesAround = getLocationsAround(enemy.location)
        for loc in tilesAround:
            if locationInBounds(loc, enemyBoard.origin, enemyBoard.dimensions):
                tile = enemyBoard.tiles[loc[0]][loc[1]]
                if tile.tileType != TileEnum.WALL and tile.tileType != TileEnum.DOOR:
                    possibleMoves.append(loc)
    elif enemy.enemyType == "ghost":
        tilesAround = getLocationsAround(enemy.location)
        for loc in tilesAround:
            if locationInLevelBounds(game.levels[game.currLevel], loc):
                possibleMoves.append(loc)
    return possibleMoves
Beispiel #2
0
def playerPossibleCardinalMoves(location: tuple, numMoves: int, level: Level,
                                boardNumber: int):
    """
    Outputs the possible moves for a player given the number of cardinal moves.
    :param location: tuple
    :param numMoves: int
    :param level: Level
    :param boardNumber: int
    """
    board = level.boards[boardNumber]
    possibleMoves = []
    while numMoves > 0:
        if len(possibleMoves) == 0:
            possibleMoves += list(filter(
                lambda lamLoc: locationInLevelBounds(level, lamLoc),
                getLocationsAround(location)))
        else:
            temp = []
            for loc in possibleMoves:
                temp += list(filter(
                    lambda lamLoc: locationInBounds(lamLoc, board.origin,
                                                    board.dimensions),
                    getLocationsAround(loc)))
            possibleMoves += temp
        numMoves -= 1
        possibleMoves = list(unique_everseen(possibleMoves))

    return possibleMoves
Beispiel #3
0
def getFieldOfView(playerName: str, level: Level):
    player: Player = getPlayer(level, playerName)
    pLocRow, pLocCol = player.location
    origin = (pLocRow - 2, pLocCol - 2)
    fieldOfView = []
    for r in range(5):
        for c in range(5):
            relLoc = (origin[0] + r, origin[1] + c)
            if locationInLevelBounds(level, relLoc):
                fieldOfView.append(relLoc)
    return fieldOfView
Beispiel #4
0
def playerPossibleCardinalMoves(location: tuple, numMoves: int, level: Level):
    """
    Outputs the possible moves for a player given the number of cardinal moves.
    :param location: tuple
    :param numMoves: int
    :param level: Level
    """
    possibleMoves = []
    while numMoves > 0:
        if len(possibleMoves) == 0:
            possibleMoves += list(
                filter(lambda lamLoc: locationInLevelBounds(level, lamLoc),
                       getLocationsAround(location)))
        else:
            temp = []
            for loc in possibleMoves:
                temp += list(
                    filter(lambda lamLoc: locationInLevelBounds(level, lamLoc),
                           getLocationsAround(loc)))
            possibleMoves += temp
        possibleMoves = list(unique_everseen(possibleMoves, key=tuple))
        numMoves -= 1
    return possibleMoves
Beispiel #5
0
def getVisibleTiles(player: Player, level: Level):
    pLocRow, pLocCol = player.location
    origin = (pLocRow - 2, pLocCol - 2)
    fieldOfView = {}
    for r in range(5):
        fovRow = {}
        relRow = origin[0] + r
        for c in range(5):
            relCol = origin[1] + c
            relLoc = (relRow, relCol)
            if locationInLevelBounds(level, relLoc):
                boardNum = whichBoardInLevel(level, relLoc)
                tile = level.boards[boardNum].tiles[relRow][relCol]
                fovRow[relCol] = tile
        fieldOfView.update({relRow: fovRow})
    return fieldOfView
Beispiel #6
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)