Mudkip balance fix and bugfix

Fix balance in mudkip, it was skewed too much towards village winning.

Also, if day ended in mudkip and nobody was being voted, it would error.
Let's make that not error.
This commit is contained in:
skizzerz 2018-04-04 17:06:03 -05:00
parent 8dc1cf4556
commit c121c0f08f
5 changed files with 153 additions and 6 deletions

View File

@ -366,10 +366,12 @@
"sorcerer_success": "After casting your ritual, you determine that \u0002{0}\u0002 is a{1} \u0002{2}\u0002!",
"sorcerer_fail": "After casting your ritual, you determine that \u0002{0}\u0002 does not have paranormal senses.",
"sorcerer_success_wolfchat": "\u0002{0}\u0002 is observing \u0002{1}\u0002.",
"already_investigated": "You may only investigate one person per round.",
"no_investigate_self": "Investigating yourself would be a waste.",
"already_investigated": "You may only investigate once per day.",
"no_investigate_self": "You may not investigate yourself.",
"investigate_success": "The results of your investigation have returned. \u0002{0}\u0002 is a... \u0002{1}\u0002!",
"investigator_reveal": "Someone accidentally drops a paper. The paper reveals that \u0002{0}\u0002 is the detective!",
"detective_reveal": "Someone accidentally drops a paper. The paper reveals that \u0002{0}\u0002 is the detective!",
"investigator_results_same": "Your investigation has revealed that \u0002{0}\u0002 and \u0002{1}\u0002 are friends.",
"investigator_results_different": "Your investigation has revealed that \u0002{0}\u0002 and \u0002{1}\u0002 do not trust each other.",
"harlot_already_visited": "You are already spending the night with \u0002{0}\u0002.",
"harlot_success": "You are spending the night with \u0002{0}\u0002. Have a good time!",
"harlot_not_self": "You may not visit yourself. Use \"pass\" to choose to not visit anyone tonight.",
@ -475,6 +477,9 @@
"detective_chance": " Each time you use your ability, you risk a {0}% chance of having your identity revealed to the wolves.",
"detective_notify": "You are a \u0002detective\u0002. It is your job to determine all the wolves and traitors. During the day you can see the true identity of all players, even traitors, by using \"id <nick>\" in PM.{0}",
"detective_simple": "You are a \u0002detective\u0002.",
"investigator_notify": "You are an \u0002investigator\u0002. During the day, you can see if two people are on the same side by using \"id <nick1> and <nick2>\" in PM.",
"investigator_simple": "You are an \u0002investigator\u0002.",
"investigator_help": "Investigate two different people by using \"id <nick1> and <nick2>\" in PM.",
"drunk_notification": "You have been drinking too much! You are the \u0002village drunk\u0002.",
"drunk_simple": "You are the \u0002village drunk\u0002.",
"mystic_notify": "You are the \u0002mystic\u0002. Each night you divine the number of evil villagers (including wolves) that are still alive.",

View File

