2016-05-26 09:52:01 +00:00
#!/usr/bin/env python3.5
2016-04-25 16:13:16 +00:00
# -*- coding: utf-8 -*-
2016-04-25 16:21:38 +00:00
from telegram . ext import Updater , CommandHandler
2016-05-26 11:42:50 +00:00
from telegram import ParseMode
2016-04-21 16:57:23 +00:00
import filemanager
2016-04-25 17:39:57 +00:00
import random
2016-05-25 11:57:15 +00:00
import strings as s
2016-04-21 16:57:23 +00:00
2016-04-21 20:14:35 +00:00
import logging
logger = logging . getLogger ( )
2016-05-22 15:13:26 +00:00
logger . setLevel ( logging . WARN )
logging . basicConfig ( level = logging . WARN ,
format = ' %(asctime)s - %(name)s - %(levelname)s - %(message)s ' )
2016-04-21 20:14:35 +00:00
2016-04-21 16:57:23 +00:00
token = filemanager . readfile ( ' telegramapi.txt ' )
updater = Updater ( token )
2016-05-26 09:04:16 +00:00
freenames = s . names_list . copy ( )
2016-04-21 16:57:23 +00:00
2016-04-21 17:52:01 +00:00
# Ruoli possibili per i giocatori
# Base di un ruolo
class Role :
2016-05-25 06:57:03 +00:00
""" Classe base di un ruolo. Da qui si sviluppano tutti gli altri ruoli. """
2016-05-22 15:13:26 +00:00
def __init__ ( self ) :
2016-05-25 09:52:53 +00:00
self . icon = " - " # Icona del ruolo, da visualizzare di fianco al nome
2016-05-22 15:13:26 +00:00
self . team = ' None ' # Squadra: 'None', 'Good', 'Evil'
2016-05-25 09:52:53 +00:00
self . name = " UNDEFINED " # Nome del ruolo, viene visualizzato dall'investigatore e durante l'assegnazione dei ruoli
2016-05-26 09:04:16 +00:00
self . powerdesc = None # Ha un potere? Se sì, inviagli le info su come usarlo.
def __repr__ ( self ) :
2016-05-26 09:08:50 +00:00
r = " < undefined Role > "
return r
2016-04-21 17:52:01 +00:00
2016-05-26 09:30:31 +00:00
def power ( self , bot , game , player , arg ) :
2016-05-25 09:52:53 +00:00
""" Il potere del ruolo. Si attiva quando il bot riceve un /power in chat privata. """
2016-04-21 17:52:01 +00:00
pass
2016-05-26 09:30:31 +00:00
def onendday ( self , bot , game ) :
2016-05-25 09:52:53 +00:00
""" Metodo chiamato alla fine di ogni giorno, per attivare o ripristinare allo stato iniziale il potere. """
2016-04-21 17:52:01 +00:00
pass
class Royal ( Role ) :
2016-05-25 09:52:53 +00:00
""" Un membro della Royal Games. Il ruolo principale, non ha alcun potere se non quello di votare. """
2016-05-22 15:13:26 +00:00
def __init__ ( self ) :
super ( ) . __init__ ( )
2016-05-25 11:57:15 +00:00
self . icon = s . royal_icon
2016-05-22 15:13:26 +00:00
self . team = ' Good '
2016-05-25 11:57:15 +00:00
self . name = s . royal_name
2016-04-21 17:52:01 +00:00
2016-05-26 09:04:16 +00:00
def __repr__ ( self ) :
2016-05-26 09:08:50 +00:00
r = " < Role: Royal > "
return r
2016-05-26 09:04:16 +00:00
2016-04-21 17:52:01 +00:00
class Mifioso ( Role ) :
2016-05-25 11:57:15 +00:00
""" Il nemico globale. Può impostare come bersaglio una persona al giorno, per poi ucciderla alla fine. """
2016-05-22 15:13:26 +00:00
def __init__ ( self ) :
super ( ) . __init__ ( )
2016-05-25 11:57:15 +00:00
self . icon = s . mifia_icon
2016-05-22 15:13:26 +00:00
self . team = ' Evil '
self . target = None
2016-05-25 11:57:15 +00:00
self . name = s . mifia_name
2016-05-26 09:04:16 +00:00
self . powerdesc = s . mifia_power_description
def __repr__ ( self ) :
2016-05-26 09:08:50 +00:00
if self . target is None :
r = " < Role: Mifioso > "
else :
r = " < Role: Mifioso, targeting {target} > " . format ( target = target . tusername )
return r
2016-04-21 17:52:01 +00:00
2016-05-26 09:30:31 +00:00
def power ( self , bot , game , player , arg ) :
2016-05-25 09:52:53 +00:00
# Imposta una persona come bersaglio da uccidere.
2016-05-26 11:42:50 +00:00
selected = game . findplayerbyusername ( arg )
2016-05-27 08:39:12 +00:00
if selected is not None :
2016-05-26 11:42:50 +00:00
self . target = selected
2016-05-25 11:57:15 +00:00
player . message ( bot , s . mifia_target_selected . format ( target = self . target . tusername ) )
2016-05-26 11:42:50 +00:00
else :
player . message ( bot , s . error_username )
2016-04-21 17:52:01 +00:00
2016-05-26 09:30:31 +00:00
def onendday ( self , bot , game ) :
2016-05-26 13:12:49 +00:00
if not game . votingmifia :
# Uccidi il bersaglio se non è protetto da un Angelo.
if self . target is not None :
if self . target . protectedby is None :
self . target . kill ( )
game . message ( bot , s . mifia_target_killed . format ( target = self . target . tusername , icon = self . target . role . icon , role = self . target . role . name ) )
else :
game . message ( bot , s . mifia_target_protected . format ( target = self . target . tusername , icon = self . target . protectedby . role . icon ,
protectedby = self . target . protectedby . tusername ) )
self . target = None
else :
2016-05-03 11:29:29 +00:00
self . target = None
2016-04-21 17:52:01 +00:00
class Investigatore ( Role ) :
2016-05-25 09:52:53 +00:00
""" L ' investigatore può indagare sul vero ruolo di una persona una volta al giorno. """
2016-05-22 15:13:26 +00:00
def __init__ ( self ) :
super ( ) . __init__ ( )
2016-05-25 11:57:15 +00:00
self . icon = s . detective_icon
2016-05-22 15:13:26 +00:00
self . team = ' Good '
self . poweruses = 1
2016-05-25 11:57:15 +00:00
self . name = s . detective_name
2016-05-26 09:04:16 +00:00
self . powerdesc = s . detective_power_description . format ( maxuses = self . poweruses )
def __repr__ ( self ) :
2016-05-26 09:08:50 +00:00
r = " < Role: Investigatore, {uses} uses left > " . format ( uses = self . poweruses )
return r
2016-04-21 17:52:01 +00:00
2016-05-26 09:30:31 +00:00
def power ( self , bot , game , player , arg ) :
2016-05-25 09:52:53 +00:00
# Indaga sul vero ruolo di una persona, se sono ancora disponibili usi del potere.
2016-04-23 15:12:52 +00:00
if self . poweruses > 0 :
target = game . findplayerbyusername ( arg )
if target is not None :
self . poweruses - = 1
2016-05-25 11:57:15 +00:00
player . message ( bot , s . detective_discovery
. format ( target = target . tusername , icon = target . role . icon , role = target . role . name , left = self . poweruses ) )
2016-04-23 15:12:52 +00:00
else :
2016-05-25 11:57:15 +00:00
player . message ( bot , s . error_username )
2016-04-23 15:12:52 +00:00
else :
2016-05-25 11:57:15 +00:00
player . message ( bot , s . error_no_uses )
2016-04-21 21:04:53 +00:00
2016-05-26 09:30:31 +00:00
def onendday ( self , bot , game ) :
2016-04-21 21:04:53 +00:00
# Ripristina il potere
self . poweruses = 1
2016-05-03 11:29:29 +00:00
class Angelo ( Role ) :
2016-05-25 09:52:53 +00:00
""" L ' angelo può proteggere una persona al giorno dalla Mifia. Se ha successo nella protezione, il suo ruolo sarà rivelato a tutti. """
2016-05-22 15:13:26 +00:00
def __init__ ( self ) :
super ( ) . __init__ ( )
2016-05-25 11:57:15 +00:00
self . icon = s . angel_icon
2016-05-22 15:13:26 +00:00
self . team = ' Good ' # Squadra: 'None', 'Good', 'Evil'
2016-05-25 11:57:15 +00:00
self . name = s . angel_name
2016-05-25 09:52:53 +00:00
self . protecting = None # La persona che questo angelo sta proteggendo
2016-05-26 09:04:16 +00:00
self . powerdesc = s . angel_power_description
def __repr__ ( self ) :
2016-05-26 09:08:50 +00:00
if protecting is None :
r = " < Role: Angelo > "
else :
r = " < Role: Angelo, protecting {target} " . format ( target = self . protecting . tusername )
return r
2016-05-03 11:29:29 +00:00
2016-05-26 09:30:31 +00:00
def power ( self , bot , game , player , arg ) :
2016-05-25 09:52:53 +00:00
# Imposta qualcuno come protetto
2016-05-03 11:29:29 +00:00
selected = game . findplayerbyusername ( arg )
2016-05-26 11:42:50 +00:00
if selected is not None :
if selected is not Player :
# Togli la protezione a quello che stavi proteggendo prima
if self . protecting is not None :
self . protecting . protectedby = None
selected . protectedby = player
self . protecting = selected
player . message ( bot , s . angel_target_selected . format ( target = self . protecting . tusername ) )
else :
player . message ( bot , error_angel_no_selfprotect )
else :
player . message ( bot , error_username )
2016-05-03 11:29:29 +00:00
2016-05-26 09:30:31 +00:00
def onendday ( self , bot , game ) :
2016-05-26 11:42:50 +00:00
2016-05-03 11:29:29 +00:00
# Resetta la protezione
2016-05-25 06:45:46 +00:00
if self . protecting is not None :
2016-05-25 06:57:03 +00:00
self . protecting . protectedby = None
2016-05-03 11:29:29 +00:00
self . protecting = None
2016-05-03 19:49:39 +00:00
2016-04-21 18:20:26 +00:00
class Player :
2016-05-25 09:52:53 +00:00
""" Classe di un giocatore. Contiene tutti i dati riguardanti un giocatore all ' interno di una partita, come il ruolo, e i dati riguardanti telegram, come ID e username. """
2016-05-26 09:30:31 +00:00
def __init__ ( self , tid , tusername ) :
2016-05-25 09:52:53 +00:00
self . tid = tid # ID di Telegram
self . tusername = tusername # Username di Telegram
2016-05-22 15:13:26 +00:00
self . role = Role ( ) # Di base, ogni giocatore è un ruolo indefinito
self . alive = True
self . votingfor = None # Diventa un player se ha votato
2016-05-25 09:52:53 +00:00
self . votes = 0 # Voti che sta ricevendo questo giocatore. Aggiornato da updatevotes()
2016-05-25 06:57:03 +00:00
self . protectedby = None # Protettore. Oggetto player che protegge questo giocatore dalla mifia.
2016-05-26 13:12:49 +00:00
self . mifiavotes = 0 # Voti che sta ricevendo questo giocatore dalla mifia. Aggiornato da updatemifiavotes()
2016-04-21 18:20:26 +00:00
2016-05-26 09:04:16 +00:00
def __repr__ ( self ) :
2016-05-26 09:08:50 +00:00
r = " < Player {username} > " . format ( username = self . tusername )
2016-05-26 09:04:16 +00:00
2016-05-26 09:30:31 +00:00
def message ( self , bot , text ) :
2016-05-26 09:04:16 +00:00
""" Manda un messaggio privato al giocatore. """
2016-05-26 13:25:54 +00:00
bot . sendMessage ( self . tid , text , parse_mode = ParseMode . MARKDOWN )
2016-05-26 09:04:16 +00:00
def kill ( self ) :
""" Uccidi il giocatore. """
# Perchè questo esiste?
self . alive = False
2016-05-25 09:52:53 +00:00
2016-04-21 18:20:26 +00:00
class Game :
2016-05-25 09:52:53 +00:00
""" Classe di una partita, contenente parametri riguardanti stato della partita e informazioni sul gruppo di Telegram. """
2016-05-26 09:30:31 +00:00
def __init__ ( self , groupid , adminid ) :
2016-05-25 09:52:53 +00:00
self . groupid = groupid # ID del gruppo in cui si sta svolgendo una partita
self . adminid = adminid # ID telegram dell'utente che ha creato la partita con /newgame
self . players = list ( ) # Lista dei giocatori in partita
2016-05-22 15:13:26 +00:00
self . tokill = list ( ) # Giocatori che verranno uccisi all'endday
2016-05-26 11:42:50 +00:00
self . phase = ' Join ' # Fase di gioco: 'Join', 'Config', 'Voting'
self . configstep = 0 # Passo attuale di configurazione
self . totalmifiosi = 0 # Numero di mifiosi da inserire
self . totaldetectives = 0 # Numero di detective da inserire
self . totalangels = 0 # Numero di angeli da inserire
2016-05-26 13:12:49 +00:00
self . votingmifia = False # Seguire le regole originali della mifia che vota?
2016-05-26 11:42:50 +00:00
2016-05-26 13:18:03 +00:00
# Liste di ruoli in gioco, per velocizzare gli endday
self . mifiosiingame = list ( )
self . detectivesingame = list ( )
self . angelsingame = list ( )
2016-05-26 09:04:16 +00:00
# Trova un nome per la partita
if len ( freenames ) > 0 :
2016-05-26 09:49:40 +00:00
random . shuffle ( freenames )
2016-05-26 09:08:50 +00:00
self . name = freenames . pop ( )
2016-05-26 09:04:16 +00:00
else :
2016-05-26 09:08:50 +00:00
self . name = str ( groupid )
2016-05-26 09:04:16 +00:00
def __del__ ( self ) :
2016-05-26 09:08:50 +00:00
# Rimetti il nome che si è liberato in disponibili.
try :
int ( self . name )
2016-05-26 09:10:52 +00:00
except ValueError :
2016-05-26 09:08:50 +00:00
freenames . append ( self . name )
2016-05-26 09:04:16 +00:00
2016-05-26 09:08:50 +00:00
def __repr__ ( self ) :
2016-05-26 09:49:40 +00:00
r = " < Game {name} in group {groupid} with {nplayers} players in phase {phase} > " . format ( name = self . name , groupid = self . groupid , nplayers = len ( self . players ) , phase = self . phase )
2016-05-26 09:08:50 +00:00
return r
2016-04-21 18:20:26 +00:00
2016-05-26 09:30:31 +00:00
def message ( self , bot , text ) :
2016-05-25 09:52:53 +00:00
""" Manda un messaggio nel gruppo. """
2016-05-26 13:25:54 +00:00
bot . sendMessage ( self . groupid , text , parse_mode = ParseMode . MARKDOWN )
2016-04-21 18:20:26 +00:00
2016-05-26 09:30:31 +00:00
def adminmessage ( self , bot , text ) :
2016-05-25 09:52:53 +00:00
""" Manda un messaggio privato al creatore della partita. """
2016-05-26 13:25:54 +00:00
bot . sendMessage ( self . adminid , text , parse_mode = ParseMode . MARKDOWN )
2016-04-21 18:20:26 +00:00
2016-05-26 09:30:31 +00:00
def mifiamessage ( self , bot , text ) :
2016-05-25 09:52:53 +00:00
""" Manda un messaggio privato a tutti i Mifiosi nella partita. """
2016-04-21 18:20:26 +00:00
# Trova tutti i mifiosi nell'elenco dei giocatori
for player in self . players :
if isinstance ( player . role , Mifioso ) :
player . message ( bot , text )
2016-05-26 09:30:31 +00:00
def findplayerbyid ( self , tid ) - > Player :
2016-05-25 09:52:53 +00:00
""" Trova il giocatore con un certo id. """
2016-04-22 17:21:50 +00:00
for player in self . players :
if player . tid == tid :
return player
else :
return None
2016-05-26 09:30:31 +00:00
def findplayerbyusername ( self , tusername ) - > Player :
2016-05-25 09:52:53 +00:00
""" Trova il giocatore con un certo username. """
2016-04-22 17:21:50 +00:00
for player in self . players :
2016-04-23 15:07:09 +00:00
if player . tusername . lower ( ) == tusername . lower ( ) :
2016-04-22 17:21:50 +00:00
return player
else :
return None
2016-05-26 11:42:50 +00:00
def assignroles ( self , bot ) :
2016-05-25 09:52:53 +00:00
""" Assegna ruoli casuali a tutti i giocatori. """
2016-04-22 17:55:24 +00:00
random . seed ( )
playersleft = self . players . copy ( )
random . shuffle ( playersleft )
2016-04-23 16:26:32 +00:00
# Seleziona mifiosi
2016-05-26 11:42:50 +00:00
while self . totalmifiosi > 0 :
2016-05-26 09:08:50 +00:00
selected = playersleft . pop ( )
2016-05-26 13:18:03 +00:00
self . mifiosiingame . append ( selected )
2016-05-26 09:08:50 +00:00
selected . role = Mifioso ( )
2016-05-26 11:42:50 +00:00
self . totalmifiosi - = 1
2016-04-23 16:26:32 +00:00
# Seleziona detective
2016-05-26 11:42:50 +00:00
while self . totaldetectives > 0 :
2016-05-26 09:08:50 +00:00
selected = playersleft . pop ( )
2016-05-26 13:18:03 +00:00
self . detectivesingame . append ( selected )
2016-05-26 09:08:50 +00:00
selected . role = Investigatore ( )
2016-05-26 11:42:50 +00:00
self . totaldetectives - = 1
2016-05-25 09:52:53 +00:00
# Seleziona angeli
2016-05-26 11:42:50 +00:00
while self . totalangels > 0 :
2016-05-26 09:08:50 +00:00
selected = playersleft . pop ( )
2016-05-26 13:18:03 +00:00
self . angelsingame . append ( selected )
2016-05-26 09:08:50 +00:00
selected . role = Angelo ( )
2016-05-26 11:42:50 +00:00
self . totalangels - = 1
2016-04-22 17:55:24 +00:00
# Assegna il ruolo di Royal a tutti gli altri
for player in playersleft :
player . role = Royal ( )
2016-04-23 16:26:32 +00:00
# Manda i ruoli assegnati a tutti
for player in self . players :
2016-05-25 11:57:15 +00:00
player . message ( bot , s . role_assigned . format ( icon = player . role . icon , name = player . role . name ) )
2016-05-26 09:40:59 +00:00
if player . role . powerdesc is not None :
player . message ( bot , player . role . powerdesc . format ( gamename = self . name ) )
2016-04-22 17:55:24 +00:00
2016-04-22 19:14:14 +00:00
def updatevotes ( self ) :
2016-05-25 09:52:53 +00:00
""" Aggiorna il conteggio dei voti di tutti i giocatori. """
2016-04-22 19:14:14 +00:00
for player in self . players :
player . votes = 0
for player in self . players :
2016-05-25 14:27:11 +00:00
if player . votingfor is not None and player . alive :
2016-04-23 15:37:43 +00:00
player . votingfor . votes + = 1
2016-04-22 19:14:14 +00:00
2016-05-27 08:51:52 +00:00
def updatemifiavotes ( self ) :
2016-05-26 13:12:49 +00:00
""" Aggiorna il conteggio dei voti mifiosi di tutti i giocatori. """
for player in self . players :
player . mifiavotes = 0
for player in self . players :
if isinstance ( player . role , Mifioso ) and player . alive :
if player . role . target is not None :
player . role . target . mifiavotes + = 1
2016-05-25 14:27:11 +00:00
def mostvotedplayer ( self ) - > list :
2016-05-25 09:52:53 +00:00
""" Trova il giocatore più votato. """
2016-05-25 14:27:11 +00:00
mostvoted = list ( )
currenttop = 0
2016-04-22 19:14:14 +00:00
self . updatevotes ( )
for player in self . players :
2016-05-25 14:27:11 +00:00
if player . votes > currenttop :
mostvoted = [ player ]
elif player . votes == currenttop :
mostvoted . append ( player )
2016-05-26 13:12:49 +00:00
if currenttop > 0 :
return mostvoted
else :
2016-05-27 08:51:52 +00:00
return list ( )
2016-05-26 13:12:49 +00:00
def mostvotedmifia ( self ) - > list :
""" Trova il giocatore più votato dalla mifia. """
mostvoted = list ( )
currenttop = 0
2016-05-27 08:51:52 +00:00
self . updatemifiavotes ( )
2016-05-26 13:12:49 +00:00
for player in self . players :
if player . mifiavotes > currenttop :
mostvoted = [ player ]
elif player . votes == currenttop :
mostvoted . append ( player )
if currenttop > 0 :
return mostvoted
else :
2016-05-27 08:51:52 +00:00
return list ( )
2016-05-26 13:12:49 +00:00
2016-04-22 19:14:14 +00:00
def endday ( self , bot ) :
2016-05-25 14:27:11 +00:00
""" Finisci la giornata, uccidi il più votato del giorno ed esegui gli endday di tutti i giocatori. """
# Conta i voti ed elimina il più votato.
topvotes = self . mostvotedplayer ( )
if len ( topvotes ) > 0 :
# In caso di pareggio, elimina un giocatore casuale.
random . seed ( )
random . shuffle ( topvotes )
lynched = topvotes . pop ( )
2016-05-26 09:59:58 +00:00
if lynched . alive :
self . message ( bot , s . player_lynched . format ( name = lynched . tusername , icon = lynched . role . icon , role = lynched . role . name ) )
lynched . kill ( )
2016-05-25 14:27:11 +00:00
else :
self . message ( bot , s . no_players_lynched )
2016-05-03 10:43:00 +00:00
# Fai gli endday in un certo ordine.
# Si potrebbe fare più velocemente, credo.
2016-05-25 14:27:11 +00:00
# Ma non sto ho voglia di ottimizzare ora.
2016-05-03 10:43:00 +00:00
# Mifiosi
2016-05-26 13:12:49 +00:00
if self . votingmifia :
# Trova il più votato dai mifiosi e uccidilo
2016-05-27 09:16:02 +00:00
killlist = self . mostvotedmifia ( )
2016-05-26 13:12:49 +00:00
if len ( killlist ) > 0 :
# In caso di pareggio, elimina un giocatore casuale.
random . seed ( )
random . shuffle ( killlist )
killed = killlist . pop ( )
if killed . alive :
self . message ( bot , s . mifia_target_killed . format ( name = killed . tusername , icon = killed . role . icon , role = killed . role . name ) )
2016-05-27 09:16:02 +00:00
# Attiva il onendday dei mifiosi
2016-05-26 13:18:03 +00:00
for player in self . mifiosiingame :
2016-05-25 14:27:11 +00:00
if isinstance ( player . role , Mifioso ) and player . alive :
2016-05-22 15:13:26 +00:00
player . role . onendday ( bot , self )
2016-05-03 10:43:00 +00:00
# Investigatori
2016-05-26 13:18:03 +00:00
for player in self . detectivesingame :
2016-05-25 14:27:11 +00:00
if isinstance ( player . role , Investigatore ) and player . alive :
2016-05-22 15:13:26 +00:00
player . role . onendday ( bot , self )
2016-05-03 11:29:29 +00:00
# Angeli
2016-05-26 13:18:03 +00:00
for player in self . angelsingame :
2016-05-25 14:27:11 +00:00
if isinstance ( player . role , Angelo ) and player . alive :
2016-05-22 15:13:26 +00:00
player . role . onendday ( bot , self )
2016-05-26 13:18:03 +00:00
# Cancella tutti i voti
2016-04-23 15:37:43 +00:00
for player in self . players :
player . votingfor = None
2016-04-23 16:26:32 +00:00
# Condizioni di vittoria
royal = 0
mifiosi = 0
for player in self . players :
2016-05-25 06:57:03 +00:00
if player . alive and player . role . team == ' Evil ' :
2016-04-23 16:26:32 +00:00
mifiosi + = 1
2016-05-03 19:49:17 +00:00
elif player . alive and player . role . team == ' Good ' :
2016-04-23 16:26:32 +00:00
royal + = 1
if mifiosi > = royal :
2016-05-25 11:57:15 +00:00
self . message ( bot , s . victory_mifia )
2016-04-23 16:26:32 +00:00
self . endgame ( )
elif mifiosi == 0 :
2016-05-25 11:57:15 +00:00
self . message ( bot , s . victory_royal )
2016-04-23 16:26:32 +00:00
self . endgame ( )
def endgame ( self ) :
inprogress . remove ( self )
2016-04-22 19:14:14 +00:00
2016-04-21 20:14:35 +00:00
# Partite in corso
inprogress = list ( )
2016-04-21 18:20:26 +00:00
2016-05-26 09:30:31 +00:00
def findgamebyid ( gid ) - > Game :
2016-05-25 09:52:53 +00:00
""" Trova una partita con un certo id. """
2016-04-21 21:04:53 +00:00
for game in inprogress :
if game . groupid == gid :
return game
2016-05-26 09:30:31 +00:00
def findgamebyname ( name ) - > Game :
2016-05-26 09:08:50 +00:00
""" Trova una partita con un certo nome. """
for game in inprogress :
if game . name . lower ( ) == name . lower ( ) :
2016-05-26 10:10:07 +00:00
return game
2016-05-26 09:04:16 +00:00
2016-04-21 17:52:01 +00:00
# Comandi a cui risponde il bot
2016-04-21 16:57:23 +00:00
def ping ( bot , update ) :
2016-05-25 09:52:53 +00:00
""" Ping! """
2016-05-26 13:25:54 +00:00
bot . sendMessage ( update . message . chat [ ' id ' ] , s . pong , parse_mode = ParseMode . MARKDOWN )
2016-04-21 16:57:23 +00:00
2016-04-21 20:14:35 +00:00
def newgame ( bot , update ) :
2016-05-25 09:52:53 +00:00
""" Crea una nuova partita. """
2016-04-21 20:14:35 +00:00
if update . message . chat [ ' type ' ] != ' private ' :
2016-05-26 09:04:16 +00:00
game = findgamebyid ( update . message . chat [ ' id ' ] )
if game is None :
game = Game ( update . message . chat [ ' id ' ] , update . message . from_user [ ' id ' ] )
inprogress . append ( game )
game . message ( bot , s . new_game . format ( groupid = game . groupid , name = game . name ) )
2016-04-25 17:39:57 +00:00
else :
2016-05-26 13:25:54 +00:00
bot . sendMessage ( update . message . chat [ ' id ' ] , s . error_game_in_progress , parse_mode = ParseMode . MARKDOWN )
2016-04-21 20:14:35 +00:00
else :
2016-05-26 13:25:54 +00:00
bot . sendMessage ( update . message . chat [ ' id ' ] , s . error_chat_type , parse_mode = ParseMode . MARKDOWN )
2016-04-21 21:04:53 +00:00
def join ( bot , update ) :
2016-05-25 09:52:53 +00:00
""" Unisciti a una partita. """
2016-04-21 21:04:53 +00:00
game = findgamebyid ( update . message . chat [ ' id ' ] )
if game is not None :
if game . phase == ' Join ' :
2016-04-22 18:39:16 +00:00
p = game . findplayerbyid ( update . message . from_user [ ' id ' ] )
if p is None :
p = Player ( update . message . from_user [ ' id ' ] , update . message . from_user [ ' username ' ] )
game . players . append ( p )
2016-05-26 09:04:16 +00:00
game . message ( bot , s . player_joined . format ( name = p . tusername ) )
2016-04-22 18:39:16 +00:00
else :
2016-05-26 09:04:16 +00:00
game . message ( bot , s . error_player_already_joined )
else :
2016-05-26 09:08:50 +00:00
game . message ( bot , s . error_join_phase_ended )
2016-05-26 09:04:16 +00:00
else :
2016-05-26 13:25:54 +00:00
bot . sendMessage ( update . message . chat [ ' id ' ] , s . error_no_games_found , parse_mode = ParseMode . MARKDOWN )
2016-04-22 17:21:50 +00:00
2016-04-23 15:37:43 +00:00
def debug ( bot , update ) :
2016-05-25 09:52:53 +00:00
""" Visualizza tutti i ruoli e gli id. """
2016-04-23 15:37:43 +00:00
game = findgamebyid ( update . message . chat [ ' id ' ] )
2016-05-26 09:04:16 +00:00
if game is not None :
2016-04-23 15:37:43 +00:00
if game . adminid == update . message . from_user [ ' id ' ] :
2016-05-25 11:57:15 +00:00
text = s . status_header . format ( name = game . groupid , admin = game . adminid , phase = game . phase )
2016-04-23 15:37:43 +00:00
game . updatevotes ( )
# Aggiungi l'elenco dei giocatori
for player in game . players :
if not player . alive :
2016-05-25 11:57:15 +00:00
text + = s . status_dead_player . format ( name = player . tusername )
2016-04-23 15:37:43 +00:00
elif player . votingfor is not None :
2016-05-26 09:04:16 +00:00
text + = s . status_voting_player . format ( icon = player . role . icon , name = player . tusername , votes = str ( player . votes ) , voting = player . votingfor . tusername )
2016-04-23 15:37:43 +00:00
else :
2016-05-26 09:04:16 +00:00
text + = s . status_idle_player . format ( icon = player . role . icon , name = player . tusername , votes = str ( player . votes ) )
game . adminmessage ( bot , text )
game . message ( bot , s . check_private )
else :
2016-05-26 09:08:50 +00:00
game . message ( bot , s . error_not_admin )
2016-05-26 09:04:16 +00:00
else :
2016-05-26 13:25:54 +00:00
bot . sendMessage ( update . message . chat [ ' id ' ] , s . error_no_games_found , parse_mode = ParseMode . MARKDOWN )
2016-04-23 15:37:43 +00:00
2016-04-22 17:21:50 +00:00
def status ( bot , update ) :
2016-05-25 09:52:53 +00:00
""" Visualizza lo stato della partita. """
2016-04-22 17:21:50 +00:00
game = findgamebyid ( update . message . chat [ ' id ' ] )
2016-05-26 09:04:16 +00:00
if game is not None :
2016-05-26 10:12:14 +00:00
text = s . status_header . format ( name = game . name , admin = game . adminid , phase = game . phase )
2016-04-23 15:37:43 +00:00
game . updatevotes ( )
2016-04-22 17:21:50 +00:00
# Aggiungi l'elenco dei giocatori
for player in game . players :
2016-04-23 15:07:09 +00:00
if not player . alive :
2016-05-26 09:52:01 +00:00
text + = s . status_dead_player . format ( name = player . tusername )
2016-04-23 15:07:09 +00:00
elif player . votingfor is not None :
2016-05-26 09:04:16 +00:00
text + = s . status_voting_player . format ( icon = " \U0001F610 " , name = player . tusername , votes = str ( player . votes ) , voting = player . votingfor . tusername )
2016-04-22 17:21:50 +00:00
else :
2016-05-26 09:04:16 +00:00
text + = s . status_idle_player . format ( icon = " \U0001F610 " , name = player . tusername , votes = str ( player . votes ) )
game . message ( bot , text )
else :
2016-05-26 13:25:54 +00:00
bot . sendMessage ( update . message . chat [ ' id ' ] , s . error_no_games_found , parse_mode = ParseMode . MARKDOWN )
2016-04-22 17:21:50 +00:00
def endjoin ( bot , update ) :
2016-05-25 09:52:53 +00:00
""" Termina la fase di join e inizia quella di votazione. """
2016-04-22 17:21:50 +00:00
game = findgamebyid ( update . message . chat [ ' id ' ] )
2016-05-26 09:04:16 +00:00
if game is not None and game . phase is ' Join ' :
2016-05-26 09:08:50 +00:00
if update . message . from_user [ ' id ' ] == game . adminid :
2016-05-26 11:42:50 +00:00
# Inizio fase di configurazione
game . phase = ' Config '
2016-05-26 09:08:50 +00:00
game . message ( bot , s . join_phase_ended )
2016-05-26 11:42:50 +00:00
game . message ( bot , s . config_list [ 0 ] )
2016-05-26 09:08:50 +00:00
else :
game . message ( bot , s . error_not_admin )
else :
2016-05-26 13:25:54 +00:00
bot . sendMessage ( update . message . chat [ ' id ' ] , s . error_no_games_found , parse_mode = ParseMode . MARKDOWN )
2016-05-25 11:57:15 +00:00
2016-05-26 11:42:50 +00:00
def config ( bot , update ) :
""" Configura il parametro richiesto. """
game = findgamebyid ( update . message . chat [ ' id ' ] )
if game is not None and game . phase is ' Config ' :
if update . message . from_user [ ' id ' ] == game . adminid :
cmd = update . message . text . split ( ' ' , 1 )
if len ( cmd ) > = 1 :
if game . configstep == 0 :
try :
game . totalmifiosi = int ( cmd [ 1 ] )
except ValueError :
game . message ( bot , s . error_invalid_config )
else :
game . configstep + = 1
game . message ( bot , s . config_list [ game . configstep ] )
elif game . configstep == 1 :
try :
game . totaldetectives = int ( cmd [ 1 ] )
except ValueError :
game . message ( bot , s . error_invalid_config )
else :
game . configstep + = 1
game . message ( bot , s . config_list [ game . configstep ] )
elif game . configstep == 2 :
try :
game . totalangels = int ( cmd [ 1 ] )
except ValueError :
game . message ( bot , s . error_invalid_config )
2016-05-26 13:12:49 +00:00
else :
game . configstep + = 1
game . message ( bot , s . config_list [ game . configstep ] )
elif game . configstep == 3 :
try :
game . votingmifia = bool ( cmd [ 1 ] )
except ValueError :
game . message ( bot , s . error_invalid_config )
2016-05-26 11:42:50 +00:00
else :
# Fine del config, inizio assegnazione ruoli
game . phase = ' Voting '
try :
game . assignroles ( bot )
except IndexError :
game . message ( bot , s . error_not_enough_players )
game . endgame ( )
else :
game . message ( bot , s . roles_assigned_successfully )
else :
game . message ( bot , s . config_list [ game . configstep ] )
2016-05-26 11:50:16 +00:00
else :
game . message ( bot , s . error_not_admin )
else :
game . message ( bot , s . error_no_games_found )
2016-04-22 17:21:50 +00:00
def vote ( bot , update ) :
2016-05-25 09:52:53 +00:00
""" Vota per uccidere una persona. """
2016-04-22 17:21:50 +00:00
game = findgamebyid ( update . message . chat [ ' id ' ] )
if game is not None and game . phase is ' Voting ' :
player = game . findplayerbyid ( update . message . from_user [ ' id ' ] )
2016-05-26 09:18:07 +00:00
if player is not None :
2016-05-26 09:08:50 +00:00
if player . alive :
target = game . findplayerbyusername ( update . message . text . split ( ' ' ) [ 1 ] )
if target is not None :
player . votingfor = target
game . message ( bot , s . vote . format ( voted = target . tusername ) )
else :
game . message ( bot , s . error_username )
else :
game . message ( bot , s . error_dead )
else :
game . message ( bot , s . error_not_in_game )
2016-04-22 17:21:50 +00:00
else :
2016-05-26 13:25:54 +00:00
bot . sendMessage ( update . message . chat [ ' id ' ] , s . error_no_games_found , parse_mode = ParseMode . MARKDOWN )
2016-04-21 21:04:53 +00:00
2016-04-21 20:14:35 +00:00
2016-04-22 19:14:14 +00:00
def endday ( bot , update ) :
2016-05-25 09:52:53 +00:00
""" Termina la giornata attuale. """
2016-04-22 19:14:14 +00:00
game = findgamebyid ( update . message . chat [ ' id ' ] )
if game is not None and game . phase is ' Voting ' and update . message . from_user [ ' id ' ] == game . adminid :
game . endday ( bot )
2016-04-23 15:07:09 +00:00
def power ( bot , update ) :
2016-05-25 09:52:53 +00:00
""" Attiva il potere del tuo ruolo. """
2016-04-23 15:07:09 +00:00
if update . message . chat [ ' type ' ] == ' private ' :
cmd = update . message . text . split ( ' ' , 2 )
2016-05-26 09:04:16 +00:00
game = findgamebyname ( cmd [ 1 ] )
# Se non lo trovi con il nome, prova con l'id
if game is None :
2016-05-26 09:08:50 +00:00
game = findgamebyid ( int ( cmd [ 1 ] ) )
2016-04-23 15:07:09 +00:00
if game is not None :
2016-05-26 10:12:14 +00:00
player = game . findplayerbyid ( int ( update . message . from_user [ ' id ' ] ) )
2016-05-26 09:04:16 +00:00
if player is not None :
2016-05-26 09:08:50 +00:00
if player . alive :
player . role . power ( bot , game , player , cmd [ 2 ] )
else :
player . message ( bot , s . error_dead )
else :
2016-05-26 13:25:54 +00:00
bot . sendMessage ( update . message . chat [ ' id ' ] , s . error_not_in_game , parse_mode = ParseMode . MARKDOWN )
2016-04-23 15:07:09 +00:00
else :
2016-05-26 13:25:54 +00:00
bot . sendMessage ( update . message . chat [ ' id ' ] , s . error_no_games_found , parse_mode = ParseMode . MARKDOWN )
2016-04-23 15:07:09 +00:00
else :
2016-05-26 13:25:54 +00:00
bot . sendMessage ( update . message . chat [ ' id ' ] , s . error_private_required , parse_mode = ParseMode . MARKDOWN )
2016-04-23 15:07:09 +00:00
2016-05-26 09:04:16 +00:00
def role ( bot , update ) :
2016-05-26 09:08:50 +00:00
""" Visualizza il tuo ruolo. """
game = findgamebyid ( update . message . chat [ ' id ' ] )
2016-05-26 09:04:16 +00:00
if game is not None and game . phase is ' Voting ' :
player = game . findplayerbyid ( update . message . from_user [ ' id ' ] )
if player is not None :
2016-05-26 09:08:50 +00:00
if player . alive :
2016-05-26 09:49:40 +00:00
player . message ( bot , s . display_role . format ( icon = player . role . icon , role = player . role . name ) )
2016-05-26 09:08:50 +00:00
game . message ( bot , s . check_private )
else :
game . message ( bot , s . error_dead )
2016-05-26 09:04:16 +00:00
else :
2016-05-26 13:25:54 +00:00
bot . sendMessage ( update . message . chat [ ' id ' ] , s . error_not_in_game , parse_mode = ParseMode . MARKDOWN )
2016-05-26 09:04:16 +00:00
else :
2016-05-26 13:25:54 +00:00
bot . sendMessage ( update . message . chat [ ' id ' ] , s . error_no_games_found , parse_mode = ParseMode . MARKDOWN )
2016-05-26 09:04:16 +00:00
2016-04-25 17:39:57 +00:00
2016-04-25 17:44:40 +00:00
def debuggameslist ( bot , update ) :
2016-05-25 09:52:53 +00:00
""" Visualizza l ' elenco delle partite in corso. """
2016-05-26 13:25:54 +00:00
bot . sendMessage ( update . message . from_user [ ' id ' ] , repr ( inprogress ) , parse_mode = ParseMode . MARKDOWN )
2016-05-26 09:04:16 +00:00
2016-05-26 09:49:40 +00:00
def kill ( bot , update ) :
2016-05-26 09:08:50 +00:00
""" Uccidi un giocatore in partita. """
game = findgamebyid ( update . message . chat [ ' id ' ] )
2016-05-26 09:04:16 +00:00
if game is not None and game . phase is ' Voting ' :
2016-05-26 09:08:50 +00:00
if update . message . from_user [ ' id ' ] == game . adminid :
target = game . findplayerbyusername ( update . message . text . split ( ' ' ) [ 1 ] )
if target is not None :
target . kill ( )
2016-05-26 12:55:02 +00:00
game . message ( bot , s . admin_killed . format ( name = target . tusername , icon = target . role . icon , role = target . role . name ) )
2016-05-26 09:08:50 +00:00
else :
2016-05-26 12:55:02 +00:00
game . message ( bot , s . error_username )
2016-05-26 09:08:50 +00:00
else :
2016-05-26 12:55:02 +00:00
game . message ( bot , s . error_not_admin )
2016-05-26 09:04:16 +00:00
else :
2016-05-26 13:25:54 +00:00
bot . sendMessage ( update . message . chat [ ' id ' ] , s . error_no_games_found , parse_mode = ParseMode . MARKDOWN )
2016-04-25 17:44:40 +00:00
2016-05-26 11:42:50 +00:00
2016-05-26 12:55:02 +00:00
def fakerole ( bot , update ) :
""" Manda un finto messaggio di ruolo. """
if update . message . chat [ ' type ' ] == ' private ' :
2016-05-26 13:25:54 +00:00
bot . sendMessage ( update . message . chat [ ' id ' ] , s . role_assigned . format ( icon = s . royal_icon , name = s . royal_name ) , parse_mode = ParseMode . MARKDOWN )
bot . sendMessage ( update . message . chat [ ' id ' ] , s . role_assigned . format ( icon = s . mifia_icon , name = s . mifia_name ) , parse_mode = ParseMode . MARKDOWN )
bot . sendMessage ( update . message . chat [ ' id ' ] , s . role_assigned . format ( icon = s . detective_icon , name = s . detective_name ) , parse_mode = ParseMode . MARKDOWN )
bot . sendMessage ( update . message . chat [ ' id ' ] , s . role_assigned . format ( icon = s . angel_icon , name = s . angel_name ) , parse_mode = ParseMode . MARKDOWN )
2016-05-26 12:55:02 +00:00
else :
2016-05-26 13:25:54 +00:00
bot . sendMessage ( update . message . chat [ ' id ' ] , s . error_private_required , parse_mode = ParseMode . MARKDOWN )
2016-05-26 12:55:02 +00:00
2016-04-25 16:21:38 +00:00
updater . dispatcher . addHandler ( CommandHandler ( ' ping ' , ping ) )
updater . dispatcher . addHandler ( CommandHandler ( ' newgame ' , newgame ) )
updater . dispatcher . addHandler ( CommandHandler ( ' join ' , join ) )
updater . dispatcher . addHandler ( CommandHandler ( ' endjoin ' , endjoin ) )
updater . dispatcher . addHandler ( CommandHandler ( ' vote ' , vote ) )
updater . dispatcher . addHandler ( CommandHandler ( ' endday ' , endday ) )
updater . dispatcher . addHandler ( CommandHandler ( ' power ' , power ) )
updater . dispatcher . addHandler ( CommandHandler ( ' status ' , status ) )
2016-05-26 09:40:59 +00:00
updater . dispatcher . addHandler ( CommandHandler ( ' role ' , role ) )
2016-05-26 09:04:16 +00:00
updater . dispatcher . addHandler ( CommandHandler ( ' debug ' , debug ) )
2016-04-25 17:44:40 +00:00
updater . dispatcher . addHandler ( CommandHandler ( ' debuggameslist ' , debuggameslist ) )
2016-05-26 09:49:40 +00:00
updater . dispatcher . addHandler ( CommandHandler ( ' kill ' , kill ) )
2016-05-26 11:50:16 +00:00
updater . dispatcher . addHandler ( CommandHandler ( ' config ' , config ) )
2016-04-21 20:14:35 +00:00
updater . start_polling ( )
2016-04-22 17:21:50 +00:00
updater . idle ( )