Ejemplo n.º 1
0
def handle_rejection_assent(info):
    """Handle when a player assents to a rejection."""
    rejecter = info['rejecter']
    assented = info['assented']

    MapsLock()
    [name, room] = get_name_and_room(flask.request.sid)

    if name not in rooms_info[room]['endgame']['review_status'][rejecter] or \
            rooms_info[room]['endgame']['review_status'][rejecter][name] != REVIEWSTATUS_ASSENTING:
        emit(
            "server_message",
            "You have already accepted whether or not your solution is incorrect. "
            + "The button you just clicked had no effect.")
        return

    if assented:
        emit("server_message",
             f"{name} has accepted that his/her solution is incorrect.",
             room=room)
        rooms_info[room]['endgame']['review_status'][rejecter][
            name] = REVIEWSTATUS_REJECTED
        track_decided_solution(room, name, False)
        return

    assert name in rooms_info[room]['endgame']['solutions']
    reevaluate_msg = {
        "writer": name,
        "solution": rooms_info[room]['endgame']['solutions'][name],
        "rejecter": rejecter,
    }

    del rooms_info[room]['endgame']['review_status'][rejecter][name]
    emit("reevaluate_solution", reevaluate_msg, room=room)
Ejemplo n.º 2
0
def handle_cube_click(pos):
    """Highlight cube if it's clicker's turn and clicker hasn't clicked yet."""
    MapsLock()
    [user, room] = get_name_and_room(flask.request.sid)

    turn_user = get_current_mover(room)
    if rooms_info[room]["game_finished"] or rooms_info[room]["challenge"] \
            or rooms_info[room]["resources"][pos] == MOVED_CUBE_IDX \
            or turn_user != user:
        return

    do_not_rehighlight = False
    if rooms_info[room]['touched_cube'] is not None:
        if rooms_info[room]['touched_cube'] == pos:
            do_not_rehighlight = True
        emit("unhighlight_cube", rooms_info[room]['touched_cube'], room=room)
        rooms_info[room]['touched_cube'] = None

    if not do_not_rehighlight:
        if not rooms_info[room]["goalset"] and len(rooms_info[room]["goal"]) >= 6:
            emit("server_message", 
                    "Max number of cubes on goal set! Please press \"Goal Set!\"", 
                    room=room)
            return
        else:
            rooms_info[room]['touched_cube'] = pos
            emit("highlight_cube", pos, room=room)
Ejemplo n.º 3
0
def handle_no_goal_siding(agreed):
    """Player agreed or disagreed with the no_goal declaration."""
    MapsLock()
    [name, room] = get_name_and_room(flask.request.sid)

    if name not in rooms_info[room]["endgame"]["siders"]:
        emit(
            "server_message",
            "You have already sided on the No Goal. The button you just clicked had no effect."
        )
        return

    if not agreed:
        if rooms_info[room]["endgame"]["challenger"] is None:
            rooms_info[room]["endgame"]["challenger"] = name
        rooms_info[room]["endgame"]["writers"].append(name)
        rooms_info[room]["endgame"]["solution_decisions"][name] = []
    else:
        rooms_info[room]["endgame"]["nonwriters"].append(name)

    rooms_info[room]["endgame"]["siders"].remove(name)
    if len(rooms_info[room]["endgame"]["siders"]) == 0:
        rooms_info[room]["endgame"]["endgame_stage"] = "waiting_for_solutions"
        if rooms_info[room]["endgame"]["challenger"] is None:
            emit("end_shake_no_goal", room=room)
            rooms_info[room]["shake_ongoing"] = False
            rooms_info[room]["endgame"]["endgame_stage"] = "no_goal_finished"
            return

    msg_diff = "" if not agreed else "not "
    emit("server_message",
         f"{name} has decided " + msg_diff + "to challenge the No Goal.",
         room=room)
    check_if_ready_to_present(room, True)
