import re import random import itertools import traceback from typing import List, Tuple, Optional from nonebot import on_command from nonebot.rule import to_me from nonebot.typing import T_State from nonebot.plugin import PluginMetadata from nonebot.params import ArgPlainText from nonebot.adapters.onebot.v11 import ( Bot, MessageEvent, GroupMessageEvent, ) from nonebot.log import logger from .life import Life from .talent import Talent __plugin_meta__ = PluginMetadata( name="人生重开", description="人生重开模拟器", usage="#人生重开", extra={ "unique_name": "remake", "example": "#人生重开", "author": "meetwq ", "version": "0.2.7", }, ) remake = on_command( "#人生重开", aliases={"liferestart", "人生重开", "人生重来"}, block=True, priority=12, ) @remake.handle() async def _(state: T_State): life_ = Life() life_.load() talents = life_.rand_talents(10) state["life"] = life_ state["talents"] = talents msg = "请发送编号选择4个天赋,如“0 1 2 3”,或发送“随机”随机选择" des = "\n".join([f"{i}.{t}" for i, t in enumerate(talents)]) await remake.send(f"{msg}\n\n{des}") @remake.got("nums") async def _(state: T_State, reply: str = ArgPlainText("nums")): def conflict_talents(talents: List[Talent]) -> Optional[Tuple[Talent, Talent]]: for (t1, t2) in itertools.combinations(talents, 2): if t1.exclusive_with(t2): return t1, t2 return None life_: Life = state["life"] talents: List[Talent] = state["talents"] match = re.fullmatch(r"\s*(\d)\s*(\d)\s*(\d)\s*(\d)\s*", reply) if match: nums = list(match.groups()) nums = [int(n) for n in nums] nums.sort() if nums[-1] >= 10: await remake.reject("请发送正确的编号") talents_selected = [talents[n] for n in nums] ts = conflict_talents(talents_selected) if ts: await remake.reject(f"你选择的天赋“{ts[0].name}”和“{ts[1].name}”不能同时拥有,请重新选择") elif reply == "随机": while True: nums = random.sample(range(10), 4) nums.sort() talents_selected = [talents[n] for n in nums] if not conflict_talents(talents_selected): break elif re.fullmatch(r"[\d\s]+", reply): await remake.reject("请发送正确的编号,如“0 1 2 3”") else: await remake.finish("人生重开已取消") life_.set_talents(talents_selected) state["talents_selected"] = talents_selected msg = ( "请发送4个数字分配“颜值、智力、体质、家境”4个属性,如“10 10 10 10”,或发送“随机”随机选择;" f"可用属性点为{life_.total_property() * 2},每个属性不能超过40" ) await remake.send(msg) @remake.got("prop") async def _( bot: Bot, event: MessageEvent, state: T_State, reply: str = ArgPlainText("prop"), ): life_: Life = state["life"] talents: List[Talent] = state["talents_selected"] total_prop = life_.total_property() * 2 match = re.fullmatch(r"\s*(\d{1,2})\s+(\d{1,2})\s+(\d{1,2})\s+(\d{1,2})\s*", reply) if match: nums = list(match.groups()) nums = [int(n) for n in nums] if sum(nums) != total_prop: await remake.reject(f"属性之和需为{total_prop},请重新发送") elif max(nums) > 40: await remake.reject("每个属性不能超过40,请重新发送") elif reply == "随机": half_prop1 = int(total_prop / 2) half_prop2 = total_prop - half_prop1 num1 = random.randint(0, half_prop1) num2 = random.randint(0, half_prop2) nums = [num1, num2, half_prop1 - num1, half_prop2 - num2] random.shuffle(nums) elif re.fullmatch(r"[\d\s]+", reply): await remake.reject("请发送正确的数字,如“10 10 10 10”") else: await remake.finish("人生重开已取消") prop = {"CHR": nums[0], "INT": nums[1], "STR": nums[2], "MNY": nums[3]} life_.apply_property(prop) await remake.send("你的人生正在重开...") msgs = [ "已选择以下天赋:\n" + "\n".join([str(t) for t in talents]), "已设置如下属性:\n" + f"颜值{nums[0]} 智力{nums[1]} 体质{nums[2]} 家境{nums[3]}", ] try: life_msgs = [] for s in life_.run(): life_msgs.append("\n".join(s)) n = 5 life_msgs = [ "\n\n".join(life_msgs[i : i + n]) for i in range(0, len(life_msgs), n) ] msgs.extend(life_msgs) msgs.append(life_.gen_summary()) await send_forward_msg(bot, event, "人生重开模拟器", bot.self_id, msgs) except: logger.warning(traceback.format_exc()) await remake.finish("你的人生重开失败(") async def send_forward_msg( bot: Bot, event: MessageEvent, name: str, uin: str, msgs: List[str], ): def to_json(msg): return {"type": "node", "data": {"name": name, "uin": uin, "content": msg}} messages = [to_json(msg) for msg in msgs] if isinstance(event, GroupMessageEvent): await bot.call_api( "send_group_forward_msg", group_id=event.group_id, messages=messages ) else: await bot.call_api( "send_private_forward_msg", user_id=event.user_id, messages=messages )