@ -1290,7 +1290,7 @@ class MudkipMode(GameMode):
self.ROLE_INDEX = ( 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 )
self.ROLE_GUIDE = reset_roles(self.ROLE_INDEX)
self.ROLE_GUIDE.update({# village roles
"detective" : ( 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ),
"investigator" : ( 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ),
"guardian angel" : ( 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ),
"shaman" : ( 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ),
"vengeful ghost" : ( 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 ),
@ -1339,7 +1339,7 @@ class MudkipMode(GameMode):
avail = len(evt.params.voters)
voted = sum(map(len, evt.data["votelist"].values()))
if avail != voted and not evt.params.timeout:
if (avail != voted and not evt.params.timeout) or voted == 0:
return
majority = avail // 2 + 1

View File

@ -55,7 +55,7 @@ def investigate(cli, nick, chan, rest):
else:
wcroles = var.WOLF_ROLES | {"traitor"}
mass_privmsg(cli, list_players(wcroles), messages["investigator_reveal"].format(nick))
mass_privmsg(cli, list_players(wcroles), messages["detective_reveal"].format(nick))
debuglog("{0} ({1}) PAPER DROP".format(nick, get_role(nick)))
@event_listener("rename_player")

141
src/roles/investigator.py Normal file
View File

@ -0,0 +1,141 @@
import re
import random
import itertools
import math
from collections import defaultdict
import botconfig
import src.settings as var
from src.utilities import *
from src import channels, users, debuglog, errlog, plog
from src.functions import get_players, get_all_players, get_main_role, get_reveal_role, get_target
from src.decorators import command, event_listener
from src.messages import messages
from src.events import Event
INVESTIGATED = set()
@command("id", chan=False, pm=True, playing=True, silenced=True, phases=("day",), roles=("investigator",))
def investigate(var, wrapper, message):
"""Investigate two players to determine their relationship to each other."""
if wrapper.source in INVESTIGATED:
wrapper.pm(messages["already_investigated"])
return
pieces = re.split(" +", message)
if len(pieces) == 1:
wrapper.pm(messages["investigator_help"])
return
target1 = pieces[0]
target2 = pieces[1]
if target2.lower() == "and" and len(pieces) > 2:
target2 = pieces[2]
target1 = get_target(var, wrapper, target1, not_self_message="no_investigate_self")
target2 = get_target(var, wrapper, target2, not_self_message="no_investigate_self")
if not target1 or not target2:
return
elif target1 is target2:
wrapper.pm(messages["investigator_help"])
return
evt = Event("targeted_command", {"target": target1, "misdirection": True, "exchange": True})
evt.dispatch(var, "identify", wrapper.source, target1, frozenset({"info", "immediate"}))
if evt.prevent_default:
return
target1 = evt.data["target"]
evt = Event("targeted_command", {"target": target2, "misdirection": True, "exchange": True})
evt.dispatch(var, "identify", wrapper.source, target2, frozenset({"info", "immediate"}))
if evt.prevent_default:
return
target2 = evt.data["target"]
t1role = get_main_role(target1)
t2role = get_main_role(target2)
# FIXME: split into amnesiac via investigate event once amnesiac is split
if t1role == "amnesiac":
t1role = var.AMNESIAC_ROLES[target1.nick]
if t2role == "amnesiac":
t2role = var.AMNESIAC_ROLES[target2.nick]
evt = Event("investigate", {"role": t1role})
evt.dispatch(wrapper.client, var, wrapper.source.nick, target1.nick) # FIXME
t1role = evt.data["role"]
evt = Event("investigate", {"role": t2role})
evt.dispatch(wrapper.client, var, wrapper.source.nick, target2.nick) # FIXME
t2role = evt.data["role"]
# FIXME: make a standardized way of getting team affiliation, and make
# augur and investigator both use it (and make it events-aware so other
# teams can be added more easily)
if t1role in var.WOLFTEAM_ROLES:
t1role = "red"
elif t1role in var.TRUE_NEUTRAL_ROLES:
t1role = "grey"
else:
t1role = "blue"
if t2role in var.WOLFTEAM_ROLES:
t2role = "red"
elif t2role in var.TRUE_NEUTRAL_ROLES:
t2role = "grey"
else:
t2role = "blue"
same = t1role == t2role
# FIXME: split into matchmaker once that is split and make this an event
if target2.nick in var.LOVERS.get(target1.nick, set()):
same = True
if same:
wrapper.pm(messages["investigator_results_same"].format(target1, target2))
else:
wrapper.pm(messages["investigator_results_different"].format(target1, target2))
INVESTIGATED.add(wrapper.source)
debuglog("{0} (investigator) ID: {1} ({2}) and {3} ({4}) as {5}".format(
wrapper.source, target1, get_main_role(target1), target2, get_main_role(target2),
"same" if same else "different"))
@event_listener("swap_player")
def on_swap(evt, var, old_user, user):
if old_user in INVESTIGATED:
INVESTIGATED.discard(old_user)
INVESTIGATED.add(user)
@event_listener("del_player")
def on_del_player(evt, var, user, mainrole, allroles, death_triggers):
INVESTIGATED.discard(user)
@event_listener("get_special")
def on_get_special(evt, var):
evt.data["special"].update(get_players(("investigator",)))
@event_listener("exchange_roles")
def on_exchange(evt, var, actor, target, actor_role, target_role):
if actor_role == "investigator" and target_role != "investigator":
INVESTIGATED.discard(actor)
elif target_role == "investigator" and actor_role != "investigator":
INVESTIGATED.discard(targe)
@event_listener("transition_night_end", priority=2)
def on_transition_night_end(evt, var):
ps = get_players()
for inv in var.ROLES["investigator"]:
pl = ps[:]
random.shuffle(pl)
pl.remove(inv)
to_send = "investigator_notify"
if inv.prefers_simple():
to_send = "investigator_simple"
inv.send(messages[to_send], "Players: " + ", ".join(p.nick for p in pl), sep="\n")
@event_listener("transition_night_begin")
def on_transition_night_begin(evt, cli, var):
INVESTIGATED.clear()
@event_listener("reset")
def on_reset(evt, var):
INVESTIGATED.clear()
# vim: set sw=4 expandtab:

View File

@ -262,6 +262,7 @@ ROLE_GUIDE = OrderedDict([ # This is order-sensitive - many parts of the code re
("vigilante" , ( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 )),
("augur" , ( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 )),
("detective" , ( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 )),
("investigator" , ( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 )),
("prophet" , ( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 )),
("guardian angel" , ( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 )),
("bodyguard" , ( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 )),