134 lines
4.6 KiB
Python
134 lines
4.6 KiB
Python
import random
|
|
import itertools
|
|
|
|
from core.builtins import Bot
|
|
from core.component import module
|
|
from simpleeval import simple_eval
|
|
|
|
no_solution = ['无解', '無解', 'none', 'n/a']
|
|
|
|
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]['active']:
|
|
await msg.finish(msg.locale.t('twenty_four.message.running'))
|
|
play_state.update({msg.target.targetId: {'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]['active']:
|
|
if expression.lower() in no_solution:
|
|
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]['active'] = False
|
|
|
|
|
|
|
|
@tf.command('stop {{twenty_four.stop.help}}')
|
|
async def s(msg: Bot.MessageSession):
|
|
state = play_state.get(msg.target.targetId, False)
|
|
if state:
|
|
if state['active']:
|
|
play_state[msg.target.targetId]['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'))
|