import random import itertools from core.builtins import Bot from core.component import module from simpleeval import simple_eval def calc(expression): try: return simple_eval(expression) except: return None def is_valid(expression): operators = ['+', '-', '*', '/', '(', ')'] numbers = [str(i) for i in range(1, 14)] valid_chars = numbers + operators valid_chars_set = set(valid_chars) i = 0 num_numbers = 0 while i < len(expression): char = expression[i] if char.isdigit(): while i < len(expression) and expression[i].isdigit(): i += 1 num_numbers += 1 elif char in valid_chars_set: i += 1 if i < len(expression) and expression[i] == ' ': i += 1 if i < len(expression) and expression[i] == ' ': return False continue elif char == ' ': i += 1 if i < len(expression) and expression[i] == ' ': return False else: return False if num_numbers > 9: return False return True def has_solution(numbers): permutations = list(itertools.permutations(numbers)) operators = ['+', '-', '*', '/'] expressions = list(itertools.product(operators, repeat=3)) for perm in permutations: for expr in expressions: exp = '((( {} {} {} ) {} {} ) {} {} )'.format(perm[0], expr[0], perm[1], expr[1], perm[2], expr[2], perm[3]) if calc(exp) == 24: return True exp = '(( {} {} {} ) {} ( {} {} {} ))'.format(perm[0], expr[0], perm[1], expr[1], perm[2], expr[2], perm[3]) if calc(exp) == 24: return True exp = '( {} {} ( {} {} ( {} {} {} )))'.format(perm[0], expr[0], perm[1], expr[1], perm[2], expr[2], perm[3]) if calc(exp) == 24: return True return False def contains_all_numbers(expression, numbers): used_numbers = [str(num) for num in numbers] i = 0 while i < len(expression): char = expression[i] if char.isdigit(): number = char while i + 1 < len(expression) and expression[i + 1].isdigit(): number += expression[i + 1] i += 1 if number in used_numbers: used_numbers.remove(number) i += 1 return len(used_numbers) == 0 tf = module('twenty_four', alias=['twentyfour', '24'], desc='{twenty_four.help.desc}', developers=['DoroWolf']) play_state = {} @tf.command('{{twenty_four.help}}') async def _(msg: Bot.MessageSession): if msg.target.targetId in play_state and play_state[msg.target.targetId]['24']['active']: await msg.finish(msg.locale.t('twenty_four.message.running')) play_state.update({msg.target.targetId: {'24': {'active': True}}}) numbers = [random.randint(1, 13) for _ in range(4)] has_solution_flag = has_solution(numbers) answer = await msg.waitNextMessage(msg.locale.t('twenty_four.message', numbers=numbers)) expression = answer.asDisplay(text_only=True) if play_state[msg.target.targetId]['24']['active']: if expression.lower() in ['无解', '無解', 'none', 'n/a']: if has_solution_flag: await answer.sendMessage(msg.locale.t('twenty_four.message.incorrect.have_solution')) else: await answer.sendMessage(msg.locale.t('twenty_four.message.correct')) elif is_valid(expression): result = calc(expression) if result == 24 and contains_all_numbers(expression, numbers): await answer.sendMessage(msg.locale.t('twenty_four.message.correct')) else: await answer.sendMessage(msg.locale.t('twenty_four.message.incorrect')) else: await answer.sendMessage(msg.locale.t('twenty_four.message.incorrect.error')) play_state[msg.target.targetId]['24']['active'] = False @tf.command('stop {{twenty_four.stop.help}}') async def s(msg: Bot.MessageSession): state = play_state.get(msg.target.targetId, {}).get('24', False) if state: if state['active']: play_state[msg.target.targetId]['24']['active'] = False await msg.sendMessage(msg.locale.t('twenty_four.stop.message')) else: await msg.sendMessage(msg.locale.t('twenty_four.stop.message.none')) else: await msg.sendMessage(msg.locale.t('twenty_four.stop.message.none'))