Beispiel #1
0
def renderPlayers(background: pygame.Surface, players: dict):
    log = logInFile("Render.py", "renderPlayers")
    log()
    playerNames = players.keys()
    for name in playerNames:
        player = players[name]
        renderPlayer(background, player)
Beispiel #2
0
def renderEnemies(background: pygame.Surface, enemies: dict):
    log = logInFile("Render.py", "renderEnemies")
    log()
    enemyNames = enemies.keys()
    for name in enemyNames:
        enemy = enemies[name]
        renderEnemy(background, enemy)
Beispiel #3
0
def renderEnemy(background: pygame.Surface, enemy: Enemy):
    x, y = getScreenLocation(enemy.location)
    tileRect = pygame.Rect(x, y, Globals.TILE_WIDTH, Globals.TILE_HEIGHT)
    # tileColor = Colors.ENEMY
    log = logInFile("Render.py", "renderEnemy")
    log(enemy.name)
    enemyLetter = Globals.FONT.render(formatInitial(enemy.name), True,
                                      Colors.ENEMY)
    # pygame.draw.rect(background, tileColor, tileRect)
    background.blit(enemyLetter, tileRect.topleft)
Beispiel #4
0
def renderBoard(background: pygame.Surface, board: Board):
    # FIXME only Rooms should render door tiles
    log = logInFile("Render.py", "renderBoard")
    log()
    for tile in board.tiles:
        renderTile(background, tile)

    log("Players in board:", str(board.players))
    renderPlayers(background, board.players)
    renderEnemies(background, board.enemies)
Beispiel #5
0
def renderTile(background: pygame.Surface, tile):
    x, y = getScreenLocation(tile.location)  # absolute
    log = logInFile("Render.py", "renderTile")
    # log("Loc: ", str(tile.location), "PixelLoc: ", str((x, y)))
    tileRect = pygame.Rect(x, y, Globals.TILE_WIDTH, Globals.TILE_HEIGHT)
    tileColor = getTileColor(tile)
    pygame.draw.rect(background, tileColor, tileRect)
    if tile.hasKey:
        radius = Globals.TILE_WIDTH / 2
        pygame.draw.circle(background, Colors.KEY, tileRect.center, radius)
Beispiel #6
0
def renderPlayer(background: pygame.Surface, player: Player):
    x, y = getScreenLocation(player.location)
    tileRect = pygame.Rect(x, y, Globals.TILE_WIDTH, Globals.TILE_HEIGHT)
    # tileColor = Colors.PLAYER
    # TODO Fonts slow down the loading
    log = logInFile("Render.py", "renderPlayer")
    log(player.name)
    playerLetter = Globals.FONT.render(formatInitial(player.name), True,
                                       Colors.BLACK)  # TODO font color
    # pygame.draw.rect(background, tileColor, tileRect)
    background.blit(playerLetter, tileRect.topleft)
Beispiel #7
0
def registerPlayers(numClients: int, sock: socket.socket):
    """
    Registers numClients amount of clients to the game on the socket
    as players and returns a dict of name -> connection.
    :params numClients: int
    :params sock: socket.socket
    """
    CONNS = {}
    numPlayersConnected = 0
    # Dish out connections + register sockets
    while numPlayersConnected < numClients:
        try:
            log = logInFile("Server.py", "Join loop")
            log("begin loop")

            # Block waiting for new connection
            conn, client_addr = sock.accept()
            log("Got a connection")

            introMsg = welcomeMsg('"Alon"')
            introMsg += "\nEnter your name"
            conn.sendall(introMsg.encode('utf-8'))

            name = conn.recv(1024).decode('utf-8').strip()
            log("Name received", name)

            CONNS[name] = conn  # register the player's conn
            log("Connected players:", str(list(CONNS.keys())))

            numPlayersConnected += 1
            if numPlayersConnected < numClients:
                conn.sendall(
                    "Welcome {}! Please wait for {} other players to join\n".
                    format(name,
                           numClients - numPlayersConnected).encode('utf-8'))
        except UnicodeDecodeError:
            log("unicode decode error")
            if name in CONNS.keys():
                del CONNS[name]
            continue
        except ConnectionResetError:
            log("conn reset error")
            if name in CONNS.keys():
                del CONNS[name]
            continue
            # raise PlayerDisconnect
        except BrokenPipeError:
            log("broken pipe error")
            if name in CONNS.keys():
                del CONNS[name]
            continue
            # raise PlayerDisconnect
    return CONNS