Ejemplo n.º 4
0
def handle_siding(writing):
    """Player sided."""
    MapsLock()
    [name, room] = get_name_and_room(flask.request.sid)

    # Case where perhaps user had two windows open and sided on both.
    # Second click to the siding buttons would trigger this if statement.
    if rooms_info[room]["endgame"]["sider"] == None:
        emit(
            "server_message",
            "You have already sided. The button you just clicked had no effect."
        )
        return

    if writing:
        rooms_info[room]["endgame"]["writers"].append(name)
        rooms_info[room]["endgame"]["solution_decisions"][name] = []
    else:
        rooms_info[room]["endgame"]["nonwriters"].append(name)

    rooms_info[room]["endgame"]["sider"] = None
    rooms_info[room]["endgame"]["endgame_stage"] = "waiting_for_solutions"

    msg_diff = "" if writing else "not "
    emit("server_message",
         f"{name} has decided " + msg_diff + "to write a solution!",
         room=room)
    check_if_ready_to_present(room, False)
Ejemplo n.º 5
0
def handle_solution_decision(info):
    """Handle when a player accepts or rejects a solution."""
    writer = info['name']
    accepted = info['accepted']

    MapsLock()
    [name, room] = get_name_and_room(flask.request.sid)

    # This is true player cannot decide on a solution but somehow clicks a button to decide.
    # (maybe from a second open window). Clientside should ensure this never happens though...
    # and make buttons that shouldn't be clicked not clickable
    if writer in rooms_info[room]['endgame']['review_status'][name]:
        emit(
            "server_message",
            "You have already decided on the correctness of this solution. " +
            "The button you just clicked had no effect.")
        return

    accepted_str = "accepted" if accepted else "rejected"
    emit("server_message",
         f"{name} " + accepted_str + f" {writer}'s solution!",
         room=room)

    if not accepted:
        rooms_info[room]['endgame']['review_status'][name][
            writer] = REVIEWSTATUS_ASSENTING
        emit("rejection_assent", {
            "rejecter": name,
            "writer": writer
        },
             room=room)
    else:
        rooms_info[room]['endgame']['review_status'][name][
            writer] = REVIEWSTATUS_ACCEPTED
        track_decided_solution(room, writer, True)
Ejemplo n.º 6
0
def handle_cube_click(pos):
    """Highlight cube if it's clicker's turn and clicker hasn't clicked yet."""
    MapsLock()
    [user, room] = get_name_and_room(flask.request.sid)

    if rooms_info[room]["game_finished"]:
        return

    if rooms_info[room]["challenge"]:
        return

    # Reject if a cube has already been clicked. You touch it you move it!
    if rooms_info[room]['touched_cube'] is not None:
        return

    if rooms_info[room]["resources"][pos] == MOVED_CUBE_IDX:
        return

    rooms_info[room]["started_move"] = True

    turn_idx = rooms_info[room]['turn']
    turn_user = rooms_info[room]['players'][turn_idx]

    if turn_user == user:
        if not rooms_info[room]["goalset"] and len(
                rooms_info[room]["goal"]) >= 6:
            emit("server_message",
                 "Max number of cubes on goal set! Please press \"Goal Set!\"",
                 room=room)
            return
        else:
            rooms_info[room]['touched_cube'] = pos
            emit("highlight_cube", pos, room=room)
Ejemplo n.º 7
0
def handle_game_time_up():
    """Thirty five minute mark has been reached."""
    MapsLock()
    [name, room] = get_name_and_room(flask.request.sid)
    if not rooms_info[room]["time_up"]:
        rooms_info[room]["time_up"] = True
        if rooms_info[room][
                "shake_ongoing"] and rooms_info[room]["endgame"] is None:
            handle_force_out(room)
Ejemplo n.º 8
0
def handle_five_minute_warning():
    """Thirty minute mark has been reached."""
    MapsLock()
    [name, room] = get_name_and_room(flask.request.sid)
    if not rooms_info[room]["five_minute_warning_called"]:
        rooms_info[room]["five_minute_warning_called"] = True
        emit("five_minute_warning_message", room=room)
    if not rooms_info[room]["shake_ongoing"]:
        clean_up_finished_room(room)
