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. Layout 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.name, game.levels[game.currLevel]) output = { "type": "player-update", "layout": getTileLayout(game, player), "position": [player.location[0], player.location[1]], "objects": getObjectsAroundPlayer(possMoves, game), "actors": getActorsAroundPlayer(possMoves, game) } return output
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)
def broadcastPlayerUpdates(conns: dict, game: Dungeon): for playerName in conns.keys(): if getPlayer(game.levels[game.currLevel], playerName): msg = "--> Player Update: {}\n".format(playerName) msg += formatted(getPlayerUpdate(playerName, game)) sendPlayer(playerName, msg, conns)