Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New moon events #113

Merged
merged 6 commits into from
Mar 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 59 additions & 15 deletions game/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
from functools import reduce
import traceback
import asyncio
import tzlocal

from game.modes.new_moon import NewMoonMode


class GamePhase(Enum):
Expand All @@ -33,12 +34,13 @@ def __init__(self, guild, interface):
config.GAMEPLAY_CHANNEL,
config.LEADERBOARD_CHANNEL,
config.WEREWOLF_CHANNEL,
# Personal channel will goes into role class
# Personal channel will go into role class
] # List of channels in game
self.next_flag = asyncio.Event()
self.timer_phase = [config.DAYTIME, config.NIGHTTIME, config.ALERT_PERIOD]
self.timer_enable = True
self.modes = {}
self.new_moon_mode = NewMoonMode()
self.play_time_start = datetime.time(0, 0, 0) # in UTC
self.play_time_end = datetime.time(0, 0, 0) # in UTC
self.play_zone = "UTC+7"
Expand Down Expand Up @@ -70,6 +72,7 @@ def reset_game_state(self):
self.winner = None
self.runtime_roles = None
self.prev_playtime = self.is_in_play_time()
self.new_moon_mode.set_random_event()
self.auto_hook = defaultdict(list)

def get_winner(self):
Expand Down Expand Up @@ -105,6 +108,12 @@ def set_mode(self, mode_id, status):
mode_str = modes_list[int(mode_id) - 1]
utils.common.update_json_file("json/game_config.json", mode_str, "True" if status == 'on' else "False")

if mode_str == "new_moon":
if status == "on":
self.new_moon_mode.turn_on()
else:
self.new_moon_mode.turn_off()

return f"Set mode `{mode_str}` to `{status.upper()}`\nWarning: This setting is permanent!"

def read_modes(self):
Expand All @@ -114,6 +123,11 @@ def read_modes(self):
if v == "True":
self.modes[k] = True

if self.modes.get("new_moon", False):
self.new_moon_mode.turn_on()
else:
self.new_moon_mode.turn_off()

#Backward compatible
if "allow_guard_self_protection" not in self.modes and "prevent_guard_self_protection" in self.modes:
self.modes["allow_guard_self_protection"] = not self.modes["prevent_guard_self_protection"]
Expand Down Expand Up @@ -525,6 +539,14 @@ async def do_new_daytime_phase(self):
embed_data = text_template.generate_player_list_embed(self.get_alive_players(), alive_status=True)
await self.interface.send_embed_to_channel(embed_data, config.GAMEPLAY_CHANNEL)

if self.modes.get("new_moon", False):
self.new_moon_mode.set_random_event()
await self.interface.send_action_text_to_channel(
f"new_moon_{'special' if self.new_moon_mode.has_special_event() else 'no'}_event_text",
config.GAMEPLAY_CHANNEL,
event_name=self.new_moon_mode.get_current_event_name()
)

