Remove diceply.py
This commit is contained in:
		
							parent
							
								
									4f56e40ca7
								
							
						
					
					
						commit
						c2280aaf1e
					
				
							
								
								
									
										218
									
								
								modules/Dice.py
									
									
									
									
									
								
							
							
						
						
									
										218
									
								
								modules/Dice.py
									
									
									
									
									
								
							| @ -22,20 +22,234 @@ from extlib import irclib | |||||||
| 
 | 
 | ||||||
| from Module import Module | from Module import Module | ||||||
| 
 | 
 | ||||||
| import diceply | import ply.lex as lex | ||||||
| import ply.yacc as yacc | import ply.yacc as yacc | ||||||
| 
 | 
 | ||||||
| # Rolls dice, for RPGs mostly | # Rolls dice, for RPGs mostly | ||||||
| 
 | 
 | ||||||
| class Dice(Module): | class Dice(Module): | ||||||
| 
 | 
 | ||||||
|  |     tokens = ['NUMBER', 'TEXT'] | ||||||
|  |     literals = ['#', '/', '+', '-', 'd', ';'] | ||||||
|  | 
 | ||||||
|  |     def build(self): | ||||||
|  |         lex.lex(module=self) | ||||||
|  |         yacc.yacc(module=self) | ||||||
|  | 
 | ||||||
|  |     t_TEXT = r'\s+[^;]+' | ||||||
|  | 
 | ||||||
|  |     def t_NUMBER(self, t): | ||||||
|  |         r'\d+' | ||||||
|  |         t.value = int(t.value) | ||||||
|  |         return t | ||||||
|  | 
 | ||||||
|  |     def t_error(self, t): | ||||||
|  |         t.lexer.skip(1) | ||||||
|  | 
 | ||||||