Ejemplo n.º 9
0
def handle_bonus_click():
    """Bonus button was clicked."""
    MapsLock()
    [name, room] = get_name_and_room(flask.request.sid)
    if get_current_mover(room) != name:
        print("non mover somehow clicked the bonus button. hacker")
        return
    assert not rooms_info[room]["bonus_clicked"]
    rooms_info[room]["bonus_clicked"] = True
    rooms_info[room]["started_move"] = True
Ejemplo n.º 10
0
def handle_set_goal():
    """Handle goal set."""
    MapsLock()
    [name, room] = get_name_and_room(flask.request.sid)
    assert name == get_current_mover(room)

    if rooms_info[room]["game_finished"]:
        return

    rooms_info[room]["goalset"] = True
    next_turn(room)
Ejemplo n.º 11
0
def receive_message(message_info):
    """Receive a chat message from client."""
    name = message_info['name']
    message = message_info['message']
    print(f"{name} send the message: {message}")

    MapsLock()
    [stored_name, room] = get_name_and_room(flask.request.sid)
    assert name == stored_name

    # Send the message to everyone in the room
    emit('message', message_info, room=room)
Ejemplo n.º 12
0
def handle_solution_submit(solution):
    """A player submitted a solution."""
    MapsLock()
    [name, room] = get_name_and_room(flask.request.sid)
    if name not in rooms_info[room]["endgame"]["solutions"]:
        rooms_info[room]["endgame"]["solutions"][name] = solution
        check_if_ready_to_present(
            room, rooms_info[room]["endgame"]["challenge"] == "no_goal")
    else:
        emit(
            "server_message", "You have already submitted a solution. " +
            "The solution you just submitted was not counted. ")
Ejemplo n.º 13
0
def handle_bonus_click():
    """Bonus button was clicked."""
    MapsLock()
    [name, room] = get_name_and_room(flask.request.sid)
    if get_current_mover(room) != name:
        print("non mover somehow clicked the bonus button. hacker")
        return

    if rooms_info[room]["started_move"]:
        print("started move but somehow clicked bonus button")
        return

    rooms_info[room]["bonus_clicked"] = not rooms_info[room]["bonus_clicked"]
    print("bonus clicked set to ", rooms_info[room]["bonus_clicked"])
Ejemplo n.º 14
0
def update_cube_orientation(info):
    """Update a goalline cube's orientation."""
    MapsLock()
    [name, room] = get_name_and_room(flask.request.sid)

    i = info['order']
    new_orientation = info['orientation']

    rooms_info[room]["goal"][i]["orientation"] = new_orientation

    update_msg = {
        "type": "orientation",
        "order": i,
        "new_val": new_orientation,
    }
    emit("update_goalline", update_msg, room=room, include_self=False)
Ejemplo n.º 15
0
def update_cube_xpos(info):
    """Update a goalline cube's x position."""
    MapsLock()
    [name, room] = get_name_and_room(flask.request.sid)

    i = info['order']
    new_x_pos = info['x_pos_per_mille']

    rooms_info[room]["goal"][i]["x"] = new_x_pos

    update_msg = {
        "type": "x_pos",
        "order": i,
        "new_val": new_x_pos,
    }
    emit("update_goalline", update_msg, room=room, include_self=False)
Ejemplo n.º 16
0
def handle_set_goal():
    """Handle goal set."""
    MapsLock()
    [name, room] = get_name_and_room(flask.request.sid)
    assert name == get_current_mover(room)

    if len(rooms_info[room]['goal']) == 0:
        emit("server_message", "You must set at least one cube on the goal!")
        return

    if rooms_info[room]["game_finished"]:
        return

    emit("hide_goal_setting_buttons", room=room)
    rooms_info[room]["goalset"] = True
    next_turn(room)
Ejemplo n.º 17
0
def handle_sector_click(sectorid):
    """Receive a click action on a playable area of the board."""
    MapsLock()
    [name, room] = get_name_and_room(flask.request.sid)
    print(f"{name} clicked {sectorid} in room {room}")

    if rooms_info[room]["game_finished"] or rooms_info[room]["touched_cube"] is None:
        return

    if name != get_current_mover(room):
        print(f"Not {name}'s turn. Do nothing.")
        return

    if rooms_info[room]["bonus_clicked"]:
        if sectorid != "forbidden-sector":
            emit("server_message", 
                 "To bonus you must first place a cube in forbidden!", 
                 room=room)
            return
        else:
            move_cube(room, sectorid)
            rooms_info[room]["bonus_clicked"] = False
            return

    if not rooms_info[room]["goalset"]:
        if sectorid != "goal-sector":
            print(f"Goalsetter clicked on a non-goal area.")
            return
    elif sectorid == "goal-sector":
        print(f"Someone clicked on goal area but goal is already set")
        return

    move_cube(room, sectorid)
    
    if rooms_info[room]["goalset"]:
        next_turn(room)
Ejemplo n.º 18
0
def on_disconnect():
    """Handle disconnect."""
    print(f"Client {flask.request.sid} disconnected!")
    socketid = flask.request.sid

    MapsLock()
    if socketid not in socket_info:
        # Note: MapsLock makes register_player atomic, so we can safely say
        # in this case socket disconnected before register_player *started*.
        print("Socket disconnected before register_player started")
        return

    [username, room] = get_name_and_room(socketid)

    # Leave the room
    leave_room(room)

    # Update socket_info
    del socket_info[socketid]

    # Update room info
    if username in rooms_info[room]['spectators']:
        # Remove spectators on disconnect. But do not remove player until game finishes.
        rooms_info[room]['spectators'].remove(username)

    rooms_info[room]["sockets"].remove(socketid)
    if len(rooms_info[room]["sockets"]) == 0:
        # If all players and spectators leave, then game is considered finished even if it's not.
        # TODO Right now this is only way a game ends. When implement timing, may need to reconsider this.
        if not rooms_info[room]["game_finished"]:
            rooms_info[room]["game_finished"] = True
            db_insert(room, rooms_info[room])

            for player in rooms_info[room]["players"]:
                assert player in user_info
                assert room in user_info[player]["gamerooms"]
                user_info[player]["gamerooms"].remove(room)

        del rooms_info[room]

    # Update user_info
    # On a refresh on a game page, due to delay in socket disconnect, new socket
    # (most likely) has connected by the time this code runs and (potentially) deletes
    # the user from the user_info dict. Even if not, worst thing that can happen
    # is that the game is marked as finished.
    assert room in user_info[username]["latest_socketids"].keys()
    user_info[username]["latest_socketids"][room].remove(socketid)
    if len(user_info[username]["latest_socketids"][room]) == 0:

        print(f"{username} is no longer connected to {room}")
        del user_info[username]["latest_socketids"][room]

        assert room in user_info[username]["room_modes"].keys()
        del user_info[username]["room_modes"][room]

        # If a player leaves before a game is started, then remove him/her as a player
        if room in rooms_info and not rooms_info[room]["game_started"] \
                and username in rooms_info[room]["players"]:
            if room in user_info[username]["gamerooms"]:
                # Need if statement because could gotten removed above in update rooms_info
                user_info[username]["gamerooms"].remove(room)
            if room in rooms_info:
                rooms_info[room]["players"].remove(username)
            emit("player_left", rooms_info[room]["players"], room=room)
        
        if room in user_info[username]["gamerooms"] and room not in rooms_info:
            user_info[username]["gamerooms"].remove(room)

        # Unmap user if he/she is not in any rooms and he/she is not playing a game
        if len(user_info[username]["latest_socketids"]) == 0 and \
                len(user_info[username]["gamerooms"]) == 0:
            del user_info[username]

        emit("server_message", f"{username} has left.", room=room)
        print(f"Client {socketid}: {username} left room {room}")

    else:
        print(f"Socket {socketid} for user {username} disconnected, but user "
               "still has another connection to the room open")
Ejemplo n.º 19
0
def handle_flip_timer():
    """Player pressed flip_timer."""
    MapsLock()
    [name, room] = get_name_and_room(flask.request.sid)
    print(f"{name} pressed flip_timer!")
Ejemplo n.º 20
0
def handle_claim_warning():
    """Player pressed claim_warning."""
    MapsLock()
    [name, room] = get_name_and_room(flask.request.sid)
    print(f"{name} pressed claim_warning!")
Ejemplo n.º 21
0
def handle_claim_minus_one():
    """Player pressed claim_minus_one."""
    MapsLock()
    [name, room] = get_name_and_room(flask.request.sid)
    print(f"{name} pressed claim_minus_one!")
Ejemplo n.º 22
0
def handle_game_over():
    """The game is finished now."""
    MapsLock()
    [_, room] = get_name_and_room(flask.request.sid)
    clean_up_finished_room(room)
Ejemplo n.º 23
0
def handle_challenge(socketid, challenge):
    """Handle a challenge."""
    MapsLock()
    [name, room] = get_name_and_room(socketid)
    print(f"{name} pressed {challenge}")

    assert room in rooms_info
    if rooms_info[room][
            "challenge"] is not None and challenge != "p_flub":  # TODO can't p flub after 1st minute. TEST!!
        print(f"{name} tried to challenge {challenge} but was too late")
        return

    defender = get_previous_mover(room)
    challenge_message = f"{name} has called {challenge_translation[challenge]}"
    if challenge == "no_goal":
        challenge_message += "!"
    else:
        if not rooms_info[room]['goalset']:
            emit("server_message",
                 "You cannot challenge; the goal has not been set!")
            return

        challenge_message += f" on {defender}!"

    sider = None
    if rooms_info[room]["started_move"]:  # TODO minus 1?
        challenge_message += f" But {name} has started their move so {name} " \
                             f"must finish the move and cannot challenge!"
        emit("server_message", challenge_message, room=room)
        return
    elif defender == name:  # TODO minus 1?
        challenge_message += f" But {name} just moved so {name} cannot challenge!"
        emit("server_message", challenge_message, room=room)
        return
    elif challenge != "no_goal" and len(rooms_info[room]['players']) == 3:
        sider_list = list(
            filter(lambda x: x != name and x != defender,
                   rooms_info[room]['players']))
        assert len(sider_list) == 1
        sider = sider_list[0]
        challenge_message += f" {sider} has two minutes to side!"

    if challenge == "no_goal":
        if rooms_info[room]["goalset"]:
            no_goal_msg = f"{name} has called Challenge No Goal! But Goal has already been set, so challenge cannot be made!"  # TODO minus one?
            emit("server_message", no_goal_msg, room=room)
            return
        else:
            assert defender is None
            if name != get_current_mover(room):
                no_goal_err_msg = f"{name} called Challenge No Goal but that is " \
                                  f"not allowed because {name} is not setting the goal!"
                emit("server_message", no_goal_err_msg, room=room)
                return
    else:
        if not rooms_info[room]["goalset"]:
            assert defender is None
            emit("server_message",
                 "Goal has not been set yet! You cannot challenge.",
                 room=room)  # TODO handle this
            return
        assert defender is not None

    if challenge == "a_flub":
        cubes_left = len([x for x in rooms_info[room]["resources"]
                          if x != -1])  # TODO magic bad
        if cubes_left < 2:
            emit("server_message",
                 f"{name} called Challenge Now but that is not allowed!",
                 room=room)  # TODO minus 1
            return

    if challenge == "p_flub":
        pass  # TODO Gotta make sure not called after first minute in a force out

    rooms_info[room]["challenge"] = challenge
    initialize_endgame(room, challenge, name, defender, sider)
    emit("server_message", challenge_message, room=room)

    challenge_info = {
        "challenge": challenge,
        "defender": defender,
        "caller": name,
        "sider": sider,
        "writers": rooms_info[room]["endgame"]["writers"],
        "nonwriters": rooms_info[room]["endgame"]["nonwriters"],
    }
    emit("handle_challenge", challenge_info, room=room)
Ejemplo n.º 24
0
def start_shake(new_game, is_restart):
    """Handle logic for starting a shake. new_game specifies if shake
    is the first shake in a game."""
    MapsLock()
    [name, room] = get_name_and_room(flask.request.sid)
    print(f"{name} pressed start_game for room {room}!")

    if rooms_info[room]["game_finished"]:
        return

    if not new_game and rooms_info[room]["five_minute_warning_called"]:
        emit("server_message", "Five minute warning has been called so a new shake cannot be started.", room=room)
        return

    if room not in rooms_info or (new_game and rooms_info[room]['game_started']) \
            or (not new_game and rooms_info[room]['shake_ongoing']):
        print("Game start rejected")
        return

    current_players = rooms_info[room]['players']

    if len(current_players) < 2:
        emit('server_message', 
             f"{name} clicked \"Start Game\" but a game can only be started with 2 or 3 players.", 
             room=room)
        return
    
    assert name in current_players
    assert len(current_players) <= 3

    random.seed(time.time())
    rolled_cubes = [random.randint(0, 5) for _ in range(24)]

    if is_restart:
        # Goalsetter needs to be the same as the previous shake.
        rooms_info[room]['goalsetter_index'] = \
            (rooms_info[room]['goalsetter_index'] - 1) % len(rooms_info[room]['players'])
    
    if new_game:
        rooms_info[room] = {
            "game_started": True,
            "game_finished": False,
            "players": current_players,
            "spectators": rooms_info[room]["spectators"],
            "sockets": rooms_info[room]["sockets"],
            "p1scores": [0],
            "p2scores": [0],
            "p3scores": [0],
            "starttime": time.time(),
            # cube_index is poorly named. fixed length of 24, index is cube's id.
            # first six are red, next six are blue, next six are green, last six are black.
            # so if the first element of cube_index was x (where 0 <= x <= 5), the
            # corresponding cube is given by the file "rx.png" (where x is replaced w/#)
            "cube_index": rolled_cubes[:], 
            "resources": rolled_cubes,  # fixed length of 24
            "goal": [],  # stores cube id, x pos on canvas, orientation of cube
            "required": [], # stores cube ids (based on cube_index); same for 2 below
            "permitted": [],
            "forbidden": [],
            "turn": random.randint(0, len(current_players) - 1),
            "goalset": False,
            "num_timer_flips": 0,
            "10s_warning_called": False,
            "challenge": None,
            "touched_cube": None,
            "bonus_clicked": False,
            "started_move": False,
            "endgame": None,
            "shake_ongoing": True,
            "five_minute_warning_called": False,
            "time_up": False,
        }

        rooms_info[room]['goalsetter_index'] = rooms_info[room]['turn']

        game_begin_instructions = {
            'cubes': rolled_cubes,
            'players': current_players,
            'starter': name,
            'goalsetter': get_current_mover(room),
            'starttime': rooms_info[room]['starttime'],
        }

        emit("begin_game", game_begin_instructions, room=room)
    else:
        rooms_info[room]["cube_index"] = rolled_cubes[:]
        rooms_info[room]["resources"] = rolled_cubes
        rooms_info[room]["goal"] = []
        rooms_info[room]["required"] = []
        rooms_info[room]["permitted"] = []
        rooms_info[room]["forbidden"] = []
        rooms_info[room]['goalsetter_index'] = \
            (rooms_info[room]['goalsetter_index'] + 1) % len(rooms_info[room]['players'])
        rooms_info[room]["turn"] = rooms_info[room]['goalsetter_index']
        rooms_info[room]["goalset"] = False
        rooms_info[room]["num_timer_flips"] = 0
        rooms_info[room]["10s_warning_called"] = False
        rooms_info[room]["challenge"] = None
        rooms_info[room]["touched_cube"] = None
        rooms_info[room]["bonus_clicked"] = False
        rooms_info[room]["started_move"] = False
        rooms_info[room]["endgame"] = None
        rooms_info[room]["shake_ongoing"] = True

        goalsetter = get_current_mover(room)
        shake_begin_instructions = {
            'cubes': rolled_cubes,
            'players': current_players,
            'goalsetter': goalsetter,
            'show_bonus': not is_leading(room, goalsetter),
        }
    

        emit("begin_shake", shake_begin_instructions, room=room)
Ejemplo n.º 25
0
def on_disconnect():
    """Handle disconnect."""
    print(f"Client {flask.request.sid} disconnected!")
    socketid = flask.request.sid

    MapsLock()
    if socketid not in socket_info:
        # Note: MapsLock makes register_player atomic, so we can safely say
        # in this case socket disconnected before it *started*.
        print("Socket disconnected before register_player started")
        return

    [username, room] = get_name_and_room(socketid)

    # Leave the room
    leave_room(room)

    # Update socket_info
    del socket_info[socketid]

    # Update room info
    filter(lambda x: x != username, rooms_info[room]["spectators"])
    rooms_info[room]["sockets"].remove(socketid)
    if len(rooms_info[room]["sockets"]) == 0:
        # If all players leave, then game is considered finished even if it's not.
        if rooms_info[room][
                "game_started"] and not rooms_info[room]["game_finished"]:
            rooms_info[room]["game_finished"] = True

            db_insert(room, rooms_info[room])

            for player in rooms_info[room]["players"]:
                assert player in user_info
                user_info[player]["gameroom"] = None

        del rooms_info[room]

    # Update user_info
    if room in user_info[username]["latest_socketids"] and \
            user_info[username]["latest_socketids"][room] == socketid:

        print(f"{username} is no longer connected to {room}")
        del user_info[username]["latest_socketids"][room]

        # If a player leaves before a game is started, then remove him/her as a player
        current_game = user_info[username]["gameroom"]
        if current_game is not None:
            if current_game not in rooms_info:
                user_info[username]["gameroom"] = None
            elif not rooms_info[current_game]["game_started"]:
                user_info[username]["gameroom"] = None
                rooms_info[current_game]["players"].remove(username)

        # Unmap user if he/she is not in any rooms and he/she is not playing a game
        if len(user_info[username]["latest_socketids"]) == 0 and \
                user_info[username]["gameroom"] is None:
            del user_info[username]

        emit("server_message", f"{username} has left.", room=room)
        print(f"Client {socketid}: {username} left room {room}")

    else:
        # User made a new connection to the room, so current socket is outdated
        print(f"Outdated socket {socketid} for user {username} disconnected")
Ejemplo n.º 26
0
def handle_start_game():
    """Player pressed start_game."""
    MapsLock()
    [name, room] = get_name_and_room(flask.request.sid)
    print(f"{name} pressed start_game for room {room}!")

    if rooms_info[room]["game_finished"]:
        return

    if room not in rooms_info or rooms_info[room]['game_started']:
        print("Game start rejected")
        return

    current_players = rooms_info[room]['players']

    if len(current_players) < 2:
        emit('server_message',
             "You can only start a game with 2 or 3 players.",
             room=room)
        return

    assert name in current_players
    assert len(current_players) <= 3
    assert not rooms_info[room]['game_started']

    random.seed(time.time())
    rolled_cubes = [random.randint(0, 5) for _ in range(24)]

    rooms_info[room] = {
        "game_started": True,
        "game_finished": False,
        "players": current_players,
        "spectators": rooms_info[room]["spectators"],
        "sockets": rooms_info[room]["sockets"],
        "p1scores": [0],
        "p2scores": [0],
        "p3scores": [0],
        "starttime": time.time(),
        "cube_index":
        rolled_cubes[:],  # fixed length of 24, index is cube's id
        "resources": rolled_cubes,  # fixed length of 24
        "goal": [],  # stores cube ids (based on cube_index); same for 3 below
        "required": [],
        "permitted": [],
        "forbidden": [],
        "turn": random.randint(0,
                               len(current_players) - 1),
        "goalset": False,
        "num_timer_flips": 0,
        "10s_warning_called": False,
        "challenge": None,
        "touched_cube": None,
        "bonus_clicked": False,
        "started_move": False,
    }

    game_begin_instructions = {
        'cubes': rolled_cubes,
        'players': current_players,
        'firstmove': rooms_info[room]['turn'],
    }

    emit("begin_game", game_begin_instructions, room=room)

    start_instruction = f"{name} started the game! The cubes have been rolled! \
        {get_current_mover(room)} is chosen to be the goal setter. \
            Move cubes by clicking a cube in resources, \
                then clicking the area on the mat you want to move it to. \
                    If you touch a cube you must move it! \
                    Press \"Goal Set!\" when you're done!"

    emit("server_message", start_instruction, room=room)