comparison orpg/tools/InterParse.py @ 28:ff154cf3350c ornery-orc

Traipse 'OpenRPG' {100203-00} Traipse is a distribution of OpenRPG that is designed to be easy to setup and go. Traipse also makes it easy for developers to work on code without fear of sacrifice. 'Ornery-Orc' continues the trend of 'Grumpy' and adds fixes to the code. 'Ornery-Orc's main goal is to offer more advanced features and enhance the productivity of the user. Update Summary (Stable) New Features: New Bookmarks Feature New 'boot' command to remote admin New confirmation window for sent nodes Miniatures Layer pop up box allows users to turn off Mini labels, from FlexiRPG New Zoom Mouse plugin added New Images added to Plugin UI Switching to Element Tree New Map efficiency, from FlexiRPG New Status Bar to Update Manager New TrueDebug Class in orpg_log (See documentation for usage) New Portable Mercurial New Tip of the Day, from Core and community New Reference Syntax added for custom PC sheets New Child Reference for gametree New Parent Reference for gametree New Gametree Recursion method, mapping, context sensitivity, and effeciency.. New Features node with bonus nodes and Node Referencing help added New Dieroller structure from Core New DieRoller portability for odd Dice New 7th Sea die roller; ie [7k3] = [7d10.takeHighest(3).open(10)] New 'Mythos' System die roller added New vs. die roller method for WoD; ie [3v3] = [3d10.vs(3)]. Included for Mythos roller also New Warhammer FRPG Die Roller (Special thanks to Puu-san for the support) New EZ_Tree Reference system. Push a button, Traipse the tree, get a reference (Beta!) New Grids act more like Spreadsheets in Use mode, with Auto Calc Fixes: Fix to allow for portability to an OpenSUSE linux OS Fix to mplay_client for Fedora and OpenSUSE Fix to Text based Server Fix to Remote Admin Commands Fix to Pretty Print, from Core Fix to Splitter Nodes not being created Fix to massive amounts of images loading, from Core Fix to Map from gametree not showing to all clients Fix to gametree about menus Fix to Password Manager check on startup Fix to PC Sheets from tool nodes. They now use the tabber_panel Fix to Whiteboard ID to prevent random line or text deleting. Fixes to Server, Remote Server, and Server GUI Fix to Update Manager; cleaner clode for saved repositories Fixes made to Settings Panel and now reactive settings when Ok is pressed Fixes to Alternity roller's attack roll. Uses a simple Tuple instead of a Splice Fix to Use panel of Forms and Tabbers. Now longer enters design mode Fix made Image Fetching. New fetching image and new failed image Fix to whiteboard ID's to prevent non updated clients from ruining the fix. default_manifest.xml renamed to default_upmana.xml
author sirebral
date Wed, 03 Feb 2010 22:16:49 -0600
parents
children 8e77f169f324
comparison
equal deleted inserted replaced
27:51428d30c59e 28:ff154cf3350c
1 from orpg.orpgCore import component
2 import re
3 from orpg.tools.orpg_log import logger
4 from wx import TextEntryDialog, ID_OK
5
6 class InterParse():
7
8 def __init__(self):
9 pass
10
11 def Post(self, s, send=False, myself=False):
12 s = self.Normalize(s)
13 component.get('chat').set_colors()
14 component.get('chat').Post(s, send, myself)
15
16 def Normalize(self, s):
17 for plugin_fname in component.get('chat').activeplugins.keys():
18 plugin = component.get('chat').activeplugins[plugin_fname]
19 try: s = plugin.pre_parse(s)
20 except Exception, e:
21 if str(e) != "'module' object has no attribute 'post_msg'":
22 logger.general(traceback.format_exc())
23 logger.general("EXCEPTION: " + str(e))
24 if component.get('chat').parsed == 0:
25 s = self.Node(s)
26 s = self.Dice(s)
27 s = self.Filter(s)
28 component.get('chat').parsed = 1
29 return s
30
31 def Filter(self, s):
32 s = component.get('chat').GetFilteredText(s)
33 return s
34
35 def Node(self, s):
36 """Parses player input for embedded nodes rolls"""
37 cur_loc = 0
38 #[a-zA-Z0-9 _\-\.]
39 reg = re.compile("(!@(.*?)@!)")
40 matches = reg.findall(s)
41 for i in xrange(0,len(matches)):
42 newstr = self.Node(self.resolve_nodes(matches[i][1]))
43 s = s.replace(matches[i][0], newstr, 1)
44 return s
45
46 def Dice(self, s):
47 """Parses player input for embedded dice rolls"""
48 reg = re.compile("\[([^]]*?)\]")
49 matches = reg.findall(s)
50 for i in xrange(0,len(matches)):
51 newstr = self.Unknown(matches[i])
52 qmode = 0
53 newstr1 = newstr
54 if newstr[0].lower() == 'q':
55 newstr = newstr[1:]
56 qmode = 1
57 if newstr[0].lower() == '#':
58 newstr = newstr[1:]
59 qmode = 2
60 try: newstr = component.get('DiceManager').proccessRoll(newstr)
61 except: pass
62 if qmode == 1:
63 s = s.replace("[" + matches[i] + "]",
64 "<!-- Official Roll [" + newstr1 + "] => " + newstr + "-->" + newstr, 1)
65 elif qmode == 2:
66 s = s.replace("[" + matches[i] + "]", newstr[len(newstr)-2:-1], 1)
67 else: s = s.replace("[" + matches[i] + "]",
68 "[" + newstr1 + "<!-- Official Roll -->] => " + newstr, 1)
69 return s
70
71 def Unknown(self, s):
72 # Uses a tuple. Usage: ?Label}dY. If no Label is assigned then use ?}DY
73 newstr = "0"
74 reg = re.compile("(\?\{*)([a-zA-Z ]*)(\}*)")
75 matches = reg.findall(s)
76 for i in xrange(0,len(matches)):
77 lb = "Replace '?' with: "
78 if len(matches[i][0]):
79 lb = matches[i][1] + "?: "
80 dlg = TextEntryDialog(self, lb, "Missing Value?")
81 dlg.SetValue('')
82 if matches[i][0] != '':
83 dlg.SetTitle("Enter Value for " + matches[i][1])
84 if dlg.ShowModal() == ID_OK: newstr = dlg.GetValue()
85 if newstr == '': newstr = '0'
86 s = s.replace(matches[i][0], newstr, 1).replace(matches[i][1], '', 1).replace(matches[i][2], '', 1)
87 dlg.Destroy()
88 return s
89
90 def NodeMap(self, s, node):
91 """Parses player input for embedded nodes rolls"""
92 cur_loc = 0
93 reg = re.compile("(!!(.*?)!!)")
94 matches = reg.findall(s)
95 for i in xrange(0,len(matches)):
96 tree_map = node.get('map')
97 tree_map = tree_map + '::' + matches[i][1]
98 newstr = '!@'+ tree_map +'@!'
99 s = s.replace(matches[i][0], newstr, 1)
100 s = self.Node(s)
101 s = self.NodeParent(s, tree_map)
102 return s
103
104 def NodeParent(self, s, tree_map):
105 """Parses player input for embedded nodes rolls"""
106 cur_loc = 0
107 reg = re.compile("(!#(.*?)#!)")
108 matches = reg.findall(s)
109 for i in xrange(0,len(matches)):
110 ## Build the new tree_map
111 new_map = tree_map.split('::')
112 del new_map[len(new_map)-1]
113 parent_map = matches[i][1].split('::')
114 ## Backwards Reference the Parent Children
115 child_node = self.get_node('::'.join(new_map))
116 newstr = self.get_root(child_node, tree_map, new_map, parent_map)
117 s = s.replace(matches[i][0], newstr, 1)
118 s = self.Node(s)
119 return s
120
121 def get_root(self, child_node, tree_map, new_map, parent_map):
122 if child_node == 'Invalid Reference!': return child_node
123 roots = child_node.getchildren(); tr = tree_map.split('::')
124 newstr = ''
125 for root in roots:
126 try: t = new_map.index(root.get('name'))
127 except: t = 1
128 if parent_map[0] == root.get('name'):
129 newstr = '!@' + '::'.join(new_map[:len(tr)-t]) + '::' + '::'.join(parent_map) + '@!'
130 if newstr != '': return newstr
131 else:
132 del new_map[len(new_map)-1]
133 child_node = self.get_node('::'.join(new_map))
134 newstr = self.get_root(child_node, tree_map, new_map, parent_map)
135 return newstr
136
137 def get_node(self, s):
138 return_node = 'Invalid Reference!'
139 value = ""
140 path = s.split('::')
141 depth = len(path)
142 try: node = component.get('tree').tree_map[path[0]]['node']
143 except Exception, e: return return_node
144 return_node = self.resolve_get_loop(node, path, 1, depth)
145 return return_node
146
147 def resolve_get_loop(self, node, path, step, depth):
148 if step == depth: return node
149 else:
150 child_list = node.findall('nodehandler')
151 for child in child_list:
152 if step == depth: break
153 if child.get('name') == path[step]:
154 node = self.resolve_get_loop(child, path, step+1, depth)
155 return node
156
157 def resolve_nodes(self, s):
158 self.passed = False
159 string = 'Invalid Reference!'
160 value = ""
161 path = s.split('::')
162 depth = len(path)
163 try: node = component.get('tree').tree_map[path[0]]['node']
164 except Exception, e: return string
165 if node.get('class') in ('dnd35char_handler',
166 "SWd20char_handler",
167 "d20char_handler",
168 "dnd3echar_handler"): string = self.resolve_cust_loop(node, path, 1, depth)
169 elif node.get('class') == 'rpg_grid_handler': self.resolve_grid(node, path, 1, depth)
170 else: string = self.resolve_loop(node, path, 1, depth)
171 return string
172
173 def resolve_loop(self, node, path, step, depth):
174 if step == depth: return self.resolution(node)
175 else:
176 child_list = node.findall('nodehandler')
177 for child in child_list:
178 if step == depth: break
179 if child.get('name') == path[step]:
180 node = child
181 step += 1
182 if node.get('class') in ('dnd35char_handler',
183 "SWd20char_handler",
184 "d20char_handler",
185 "dnd3echar_handler"):
186 string = self.resolve_cust_loop(node, path, step, depth)
187 elif node.get('class') == 'rpg_grid_handler':
188 string = self.resolve_grid(node, path, step, depth)
189 else: string = self.resolve_loop(node, path, step, depth)
190 return string
191
192 def resolution(self, node):
193 if self.passed == False:
194 self.passed = True
195 if node.get('class') == 'textctrl_handler':
196 s = str(node.find('text').text)
197 else: s = 'Nodehandler for '+ node.get('class') + ' not done!' or 'Invalid Reference!'
198 else:
199 s = ''
200 s = self.NodeMap(s, node)
201 s = self.NodeParent(s, node.get('map'))
202 return s
203
204 def resolve_grid(self, node, path, step, depth):
205 if step == depth:
206 return 'Invalid Grid Reference!'
207 cell = tuple(path[step].strip('(').strip(')').split(','))
208 grid = node.find('grid')
209 rows = grid.findall('row')
210 col = rows[int(self.Dice(cell[0]))-1].findall('cell')
211 try: s = self.NodeMap(col[int(self.Dice(cell[1]))-1].text, node) or 'No Cell Data'
212 except: s = 'Invalid Grid Reference!'
213 return s
214
215 def resolve_cust_loop(self, node, path, step, depth):
216 s = 'Invalid Reference!'
217 node_class = node.get('class')
218 ## Code needs clean up. Either choose .lower() or .title(), then reset the path list's content ##
219 if step == depth: self.resolution(node)
220 ##Build Abilities dictionary##
221 if node_class not in ('d20char_handler', "SWd20char_handler"): ab = node.find('character').find('abilities')
222 else: ab = node.find('abilities')
223 ab_list = ab.findall('stat'); pc_stats = {}
224
225 for ability in ab_list:
226 pc_stats[ability.get('name')] = (
227 str(ability.get('base')),
228 str((int(ability.get('base'))-10)/2) )
229 pc_stats[ability.get('abbr')] = (
230 str(ability.get('base')),
231 str((int(ability.get('base'))-10)/2) )
232
233 if node_class not in ('d20char_handler', "SWd20char_handler"): ab = node.find('character').find('saves')
234 else: ab = node.find('saves')
235 ab_list = ab.findall('save')
236 for save in ab_list:
237 pc_stats[save.get('name')] = (str(save.get('base')), str(int(save.get('magmod')) + int(save.get('miscmod')) + int(pc_stats[save.get('stat')][1]) ) )
238 if save.get('name') == 'Fortitude': abbr = 'Fort'
239 if save.get('name') == 'Reflex': abbr = 'Ref'
240 if save.get('name') == 'Will': abbr = 'Will'
241 pc_stats[abbr] = ( str(save.get('base')), str(int(save.get('magmod')) + int(save.get('miscmod')) + int(pc_stats[save.get('stat')][1]) ) )
242
243 if path[step].lower() == 'skill':
244 if node_class not in ('d20char_handler', "SWd20char_handler"): node = node.find('snf')
245 node = node.find('skills')
246 child_list = node.findall('skill')
247 for child in child_list:
248 if path[step+1].lower() == child.get('name').lower():
249 if step+2 == depth: s = child.get('rank')
250 elif path[step+2].lower() == 'check':
251 s = '<b>Skill Check:</b> ' + child.get('name') + ' [1d20+'+str( int(child.get('rank')) + int(pc_stats[child.get('stat')][1]) )+']'
252 return s
253
254 if path[step].lower() == 'feat':
255 if node_class not in ('d20char_handler', "SWd20char_handler"): node = node.find('snf')
256 node = node.find('feats')
257 child_list = node.findall('feat')
258 for child in child_list:
259 if path[step+1].lower() == child.get('name').lower():
260 if step+2 == depth: s = '<b>'+child.get('name')+'</b>'+': '+child.get('desc')
261 return s
262 if path[step].lower() == 'cast':
263 if node_class not in ('d20char_handler', "SWd20char_handler"): node = node.find('snp')
264 node = node.find('spells')
265 child_list = node.findall('spell')
266 for child in child_list:
267 if path[step+1].lower() == child.get('name').lower():
268 if step+2 == depth: s = '<b>'+child.get('name')+'</b>'+': '+child.get('desc')
269 return s
270 if path[step].lower() == 'attack':
271 if node_class not in ('d20char_handler', "SWd20char_handler"): node = node.find('combat')
272 if path[step+1].lower() == 'melee' or path[step+1].lower() == 'm':
273 bonus_text = '(Melee)'
274 bonus = node.find('attacks')
275 bonus = bonus.find('melee')
276 bonus = bonus.attrib; d = int(pc_stats['Str'][1])
277 elif path[step+1].lower() == 'ranged' or path[step+1].lower() == 'r':
278 bonus_text = '(Ranged)'
279 bonus = node.find('attacks')
280 bonus = bonus.find('ranged')
281 bonus = bonus.attrib; d = int(pc_stats['Dex'][1])
282 for b in bonus:
283 d += int(bonus[b])
284 bonus = str(d)
285 if path[step+2] == None: s= bonus
286 else:
287 weapons = node.find('attacks')
288 weapons = weapons.findall('weapon')
289 for child in weapons:
290 if path[step+2].lower() == child.get('name').lower():
291 s = '<b>Attack: '+bonus_text+'</b> '+child.get('name')+' [1d20+'+bonus+'] ' + 'Damage: ['+child.get('damage')+']'
292 return s
293 elif pc_stats.has_key(path[step].title()):
294 if step+1 == depth: s = pc_stats[path[step].title()][0] + ' +('+pc_stats[path[step].title()][1]+')'
295 elif path[step+1].title() == 'Mod': s = pc_stats[path[step].title()][1]
296 elif path[step+1].title() == 'Check': s = '<b>'+path[step].title()+' Check:</b> [1d20+'+str(pc_stats[path[step].title()][1])+']'
297 return s
298 return s
299
300 Parse = InterParse()