Пример #1
0
def getPlayerUpdate(playerName: str, game: Dungeon):
    """
    PlayerUpdateType is:
    {
      "type": "player-update",
      "layout": (tile-layout), # getLayout?
      "position": (point), # getPlayer.location
      "objects": (object-list), # getLocationsAround.map(if destHasItem || desthasKey -> return object)
        [ { "type": "key", "position": [ 4, 2 ] },
               { "type": "exit", "position": [ 7, 17 ] } ]
      "actors": (actor-position-list) # potentially getLocationsAround.map(if destHasEnemy -> return enemy)
    }

    1. Finds 25 points: surrounding 24 of given point
    2.Layput based on the 25 points
    3. Will check if enemies exist on any of those 25
    4. Will check if key or exit on any of those 25

    """
    player: Player = getPlayer(game.levels[game.currLevel], playerName)
    possMoves = getFieldOfView(player, game.levels[game.currLevel])
    output = [
        playerName, {
            "type": "player-update",
            "layout": getTileLayout(game, player),
            "position": [player.location[0], player.location[1]],
            "objects": getObjectsAroundPlayer(possMoves, game),
            "actors": getEnemiesAroundPlayer(possMoves, game)
        }
    ]
    return output
Пример #2
0
def moveEntity(level: Level, name: str, currBoard: int, newBoardNum: int,
               destination: tuple, isPlayer: bool):
    """
    Move the Player/Enemy with the given name to the given destination
    in the level.
    :param level: Level
    :param name: str
    :param currBoard: int
    :param newBoardNum: int
    :param destination: tuple
    :param isPlayer: bool
    """
    board = level.boards[currBoard]
    entity = getPlayer(level, name) if isPlayer else getEnemy(level, name)
    destInBoard = locationInBounds(destination, board.origin, board.dimensions)

    if destInBoard:
        entity.location = destination
    else:
        boardEntities = board.players if isPlayer else board.enemies
        del boardEntities[name]
        if newBoardNum != -1:
            otherBoard = level.boards[newBoardNum]
            entity.location = destination

            if isPlayer:
                otherBoard.players[name] = entity
            else:
                otherBoard.enemies[name] = entity

            level.currBoard = newBoardNum

    return level
Пример #3
0
def move(entityName: str, destination, game: Dungeon, isPlayer=True):
    """
    Updates the game to reflect the movement of a player if they
    can move to the given destination in the game or skip a turn when
    destination is None. Returns an unmodified game if the player cannot
    move based on game rules.
    :param entityName: str
    :param destination: tuple | None
    :param game: Dungeon
    """
    currLevel: Level = game.levels[game.currLevel]

    # Player move is skipped
    if destination is None:
        # only increment player turn
        updatedPlayerTurn = currLevel.playerTurn + 1
        if updatedPlayerTurn == len(game.players) - 1:
            currLevel.playerTurn = 0
        else:
            currLevel.playerTurn = updatedPlayerTurn
        return game

    entity = getPlayer(currLevel, entityName) if isPlayer else getEnemy(
        currLevel, entityName)
    currBoardNum = whichBoardInLevel(currLevel, entity.location)
    newBoardNum = whichBoardInLevel(currLevel, destination)
    numMoves = 2
    if isPlayer and playerCanMoveTo(destination, entity, currLevel, numMoves):
        updatedLevel = moveEntity(currLevel,
                                  entityName,
                                  currBoardNum,
                                  newBoardNum,
                                  destination,
                                  isPlayer=True)
        if updatedLevel.playerTurn == len(game.players) - 1:
            updatedLevel.playerTurn = 0
            updatedLevel.enemyTurn = updatedLevel.enemyTurn + 1
        else:
            updatedLevel.playerTurn = updatedLevel.playerTurn + 1
            updatedLevel.enemyTurn = updatedLevel.enemyTurn + 1
        game.levels[game.currLevel] = updatedLevel
        updatedGame = interact(entityName, destination, game)
        return updatedGame
    elif not isPlayer:
        updatedLevel = moveEntity(currLevel,
                                  entityName,
                                  currBoardNum,
                                  newBoardNum,
                                  destination,
                                  isPlayer=False)
        game.levels[game.currLevel] = updatedLevel
        updatedGame = enemyInteract(entityName, destination, game)
        return updatedGame
    else:
        return game
Пример #4
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
Пример #5
0
def executeTurns(game: Dungeon, maxNumTurns: int, jsonActorMoveListList: list,
                 jsonNameList: list, jsonLevel: dict):
    # Send initial player updates to all players in game
    managerTrace = getPlayersUpdates(game, [])
    i = 0
    while i < maxNumTurns:
        # 0. Exit checking
        if anyOutOfMoves(jsonActorMoveListList) or isCurrentLevelOver(game):
            break
        # 1. Run all moves in turn
        for j in range(len(jsonActorMoveListList)
                       ):  # execute each move for a player in a turn
            playerMoveList = jsonActorMoveListList[j]
            validMove = False

            while not validMove and len(playerMoveList) > 0:
                # do first move in playerMoveList, if valid, set flag
                move = playerMoveList[0]
                playerName = jsonNameList[j]
                if not isPlayerInGame(playerName, game):
                    break

                currLevel: Level = game.levels[game.currLevel]
                player = getPlayer(currLevel, playerName)  # pot bug??
                dest = move["to"]
                # apply
                if not dest:  # skipped turn
                    validMove = True
                    managerTrace.append([playerName, move,
                                         "OK"])  # pot bug adding??
                    managerTrace = getPlayersUpdates(game, managerTrace)
                elif playerCanMoveTo(intifyTuple(dest), player, currLevel, 2):
                    GameManager.move(playerName, intifyTuple(dest),
                                     game)  # pot bug not mutating??
                    managerTrace.append(
                        getMoveStatus(currLevel, playerName,
                                      move))  # pot bug wrong return types??
                    managerTrace = getPlayersUpdates(game, managerTrace)
                    validMove = True
                else:
                    managerTrace.append([playerName, move, "Invalid"])
                    validMove = False

                del playerMoveList[0]

        i += 1
    return managerTrace, game
Пример #6
0
def getPlayersInRoomAndLevel(boardNum: int, game: Dungeon):
    """
    Returns a tuple of a list of the players alive at the given board number
    in the current level and a list of the players alive in the current level.
    :params boardNum: int
    :params game: Dungeon
    """
    board: Board = game.levels[game.currLevel].boards[boardNum]
    playersInOurRoom = []
    playersInLevel = []
    for playerName in game.players:
        player = getPlayer(game.levels[game.currLevel], playerName)
        if player:
            playersInLevel.append(player)
            if player.location[0] in board.tiles.keys():
                if player.location[1] in board.tiles[player.location[0]].keys():
                    playersInOurRoom.append(player)
    return playersInOurRoom, playersInLevel
Пример #7
0
def getFinalState(game: Dungeon, jsonLevel: dict, jsonEnemies: list):
    players = []
    for playerName in game.players:

        if isPlayerInGame(playerName, game):
            player: Player = getPlayer(game.levels[game.currLevel], playerName)
            newPlayer = {
                "type": "player",
                "name": playerName,
                "position": player.location
            }
            players.append(newPlayer)
    exitLocked = not game.levels[game.currLevel].exitUnlocked
    return {
        "type": "state",
        "level": jsonLevel,
        "players": players,
        "adversaries": jsonEnemies,
        "exit-locked": exitLocked
    }
Пример #8
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)