Beispiel #8
0
def renderLevel(background: pygame.Surface, level: Level):
    """
    Render the board in the level at the given board number onto the background.
    :param background:
    :param level:
    :param boardNumber:
    :return:
    """
    log = logInFile("Render.py", "renderLevel")
    log()
    # TODO render entire level (including all boards)
    for board in level.boards:
        renderBoard(background, board)
Beispiel #9
0
import pygame
from pygame.locals import *
import argparse
import math
from Render import renderPlayerView, renderObserverView, renderStatusBar
from Util import logInFile, genXRandCoords, getPlayer, getAllTiles, \
    translateScreenLocation, whichBoardInLevel, locationInLevelBounds, \
    getRandomRoomInLevel, getEnemiesInLevel, getAllEnemies, getAllPlayers, getRandCoordInLevel
from Convert import convertJsonLevel
from Create import addPlayersToBoard, addEnemiesToBoard
from Types import *
from Player import getVisibleTiles
import GameManager
import Enemy as EnemyMove

log = logInFile("localSnarl.py")


def populateEnemies(levelNum: int, levelEnemies: dict, game: Dungeon):
    for enemyName in levelEnemies.keys():  # Populate enemies in level
        enemyBoardNum = levelEnemies[enemyName][0]
        board: Board = game.levels[levelNum].boards[enemyBoardNum]
        game.levels[levelNum].boards[enemyBoardNum] = addEnemiesToBoard(
            board, {
                enemyName: levelEnemies[enemyName][1]})


def main():
    DEFAULT_LEVEL = './tests/snarl.levels'
    numPlayers = 1
    startLevel = 1
Beispiel #10
0
import pygame
import sys
from pygame.locals import *
from Create import createDungeon, createLevel, createGenericBoardTiles
from Types import *
from Render import renderDungeon, renderLevel
from Util import logInFile
import Globals
from example2 import exampleLevel2, players, enemies

log = logInFile("main.py")


def main():
    # Initialize screen
    pygame.init()
    clock = pygame.time.Clock()
    screen = pygame.display.set_mode(Globals.SCREEN_DIMENSIONS)
    pygame.display.set_caption("Snarl Demo")

    # Fill background. Draw onto this
    background = pygame.Surface(screen.get_size())
    background = background.convert()  # converts Surface to single-pixel format
    background.fill(Globals.BG_COLOR)

    # render test level (400 x 300)
    dung = createDungeon(exampleLevel2, players, enemies)
    log("DUNGEON BELOW")
    log(str(dung.players), str(dung.levels[0].boards[0]))

    renderDungeon(background, dung)
Beispiel #11
0
from Types import *
from GameManager import move
from example2 import exampleDungeon2, exampleLevel2, player1
from Util import logInFile, locationInBounds

log = logInFile("test_GameManager.py")

"""
Cases:
- one normal, valid move of 1 space
- one normal, valid move of 2 spaces
- move into a wall
- move onto a key (interaction)
- move into an exit (interaction) (players moved)
- move into an exit (from last level)
- move into player
- move onto enemy (interaction)
- move into the void
"""

# TODO MAKE THINGS LOOK GOOD

def testOneNormalMove():
    orig = player1.location
    dest = (11, 2)
    res: Dungeon = move("Saleha", dest, exampleDungeon2)
    level: Level = res.levels[res.currLevel]
    board: Board = level.boards[level.currBoard]
    updatedPlayer: Player = board.players["Saleha"]
    assert updatedPlayer.location is not orig
    assert updatedPlayer.location == dest
Beispiel #12
0
from Types import *
from Create import createDungeon, addPlayersToBoard, removePlayersFromBoard
from Move import moveEntity
from Rulechecker import destHasEnemy, destHasKey, destHasExit, destHasPlayer, \
    destHasWall, playerCanMoveTo
