You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

262 lines
9.8 KiB

PING_WAIT = 300 # Seconds
PING_MIN_WAIT = 30
MINIMUM_WAIT = 60
EXTRA_WAIT = 20
MAXIMUM_WAITED = 2 # limit for amount of !wait's
STATS_RATE_LIMIT = 15
VOTES_RATE_LIMIT = 15
ADMINS_RATE_LIMIT = 300
SHOTS_MULTIPLIER = .12 # ceil(shots_multiplier * len_players) = bullets given
MAX_PLAYERS = 30
DRUNK_SHOTS_MULTIPLIER = 3
NIGHT_TIME_LIMIT = 100
NIGHT_TIME_WARN = 20 # should be less than NIGHT_TIME_LIMIT
DAY_TIME_LIMIT_WARN = 100
DAY_TIME_LIMIT_CHANGE = 20 # seconds after DAY_TIME_LIMIT_WARN has passed
KILL_IDLE_TIME = 300
WARN_IDLE_TIME = 180
PART_GRACE_TIME = 7
QUIT_GRACE_TIME = 30
MAX_PRIVMSG_TARGETS = 1
LOG_FILENAME = "wolfbot.log"
BARE_LOG_FILENAME = "wolfbot_bare.log"
# HIT MISS SUICIDE
GUN_CHANCES = ( 5/7 , 1/7 , 1/7 )
DRUNK_GUN_CHANCES = ( 2/7 , 4/7 , 1/7 )
MANSLAUGHTER_CHANCE = 1/5 # ACCIDENTAL HEADSHOT (FATAL)
GUNNER_KILLS_WOLF_AT_NIGHT_CHANCE = 0
GUARDIAN_ANGEL_DIES_CHANCE = 1/2
rechercheur_REVEALED_CHANCE = 2/5
#################################################################################################################
# ROLE INDEX: PLAYERS SEER WOLF CURSED DRUNK HARLOT TRAITOR GUNNER CROW ANGEL rechercheur ##
#################################################################################################################
ROLES_GUIDE = { 4 : ( 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ), ##
6 : ( 1 , 1 , 1 , 0 , 1 , 0 , 0 , 0 , 0 , 0 ), ##
8 : ( 1 , 2 , 1 , 0 , 1 , 1 , 1 , 0 , 0 , 0 ), ##
10 : ( 1 , 2 , 1 , 0 , 1 , 1 , 1 , 0 , 1 , 0 ), ##
11 : ( 1 , 2 , 1 , 0 , 1 , 1 , 1 , 0 , 1 , 0 ), ##
15 : ( 1 , 3 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 0 ), ##
22 : ( 1 , 4 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 ), ##
29 : ( 1 , 5 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 ), ##
None : ( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 )} ##
#################################################################################################################
# Notes: ##
#################################################################################################################
GAME_MODES = {}
AWAY = [] # cloaks of people who are away.
SIMPLE_NOTIFY = [] # cloaks of people who !simple, who want everything /notice'd
ROLE_INDICES = {0 : "ziener",
1 : "wolf",
2 : "vervloekte burger",
3 : "dronken burger",
4 : "onschuldige meisje",
5 : "verrader",
6 : "kanonnier",
7 : "weerkraai",
8 : "bescherm engel",
9 : "rechercheur"}
INDEX_OF_ROLE = dict((v,k) for k,v in ROLE_INDICES.items())
NO_VICTIMS_MESSAGES = ("Het lichaam van een jonge huisdier is gevonden.",
"Een plas van bloed en wolfpoot afdrukken zijn gevonden.",
"Een pluk van wolvenhaar is gevonden.")
LYNCH_MESSAGES = ("De burgers hebben, na lang overleg, besloten om \u0002{0}\u0002 te elimineren. Hij/zij was een... \u0002{1}\u0002.",
"Onder veel lawaai hebben de woedende burgers \u0002{0}\u0002 geelimineerd. Hij/zij was een... \u0002{1}\u0002.",
"De menigte sleept een protesterende \u0002{0}\u0002 naar de galg. Hij/zij bezwijkt aan de wil van de groep, en wordt opgehangen. Hij/zij was een \u0002{1}\u0002.",
"Verslagen door zijn/haar lot, is \u0002{0}\u0002 naar de galg geleid. Na de dood bleek hij/zij een \u0002{1}\u0002 te zijn.")
import botconfig
RULES = (botconfig.CHANNEL + " Kanaal regels: 1) Wees aardig voor elkaar. 2) Deel geen spel infomatie "+
"na je dood. 3) Bots zijn niet toegestaan. 4) Speel niet met clones van jezelf.\n"+
"5) Stop niet met spelen, tenzij het niet anders kan. 6) Niet vloeken en hou het leuk "+
"voor iedereen. 7) Sla geen Prive berichten over van het spel tijdens het spel. "+
"8) Gebruik je gezonde verstand. 9) Wachten op timeouts is niet leuk.")
# Other settings:
START_WITH_DAY = False
WOLF_STEALS_GUN = False # at night, the wolf can steal steal the victim's bullets
OPT_IN_PING = False # instead of !away/!back, users can opt-in to be pinged
PING_IN = [] # cloaks of users who have opted in for ping
is_role = lambda plyr, rol: rol in ROLES and plyr in ROLES[rol]
def plural(role):
if role == "wolf": return "wolven"
elif role == "persoon": return "personen"
else: return role + "s"
def list_players():
pl = []
for x in ROLES.values():
pl.extend(x)
return pl
def list_players_and_roles():
plr = {}
for x in ROLES.keys():
for p in ROLES[x]:
plr[p] = x
return plr
get_role = lambda plyr: list_players_and_roles()[plyr]
def del_player(pname):
prole = get_role(pname)
ROLES[prole].remove(pname)
class InvalidModeException(Exception): pass
def game_mode(name):
def decor(c):
GAME_MODES[name] = c
return c
return decor
CHANGEABLE_ROLES = { "zieners" : INDEX_OF_ROLE["ziener"],
"wolven" : INDEX_OF_ROLE["wolf"],
"vervloekten" : INDEX_OF_ROLE["vervloekte burger"],
"dronkaarts" : INDEX_OF_ROLE["dronken burger"],
"onschuldige meisjes" : INDEX_OF_ROLE["onschuldige meisje"],
"verraders" : INDEX_OF_ROLE["verrader"],
"kanonniers" : INDEX_OF_ROLE["kanonnier"],
"weerkraaien" : INDEX_OF_ROLE["weerkraai"],
"engelen" : INDEX_OF_ROLE["bescherm engel"],
"rechercheurs" : INDEX_OF_ROLE["rechercheur"]}
# TODO: implement game modes
@game_mode("roles")
class ChangedRolesMode(object):
"""Example: !fgame roles=wolves:1,seers:0,angels:1"""
def __init__(self, arg):
self.ROLES_GUIDE = ROLES_GUIDE.copy()
lx = list(ROLES_GUIDE[None])
pairs = arg.split(",")
pl = list_players()
if not pairs:
raise InvalidModeException("Invalid syntax for mode roles.")
for pair in pairs:
change = pair.split(":")
if len(change) != 2:
raise InvalidModeException("Invalid syntax for mode roles.")
role, num = change
try:
num = int(num)
try:
lx[CHANGEABLE_ROLES[role.lower()]] = num
except KeyError:
raise InvalidModeException(("De rol \u0002{0}\u0002 "+
"is niet geldig.").format(role))
except ValueError:
raise InvalidModeException("A bad value was used in mode roles.")
for k in ROLES_GUIDE.keys():
self.ROLES_GUIDE[k] = tuple(lx)
# Persistence
# Load saved settings
import sqlite3
import os
conn = sqlite3.connect("data.sqlite3", check_same_thread = False)
with conn:
c = conn.cursor()
c.execute('CREATE TABLE IF NOT EXISTS away (nick TEXT)') # whoops, i mean cloak, not nick
c.execute('CREATE TABLE IF NOT EXISTS simple_role_notify (cloak TEXT)') # people who understand each role
c.execute('SELECT * FROM away')
for row in c:
AWAY.append(row[0])
c.execute('SELECT * FROM simple_role_notify')
for row in c:
SIMPLE_NOTIFY.append(row[0])
# populate the roles table
c.execute('DROP TABLE IF EXISTS roles')
c.execute('CREATE TABLE roles (id INTEGER PRIMARY KEY AUTOINCREMENT, role TEXT)')
for x in ["burger"]+list(ROLE_INDICES.values()):
c.execute("INSERT OR REPLACE INTO roles (role) VALUES (?)", (x,))
c.execute(('CREATE TABLE IF NOT EXISTS rolestats (player TEXT, role TEXT, '+
'teamwins SMALLINT, individualwins SMALLINT, totalgames SMALLINT, '+
'UNIQUE(player, role))'))
if OPT_IN_PING:
c.execute('CREATE TABLE IF NOT EXISTS ping (cloak text)')
c.execute('SELECT * FROM ping')
for row in c:
PING_IN.append(row[0])
def remove_away(clk):
with conn:
c.execute('DELETE from away where nick=?', (clk,))
def add_away(clk):
with conn:
c.execute('INSERT into away VALUES (?)', (clk,))
def remove_simple_rolemsg(clk):
with conn:
c.execute('DELETE from simple_role_notify where cloak=?', (clk,))
def add_simple_rolemsg(clk):
with conn:
c.execute('INSERT into simple_role_notify VALUES (?)', (clk,))
def remove_ping(clk):
with conn:
c.execute('DELETE from ping where cloak=?', (clk,))
def add_ping(clk):
with conn:
c.execute('INSERT into ping VALUES (?)', (clk,))
def update_role_stats(acc, role, won, iwon):
with conn:
wins, iwins, totalgames = 0, 0, 0
c.execute(("SELECT teamwins, individualwins, totalgames FROM rolestats "+
"WHERE player=? AND role=?"), (acc, role))
row = c.fetchone()
if row:
wins, iwins, total = row
else:
wins, iwins, total = 0,0,0
if won:
wins += 1
if iwon:
iwins += 1
total += 1
c.execute("INSERT OR REPLACE INTO rolestats VALUES (?,?,?,?,?)",
(acc, role, wins, iwins, total))