|  |     precedence = ( | ||||||
|  |         ('left', ';'), | ||||||
|  |         ('left', '+', '-'), | ||||||
|  |         ('right', 'd'), | ||||||
|  |         ('left', '#'), | ||||||
|  |         ('left', '/') | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|  |     output = "" | ||||||
|  | 
 | ||||||
|  |     # Takes the parsed dice string for a single roll (eg 3/4d20) and performs | ||||||
|  |     # the actual roll. Returns a string representing the result | ||||||
|  |     def roll_dice(self, keep, dice, size): | ||||||
|  |         a = range(dice) | ||||||
|  |         for i in range(dice): | ||||||
|  |             a[i] = random.randint(1, size) | ||||||
|  |         if keep != dice: | ||||||
|  |             b = sorted(a, reverse=True) | ||||||
|  |             b = b[0:keep] | ||||||
|  |         else: | ||||||
|  |             b = a | ||||||
|  |         total = sum(b) | ||||||
|  |         outstr = "["; | ||||||
|  |         if len(b) != len(a): | ||||||
|  |             # Bold is \002 | ||||||
|  |             outstr += ",".join(str(i) for i in b) + "," | ||||||
|  |             temp = sorted(a, reverse=True) | ||||||
|  |             temp = temp[keep:] | ||||||
|  |             bstr = ",".join(str(i) for i in temp) | ||||||
|  |             outstr += bstr | ||||||
|  |         else: | ||||||
|  |             outstr += ",".join(str(i) for i in a) | ||||||
|  |         outstr += "]"	 | ||||||
|  |          | ||||||
|  |         return (total, outstr) | ||||||
|  | 
 | ||||||
|  |     # Processes rolls coming from the parser. This generates the inputs | ||||||
|  |     # for the roll_dice() command, and returns the full string representing | ||||||
|  |     # the whole current dice string (the part up to a semicolon or end of line) | ||||||
|  |     def process_roll(self, trials, mods, comment): | ||||||
|  |         output = "" | ||||||
|  |         mode = 1 | ||||||
|  |         repeat = 1 | ||||||
|  |         if trials != None: | ||||||
|  |             repeat = trials | ||||||
|  |         for i in range(repeat): | ||||||
|  |             total = 0 | ||||||
|  |             curr_str = "" | ||||||
|  |             if i > 0: | ||||||
|  |                 output += ", " | ||||||
|  |             for m in mods: | ||||||
|  |                 keep = 0 | ||||||
|  |                 dice = 1 | ||||||
|  |                 res = 0 | ||||||
|  |                 # if m is a tuple, then it is a die roll | ||||||
|  |                 # m[0] = (keep, num dice) | ||||||
|  |                 # m[1] = num faces on the die | ||||||
|  |                 if type(m) == tuple: | ||||||
|  |                     if m[0] != None: | ||||||
|  |                         if m[0][0] != None: | ||||||
|  |                             keep = m[0][0] | ||||||
|  |                         dice = m[0][1] | ||||||
|  |                     size = m[1] | ||||||
|  |                     if keep > dice or keep == 0: | ||||||
|  |                         keep = dice | ||||||
|  |                     res = self.roll_dice(keep, dice, size) | ||||||
|  |                     curr_str += "%d%s" % (res[0], res[1]) | ||||||
|  |                     res = res[0] | ||||||
|  |                 elif m == "+": | ||||||
|  |                     mode = 1 | ||||||
|  |                     curr_str += "+" | ||||||
|  |                 elif m == "-": | ||||||
|  |                     mode = -1 | ||||||
|  |                     curr_str += "-" | ||||||
|  |                 else: | ||||||
|  |                     res = m | ||||||
|  |                     curr_str += str(m) | ||||||
|  |                 total += mode * res | ||||||
|  |             output += "%d (%s)" % (total, curr_str) | ||||||
|  |         if comment != None: | ||||||
|  |             output = "%s: %s" % (comment.strip(), output) | ||||||
|  |         return output | ||||||
|  | 
 | ||||||
|  |     # General idea I had when creating this grammar: A roll string is a chain | ||||||
|  |     # of modifiers, which may be repeated for a certain number of trials. It can | ||||||
|  |     # have a comment that describes the roll | ||||||
|  |     # Multiple roll strings can be chained with semicolon | ||||||
|  |     def p_roll_r(self, p): | ||||||
|  |         'roll : roll ";" roll' | ||||||
|  |         global output | ||||||
|  |         p[0] = p[1] + "; " + p[3] | ||||||
|  |         output = p[0] | ||||||
|  | 
 | ||||||
|  |     # The basic roll string | ||||||
|  |     def p_roll(self, p): | ||||||
|  |         'roll : trial modifier comment' | ||||||
|  |         global output | ||||||
|  |         mods = [] | ||||||
|  |         if type(p[2]) == list: | ||||||
|  |             mods = p[2] | ||||||
|  |         else: | ||||||
|  |             mods = [p[2]] | ||||||
|  |         p[0] = self.process_roll(p[1], mods, p[3]) | ||||||
|  |         output = p[0] | ||||||
|  | 
 | ||||||
|  |     # Trial is optional so have a rule without it | ||||||
|  |     def p_roll_no_trials(self, p): | ||||||
|  |         'roll : modifier comment' | ||||||
|  |         global output | ||||||
|  |         mods = [] | ||||||
|  |         if type(p[1]) == list: | ||||||
|  |             mods = p[1] | ||||||
|  |         else: | ||||||
|  |             mods = [p[1]] | ||||||
|  |         p[0] = self.process_roll(None, mods, p[2])  | ||||||
|  |         output = p[0] | ||||||
|  | 
 | ||||||
|  |     def p_comment(self, p): | ||||||
|  |         '''comment : TEXT | ||||||
|  |                    |''' | ||||||
|  |         if len(p) == 2: | ||||||
|  |             p[0] = p[1] | ||||||
|  |         else: | ||||||
|  |             p[0] = None | ||||||
|  | 
 | ||||||
|  |     def p_modifier(self, p): | ||||||
|  |         '''modifier : modifier "+" modifier | ||||||
|  |                     | modifier "-" modifier''' | ||||||
|  |         # Use append to prevent nested lists (makes dealing with this easier) | ||||||
|  |         if type(p[1]) == list: | ||||||
|  |             p[1].append(p[2]) | ||||||
|  |             p[1].append(p[3]) | ||||||
|  |             p[0] = p[1] | ||||||
|  |         elif type(p[3]) == list: | ||||||
|  |             p[3].insert(0, p[2]) | ||||||
|  |             p[3].insert(0, p[1]) | ||||||
|  |             p[0] = p[3] | ||||||
|  |         else: | ||||||
|  |             p[0] = [p[1], p[2], p[3]] | ||||||
|  | 
 | ||||||
|  |     # Return the left side before the "d", and the number of faces | ||||||
|  |     def p_die(self, p): | ||||||
|  |         'modifier : left NUMBER' | ||||||
|  |         p[0] = (p[1], p[2]) | ||||||
|  | 
 | ||||||
|  |     def p_die_num(self, p): | ||||||
|  |         'modifier : NUMBER' | ||||||
|  |         p[0] = p[1] | ||||||
|  | 
 | ||||||
|  |     # left is the number of dice we are rolling, and how many we are keeping | ||||||
|  |     def p_left(self, p): | ||||||
|  |         'left : keep dice' | ||||||
|  |         if p[1] == None: | ||||||
|  |             p[0] = [None, p[2]] | ||||||
|  |         else: | ||||||
|  |             p[0] = [p[1], p[2]] | ||||||
|  | 
 | ||||||
|  |     def p_left_all(self, p): | ||||||
|  |         'left : dice' | ||||||
|  |         p[0] = [None, p[1]] | ||||||
|  | 
 | ||||||
|  |     def p_left_e(self, p): | ||||||
|  |         'left :' | ||||||
|  |         p[0] = None | ||||||
|  | 
 | ||||||
|  |     def p_total(self, p): | ||||||
|  |         'trial : NUMBER "#"' | ||||||
|  |         if len(p) > 1: | ||||||
|  |             p[0] = p[1] | ||||||
|  |         else: | ||||||
|  |             p[0] = None | ||||||
|  | 
 | ||||||
|  |     def p_keep(self, p): | ||||||
|  |         'keep : NUMBER "/"' | ||||||
|  |         if p[1] != None: | ||||||
|  |             p[0] = p[1] | ||||||
|  |         else: | ||||||
|  |             p[0] = None | ||||||
|  | 
 | ||||||
|  |     def p_dice(self, p):  | ||||||
|  |         'dice : NUMBER "d"' | ||||||
|  |         p[0] = p[1] | ||||||
|  | 
 | ||||||
|  |     def p_dice_one(self, p): | ||||||
|  |         'dice : "d"' | ||||||
|  |         p[0] = 1 | ||||||
|  | 
 | ||||||
|  |     # Provide the user with something (albeit not much) when the roll can't be parsed | ||||||
|  |     def p_error(self, p): | ||||||
|  |         global output | ||||||
|  |         output = "Unable to parse roll" | ||||||
|  | 
 | ||||||
|  |     def get_result(self): | ||||||
|  |         global output | ||||||
|  |         return output | ||||||
|  | 
 | ||||||
|     def do(self, connection, event, nick, userhost, replypath, what, admin_unlocked): |     def do(self, connection, event, nick, userhost, replypath, what, admin_unlocked): | ||||||
|         whats = what.split(' ') |         whats = what.split(' ') | ||||||
| 
 | 
 | ||||||
|         if whats[0] == 'roll': |         if whats[0] == 'roll': | ||||||
|             dicestr = ' '.join(whats[1:]) |             dicestr = ' '.join(whats[1:]) | ||||||
|  |             self.build() | ||||||
|             yacc.parse(dicestr) |             yacc.parse(dicestr) | ||||||
|             reply = diceply.get_result() |             reply = self.get_result() | ||||||
|             if reply is not "": |             if reply is not "": | ||||||
|                 return self.reply(connection, replypath, nick + ': ' + reply) |                 return self.reply(connection, replypath, nick + ': ' + reply) | ||||||
|         if whats[0] == 'ctech': |         if whats[0] == 'ctech': | ||||||
|  | |||||||
| @ -1,246 +0,0 @@ | |||||||
| # diceply.py |  | ||||||
| # Dice string grammar using PLY |  | ||||||
| # After initial run, parser.out should have the full grammar and the states |  | ||||||
| # and any shift/reduce or reduce/reduce conflicts. |  | ||||||
| # |  | ||||||
| # The current state of the grammar has some shift/reduce conflicts, because |  | ||||||
| # I don't know LR parsers well enough to prevent them. Also, currently spaces |  | ||||||
| # in the roll string aren't working if we want comments (for now) |  | ||||||
| # |  | ||||||
| # This script can be run standalone if you enable the tests at the bottom |  | ||||||
| 
 |  | ||||||
| import sys |  | ||||||
| import random |  | ||||||
| 
 |  | ||||||
| tokens = ['NUMBER', 'TEXT'] |  | ||||||
|      |  | ||||||
| literals = ['#', '/', '+', '-', 'd', ';'] |  | ||||||
| 
 |  | ||||||
| t_TEXT = r'\s+[^;]+' |  | ||||||
| 
 |  | ||||||
| def t_NUMBER(t): |  | ||||||
|     r'\d+' |  | ||||||
|     t.value = int(t.value) |  | ||||||
|     return t |  | ||||||
| 
 |  | ||||||
| def t_error(t): |  | ||||||
|     t.lexer.skip(1) |  | ||||||
|      |  | ||||||
| import ply.lex as lex |  | ||||||
| lex.lex() |  | ||||||
| 
 |  | ||||||
| precedence = ( |  | ||||||
|     ('left', ';'), |  | ||||||
|     ('left', '+', '-'), |  | ||||||
|     ('right', 'd'), |  | ||||||
|     ('left', '#'), |  | ||||||
|     ('left', '/') |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| output = "" |  | ||||||
| 
 |  | ||||||
| # Takes the parsed dice string for a single roll (eg 3/4d20) and performs |  | ||||||
| # the actual roll. Returns a string representing the result |  | ||||||
| def roll_dice(keep, dice, size): |  | ||||||
|     a = range(dice) |  | ||||||
|     for i in range(dice): |  | ||||||
|         a[i] = random.randint(1, size) |  | ||||||
|     if keep != dice: |  | ||||||
|         b = sorted(a, reverse=True) |  | ||||||
|         b = b[0:keep] |  | ||||||
|     else: |  | ||||||
|         b = a |  | ||||||
|     total = sum(b) |  | ||||||
|     outstr = "["; |  | ||||||
|     if len(b) != len(a): |  | ||||||
|         # Bold is \002 |  | ||||||
|         outstr += ",".join(str(i) for i in b) + "," |  | ||||||
|         temp = sorted(a, reverse=True) |  | ||||||
|         temp = temp[keep:] |  | ||||||
|         bstr = ",".join(str(i) for i in temp) |  | ||||||
|         outstr += bstr |  | ||||||
|     else: |  | ||||||
|         outstr += ",".join(str(i) for i in a) |  | ||||||
|     outstr += "]"	 |  | ||||||
|      |  | ||||||
|     return (total, outstr) |  | ||||||
| 
 |  | ||||||
| # Processes rolls coming from the parser. This generates the inputs |  | ||||||
| # for the roll_dice() command, and returns the full string representing |  | ||||||
| # the whole current dice string (the part up to a semicolon or end of line) |  | ||||||
| def process_roll(trials, mods, comment): |  | ||||||
|     output = "" |  | ||||||
|     mode = 1 |  | ||||||
|     repeat = 1 |  | ||||||
|     if trials != None: |  | ||||||
|         repeat = trials |  | ||||||
|     for i in range(repeat): |  | ||||||
|         total = 0 |  | ||||||
|         curr_str = "" |  | ||||||
|         if i > 0: |  | ||||||
|             output += ", " |  | ||||||
|         for m in mods: |  | ||||||
|             keep = 0 |  | ||||||
|             dice = 1 |  | ||||||
|             res = 0 |  | ||||||
|             # if m is a tuple, then it is a die roll |  | ||||||
|             # m[0] = (keep, num dice) |  | ||||||
|             # m[1] = num faces on the die |  | ||||||
|             if type(m) == tuple: |  | ||||||
|                 if m[0] != None: |  | ||||||
|                     if m[0][0] != None: |  | ||||||
|                         keep = m[0][0] |  | ||||||
|                     dice = m[0][1] |  | ||||||
|                 size = m[1] |  | ||||||
|                 if keep > dice or keep == 0: |  | ||||||
|                     keep = dice |  | ||||||
|                 res = roll_dice(keep, dice, size) |  | ||||||
|                 curr_str += "%d%s" % (res[0], res[1]) |  | ||||||
|                 res = res[0] |  | ||||||
|             elif m == "+": |  | ||||||
|                 mode = 1 |  | ||||||
|                 curr_str += "+" |  | ||||||
|             elif m == "-": |  | ||||||
|                 mode = -1 |  | ||||||
|                 curr_str += "-" |  | ||||||
|             else: |  | ||||||
|                 res = m |  | ||||||
|                 curr_str += str(m) |  | ||||||
|             total += mode * res |  | ||||||
|         output += "%d (%s)" % (total, curr_str) |  | ||||||
|     if comment != None: |  | ||||||
|         output = "%s: %s" % (comment.strip(), output) |  | ||||||
|     return output |  | ||||||
| 
 |  | ||||||
| # General idea I had when creating this grammar: A roll string is a chain |  | ||||||
| # of modifiers, which may be repeated for a certain number of trials. It can |  | ||||||
| # have a comment that describes the roll |  | ||||||
| # Multiple roll strings can be chained with semicolon |  | ||||||
| def p_roll_r(p): |  | ||||||
|     'roll : roll ";" roll' |  | ||||||
|     global output |  | ||||||
|     p[0] = p[1] + "; " + p[3] |  | ||||||
|     output = p[0] |  | ||||||
| 
 |  | ||||||
| # The basic roll string |  | ||||||
| def p_roll(p): |  | ||||||
|     'roll : trial modifier comment' |  | ||||||
|     global output |  | ||||||
|     mods = [] |  | ||||||
|     if type(p[2]) == list: |  | ||||||
|         mods = p[2] |  | ||||||
|     else: |  | ||||||
|         mods = [p[2]] |  | ||||||
|     p[0] = process_roll(p[1], mods, p[3]) |  | ||||||
|     output = p[0] |  | ||||||
|      |  | ||||||
| # Trial is optional so have a rule without it |  | ||||||
| def p_roll_no_trials(p): |  | ||||||
|     'roll : modifier comment' |  | ||||||
|     global output |  | ||||||
|     mods = [] |  | ||||||
|     if type(p[1]) == list: |  | ||||||
|         mods = p[1] |  | ||||||
|     else: |  | ||||||
|         mods = [p[1]] |  | ||||||
|     p[0] = process_roll(None, mods, p[2])  |  | ||||||
|     output = p[0] |  | ||||||
| 
 |  | ||||||
| def p_comment(p): |  | ||||||
|     '''comment : TEXT |  | ||||||
|                |''' |  | ||||||
|     if len(p) == 2: |  | ||||||
|         p[0] = p[1] |  | ||||||
|     else: |  | ||||||
|         p[0] = None |  | ||||||
| 
 |  | ||||||
| def p_modifier(p): |  | ||||||
|     '''modifier : modifier "+" modifier |  | ||||||
|                 | modifier "-" modifier''' |  | ||||||
|     # Use append to prevent nested lists (makes dealing with this easier) |  | ||||||
|     if type(p[1]) == list: |  | ||||||
|         p[1].append(p[2]) |  | ||||||
|         p[1].append(p[3]) |  | ||||||
|         p[0] = p[1] |  | ||||||
|     elif type(p[3]) == list: |  | ||||||
|         p[3].insert(0, p[2]) |  | ||||||
|         p[3].insert(0, p[1]) |  | ||||||
|         p[0] = p[3] |  | ||||||
|     else: |  | ||||||
|         p[0] = [p[1], p[2], p[3]] |  | ||||||
| 
 |  | ||||||
| # Return the left side before the "d", and the number of faces |  | ||||||
| def p_die(p): |  | ||||||
|     'modifier : left NUMBER' |  | ||||||
|     p[0] = (p[1], p[2]) |  | ||||||
| 
 |  | ||||||
| def p_die_num(p): |  | ||||||
|     'modifier : NUMBER' |  | ||||||
|     p[0] = p[1] |  | ||||||
| 
 |  | ||||||
| # left is the number of dice we are rolling, and how many we are keeping |  | ||||||
| def p_left(p): |  | ||||||
|     'left : keep dice' |  | ||||||
|     if p[1] == None: |  | ||||||
|         p[0] = [None, p[2]] |  | ||||||
|     else: |  | ||||||
|         p[0] = [p[1], p[2]] |  | ||||||
| 
 |  | ||||||
| def p_left1(p): |  | ||||||
|     'left : dice' |  | ||||||
|     p[0] = [None, p[1]] |  | ||||||
| 
 |  | ||||||
| def p_left_e(p): |  | ||||||
|     'left :' |  | ||||||
|     p[0] = None |  | ||||||
| 
 |  | ||||||
| def p_total(p): |  | ||||||
|     'trial : NUMBER "#"' |  | ||||||
|     if len(p) > 1: |  | ||||||
|         p[0] = p[1] |  | ||||||
|     else: |  | ||||||
|         p[0] = None |  | ||||||
| 
 |  | ||||||
| def p_keep(p): |  | ||||||
|     'keep : NUMBER "/"' |  | ||||||
|     if p[1] != None: |  | ||||||
|         p[0] = p[1] |  | ||||||
|     else: |  | ||||||
|         p[0] = None |  | ||||||
| 
 |  | ||||||
| def p_dice(p):  |  | ||||||
|     'dice : NUMBER "d"' |  | ||||||
|     p[0] = p[1] |  | ||||||
|      |  | ||||||
| def p_dice2(p): |  | ||||||
|     'dice : "d"' |  | ||||||
|     p[0] = 1 |  | ||||||
| 
 |  | ||||||
| # Provide the user with something (albeit not much) when the roll can't be parsed |  | ||||||
| def p_error(p): |  | ||||||
|     print "Unable to parse roll" |  | ||||||
|     print yacc.token() |  | ||||||
|     global output |  | ||||||
|     output = "Unable to parse roll" |  | ||||||
|      |  | ||||||
| def get_result(): |  | ||||||
|     global output |  | ||||||
|     return output |  | ||||||
| 
 |  | ||||||
| import ply.yacc as yacc |  | ||||||
| yacc.yacc() |  | ||||||
| 
 |  | ||||||
| # Testing stuff: |  | ||||||
| 
 |  | ||||||
| # rolls = ( |  | ||||||
|     # "5#3/4d20+1+2+d20;3/4d20;4d20", |  | ||||||
|     # "d20+10 attack;d8+6 damage", |  | ||||||
|     # "2#d20+10 twin strike!111;d10+9 damage", |  | ||||||
|     # "d20+d20;d20+d20;d20+d20+d20", |  | ||||||
|     # "error" |  | ||||||
| # ) |  | ||||||
| 
 |  | ||||||
| # for roll in rolls: |  | ||||||
|     # print "***** trying roll " + roll |  | ||||||
|     # yacc.parse(roll, debug=0) |  | ||||||
|     # print output |  | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user