from Util import whichBoardInLevel, logInFile, getPlayer, genXRandCoords, \
    getRandomRoomInLevel, getPlayersInLevel, getEnemy, getAllPlayers

log = logInFile("GameManager.py")


def move(entityName: str, destination: tuple, 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. Returns an
    unmodified game if the player cannot move based on game rules.
    :param entityName: str
    :param destination: tuple
    :param game: Dungeon
    """
    currLevel: Level = game.levels[game.currLevel]
    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,
Beispiel #13
0
def renderItems(background: pygame.Surface, items):
    log = logInFile("Render.py", "renderItems")
    log()
    for item in items:
        if not item.hasBeenAcquired:
            renderItem(background, item)
Beispiel #14
0
def start(args):
    log = logInFile("Server.py")

    # Global vars
    JSON_LEVELS = args['jsonLevels']
    NUM_LEVELS = args['numLevels']
    NUM_CLIENTS = args['numClients']
    WAIT = args['wait']
    OBSERVE = args['observe']
    ADDRESS = args['address']
    PORT = args['port']

    # Ready to begin

    CONNS = {}
    SOCK = None

    try:
        SOCK = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        SOCK.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        SOCK.settimeout(WAIT)
        SOCK.bind((ADDRESS, PORT))
        SOCK.listen(NUM_CLIENTS)

        CONNS = registerPlayers(NUM_CLIENTS, SOCK)

        # Setup game (Convert levels, populate players, populate enemies,
        # create dungeon)
        GAME, playerNames = setupGame(list(CONNS.keys()), JSON_LEVELS)

        # Broadcast initial game state
        broadcast(startLevelMsg(1, playerNames), CONNS)

        # Send initial player update msgs
        broadcastPlayerUpdates(CONNS, GAME)

        log("GAME INITIALIZED!")

        # Enter main loop
        while True:

            # Obtain the current level
            currLevel: Level = GAME.levels[GAME.currLevel]

            # Check if the level has been completed
            if isLevelOver(currLevel):
                GAME = advanceLevel(GAME)
                broadcastLevelOver(GAME, CONNS)

            # Check if game is over
            if GAME.isGameOver:
                broadcastGameOver(GAME, CONNS)
                broadcast("disconnect", CONNS)

            # Execute player turns
            for playerName in playerNames:
                try:
                    player = getPlayer(currLevel, playerName)
                    if player:
                        initLoc = player.location
                        playerTurn = GAME.levels[GAME.currLevel].playerTurn
                        MAX_TRIES = 5
                        for tries in range(MAX_TRIES):
                            time.sleep(1)
                            playerMove = executeTurn(CONNS[playerName])
                            GAME = move(playerName, playerMove, GAME)
                            playerAfter = getPlayer(currLevel, playerName)
                            moveMade = not playerAfter or playerTurn != \
                                       GAME.levels[
                                           GAME.currLevel].playerTurn
                            if moveMade:
                                break
                            # last turn and still no valid move made
                            if not moveMade:
                                if tries == (MAX_TRIES - 1):
                                    GAME = move(playerName, None, GAME)
                                else:
                                    sendPlayer(playerName,
                                               "Invalid move. Try again...",
                                               CONNS)

                        broadcastPlayerUpdates(CONNS, GAME)
                except PlayerDisconnect:
                    # TODO broadcast??
                    log("PLAYER DISCONNECTED")
                    player: Player = getPlayer(currLevel, playerName)
                    playerBoardNum = whichBoardInLevel(currLevel,
                                                       player.location)
                    GAME = removePlayer(playerName, playerBoardNum, GAME)
                    # TODO reset playerNames
                    continue

            # Execute enemy turns
            currLevel: Level = GAME.levels[GAME.currLevel]
            for enemy in getEnemiesInLevel(currLevel):
                nextMove = enemyNextMove(enemy, GAME)
                GAME = move(enemy.name, nextMove, GAME, isPlayer=False)
                broadcastPlayerUpdates(CONNS, GAME)
                # for playerName in playerNames:
                # msg = enemy.name + " moved"
                # broadcast(playerUpdateMsg(playerName, GAME, msg), CONNS)

    except json.JSONDecodeError:
        print("Malformed level file. Check your formatting")
        closeConns(CONNS)
        if SOCK:
            SOCK.close()
        sys.exit(1)
    except KeyboardInterrupt:
        print("\nExiting...")
        closeConns(CONNS)
        if SOCK:
            SOCK.close()
        sys.exit(0)
Beispiel #15
0
from Messages import *
from Convert import convertJsonLevel, addPlayersToBoard, addEnemiesToBoard
from more_itertools import first_true
"""
The Snarl Server:

- dish out connections
- create new game 
- handle joins 
- start game 
- administer game
    - broadcast game 
- end game
"""

log = logInFile("Server.py")


class PlayerDisconnect(Exception):
    pass


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)
Beispiel #16
0
from Types import *
from Util import whichBoardInLevel, getLocationsAround, locationInBounds, \
    locationInLevelBounds, isTileOnBoard, logInFile, getAllPlayers
from more_itertools import unique_everseen

log = logInFile("Rulechecker.py")


def playerCanMoveTo(destination: tuple, player: Player, level: Level,
                    numMoves: int):
    """
    Check if the destination given can be moved to by a given player.
    (True if destination does not have a player and is traversable)
    :param destination: tuple
    :param player: Player
    :param level: Level
    :param numMoves: int
    """
    # NOTE this gets all locations in the board
    destBoardNumber = whichBoardInLevel(level, destination)
    playerBoardNumber = whichBoardInLevel(level, player.location)
    possibleMoves = playerPossibleCardinalMoves(player.location, numMoves,
                                                level)
    if destination not in possibleMoves:
        return False

    board = level.boards[destBoardNumber]

    if isTileOnBoard(destination, board):
        if board.tiles[destination[0]][
            destination[1]].tileType is not TileEnum.WALL \
Beispiel #17
0
def renderDungeon(background: pygame.Surface, dungeon: Dungeon):
    log = logInFile("Render.py", "renderDungeon")
    log()
    renderLevel(background, dungeon.levels[dungeon.currLevel])
Beispiel #18
0
import sys
import json
from Util import intifyTuple, whichBoardInLevel, locationInLevelBounds, \
    isDoorLocation, isTraversable, isPlayerInGame, getPlayer, logInFile
from Convert import convertJsonDungeon
from Types import *
import GameManager
from Rulechecker import playerCanMoveTo, destHasKey, destHasExit, destHasEnemy, \
    isCurrentLevelOver
from more_itertools import first_true
from Player import getFieldOfView

log = logInFile("testManager.py")
"""
PLANNING SESSION:
Flow:
0. [X] parse json
1. [X] Take in data, convert it to dungeon
2. [X] Init a manager-trace (MT)
3. [X] Output an initial player vision to each player (Loop), add those updates to MT
4. [X] Loop on turns Executing Moves (The given number of turns was performed)
    EXIT immediately if:
        - One of the move input streams is exhausted
        - The level is over

    a. we do the MOVE
        if need to execute another move (invalid)
            bb. `continue` if invalid
        else
            b. append the status (could be generated by acc on dungeon)
    c. append the updates
Beispiel #19
0
from Types import *
from Util import intifyTuple, whichBoardInLevel, logInFile
from Create import addPlayersToBoard, addEnemiesToBoard

log = logInFile("Convert.py")
"""
What a json room looks like: 
{ "type"   : "room",
  "origin" : (point),
  "bounds" : (boundary-data),
  "layout" : (tile-layout)
}
"""


def convertJsonPlayer(jsonPlayer: dict):
    newPlayer = Player(jsonPlayer["name"], intifyTuple(jsonPlayer["position"]))
    return newPlayer


def convertJsonEnemy(jsonEnemy: dict):
    newEnemy = Enemy(jsonEnemy["name"], intifyTuple(jsonEnemy["position"]))
    return newEnemy


def convertJsonRoom(origin: list, boundaryData: list, tileLayout: list):
    boardEnum = BoardEnum.ROOM
    dimensions = intifyTuple(tuple(boundaryData))
    upperLeftCorner = intifyTuple(tuple(origin))
    tiles = dict()
    doorLocations = []