# Unmute all alive players in config.GAMEPLAY_CHANNEL
await asyncio.gather(
*[self.interface.add_user_to_channel(_id, config.GAMEPLAY_CHANNEL, is_read=True, is_send=True)
Expand All @@ -537,26 +559,41 @@ async def do_new_daytime_phase(self):
async def do_end_daytime_phase(self):
await self.do_run_auto_hook()
print("do_end_daytime_phase")
lynched, votes = None, 0
if self.voter_dict:
lynched, votes = Game.get_top_voted(list(self.voter_dict.values()))
print("lynched list:", self.voter_dict)
self.voter_dict = {}
if lynched:
await self.players[lynched].get_killed()

if self.modes.get("new_moon", False):
if self.new_moon_mode.current_event == "heads_or_tails":
coin_toss_value = self.new_moon_mode.do_coin_toss()
print("coin toss value =", coin_toss_value)
if coin_toss_value != 0:
coin_value_str = text_templates.get_word_in_language("coin_head")
lynched, votes = None, 0
else:
coin_value_str = text_templates.get_word_in_language("coin_tail")

await self.interface.send_action_text_to_channel(
"execution_player_text", config.GAMEPLAY_CHANNEL,
voted_user=f"<@{lynched}>", highest_vote_number=votes
"new_moon_heads_or_tails_result_text", config.GAMEPLAY_CHANNEL,
coin_value_str=coin_value_str
)

cupid_couple = self.cupid_dict.get(lynched)
if cupid_couple is not None:
await self.players[cupid_couple].get_killed(True)
await self.interface.send_action_text_to_channel(
"couple_died_on_day_text", config.GAMEPLAY_CHANNEL,
died_player=f"<@{lynched}>", follow_player=f"<@{cupid_couple}>"
)
else:
await self.interface.send_action_text_to_channel("execution_none_text", config.GAMEPLAY_CHANNEL)
if lynched:
await self.players[lynched].get_killed()
await self.interface.send_action_text_to_channel(
"execution_player_text", config.GAMEPLAY_CHANNEL,
voted_user=f"<@{lynched}>", highest_vote_number=votes
)

cupid_couple = self.cupid_dict.get(lynched)
if cupid_couple is not None:
await self.players[cupid_couple].get_killed(True)
await self.interface.send_action_text_to_channel(
"couple_died_on_day_text", config.GAMEPLAY_CHANNEL,
died_player=f"<@{lynched}>", follow_player=f"<@{cupid_couple}>"
)
else:
await self.interface.send_action_text_to_channel("execution_none_text", config.GAMEPLAY_CHANNEL)

Expand Down Expand Up @@ -749,6 +786,13 @@ async def do_process_with_play_time(self):
timer_remaining_text=text_template.generate_timer_remaining_text(self.timecounter)
)

async def do_new_moon_event_action(self):
if not self.modes.get("new_moon", False):
return None

# TODO
return None

async def do_player_action(self, cmd, author_id, *targets_id):
assert self.players is not None
# print(self.players)
Expand Down
9 changes: 9 additions & 0 deletions game/modes/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import random
from typing import List

from config import BOT_PREFIX, TEXT_LANGUAGE, GAMEPLAY_CHANNEL
import utils

mode_info_dict = utils.common.read_json_file("json/mode_info.json")


39 changes: 39 additions & 0 deletions game/modes/new_moon.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import random
from typing import List

from config import BOT_PREFIX, TEXT_LANGUAGE, GAMEPLAY_CHANNEL
import utils

new_moon_event_dict = utils.common.read_json_file("json/new_moon_events_info.json")


class NewMoonMode:
NO_EVENT = "no_event"
ALL_EVENTS = new_moon_event_dict

def __init__(self, is_on=False):
self.is_on = is_on
self.current_event = NewMoonMode.NO_EVENT

def turn_on(self):
self.is_on = True
self.current_event = self.set_random_event()

def turn_off(self):
self.is_on = False
self.current_event = NewMoonMode.NO_EVENT

def set_random_event(self):
if self.is_on:
self.current_event = random.choices(*zip(*[(event_key, event["rate"]) for event_key, event in new_moon_event_dict.items()]))[0]
else:
self.current_event = NewMoonMode.NO_EVENT

def has_special_event(self):
return self.current_event != NewMoonMode.NO_EVENT

def get_current_event_name(self):
return NewMoonMode.ALL_EVENTS[self.current_event]["title"][TEXT_LANGUAGE]

def do_coin_toss(self):
return random.randint(0, 1)
3 changes: 2 additions & 1 deletion json/game_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
"seer_can_kill_fox": "True",
"allow_guard_self_protection": "True",
"witch_can_kill": "True",
"couple_random": "False"
"couple_random": "False",
"new_moon": "True"
}
44 changes: 44 additions & 0 deletions json/mode_info.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"hidden_role": {
"title": {
"vi": "Ẩn danh sách các nhân vật đầu game",
"en": "Hide the list of role on start"
}
},
"seer_can_kill_fox": {
"title": {
"vi": "Tiên tri có thể giết Cáo",
"en": "Seer can kill Fox"
}
},
"prevent_guard_self_protection": {
"title": {
"vi": "Không cho phép Bảo vệ bản thân",
"en": "Do not allow Guard self-defense"
}
},
neihousaigaai marked this conversation as resolved.
Show resolved Hide resolved
"allow_guard_self_protection": {
"title": {
"vi": "Cho phép Bảo vệ bản thân",
"en": "Allow Guard self-defense"
}
},
"witch_can_kill": {
"title": {
"vi": "Phù thủy (Witch) có thể giết người",
"en": "Witch can kill people"
}
},
"couple_random": {
"title": {
"vi": "Ghép cặp ngẫu nhiên",
"en": "Random pairing"
}
},
"new_moon": {
"title": {
"vi": "Sự kiện New moon",
"en": "New moon event"
}
}
}
Loading