我正在python中编写一个自定义骰子滚动解析器(如果必须,可以使用snicker)。基本上,我想使用标准数学评估,但添加'd'运算符:
#xdy
sum = 0
for each in range(x):
sum += randInt(1, y)
return sum
因此,例如,1d6 + 2d6 + 2d6-72 + 4d100 =(5)+(1 + 1)+(6 + 2)-72+(5 + 39 + 38 + 59)= 84
我正在使用正则表达式来替换所有'和s,然后使用eval,但是我的正则表达式在处理任何一方的括号时都崩溃了。有没有比实现我自己的递归解析更快的方法呢?也许在eval中添加运算符?
编辑:我似乎给出了一个不好的例子,因为上面的例子适用于我当前的版本。我正在寻找的是一些评估方法,比如说,(5 +(6d6))d(7-2 *(1d4))。
通过“分崩离析”,我只是意味着我当前的正则表达式失败了。
我对自己的失败过于模糊,对此感到抱歉。这是我目前的代码:
def evalDice(roll_matchgroup):
roll_split = roll_matchgroup.group('roll').split('d')
print roll_split
roll_list = []
for die in range(int(roll_split[0])):
roll = random.randint(1,int(roll_split[1]))
roll_list.append(roll)
def EvalRoll(roll):
if not roll: return 0
rollPattern = re.compile('(?P<roll>\d*d\d+)')
roll_string = rollPattern.sub(evalDice, roll.lower())
为此,“1d6 + 4d100”工作正常,但“(1d6 + 4)d100”或甚至“1d6 + 4d(100)”失败。
答案 0 :(得分:6)
您可以将callback function与re.sub
一起使用。当您点击该链接时,请向下搜索以“如果repl是一个函数...”
import re
import random
def xdy(matchobj):
x,y=map(int,matchobj.groups())
s = 0
for each in range(x):
s += random.randint(1, y)
return str(s)
s='1d6+2d6+2d6-72+4d100'
t=re.sub('(\d+)d(\d+)',xdy,s)
print(t)
# 5+10+8-72+197
print(eval(t))
# 148
答案 1 :(得分:5)
Python不允许你编写全新的操作符,也不能用常规语言编写括号。你必须编写一个递归下降解析器。对于你的骰子滚动语言,这应该非常简单。
或者,您可以使用现有的Python运算符并使用Pythons解析工具将文本转换为AST。
答案 2 :(得分:2)
查看PyParsing库。特别是,examples页面的sample非常接近您想要的内容:
骰子滚动解析器和评估器,用于评估字符串,例如“4d20 + 5.5 + 4d6.takeHighest(3)”。
答案 3 :(得分:0)
这使用了eval,实际上非常糟糕,但是你去了
>>> x = '1d6+2d6+2d6-72+4d100'
>>> eval(re.sub(r'(\d+)d(\d+)',r'sum((random.randint(1,x) for x in \1 * [\2]))', x))
一些快速说明:
这会将4d6
替换为sum((random.randint(1,x) for x in 4 * [6]))
。
4 * [6]
会生成列表[6,6,6,6]
。
((random.randint(1,x) for x in [6,6,6,6]))
是生成器等同于列表理解;这个特殊的将返回1到6之间的四个随机数。
答案 4 :(得分:0)
在我的Supybot dice plugin中,我用
解析表达式r'(?P<sign>[+-])((?P<dice>\d*)d(?P<sides>\d+)|(?P<mod>\d+))'
然后得到每个骰子和总修饰符的总数,滚动它们并获得总结果(我想显示每个骰子的总数)。