def inform_sunken_ship(pl_id, ship_id): '''Informs other players when a ship has been sunken :param pl_id: id of the player whose ship got sunken :param ship_id: id of the ships that has been sunken ''' for index in game.players[int(pl_id) - 1].ships_dict[str(ship_id)]: cv.acquire() queue.put( common.marshal(common.CTRL_SHIP_SUNKEN, index[0], index[1], pl_id)) cv.notify_all() cv.release()
def inform_other_clients(x, y, sufferer_id, bomber_id): ''' Sends info of the hit to other players with the name of bomber :param x: x-coordinate of the hit :param y: y-coordinate of the hit :param sufferer_id: id of the player who got hit :param bomber_id: id of the player who made the hit ''' bomber_name = game.players[int(bomber_id) - 1].get_name() cv.acquire() queue.put( common.marshal(common.CTRL_NOTIFY_HIT, sufferer_id, x, y, bomber_name)) cv.notify_all() cv.release()
def start_game(player_id): ''' Creates the battleship game board and notifies all players to request newly created board. :param player_id: id of the player trying to start the game :return: OK if player is admin NOT_ADMIN if player is not admin ''' for player in game.players: if int(player.get_id()) == int(player_id) and player.is_admin(): global board board = game.create_and_populate_board( ) # Creates and populates the board after admin starts the game cv.acquire() queue.put( common.marshal(common.CTRL_START_GAME, common.CTRL_ALL_PLAYERS)) cv.notify_all() cv.release() global game_not_started game_not_started = False # Stops server from sending broadcasts return common.CTRL_OK return common.CTRL_NOT_ADMIN
def on_request(ch, method, props, body): ''' Responds to rpc calls, (receives requests from players and responds to them) :param ch: :param method: :param props: :param body: body of the rpc call that a player has made ''' request = common.unmarshal(body) CTRL_CODE = int(request[0]) if CTRL_CODE == common.CTRL_REQ_ID: response = request_new_id(request[1], request[2]) elif CTRL_CODE == common.CTRL_CHECK_ADMIN: if game.players[int(request[1]) - 1].is_admin(): response = 1 else: response = 0 elif CTRL_CODE == common.CTRL_START_GAME: response = start_game(request[1]) elif CTRL_CODE == common.CTRL_REQ_BOARD: board_array = board.get_board( ) # Array needed to send board to a client board_shape = board_array.shape #time.sleep(0.2) board_str = board_array.tostring() response = common.marshal(board_str, board_shape[0], board_shape[1]) elif CTRL_CODE == common.CTRL_HIT_SHIP: global entered_correct_coords, stop_loop, player_has_hit entered_correct_coords = False if int(request[2]) == common.CTRL_ERR_HIT or int( request[3]) == common.CTRL_ERR_HIT: response = common.CTRL_ERR_HIT stop_loop = True else: try: value = board.get_value(int(request[2]), int(request[3])) if int(value) < 100 and int( value ) > 0: # If that coordinate has not been hit before pl_id = str(value)[0] ship_id = str(value)[1] if int(pl_id) != int( request[1]): # If player did not hit his own ship game.players[ int(pl_id) - 1].ships_dmg[ship_id] += 1 # Records the hit # If ship sunk if int(game.players[int(pl_id) - 1].ships_dmg[ship_id]) == int( game.ships_l[ship_id]): inform_sunken_ship(pl_id, ship_id) response, suffer_id = board.hit_ship(int(request[2]), int(request[3]), int(request[1])) entered_correct_coords = True check_win() if int(response) == 1: # In case someone got hit, let him know inform_other_clients(request[2], request[3], suffer_id, request[1]) except Exception as err: logging.info(err) response = common.CTRL_ERR_HIT player_has_hit = True ch.basic_publish( exchange='', routing_key=props.reply_to, properties=pika.BasicProperties(correlation_id=props.correlation_id), body=str(response)) ch.basic_ack(delivery_tag=method.delivery_tag)
if game.get_nof_players( ) == 0: # Not worth sending it, when no clients are connected logging.debug("Waiting a player to join") game.cv_create_player.wait(timeout=5) game.cv_create_player.release() if game.get_nof_players() == 0: continue else: time.sleep(5) cv.acquire() queue.put( common.marshal( common.CTRL_BRDCAST_MSG, "Game not started yet, {nof_clients} client(s) connected, {admin} has rights to start the game." .format(nof_clients=game.get_nof_players(), admin=game.get_admin()))) cv.notify_all() cv.release() except KeyboardInterrupt: bcast_con.close() announc_con.close() rpc_con.close() watchdog_con.close() is_running = False game_not_finished = False logging.debug("Bye bye") logging.debug("Exiting initial loop") try: