async def confirm_expelliarmus(body: VoteRequest, room_name: str = Path( ..., min_length=6, max_length=20, ), username: str = Depends(get_username_from_token)): """ Endpoint used by the minister to confirm the Expelliarmus Spell """ room = check_game_preconditions(username, room_name, hub) game = room.get_game() phase = game.get_phase() minister = game.get_minister_user() if (phase == GamePhase.CONFIRM_EXPELLIARMUS and minister == username): if body.vote not in [Vote.LUMOS.value, Vote.NOX.value]: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Invalid selection") else: game.expelliarmus(body.vote) room.post_message(f"{username} has casted Expelliarmus!") return {"message": "Expelliarmus! confirmation received"} else: raise HTTPException( status_code=status.HTTP_405_METHOD_NOT_ALLOWED, detail="Game is not in expelliarmus phase")
async def discard(body: DiscardRequest, room_name: str = Path( ..., min_length=6, max_length=20, ), username: str = Depends(get_username_from_token)): """ Endpoint used for discarding a card, both by minister and director. Expects a body containing 1 field ("card_index") that represents the index of the card you want to discard (as returned by the /cards endpoint) """ room = check_game_preconditions(username, room_name, hub) game = room.get_game() phase = game.get_phase() if (phase == GamePhase.MINISTER_DISCARD and game.get_minister_user() == username): if (body.card_index not in [0, 1, 2]): raise HTTPException(detail="Index out of bounds", status_code=400) game.discard(body.card_index) game.set_phase(GamePhase.DIRECTOR_DISCARD) return {"message": "Successfully discarded"} elif (phase == GamePhase.DIRECTOR_DISCARD and game.get_director_user() == username): if (body.card_index not in [0, 1, 3]): raise HTTPException(detail="Index out of bounds", status_code=400) elif (body.card_index == 3): if (game.get_de_procs() >= 5): if (not game.is_expelliarmus_casted()): game.cast_expelliarmus() game.set_phase(GamePhase.CONFIRM_EXPELLIARMUS) return {"message": "Successfully casted Expelliarmus!"} else: raise HTTPException( detail="You cant cast expelliarmus twice in the round", status_code=status.HTTP_403_FORBIDDEN) else: raise HTTPException(detail="You can't cast Expelliarmus! yet", status_code=403) else: game.discard(body.card_index) game.proc_leftover_card() return {"message": "Successfully discarded"} elif (phase == GamePhase.REJECTED_EXPELLIARMUS and game.get_director_user() == username): if (body.card_index not in [0, 1]): raise HTTPException(detail="Index out of bounds", status_code=400) else: game.discard(body.card_index) game.proc_leftover_card() return {"message": "Successfully discarded"} else: raise HTTPException(detail="You're not allowed to do this", status_code=405)
async def get_cards(room_name: str = Path( ..., min_length=6, max_length=20, ), username: str = Depends(get_username_from_token)): """ Endpoint for getting the cards, used both by minister and director, but at their respective times. Will return a list similar to this: ['Order of the Fenix proclamation', 'Order of the Fenix proclamation', 'Death Eater proclamation'] """ room = check_game_preconditions(username, room_name, hub) game = room.get_game() phase = game.get_phase() minister = game.get_minister_user() director = game.get_director_user() if ((phase == GamePhase.MINISTER_DISCARD and minister == username) or (phase == GamePhase.DIRECTOR_DISCARD and director == username) or (phase == GamePhase.REJECTED_EXPELLIARMUS and director == username)): return {"cards": game.get_cards()} else: raise HTTPException(detail="You're not allowed to do this", status_code=405)
async def propose_director(body: ProposeDirectorRequest, room_name: str = Path( ..., min_length=6, max_length=20, ), username: str = Depends(get_username_from_token)): """ Endpoint used by the minister to propose the director """ room = check_game_preconditions(username, room_name, hub) game = room.get_game() phase = game.get_phase() minister = game.get_minister_user() if (phase == GamePhase.PROPOSE_DIRECTOR and minister == username): if body.director_uname not in game.get_alive_players(): raise HTTPException(status_code=404, detail="Player dead or not found") elif (body.director_uname == game.get_last_director_user() or minister == body.director_uname): raise HTTPException( status_code=403, detail="That player cannot be the director this round") else: game.set_director(body.director_uname) game.set_phase(GamePhase.VOTE_DIRECTOR) await save_game_on_database(room) return {"message": "Director proposed successfully"} else: raise HTTPException(detail="You're not allowed to do this", status_code=405)
async def cast_divination(room_name: str = Path(..., min_length=6, max_length=20), username: str = Depends(get_username_from_token)): global hub room = check_game_preconditions(username, room_name, hub) game = room.get_game() phase = game.get_phase() minister = game.get_minister_user() if (phase == GamePhase.CAST_DIVINATION and username == minister): return {"cards": game.divination()} else: raise HTTPException( detail="You're not allowed to do this", status_code=405)
async def confirm_divination(room_name: str = Path(..., min_length=6, max_length=20), username: str = Depends(get_username_from_token)): global hub room = check_game_preconditions(username, room_name, hub) game = room.get_game() phase = game.get_phase() minister = game.get_minister_user() if (phase == GamePhase.CAST_DIVINATION and username == minister): game.restart_turn() room.post_message(f"{username} knows someone loyalty:") return {"message": "Divination confirmed, moving on"} else: raise HTTPException( detail="You're not allowed to do this", status_code=405)
async def confirm_crucio(room_name: str = Path(..., min_length=6, max_length=20), username: str = Depends(get_username_from_token)): global hub room = check_game_preconditions(username, room_name, hub) game = room.get_game() phase = game.get_phase() minister = game.get_minister_user() if (phase == GamePhase.CAST_CRUCIO and username == minister): room.post_message(f"{username} has tortured someone!") game.restart_turn() return {"message": "Crucio confirmed, moving on"} else: raise HTTPException( detail="You're not allowed to do this", status_code=405)
async def cast_crucio(body: TargetedSpellRequest, room_name: str = Path(..., min_length=6, max_length=20), username: str = Depends(get_username_from_token)): """ Endpoint that casts the spell "crucio", revealing the loyalty of some player to the minister. THROWS: 200 if OK 400 if game is not in CAST_CRUCIO phase 405 if who made the request is not the minister 406 if the victim is the minister (minister voted himself) 409 if the playet is dead or was already investigated """ global hub room = check_game_preconditions(username, room_name, hub) game = room.get_game() phase = game.get_phase() minister = game.get_minister_user() victim = body.target_uname if username == minister: if phase != GamePhase.CAST_CRUCIO: raise HTTPException( detail="Game is not in Cruciatus phase", status_code=400) elif victim not in game.get_alive_players(): raise HTTPException( detail="Let him rest in peace!", status_code=409) elif victim == minister: raise HTTPException( detail="You can`t choose yourself", status_code=406) elif victim in game.get_investigated_players(): raise HTTPException( detail="Player already investigated", status_code=409) else: return {"loyalty": game.crucio(victim)} else: raise HTTPException( detail="You`re not allowed to do this", status_code=405)
async def vote(vote_req: VoteRequest, username: str = Depends(get_username_from_token), room_name: str = Path( ..., min_length=6, max_length=20, )): """ This endpoint registers a vote and who`s voting. Throws 409 if the game if you already voted Throws 405 if the game is not in phase of voting Throws 404 if the game cannot be found in Hub Throws 400 if the vote is not Lumos or Nox """ room = check_game_preconditions(username, room_name, hub) game = room.get_game() if game.phase == GamePhase.VOTE_DIRECTOR: if vote_req.vote not in [Vote.LUMOS.value, Vote.NOX.value]: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Invalid vote") elif username in game.get_votes(True).keys(): raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail="You already voted") else: game.register_vote(vote_req.vote, username) else: raise HTTPException(status_code=status.HTTP_405_METHOD_NOT_ALLOWED, detail="Game is not in voting phase") if len(game.get_alive_players()) == len(game.votes): await game.compute_votes() return {"message": "Succesfully voted!"}
async def cast_avada_kedavra(body: TargetedSpellRequest, room_name: str = Path(..., min_length=6, max_length=20), username: str = Depends(get_username_from_token)): global hub room = check_game_preconditions(username, room_name, hub) game = room.get_game() phase = game.get_phase() minister = game.get_minister_user() if (phase == GamePhase.CAST_AVADA_KEDAVRA and username == minister): if body.target_uname not in game.get_current_players(): raise HTTPException(detail="Player not found", status_code=404) elif body.target_uname not in game.get_alive_players(): raise HTTPException( detail="Player is already dead", status_code=409) else: game.avada_kedavra(body.target_uname) room.post_message( f"{username} killed {body.target_uname} in cold blood:") return {"message": "Successfully casted Avada Kedavra"} else: raise HTTPException( detail="You're not allowed to do this", status_code=405)
async def cast_imperius(body: TargetedSpellRequest, room_name: str = Path(..., min_length=6, max_length=20), username: str = Depends(get_username_from_token)): global hub room = check_game_preconditions(username, room_name, hub) game = room.get_game() phase = game.get_phase() minister = game.get_minister_user() if (phase == GamePhase.CAST_IMPERIUS and username == minister): if body.target_uname not in game.get_current_players(): raise HTTPException(detail="Player not found", status_code=404) elif body.target_uname == minister: raise HTTPException( detail="You cant choose yourself", status_code=409) else: game.imperius(casted_by=minister, target=body.target_uname) room.post_message( f"{username} has choosen {body.target_uname} to be his successor!") return {"message": "Successfully casted Imperius"} else: raise HTTPException( detail="You're not allowed to do this", status_code=405)