Skip to content

Commit

Permalink
Feature/auto cmd (#118)
Browse files Browse the repository at this point in the history
* Add !auto command

* Fix !auto command

* Remove !auto vote and !auto kill

---------

Co-authored-by: Stanley <[email protected]>
Co-authored-by: Stanley00 <[email protected]>
  • Loading branch information
3 people authored May 8, 2023
1 parent a4fa363 commit 083a637
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 7 deletions.
12 changes: 8 additions & 4 deletions commands/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ async def parse_command(client, game, message):
elif cmd == "stopgame":
await player.do_stop(game, message, force=False)

elif cmd in ("vote", "kill", "guard", "seer", "reborn", "curse", "zombie", "ship"):
elif cmd in ("vote", "kill", "guard", "seer", "reborn", "curse", "zombie", "ship", "auto"):
if not game.is_started():
# prevent user uses command before game starts
await message.reply(text_templates.generate_text("game_not_started_text"))
Expand All @@ -81,14 +81,18 @@ async def parse_command(client, game, message):
is_valid_channel = \
(cmd == "vote" and message.channel.name == config.GAMEPLAY_CHANNEL) or\
(cmd == "kill" and message.channel.name == config.WEREWOLF_CHANNEL) or\
(cmd in ("guard", "seer", "reborn", "curse", "zombie", "ship")
(cmd in ("guard", "seer", "reborn", "curse", "zombie", "ship", "auto")
and message.channel.name.strip().startswith("personal"))

if is_valid_channel:
author = message.author
required_param_number = len(commands.get_command_required_params(cmd))

if len(message.raw_mentions) == required_param_number:
if cmd == "auto":
msg = await game.do_player_action(cmd, author.id, *parameters)
await message.reply(msg)

elif len(message.raw_mentions) == required_param_number:
msg = await game.do_player_action(cmd, author.id, *message.raw_mentions)
await message.reply(msg)

Expand Down Expand Up @@ -145,7 +149,7 @@ async def parse_command(client, game, message):
await admin.send_embed_to_channel(message.channel.guild, embed_data, message.channel.name)

elif cmd == "timer":
""" Usage:
""" Usage:
`!timer 60 30 20` -> dayphase=60s, nightphase=30s, alertperiod=20s
"""
if len(parameters) < 3:
Expand Down
78 changes: 75 additions & 3 deletions game/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import time
import json
from enum import Enum
from collections import Counter
from collections import Counter, defaultdict
from functools import reduce
import traceback
import asyncio
Expand Down Expand Up @@ -70,6 +70,7 @@ def reset_game_state(self):
self.winner = None
self.runtime_roles = None
self.prev_playtime = self.is_in_play_time()
self.auto_hook = defaultdict(list)

def get_winner(self):
if self.winner is None:
Expand Down Expand Up @@ -138,7 +139,7 @@ def dict_to_list(config, number=0):
interface, id_, names_dict[id_]) for id_, role_name in zip(ids, game_role)}
print("Player list:", r)
return r

def get_role_list(self):
role_list = dict(Counter(v.__class__.__name__ for v in self.players.values()))
if not self.modes.get("hidden_role"):
Expand All @@ -158,7 +159,7 @@ async def start(self, init_players=None):
else:
self.players = init_players



await self.create_channel()
await self.interface.send_text_to_channel(text_template.generate_modes(dict(zip(self.modes, map(lambda x: "True", self.modes.values())))), config.GAMEPLAY_CHANNEL)
Expand Down Expand Up @@ -508,6 +509,7 @@ async def do_new_daytime_phase(self):
await self.stop()

async def do_end_daytime_phase(self):
await self.do_run_auto_hook()
print("do_end_daytime_phase")
if self.voter_dict:
lynched, votes = Game.get_top_voted(list(self.voter_dict.values()))
Expand Down Expand Up @@ -563,6 +565,7 @@ async def do_new_nighttime_phase(self):
await asyncio.gather(*[player.on_action(embed_data) for player in self.get_alive_players() if isinstance(player, roles.Witch) and player.get_power()])

async def do_end_nighttime_phase(self):
await self.do_run_auto_hook()
print("do_end_nighttime_phase")
kills = None
if self.wolf_kill_dict:
Expand Down Expand Up @@ -728,6 +731,10 @@ async def do_player_action(self, cmd, author_id, *targets_id):
if cmd != "zombie": # Zombie can use skill after death
return text_templates.generate_text("invalid_alive_author_text")

if cmd == "auto":
return await self.register_auto(author, *targets_id)


targets = []
for target_id in targets_id:
target = self.players.get(target_id)
Expand Down Expand Up @@ -915,6 +922,71 @@ async def ship(self, author, target1, target2):

return text_templates.generate_text("cupid_after_ship_text", target1=f"<@{target1_id}>", target2=f"<@{target2_id}>")

async def register_auto(self, author, subcmd):
def check(pred):
def wrapper(f):
async def execute(*a, **kw):
if pred():
print("Check success")
return await f(*a, **kw)
else:
print("Check failed")
return execute
return wrapper

def is_night():
return self.game_phase == GamePhase.NIGHT

def is_day():
return self.game_phase == GamePhase.DAY

def has_role(role):
return lambda: isinstance(author, role)

def is_alive():
return author.is_alive()

@check(is_alive)
@check(is_night)
@check(has_role(roles.Guard))
async def auto_guard():
target = random.choice(self.get_alive_players())
msg = await self.guard(author, target)
await self.interface.send_text_to_channel("[Auto] " + msg, author.channel_name)

@check(is_alive)
@check(is_night)
@check(has_role(roles.Seer))
async def auto_seer():
target = random.choice(self.get_alive_players())
if author.player_id in self.cupid_dict:
while target.player_id in self.cupid_dict:
target = random.choice(self.get_alive_players())
msg = await self.seer(author, target)
await self.interface.send_text_to_channel("[Auto] " + msg, author.channel_name)

if subcmd == "off":
self.auto_hook[author] = []
return "Clear auto successed"
elif subcmd == "seer":
if has_role(roles.Seer)():
self.auto_hook[author].append(auto_seer)
return "Register auto seer success"
else:
return "You are not a seer"
elif subcmd == "guard":
if has_role(roles.Guard)():
self.auto_hook[author].append(auto_guard)
return "Register auto guard success"
else:
return "You are not a guard"
else:
return "Unknown auto command, please try again"

async def do_run_auto_hook(self):
print("do_run_auto_hook")
await asyncio.gather(*[f() for k in self.auto_hook for f in self.auto_hook[k]])

async def test_game(self):
print("====== Begin test game =====")
await self.test_case_real_players() # Will tag real people on Discord
Expand Down

0 comments on commit 083a637

Please sign in to comment.