Mercurial > traipse_dev
comparison orpg/tools/InterParse.py @ 195:b633f4c64aae alpha
Traipse Alpha 'OpenRPG' {100219-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 (Patch-2)
New Features:
New Namespace method with two new syntaxes
Fixes:
Fix to Server GUI startup errors
Fix to Server GUI Rooms tab updating
Fix to Chat and Settings if non existant die roller is picked
Fix to Dieroller and .open() used with .vs(). Successes are correctly calculated
Fix to Alias Lib's Export to Tree, Open, Save features
Fix to alias node, now works properly
Fix to Splitter node, minor GUI cleanup
author | sirebral |
---|---|
date | Sat, 24 Apr 2010 08:37:20 -0500 |
parents | |
children | 0bc44a57ae6c |
comparison
equal
deleted
inserted
replaced
182:4b2884f29a72 | 195:b633f4c64aae |
---|---|
1 #!/usr/bin/env python | |
2 # Copyright (C) 2000-2010 The OpenRPG Project | |
3 # | |
4 # openrpg-dev@lists.sourceforge.net | |
5 # | |
6 # This program is free software; you can redistribute it and/or modify | |
7 # it under the terms of the GNU General Public License as published by | |
8 # the Free Software Foundation; either version 2 of the License, or | |
9 # (at your option) any later version. | |
10 # | |
11 # This program is distributed in the hope that it will be useful, | |
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 # GNU General Public License for more details. | |
15 # | |
16 # You should have received a copy of the GNU General Public License | |
17 # along with this program; if not, write to the Free Software | |
18 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
19 # -- | |
20 # | |
21 # File: InterParse.py | |
22 # Author: | |
23 # Maintainer: Tyler Starke (Traipse) | |
24 # Version: | |
25 # $Id: InterParse.py,v Traipse 'Ornery-Orc' prof.ebral Exp $ | |
26 # | |
27 # Description: InterParse = Interpretor Parser. This class parses all of the node referencing. | |
28 # | |
29 | |
30 from orpg.orpgCore import component | |
31 import re | |
32 from orpg.tools.orpg_log import logger | |
33 from wx import TextEntryDialog, ID_OK | |
34 | |
35 class InterParse(): | |
36 | |
37 def __init__(self): | |
38 pass | |
39 | |
40 def Post(self, s, send=False, myself=False): | |
41 s = self.Normalize(s) | |
42 component.get('chat').set_colors() | |
43 component.get('chat').Post(s, send, myself) | |
44 | |
45 def ParseLogic(self, s, node): | |
46 'Nodes now parse through ParsLogic. Easily add new parse rules right here!!' | |
47 s = self.NameSpaceE(s) | |
48 s = self.NameSpaceI(s, node) | |
49 s = self.NodeMap(s, node) | |
50 s = self.NodeParent(s, node.get('map')) | |
51 return s | |
52 | |
53 def Normalize(self, s): | |
54 for plugin_fname in component.get('chat').activeplugins.keys(): | |
55 plugin = component.get('chat').activeplugins[plugin_fname] | |
56 try: s = plugin.pre_parse(s) | |
57 except Exception, e: | |
58 if str(e) != "'module' object has no attribute 'post_msg'": | |
59 logger.general(traceback.format_exc()) | |
60 logger.general("EXCEPTION: " + str(e)) | |
61 if component.get('chat').parsed == 0: | |
62 s = self.NameSpaceE(s) | |
63 s = self.Node(s) | |
64 s = self.Dice(s) | |
65 s = self.Filter(s) | |
66 component.get('chat').parsed = 1 | |
67 return s | |
68 | |
69 def Filter(self, s): | |
70 s = component.get('chat').GetFilteredText(s) | |
71 return s | |
72 | |
73 def Node(self, s): | |
74 """Parses player input for embedded nodes rolls""" | |
75 cur_loc = 0 | |
76 #[a-zA-Z0-9 _\-\.] | |
77 reg = re.compile("(!@(.*?)@!)") | |
78 matches = reg.findall(s) | |
79 for i in xrange(0,len(matches)): | |
80 newstr = self.Node(self.resolve_nodes(matches[i][1])) | |
81 s = s.replace(matches[i][0], newstr, 1) | |
82 return s | |
83 | |
84 def Dice(self, s): | |
85 """Parses player input for embedded dice rolls""" | |
86 reg = re.compile("\[([^]]*?)\]") | |
87 matches = reg.findall(s) | |
88 for i in xrange(0,len(matches)): | |
89 newstr = self.Unknown(matches[i]) | |
90 qmode = 0 | |
91 newstr1 = newstr | |
92 if newstr[0].lower() == 'q': | |
93 newstr = newstr[1:] | |
94 qmode = 1 | |
95 if newstr[0].lower() == '#': | |
96 newstr = newstr[1:] | |
97 qmode = 2 | |
98 try: newstr = component.get('DiceManager').proccessRoll(newstr) | |
99 except: pass | |
100 if qmode == 1: | |
101 s = s.replace("[" + matches[i] + "]", | |
102 "<!-- Official Roll [" + newstr1 + "] => " + newstr + "-->" + newstr, 1) | |
103 elif qmode == 2: | |
104 s = s.replace("[" + matches[i] + "]", newstr[len(newstr)-2:-1], 1) | |
105 else: s = s.replace("[" + matches[i] + "]", | |
106 "[" + newstr1 + "<!-- Official Roll -->] => " + newstr, 1) | |
107 return s | |
108 | |
109 def Unknown(self, s): | |
110 # Uses a tuple. Usage: ?Label}dY. If no Label is assigned then use ?}DY | |
111 newstr = "0" | |
112 reg = re.compile("(\?\{*)([a-zA-Z ]*)(\}*)") | |
113 matches = reg.findall(s) | |
114 for i in xrange(0,len(matches)): | |
115 lb = "Replace '?' with: " | |
116 if len(matches[i][0]): | |
117 lb = matches[i][1] + "?: " | |
118 dlg = TextEntryDialog(component.get('chat'), lb, "Missing Value?") | |
119 dlg.SetValue('') | |
120 if matches[i][0] != '': | |
121 dlg.SetTitle("Enter Value for " + matches[i][1]) | |
122 if dlg.ShowModal() == ID_OK: newstr = dlg.GetValue() | |
123 if newstr == '': newstr = '0' | |
124 s = s.replace(matches[i][0], newstr, 1).replace(matches[i][1], '', 1).replace(matches[i][2], '', 1) | |
125 dlg.Destroy() | |
126 return s | |
127 | |
128 def NameSpaceI(self, s, node): | |
129 reg = re.compile("(!=(.*?)=!)") | |
130 matches = reg.findall(s) | |
131 for i in xrange(0,len(matches)): | |
132 tree_map = node.get('map').split('::') | |
133 root = self.get_node(tree_map[0]) | |
134 find = matches[i][1].split('::') | |
135 names = root.getiterator('nodehandler') | |
136 for name in names: | |
137 if find[0] == name.get('name'): | |
138 if name.get('class') == 'rpg_grid_handler': | |
139 newstr = self.NameSpaceGrid(find, name); break | |
140 else: newstr = str(name.find('text').text); break | |
141 else: newstr = 'Invalid Reference!' | |
142 s = s.replace(matches[i][0], newstr, 1) | |
143 s = self.ParseLogic(s, name) | |
144 return s | |
145 | |
146 def NameSpaceE(self, s): | |
147 reg = re.compile("(!&(.*?)&!)") | |
148 matches = reg.findall(s) | |
149 for i in xrange(0,len(matches)): | |
150 find = matches[i][1].split('::') | |
151 root = find[0] | |
152 root = self.get_node(root) | |
153 names = root.getiterator('nodehandler') | |
154 for name in names: | |
155 if find[1] == name.get('name'): | |
156 if name.get('class') == 'rpg_grid_handler': | |
157 newstr = self.NameSpaceGrid([find[1], find[2]], name); break | |
158 else: newstr = str(name.find('text').text); break | |
159 else: newstr = 'Invalid Reference!' | |
160 s = s.replace(matches[i][0], newstr, 1) | |
161 s = self.ParseLogic(s, name) | |
162 return s | |
163 | |
164 def NameSpaceGrid(self, s, node): | |
165 cell = tuple(s[1].strip('(').strip(')').split(',')) | |
166 grid = node.find('grid') | |
167 rows = grid.findall('row') | |
168 col = rows[int(self.Dice(cell[0]))-1].findall('cell') | |
169 try: s = self.ParseLogic(col[int(self.Dice(cell[1]))-1].text, node) or 'No Cell Data' | |
170 except: s = 'Invalid Grid Reference!' | |
171 return s | |
172 | |
173 def NodeMap(self, s, node): | |
174 """Parses player input for embedded nodes rolls""" | |
175 cur_loc = 0 | |
176 reg = re.compile("(!!(.*?)!!)") | |
177 matches = reg.findall(s) | |
178 for i in xrange(0,len(matches)): | |
179 tree_map = node.get('map') | |
180 tree_map = tree_map + '::' + matches[i][1] | |
181 newstr = '!@'+ tree_map +'@!' | |
182 s = s.replace(matches[i][0], newstr, 1) | |
183 s = self.Node(s) | |
184 s = self.NodeParent(s, tree_map) | |
185 return s | |
186 | |
187 def NodeParent(self, s, tree_map): | |
188 """Parses player input for embedded nodes rolls""" | |
189 cur_loc = 0 | |
190 reg = re.compile("(!#(.*?)#!)") | |
191 matches = reg.findall(s) | |
192 for i in xrange(0,len(matches)): | |
193 ## Build the new tree_map | |
194 new_map = tree_map.split('::') | |
195 del new_map[len(new_map)-1] | |
196 parent_map = matches[i][1].split('::') | |
197 ## Backwards Reference the Parent Children | |
198 child_node = self.get_node('::'.join(new_map)) | |
199 newstr = self.get_root(child_node, tree_map, new_map, parent_map) | |
200 s = s.replace(matches[i][0], newstr, 1) | |
201 s = self.Node(s) | |
202 return s | |
203 | |
204 def get_root(self, child_node, tree_map, new_map, parent_map): | |
205 if child_node == 'Invalid Reference!': return child_node | |
206 roots = child_node.getchildren(); tr = tree_map.split('::') | |
207 newstr = '' | |
208 for root in roots: | |
209 try: t = new_map.index(root.get('name')) | |
210 except: t = 1 | |
211 if parent_map[0] == root.get('name'): | |
212 newstr = '!@' + '::'.join(new_map[:len(tr)-t]) + '::' + '::'.join(parent_map) + '@!' | |
213 if newstr != '': return newstr | |
214 else: | |
215 del new_map[len(new_map)-1] | |
216 child_node = self.get_node('::'.join(new_map)) | |
217 newstr = self.get_root(child_node, tree_map, new_map, parent_map) | |
218 return newstr | |
219 | |
220 def get_node(self, s): | |
221 return_node = 'Invalid Reference!' | |
222 value = "" | |
223 path = s.split('::') | |
224 depth = len(path) | |
225 try: node = component.get('tree').tree_map[path[0]]['node'] | |
226 except Exception, e: return return_node | |
227 return_node = self.resolve_get_loop(node, path, 1, depth) | |
228 return return_node | |
229 | |
230 def resolve_get_loop(self, node, path, step, depth): | |
231 if step == depth: return node | |
232 else: | |
233 child_list = node.findall('nodehandler') | |
234 for child in child_list: | |
235 if step == depth: break | |
236 if child.get('name') == path[step]: | |
237 node = self.resolve_get_loop(child, path, step+1, depth) | |
238 return node | |
239 | |
240 def resolve_nodes(self, s): | |
241 self.passed = False | |
242 string = 'Invalid Reference!' | |
243 value = "" | |
244 path = s.split('::') | |
245 depth = len(path) | |
246 try: node = component.get('tree').tree_map[path[0]]['node'] | |
247 except Exception, e: return string | |
248 if node.get('class') in ('dnd35char_handler', | |
249 "SWd20char_handler", | |
250 "d20char_handler", | |
251 "dnd3echar_handler"): string = self.resolve_cust_loop(node, path, 1, depth) | |
252 elif node.get('class') == 'rpg_grid_handler': self.resolve_grid(node, path, 1, depth) | |
253 else: string = self.resolve_loop(node, path, 1, depth) | |
254 return string | |
255 | |
256 def resolve_loop(self, node, path, step, depth): | |
257 if step == depth: return self.resolution(node) | |
258 else: | |
259 child_list = node.findall('nodehandler') | |
260 for child in child_list: | |
261 if step == depth: break | |
262 if child.get('name') == path[step]: | |
263 node = child | |
264 step += 1 | |
265 if node.get('class') in ('dnd35char_handler', | |
266 "SWd20char_handler", | |
267 "d20char_handler", | |
268 "dnd3echar_handler"): | |
269 string = self.resolve_cust_loop(node, path, step, depth) | |
270 elif node.get('class') == 'rpg_grid_handler': | |
271 string = self.resolve_grid(node, path, step, depth) | |
272 else: string = self.resolve_loop(node, path, step, depth) | |
273 return string | |
274 | |
275 def resolution(self, node): | |
276 if self.passed == False: | |
277 self.passed = True | |
278 if node.get('class') == 'textctrl_handler': | |
279 s = str(node.find('text').text) | |
280 else: s = 'Nodehandler for '+ node.get('class') + ' not done!' or 'Invalid Reference!' | |
281 else: s = '' | |
282 s = self.ParseLogic(s, node) | |
283 return s | |
284 | |
285 def resolve_grid(self, node, path, step, depth): | |
286 if step == depth: | |
287 return 'Invalid Grid Reference!' | |
288 cell = tuple(path[step].strip('(').strip(')').split(',')) | |
289 grid = node.find('grid') | |
290 rows = grid.findall('row') | |
291 col = rows[int(self.Dice(cell[0]))-1].findall('cell') | |
292 try: s = self.ParseLogic(col[int(self.Dice(cell[1]))-1].text, node) or 'No Cell Data' | |
293 except: s = 'Invalid Grid Reference!' | |
294 return s | |
295 | |
296 def resolve_cust_loop(self, node, path, step, depth): | |
297 s = 'Invalid Reference!' | |
298 node_class = node.get('class') | |
299 ## Code needs clean up. Either choose .lower() or .title(), then reset the path list's content ## | |
300 if step == depth: self.resolution(node) | |
301 ##Build Abilities dictionary## | |
302 if node_class not in ('d20char_handler', "SWd20char_handler"): ab = node.find('character').find('abilities') | |
303 else: ab = node.find('abilities') | |
304 ab_list = ab.findall('stat'); pc_stats = {} | |
305 | |
306 for ability in ab_list: | |
307 pc_stats[ability.get('name')] = ( | |
308 str(ability.get('base')), | |
309 str((int(ability.get('base'))-10)/2) ) | |
310 pc_stats[ability.get('abbr')] = ( | |
311 str(ability.get('base')), | |
312 str((int(ability.get('base'))-10)/2) ) | |
313 | |
314 if node_class not in ('d20char_handler', "SWd20char_handler"): ab = node.find('character').find('saves') | |
315 else: ab = node.find('saves') | |
316 ab_list = ab.findall('save') | |
317 for save in ab_list: | |
318 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]) ) ) | |
319 if save.get('name') == 'Fortitude': abbr = 'Fort' | |
320 if save.get('name') == 'Reflex': abbr = 'Ref' | |
321 if save.get('name') == 'Will': abbr = 'Will' | |
322 pc_stats[abbr] = ( str(save.get('base')), str(int(save.get('magmod')) + int(save.get('miscmod')) + int(pc_stats[save.get('stat')][1]) ) ) | |
323 | |
324 if path[step].lower() == 'skill': | |
325 if node_class not in ('d20char_handler', "SWd20char_handler"): node = node.find('snf') | |
326 node = node.find('skills') | |
327 child_list = node.findall('skill') | |
328 for child in child_list: | |
329 if path[step+1].lower() == child.get('name').lower(): | |
330 if step+2 == depth: s = child.get('rank') | |
331 elif path[step+2].lower() == 'check': | |
332 s = '<b>Skill Check:</b> ' + child.get('name') + ' [1d20+'+str( int(child.get('rank')) + int(pc_stats[child.get('stat')][1]) )+']' | |
333 return s | |
334 | |
335 if path[step].lower() == 'feat': | |
336 if node_class not in ('d20char_handler', "SWd20char_handler"): node = node.find('snf') | |
337 node = node.find('feats') | |
338 child_list = node.findall('feat') | |
339 for child in child_list: | |
340 if path[step+1].lower() == child.get('name').lower(): | |
341 if step+2 == depth: s = '<b>'+child.get('name')+'</b>'+': '+child.get('desc') | |
342 return s | |
343 if path[step].lower() == 'cast': | |
344 if node_class not in ('d20char_handler', "SWd20char_handler"): node = node.find('snp') | |
345 node = node.find('spells') | |
346 child_list = node.findall('spell') | |
347 for child in child_list: | |
348 if path[step+1].lower() == child.get('name').lower(): | |
349 if step+2 == depth: s = '<b>'+child.get('name')+'</b>'+': '+child.get('desc') | |
350 return s | |
351 if path[step].lower() == 'attack': | |
352 if node_class not in ('d20char_handler', "SWd20char_handler"): node = node.find('combat') | |
353 if path[step+1].lower() == 'melee' or path[step+1].lower() == 'm': | |
354 bonus_text = '(Melee)' | |
355 bonus = node.find('attacks') | |
356 bonus = bonus.find('melee') | |
357 bonus = bonus.attrib; d = int(pc_stats['Str'][1]) | |
358 elif path[step+1].lower() == 'ranged' or path[step+1].lower() == 'r': | |
359 bonus_text = '(Ranged)' | |
360 bonus = node.find('attacks') | |
361 bonus = bonus.find('ranged') | |
362 bonus = bonus.attrib; d = int(pc_stats['Dex'][1]) | |
363 for b in bonus: | |
364 d += int(bonus[b]) | |
365 bonus = str(d) | |
366 if path[step+2] == None: s= bonus | |
367 else: | |
368 weapons = node.find('attacks') | |
369 weapons = weapons.findall('weapon') | |
370 for child in weapons: | |
371 if path[step+2].lower() == child.get('name').lower(): | |
372 s = '<b>Attack: '+bonus_text+'</b> '+child.get('name')+' [1d20+'+bonus+'] ' + 'Damage: ['+child.get('damage')+']' | |
373 return s | |
374 elif pc_stats.has_key(path[step].title()): | |
375 if step+1 == depth: s = pc_stats[path[step].title()][0] + ' +('+pc_stats[path[step].title()][1]+')' | |
376 elif path[step+1].title() == 'Mod': s = pc_stats[path[step].title()][1] | |
377 elif path[step+1].title() == 'Check': s = '<b>'+path[step].title()+' Check:</b> [1d20+'+str(pc_stats[path[step].title()][1])+']' | |
378 return s | |
379 return s | |
380 | |
381 Parse = InterParse() |