From: Christian Heller <c.heller@plomlompom.de>
Date: Thu, 10 Jun 2021 20:54:48 +0000 (+0200)
Subject: Refactor parser code.
X-Git-Url: https://plomlompom.com/repos/%7B%7Bprefix%7D%7D/%22https:/validator.w3.org/do_tasks?a=commitdiff_plain;p=plomrogue2
Refactor parser code.
---
diff --git a/plomrogue/game.py b/plomrogue/game.py
index b76860a..cb749cf 100755
--- a/plomrogue/game.py
+++ b/plomrogue/game.py
@@ -2,7 +2,6 @@ from plomrogue.errors import GameError, PlayError
from plomrogue.io import GameIO
from plomrogue.misc import quote
from plomrogue.mapping import YX, MapGeometrySquare, MapGeometryHex, Map
-import string
import datetime
@@ -123,6 +122,7 @@ import os
class Game(GameBase):
def __init__(self, save_file, *args, **kwargs):
+ import string
from plomrogue.misc import Terrain
super().__init__(*args, **kwargs)
self.changed = True
@@ -159,9 +159,11 @@ class Game(GameBase):
if os.path.exists(self.io.save_file):
if not os.path.isfile(self.io.save_file):
raise GameError('save file path refers to non-file')
+ self.io.train_parser()
def register_thing_type(self, thing_type):
self._register_object(thing_type, 'thing_type', 'Thing_')
+ self.io.train_parser()
def register_task(self, task):
self._register_object(task, 'task', 'Task_')
@@ -190,20 +192,6 @@ class Game(GameBase):
return False
return True
- def get_string_options(self, string_option_type):
- if string_option_type == 'direction':
- return self.map_geometry.directions
- elif string_option_type == 'direction+here':
- return ['HERE'] + self.map_geometry.directions
- elif string_option_type == 'char':
- return [c for c in
- string.digits + string.ascii_letters + string.punctuation + ' ']
- elif string_option_type == 'map_geometry':
- return ['Hex', 'Square']
- elif string_option_type == 'thing_type':
- return self.thing_types.keys()
- return None
-
def get_default_spawn_point(self):
import random
if len(self.spawn_points) == 0:
@@ -646,6 +634,7 @@ class Game(GameBase):
self.portals = {}
self.admin_passwords = []
self.map_geometry = map_geometry
+ self.io.train_parser()
self.map_control_passwords = {'X': 'secret'}
self.get_map(YX(0, 0))
self.get_map(YX(0, 0), 'control')
diff --git a/plomrogue/io.py b/plomrogue/io.py
index 438b8b6..490706e 100644
--- a/plomrogue/io.py
+++ b/plomrogue/io.py
@@ -13,6 +13,18 @@ class GameIO():
self.save_file = save_file
self.servers = []
+ def train_parser(self):
+ import string
+ self.parser.string_options = {
+ 'map_geometry': {'Hex', 'Square'},
+ 'char': [c for c in
+ string.digits + string.ascii_letters + string.punctuation
+ + ' '],
+ 'direction': self.game.map_geometry.directions,
+ 'direction+here': ['HERE'] + self.game.map_geometry.directions,
+ 'thing_type': self.game.thing_types.keys()
+ }
+
def loop(self, q):
"""Handle commands coming through queue q, run game, send results back.
diff --git a/plomrogue/parser.py b/plomrogue/parser.py
index 302733d..51f5cc2 100644
--- a/plomrogue/parser.py
+++ b/plomrogue/parser.py
@@ -6,6 +6,7 @@ class Parser:
def __init__(self, game=None):
self.game = game
+ self.string_options = {}
def tokenize(self, msg):
"""Parse msg string into tokens.
@@ -73,16 +74,17 @@ class Parser:
x = get_axis_position_from_argument('X', tokens[1])
return YX(y, x)
- def parse(self, msg):
+ def parse(self, msg, replace_newline=True):
"""Parse msg as call to function, return function with args tuple.
Respects function signature defined in function's .argtypes attribute.
- Throws out messages with any but a small list of acceptable characters.
+ Refuses messages with any but a small list of acceptable characters.
"""
import string
- msg = msg.replace('\n', ' ') # Inserted by some tablet keyboards.
+ if replace_newline:
+ msg = msg.replace('\n', ' ') # Inserted by some tablet keyboards.
legal_chars = string.digits + string.ascii_letters +\
string.punctuation + ' ' + 'ÃäÃöÃüç' + 'éèáà ô' + 'ââ¦'
for c in msg:
@@ -151,12 +153,10 @@ class Parser:
elif tmpl == string_string:
args += [arg]
elif tmpl[:len(string_string) + 1] == string_string + ':':
- if not hasattr(self.game, 'get_string_options'):
- raise ArgError('No string option directory.')
string_option_type = tmpl[len(string_string) + 1:]
- options = self.game.get_string_options(string_option_type)
- if options is None:
- raise ArgError('Unknown string option type.')
+ if not string_option_type in self.string_options.keys():
+ raise ArgError('Unknown string option type: %s' % string_option_type)
+ options = self.string_options[string_option_type]
if arg not in options:
msg = 'Argument #%s must be one of: %s' % (i + 1, options)
raise ArgError(msg)
diff --git a/rogue_chat_curses.py b/rogue_chat_curses.py
index 91418f6..4f6981d 100755
--- a/rogue_chat_curses.py
+++ b/rogue_chat_curses.py
@@ -302,6 +302,7 @@ cmd_TASKS.argtypes = 'string'
def cmd_THING_TYPE(game, thing_type, symbol_hint):
game.thing_types[thing_type] = symbol_hint
+ game.train_parser()
cmd_THING_TYPE.argtypes = 'string char'
def cmd_THING_INSTALLED(game, thing_id):
@@ -383,13 +384,14 @@ class Game(GameBase):
self.portals_new = {}
self.terrains = {}
self.player = None
+ self.parser = Parser(self)
+ self.train_parser()
- def get_string_options(self, string_option_type):
- if string_option_type == 'map_geometry':
- return ['Hex', 'Square']
- elif string_option_type == 'thing_type':
- return self.thing_types.keys()
- return None
+ def train_parser(self):
+ self.parser.string_options = {
+ 'map_geometry': {'Hex', 'Square'},
+ 'thing_type': self.thing_types.keys()
+ }
def get_command(self, command_name):
from functools import partial
@@ -497,7 +499,6 @@ class RogueChatTUI(TUI):
self.socket = ClientSocket(host, self.socket_log)
self.game = Game()
self.game.tui = self
- self.parser = Parser(self.game)
self.login_name = None
self.map_mode = 'terrain + things'
self.password = 'foo'
@@ -589,6 +590,10 @@ class RogueChatTUI(TUI):
super().__init__(*args, **kwargs)
def update_on_connect(self):
+ self.game.thing_types = {}
+ self.game.terrains = {}
+ self.game.train_parser()
+ self.is_admin = False
self.socket.send('TASKS')
self.socket.send('TERRAINS')
self.socket.send('THING_TYPES')
@@ -1093,7 +1098,7 @@ class RogueChatTUI(TUI):
self.draw_face_popup()
def handle_server_message(self, msg):
- command, args = self.parser.parse(msg)
+ command, args = self.game.parser.parse(msg)
command(*args)
def on_each_loop_start(self):