Add alternate win condition if only lovers are alive
The message could use a better phrasing, but anyway this works.
This commit is contained in:
parent
26e7acc8f8
commit
04180bc036
@ -16,6 +16,39 @@ def game_mode(name, minp, maxp, likelihood = 0):
|
||||
|
||||
reset_roles = lambda i: OrderedDict([(role, (0,) * len(i)) for role in var.ROLE_GUIDE])
|
||||
|
||||
def get_lovers():
|
||||
lovers = []
|
||||
pl = var.list_players()
|
||||
for lover in var.LOVERS:
|
||||
done = None
|
||||
for i, lset in enumerate(lovers):
|
||||
if lover in pl and lover in lset:
|
||||
if done is not None: # plot twist! two clusters turn out to be linked!
|
||||
done.update(lset)
|
||||
for lvr in var.LOVERS[lover]:
|
||||
if lvr in pl:
|
||||
done.add(lvr)
|
||||
|
||||
lset.clear()
|
||||
continue
|
||||
|
||||
for lvr in var.LOVERS[lover]:
|
||||
if lvr in pl:
|
||||
lset.add(lvr)
|
||||
done = lset
|
||||
|
||||
if done is None and lover in pl:
|
||||
lovers.append(set())
|
||||
lovers[-1].add(lover)
|
||||
for lvr in var.LOVERS[lover]:
|
||||
if lvr in pl:
|
||||
lovers[-1].add(lvr)
|
||||
|
||||
while set() in lovers:
|
||||
lovers.remove(set())
|
||||
|
||||
return lovers
|
||||
|
||||
class GameMode:
|
||||
def __init__(self, arg=""):
|
||||
if not arg:
|
||||
@ -64,6 +97,23 @@ class GameMode:
|
||||
def teardown(self):
|
||||
pass
|
||||
|
||||
# Here so any game mode can use it
|
||||
def lovers_chk_win(self, evt, var, lpl, lwolves, lrealwolves):
|
||||
winner = evt.data["winner"]
|
||||
if winner is not None and winner.startswith("@"):
|
||||
return # fool won, lovers can't win even if they would
|
||||
all_lovers = get_lovers()
|
||||
if len(all_lovers) != 1:
|
||||
return # we need exactly one cluster alive for this to trigger
|
||||
|
||||
lovers = all_lovers[0]
|
||||
|
||||
if len(lovers) == lpl:
|
||||
evt.data["winner"] = "lovers"
|
||||
evt.data["message"] = "Game over! All of the remaining villagers are in love with each other! All of them win."
|
||||
evt.data["players"] = ["{0} ({1})".format(x, var.get_role(x)) for x in lovers]
|
||||
evt.data["winners"] = list(lovers)
|
||||
|
||||
@game_mode("roles", minp = 4, maxp = 35)
|
||||
class ChangedRolesMode(GameMode):
|
||||
"""Example: !fgame roles=wolf:1,seer:0,guardian angel:1"""
|
||||
@ -398,6 +448,12 @@ class MatchmakerMode(GameMode):
|
||||
"mad scientist" : [i >= 18 for i in self.ROLE_INDEX],
|
||||
})
|
||||
|
||||
def startup(self):
|
||||
events.add_listener("chk_win", self.lovers_chk_win, 1)
|
||||
|
||||
def teardown(self):
|
||||
events.remove_listener("chk_win", self.lovers_chk_win, 1)
|
||||
|
||||
@game_mode("random", minp = 8, maxp = 24, likelihood = 0)
|
||||
class RandomMode(GameMode):
|
||||
"""Completely random and hidden roles."""
|
||||
@ -430,9 +486,11 @@ class RandomMode(GameMode):
|
||||
|
||||
def startup(self):
|
||||
events.add_listener("role_attribution", self.role_attribution, 1)
|
||||
events.add_listener("chk_win", self.lovers_chk_win, 1)
|
||||
|
||||
def teardown(self):
|
||||
events.remove_listener("role_attribution", self.role_attribution, 1)
|
||||
events.remove_listener("chk_win", self.lovers_chk_win, 1)
|
||||
|
||||
def role_attribution(self, evt, cli, chk_win_conditions, var, villagers):
|
||||
lpl = len(villagers) - 1
|
||||
|
@ -2275,7 +2275,7 @@ def chk_traitor(cli):
|
||||
"frightened as they hear a loud howl. The wolves are "+
|
||||
"not gone!\u0002")
|
||||
|
||||
def stop_game(cli, winner = "", abort = False):
|
||||
def stop_game(cli, winner = "", abort = False, winners = None):
|
||||
chan = botconfig.CHANNEL
|
||||
if abort:
|
||||
cli.msg(chan, "The role attribution failed 3 times. Game was canceled.")
|
||||
@ -2369,6 +2369,7 @@ def stop_game(cli, winner = "", abort = False):
|
||||
# Only update if someone actually won, "" indicates everyone died or abnormal game stop
|
||||
if winner != "":
|
||||
plrl = {}
|
||||
if winners is None:
|
||||
winners = []
|
||||
for role,ppl in var.ORIGINAL_ROLES.items():
|
||||
if role in var.TEMPLATE_RESTRICTIONS.keys():
|
||||
@ -2426,7 +2427,7 @@ def stop_game(cli, winner = "", abort = False):
|
||||
iwon = False
|
||||
elif rol == "fool" and "@" + splr == winner:
|
||||
iwon = True
|
||||
elif splr in var.LOVERS and splr in survived and len([x for x in var.LOVERS[splr] if x in survived]) > 0:
|
||||
elif winner != "lovers" and splr in var.LOVERS and splr in survived and len([x for x in var.LOVERS[splr] if x in survived]) > 0:
|
||||
for lvr in var.LOVERS[splr]:
|
||||
if lvr not in survived:
|
||||
# cannot win with dead lover (if splr in survived and lvr is not, that means lvr idled out)
|
||||
@ -2622,7 +2623,7 @@ def chk_win_conditions(lpl, lwolves, lcubs, lrealwolves, lmonsters, ltraitors, l
|
||||
ltraitors = len(var.ROLES.get("traitor", ()))
|
||||
return chk_win_conditions(lpl, lwolves, lcubs, lrealwolves, lmonsters, ltraitors, lpipers, cli, end_game)
|
||||
|
||||
event = Event("chk_win", {"winner": winner, "message": message})
|
||||
event = Event("chk_win", {"winner": winner, "message": message, "players": [], "winners": None})
|
||||
event.dispatch(var, lpl, lwolves, lrealwolves)
|
||||
winner = event.data["winner"]
|
||||
message = event.data["message"]
|
||||
@ -2631,7 +2632,7 @@ def chk_win_conditions(lpl, lwolves, lcubs, lrealwolves, lmonsters, ltraitors, l
|
||||
return False
|
||||
|
||||
if end_game:
|
||||
players = []
|
||||
players = event.data["players"]
|
||||
if winner == "monsters":
|
||||
for plr in var.ROLES["monster"]:
|
||||
players.append("{0} ({1})".format(plr, var.get_role(plr)))
|
||||
@ -2648,7 +2649,7 @@ def chk_win_conditions(lpl, lwolves, lcubs, lrealwolves, lmonsters, ltraitors, l
|
||||
debuglog("WIN:", winner)
|
||||
debuglog("PLAYERS:", ", ".join(players))
|
||||
cli.msg(chan, message)
|
||||
stop_game(cli, winner)
|
||||
stop_game(cli, winner, winners=event.data["winners"])
|
||||
return True
|
||||
|
||||
def del_player(cli, nick, forced_death = False, devoice = True, end_game = True, death_triggers = True, killer_role = "", deadlist = [], original = "", cmode = [], ismain = True):
|
||||
|
Loading…
Reference in New Issue
Block a user