diff --git a/messages/en.json b/messages/en.json index 370783a..7c7f456 100644 --- a/messages/en.json +++ b/messages/en.json @@ -225,7 +225,9 @@ "wild_child_success": "You have picked {0} to be your idol for this game.", "wild_child_as_wolf": "\u0002{0}\u0002's idol has died, and is now a \u0002wolf\u0002!", "wild_child_random_idol": "Upon waking up, the first person you see is \u0002{0}\u0002, and they become your idol.", - "idol_died": "Your idol has died, and you are now a \u0002wolf\u0002!", + "wild_child_revealroles_picked": "picked {0} as idol", + "wild_child_revealroles_no_idol": "no idol picked yet", + "wild_child_idol_died": "Your idol has died, and you are now a \u0002wolf\u0002!", "wild_child_idol": "Your idol is \u0002{0}\u0002.", "idle_death": "\u0002{0}\u0002 didn't get out of bed for a very long time and has been found dead. The survivors bury the \u0002{1}\u0002's body.", "idle_death_no_reveal": "\u0002{0}\u0002 didn't get out of bed for a very long time and has been found dead.", diff --git a/src/roles/wildchild.py b/src/roles/wildchild.py index 580f8c3..bbee209 100644 --- a/src/roles/wildchild.py +++ b/src/roles/wildchild.py @@ -1,83 +1,67 @@ -import random import re +import random +import itertools +import math +from collections import defaultdict -import src.settings as var from src.utilities import * -from src import users, channels, debuglog, errlog, plog -from src.functions import get_players, get_all_players, get_main_role -from src.decorators import cmd, event_listener +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.containers import UserList, UserSet, UserDict, DefaultUserDict from src.messages import messages from src.events import Event -WILD_CHILDREN = set() -IDOLS = {} +WILD_CHILDREN = UserSet() +IDOLS = UserDict() -@cmd("choose", chan=False, pm=True, playing=True, phases=("night",), roles=("wild child",)) -def choose_idol(cli, nick, chan, rest): +@command("choose", chan=False, pm=True, playing=True, phases=("night",), roles=("wild child",)) +def choose_idol(var, wrapper, message): """Pick your idol, if they die, you'll become a wolf!""" if not var.FIRST_NIGHT: return - if nick in IDOLS: - pm(cli, nick, messages["wild_child_already_picked"]) + if wrapper.source in IDOLS: + wrapper.pm(messages["wild_child_already_picked"]) return - victim = get_victim(cli, nick, re.split(" +", rest)[0], False) - if not victim: + idol = get_target(var, wrapper, re.split(" +", message)[0]) + if not idol: return - if nick == victim: - pm(cli, nick, messages["no_target_self"]) - return - - IDOLS[nick] = victim - pm(cli, nick, messages["wild_child_success"].format(victim)) - - debuglog("{0} (wild child) IDOLIZE: {1} ({2})".format(nick, victim, get_role(victim))) + IDOLS[wrapper.source] = idol + wrapper.send(messages["wild_child_success"].format(idol)) + debuglog("{0} (wild child) IDOLIZE: {1} ({2})".format(wrapper.source, idol, get_main_role(idol))) @event_listener("see") def on_see(evt, var, seer, target): - if target.nick in WILD_CHILDREN: + if target in WILD_CHILDREN: evt.data["role"] = "wild child" -@event_listener("rename_player") -def on_rename(evt, var, prefix, nick): - if prefix in WILD_CHILDREN: - WILD_CHILDREN.remove(prefix) - WILD_CHILDREN.add(nick) - - for (wildchild, idol) in IDOLS.items(): - if wildchild == prefix: - IDOLS[nick] = IDOLS[wildchild] - del IDOLS[wildchild] - elif idol == prefix: - IDOLS[wildchild] = nick - @event_listener("exchange_roles") def on_exchange(evt, var, actor, target, actor_role, target_role): - if actor_role == "wolf" and actor.nick in WILD_CHILDREN and target.nick not in WILD_CHILDREN: - WILD_CHILDREN.discard(actor.nick) - WILD_CHILDREN.add(target.nick) + if actor_role == "wolf" and actor in WILD_CHILDREN and target not in WILD_CHILDREN: + WILD_CHILDREN.discard(actor) + WILD_CHILDREN.add(target) elif actor_role == "wild child": if target_role == "wild child": - IDOLS[actor.nick], IDOLS[target.nick] = IDOLS[target.nick], IDOLS[actor.nick] - evt.data["actor_messages"].append(messages["wild_child_idol"].format(IDOLS[actor.nick])) - evt.data["target_messages"].append(messages["wild_child_idol"].format(IDOLS[target.nick])) + IDOLS[actor], IDOLS[target] = IDOLS[target], IDOLS[actor] + evt.data["actor_messages"].append(messages["wild_child_idol"].format(IDOLS[actor])) + evt.data["target_messages"].append(messages["wild_child_idol"].format(IDOLS[target])) else: - IDOLS[target.nick] = IDOLS.pop(actor.nick) - evt.data["target_messages"].append(messages["wild_child_idol"].format(IDOLS[target.nick])) - if target_role == "wolf" and target.nick in WILD_CHILDREN and actor.nick not in WILD_CHILDREN: - WILD_CHILDREN.discard(target.nick) - WILD_CHILDREN.add(actor.nick) + IDOLS[target] = IDOLS.pop(actor) + evt.data["target_messages"].append(messages["wild_child_idol"].format(IDOLS[target])) + if target_role == "wolf" and target in WILD_CHILDREN and actor not in WILD_CHILDREN: + WILD_CHILDREN.discard(target) + WILD_CHILDREN.add(actor) elif target_role == "wild child" and actor_role != "wild child": # if they're both wild children, already swapped idols above - IDOLS[actor.nick] = IDOLS.pop(target.nick) - evt.data["actor_messages"].append(messages["wild_child_idol"].format(IDOLS[actor.nick])) + IDOLS[actor] = IDOLS.pop(target) + evt.data["actor_messages"].append(messages["wild_child_idol"].format(IDOLS[actor])) @event_listener("myrole") def on_myrole(evt, var, user): - if user.nick in IDOLS: - evt.data["messages"].append(messages["wild_child_idol"].format(IDOLS[user.nick])) + if user in IDOLS: + evt.data["messages"].append(messages["wild_child_idol"].format(IDOLS[user])) @event_listener("del_player") def on_del_player(evt, var, user, mainrole, allroles, death_triggers): @@ -85,41 +69,42 @@ def on_del_player(evt, var, user, mainrole, allroles, death_triggers): return for child in get_all_players(("wild child",)): - if child.nick not in IDOLS or child in evt.params.deadlist or users._get(IDOLS[child.nick]) not in evt.params.deadlist: # FIXME + if child in evt.params.deadlist or IDOLS.get(child) not in evt.params.deadlist: continue - # change their main role to wolf, even if wild child was a template - child.send(messages["idol_died"]) - WILD_CHILDREN.add(child.nick) + # Change their main role to wolf + child.send(messages["wild_child_idol_died"]) + WILD_CHILDREN.add(child) change_role(child, get_main_role(child), "wolf") var.ROLES["wild child"].discard(child) - wcroles = var.WOLFCHAT_ROLES if var.RESTRICT_WOLFCHAT & var.RW_REM_NON_WOLVES: if var.RESTRICT_WOLFCHAT & var.RW_TRAITOR_NON_WOLF: wcroles = var.WOLF_ROLES else: wcroles = var.WOLF_ROLES | {"traitor"} - wolves = get_players(wcroles) - wolves.remove(child) - if wolves: - for wolf in wolves: - wolf.queue_message(messages["wild_child_as_wolf"].format(child)) - wolf.send_messages() - if var.PHASE == "day": - random.shuffle(wolves) - new = [] - for i, wolf in enumerate(wolves): - wolfroles = get_main_role(wolf) - cursed = "" - if wolf in get_all_players(("cursed villager",)): - cursed = "cursed " - new.append("\u0002{0}\u0002 ({1}{2})".format(wolf, cursed, wolfroles)) - if new: - child.send(messages["wolves_list"].format(", ".join(new))) - else: - child.send(messages["no_other_wolves"]) + wolves = get_players(wcroles) + wolves.remove(child) + if wolves: + for wolf in wolves: + wolf.queue_message(messages["wild_child_as_wolf"].format(child)) + wolf.send_messages() + + # Send wolf list + if var.PHASE == "day": + random.shuffle(wolves) + names = [] + cursed_list = get_all_players(("cursed villager",)) + for i, wolf in enumerate(wolves): + role = get_main_role(wolf) + cursed = "cursed " if wolf in cursed_list else "" + names.append("\u0002{0}\u0002 ({1}{2})".format(wolf, cursed, role)) + + if names: + child.send(messages["wolves_list"].format(", ".join(names))) + else: + child.send(messages["no_other_wolves"]) @event_listener("chk_nightdone") def on_chk_nightdone(evt, var): @@ -131,33 +116,35 @@ def on_chk_nightdone(evt, var): def on_transition_day_begin(evt, var): if (not var.START_WITH_DAY or not var.FIRST_DAY) and var.FIRST_NIGHT: for child in get_all_players(("wild child",)): - if child.nick not in IDOLS: - pl = get_players() - pl.remove(child) - if pl: - target = random.choice(pl) - IDOLS[child.nick] = target.nick - child.send(messages["wild_child_random_idol"].format(target)) + if child not in IDOLS: + players = get_players() + players.remove(child) + if players: + idol = random.choice(players) + IDOLS[child] = idol + child.send(messages["wild_child_random_idol"].format(idol)) + idol_role = get_main_role(idol) + debuglog("{0} (wild child) IDOLIZE RANDOM: {1} ({2})".format(child, idol, idol_role)) @event_listener("transition_night_end", priority=2) def on_transition_night_end(evt, var): for child in get_all_players(("wild child",)): - to_send = "child_notify" if child.prefers_simple(): - to_send = "child_simple" - child.send(messages[to_send]) + child.send(messages["child_simple"]) + else: + child.send(messages["child_notify"]) @event_listener("revealroles_role") def on_revealroles_role(evt, var, user, role): if role == "wild child": - if user.nick in IDOLS: - evt.data["special_case"].append("picked {0} as idol".format(IDOLS[user.nick])) + if user in IDOLS: + evt.data["special_case"].append(messages["wild_child_revealroles_picked"].format(IDOLS[user])) else: - evt.data["special_case"].append("no idol picked yet") + evt.data["special_case"].append(messages["wild_child_revealroles_no_idol"]) @event_listener("get_reveal_role") def on_get_reveal_role(evt, var, user): - if user.nick in WILD_CHILDREN: + if user in WILD_CHILDREN: evt.data["role"] = "wild child" @event_listener("reset")