|
|
|
@ -1,10 +1,15 @@ |
|
|
|
|
import math |
|
|
|
|
import random |
|
|
|
|
|
|
|
|
|
from django.http import HttpResponse |
|
|
|
|
from django.shortcuts import get_object_or_404, render |
|
|
|
|
from django.shortcuts import get_object_or_404, redirect, render |
|
|
|
|
from django.views.decorators.http import require_safe,\ |
|
|
|
|
require_POST,\ |
|
|
|
|
require_http_methods |
|
|
|
|
|
|
|
|
|
from .models import Game, Player |
|
|
|
|
from .forms import NewGameForm, JoinGameForm, StartGameForm |
|
|
|
|
from .helpers import mission_size, mission_size_string |
|
|
|
|
from .models import Game, GameRound, Player |
|
|
|
|
|
|
|
|
|
# helpers to interpret arguments |
|
|
|
|
def lookup_access_code(func): |
|
|
|
@ -30,53 +35,215 @@ def index(request): |
|
|
|
|
|
|
|
|
|
@require_http_methods(["HEAD", "GET", "POST"]) |
|
|
|
|
def enter_code(request): |
|
|
|
|
if request.method == 'GET': |
|
|
|
|
pass |
|
|
|
|
elif request.method == 'POST': |
|
|
|
|
pass |
|
|
|
|
if request.method == 'POST': |
|
|
|
|
form = JoinGameForm(request.POST) |
|
|
|
|
if form.is_valid(): |
|
|
|
|
game = form.cleaned_data.get('game') |
|
|
|
|
player = form.cleaned_data.get('player') |
|
|
|
|
return redirect('game', |
|
|
|
|
access_code=game.access_code, |
|
|
|
|
player_secret=player.secret_id) |
|
|
|
|
else: |
|
|
|
|
form = JoinGameForm() |
|
|
|
|
|
|
|
|
|
return render(request, 'join_game.html', {'form': form}) |
|
|
|
|
|
|
|
|
|
@require_http_methods(["HEAD", "GET", "POST"]) |
|
|
|
|
def new_game(request): |
|
|
|
|
if request.method == 'GET': |
|
|
|
|
pass |
|
|
|
|
elif request.method == 'POST': |
|
|
|
|
pass |
|
|
|
|
if request.method == 'POST': |
|
|
|
|
form = NewGameForm(request.POST) |
|
|
|
|
if form.is_valid(): |
|
|
|
|
game = Game.objects.create() |
|
|
|
|
name = form.cleaned_data.get('name') |
|
|
|
|
player = Player.objects.create(game=game, name=name) |
|
|
|
|
return redirect('game', |
|
|
|
|
access_code=game.access_code, |
|
|
|
|
player_secret=player.secret_id) |
|
|
|
|
else: |
|
|
|
|
form = NewGameForm() |
|
|
|
|
|
|
|
|
|
return render(request, 'new_game.html', {'form': form}) |
|
|
|
|
|
|
|
|
|
@lookup_access_code |
|
|
|
|
@require_safe |
|
|
|
|
def join_game(request, game): |
|
|
|
|
pass |
|
|
|
|
form = JoinGameForm(initial={'game': game.access_code}) |
|
|
|
|
return render(request, 'join_game.html', {'access_code': game.access_code, |
|
|
|
|
'form': form}) |
|
|
|
|
|
|
|
|
|
def game_base_context(game, player): |
|
|
|
|
players = Player.objects.filter(game=game).order_by('order') |
|
|
|
|
num_players = players.count() |
|
|
|
|
|
|
|
|
|
context = {} |
|
|
|
|
|
|
|
|
|
context['access_code'] = game.access_code |
|
|
|
|
context['player_secret'] = player.secret_id |
|
|
|
|
context['players'] = players |
|
|
|
|
context['player'] = player |
|
|
|
|
|
|
|
|
|
try: |
|
|
|
|
round_scores = {} |
|
|
|
|
for round_num in range(1, 6): |
|
|
|
|
round_scores[round_num] = {'mission_size': mission_size_string(mission_size(num_players=num_players, round_num=round_num)), 'winner': ''} |
|
|
|
|
for game_round in GameRound.objects.filter(game=game): |
|
|
|
|
round_scores[game_round.round_num]['winner'] = game_round.winner_string() |
|
|
|
|
context['round_scores'] = round_scores |
|
|
|
|
except ValueError: |
|
|
|
|
pass |
|
|
|
|
|
|
|
|
|
if game.game_phase != Game.GAME_PHASE_LOBBY: |
|
|
|
|
context['game_has_mordred'] = players.filter(role=Player.ROLE_MORDRED)\ |
|
|
|
|
.exists() |
|
|
|
|
context['visible_spies'] = [p for p in players |
|
|
|
|
if player.sees_as_spy(p)] |
|
|
|
|
if player.is_percival(): |
|
|
|
|
possible_merlins = " or ".join([p.name for p in players |
|
|
|
|
if p.appears_as_merlin()]) |
|
|
|
|
context['possible_merlins'] = possible_merlins |
|
|
|
|
|
|
|
|
|
return context |
|
|
|
|
|
|
|
|
|
@lookup_player_secret |
|
|
|
|
@lookup_access_code |
|
|
|
|
@lookup_player_secret |
|
|
|
|
@require_safe |
|
|
|
|
def game(request, game, player): |
|
|
|
|
pass |
|
|
|
|
player.save() # update last_accessed |
|
|
|
|
|
|
|
|
|
context = game_base_context(game, player) |
|
|
|
|
|
|
|
|
|
if game.game_phase == Game.GAME_PHASE_LOBBY: |
|
|
|
|
context['form'] = StartGameForm() |
|
|
|
|
return render(request, 'lobby.html', context) |
|
|
|
|
elif game.game_phase == Game.GAME_PHASE_ROLE: |
|
|
|
|
return render(request, 'role_phase.html', context) |
|
|
|
|
elif game.game_phase == Game.GAME_PHASE_PICK: |
|
|
|
|
pass |
|
|
|
|
elif game.game_phase == Game.GAME_PHASE_VOTE: |
|
|
|
|
pass |
|
|
|
|
elif game.game_phase == Game.GAME_PHASE_MISSION: |
|
|
|
|
pass |
|
|
|
|
elif game.game_phase == Game.GAME_PHASE_ASSASSIN: |
|
|
|
|
pass |
|
|
|
|
elif game.game_phase == Game.GAME_PHASE_END: |
|
|
|
|
pass |
|
|
|
|
else: |
|
|
|
|
pass |
|
|
|
|
|
|
|
|
|
return render(request, 'in_game.html', context) |
|
|
|
|
|
|
|
|
|
@lookup_access_code |
|
|
|
|
@lookup_player_secret |
|
|
|
|
@require_POST |
|
|
|
|
def leave(request, game, player): |
|
|
|
|
player.delete() |
|
|
|
|
num_players = Player.objects.filter(game=game).count() |
|
|
|
|
if num_players == 0: |
|
|
|
|
game.delete() |
|
|
|
|
return redirect('index') |
|
|
|
|
|
|
|
|
|
@lookup_access_code |
|
|
|
|
def ready(request, game, player): |
|
|
|
|
pass |
|
|
|
|
@lookup_player_secret |
|
|
|
|
@require_POST |
|
|
|
|
def start(request, game, player): |
|
|
|
|
player.save() # update last_accessed |
|
|
|
|
|
|
|
|
|
if game.game_phase != Game.GAME_PHASE_LOBBY: |
|
|
|
|
return redirect('game', access_code=game.access_code, |
|
|
|
|
player_secret=player.secret_id) |
|
|
|
|
|
|
|
|
|
players = Player.objects.filter(game=game) |
|
|
|
|
num_players = players.count() |
|
|
|
|
|
|
|
|
|
form = StartGameForm(request.POST) |
|
|
|
|
if num_players < 5: |
|
|
|
|
form.add_error(None, "You must have at least 5 players to play!") |
|
|
|
|
elif num_players > 10: |
|
|
|
|
form.add_error(None, "You can't have more than 10 players to play!") |
|
|
|
|
|
|
|
|
|
if form.is_valid(): |
|
|
|
|
num_spies = int(math.ceil(num_players / 3.0)) |
|
|
|
|
spy_roles = [] |
|
|
|
|
if form.cleaned_data.get('assassin'): |
|
|
|
|
spy_roles.append(Player.ROLE_ASSASSIN) |
|
|
|
|
if form.cleaned_data.get('morgana'): |
|
|
|
|
spy_roles.append(Player.ROLE_MORGANA) |
|
|
|
|
if form.cleaned_data.get('mordred'): |
|
|
|
|
spy_roles.append(Player.ROLE_MORDRED) |
|
|
|
|
if form.cleaned_data.get('oberon'): |
|
|
|
|
spy_roles.append(Player.ROLE_OBERON) |
|
|
|
|
if len(spy_roles) > num_spies: |
|
|
|
|
form.add_error(None, "There will only be %d spies. Select no more than that many special roles for spies." % num_spies) |
|
|
|
|
else: |
|
|
|
|
game.display_history = form.cleaned_data.get('display_history') |
|
|
|
|
game.game_phase = Game.GAME_PHASE_ROLE |
|
|
|
|
|
|
|
|
|
resistance_roles = [] |
|
|
|
|
if form.cleaned_data.get('merlin'): |
|
|
|
|
resistance_roles.append(Player.ROLE_MERLIN) |
|
|
|
|
if form.cleaned_data.get('percival'): |
|
|
|
|
resistance_roles.append(Player.ROLE_PERCIVAL) |
|
|
|
|
|
|
|
|
|
num_resistance = num_players - num_spies |
|
|
|
|
roles = spy_roles + resistance_roles +\ |
|
|
|
|
[Player.ROLE_SPY]*(num_spies - len(spy_roles)) +\ |
|
|
|
|
[Player.ROLE_GOOD]*(num_resistance - len(resistance_roles)) |
|
|
|
|
assert len(roles) == num_players |
|
|
|
|
|
|
|
|
|
play_order = range(num_players) |
|
|
|
|
random.shuffle(play_order) |
|
|
|
|
random.shuffle(roles) |
|
|
|
|
|
|
|
|
|
for p, role, order in zip(players, roles, play_order): |
|
|
|
|
p.role = role |
|
|
|
|
p.order = order |
|
|
|
|
p.save() |
|
|
|
|
|
|
|
|
|
game.save() |
|
|
|
|
return redirect('game', access_code=game.access_code, |
|
|
|
|
player_secret=player.secret_id) |
|
|
|
|
context = game_base_context(game, player) |
|
|
|
|
context['form'] = form |
|
|
|
|
|
|
|
|
|
return render(request, 'lobby.html', context) |
|
|
|
|
|
|
|
|
|
@lookup_access_code |
|
|
|
|
@lookup_player_secret |
|
|
|
|
@require_POST |
|
|
|
|
def ready(request, game, player): |
|
|
|
|
if game.game_phase == Game.GAME_PHASE_ROLE: |
|
|
|
|
player.ready = True |
|
|
|
|
player.save() |
|
|
|
|
|
|
|
|
|
if not Player.objects.filter(game=game, ready=False): |
|
|
|
|
game.game_phase = Game.GAME_PHASE_PICK |
|
|
|
|
game.save() |
|
|
|
|
GameRound.objects.create(game=game, round_num=1) |
|
|
|
|
|
|
|
|
|
return redirect('game', access_code=game.access_code, |
|
|
|
|
player_secret=player.secret_id) |
|
|
|
|
|
|
|
|
|
@lookup_access_code |
|
|
|
|
@lookup_player_secret |
|
|
|
|
def choose(request, game, player, round_num, vote_num, who): |
|
|
|
|
pass |
|
|
|
|
|
|
|
|
|
@lookup_player_secret |
|
|
|
|
@lookup_access_code |
|
|
|
|
def remove(request, game, player, round_num, vote_num, who): |
|
|
|
|
@lookup_player_secret |
|
|
|
|
def unchoose(request, game, player, round_num, vote_num, who): |
|
|
|
|
pass |
|
|
|
|
|
|
|
|
|
@lookup_player_secret |
|
|
|
|
@lookup_access_code |
|
|
|
|
@lookup_player_secret |
|
|
|
|
def vote(request, game, player, round_num, vote_num, vote): |
|
|
|
|
pass |
|
|
|
|
|
|
|
|
|
@lookup_player_secret |
|
|
|
|
@lookup_access_code |
|
|
|
|
@lookup_player_secret |
|
|
|
|
def mission(request, game, player, round_num, mission_action): |
|
|
|
|
pass |
|
|
|
|
|
|
|
|
|
@lookup_player_secret |
|
|
|
|
@lookup_access_code |
|
|
|
|
@lookup_player_secret |
|
|
|
|
def assassinate(request, game, player, target): |
|
|
|
|
pass |
|
|
|
|