2

I need a system for creating Python subclasses in a simple manner, and I was thinking of using a (custom) config language similar to json, xml, etc.

Here's the initial structure I thought of (one file = one subclass, files are in a folder where they're read from automatically), which is basically just a simple config language, with Python function bodies on as event handlers:

name: Warrior
description: Excels at close combat

Item:
    name: Shield
    description: Block 10% of incoming damage, but move 10% slower

    Event defend:
        # Everything after "event <event_name>" line
        # is parsed as normal python until unindentation
        event_args['damage'] *= 0.9

    Event spawn:
        event_args['player'].speed -= 0.1

I'm open for any suggestions, so if it's much easier to use some other formatting (XML or such), I'm up for it. However, this would be the ideal format.

How would I go on about writing mixed Python and config language? Are there any existing projects which I could study? I've researched ast a little, which is apparently designed for Python parsing, but I'm just looking for some guidance to get started.

The only solution that comes into mind is to:

  1. read through the file line-by-line, and parse every line manually with Python's string functions like .split()
  2. If the line content matches regex ^Event .*:$, I will parse as Python until an unindentation (how do I do this?)

But even this seems unfeasible, and it feels like there must be a better way.

  • see Where to start? – gnat Apr 11 '17 at 13:12
  • 1
    @gnat So, what do you suggest I change? If it's completely irrelevant to softwareengineering.stackexchange.com, got any tips where to ask instead? – Markus Meskanen Apr 11 '17 at 13:15
  • This isn't (easily) possible in Python, not without a lot of custom parsing work at least, but what you wrote would work almost as-is (you'd need to put the text strings in quotes, but that's all) in Boo, a Python-flavored language for the CLR, with no special parsing logic needed. It would allow you to define custom commands such as Item and Event as macros, which you could use to rewrite the code into the appropriate configuration and setup logic. I've actually used it for something very similar in a game engine. It's worth checking out! :) – Mason Wheeler Apr 11 '17 at 13:27
3

I once wrote a regex-based parser for a similar config language, but it was a lot of unnecessary work. Instead: use an existing configuration language like YAML – it has a JSON-like datamodel and a syntax almost indistinguishable from your example (you just need to use : | instead of : to start verbatim lines). Parsing is difficult to get right, so let someone else handle that.

The disadvantage of using any existing config language is that you can't create good error message. When one of your code snippets throws an error, the stack trace cannot point to the correct line of your config file.

Alternatively, it may be preferable to just write this as Python code. It's not that much extra syntax! At least that gives you syntax highlighting for your code, and proper line numbers for your stack traces. You can define decorators to perform validation or to register callbacks etc.

class Shield(GameObject):
  name = "Shield"
  description = "Block 10% of incoming damage, but move 10% slower"

  @event
  def event_defend(self, event_args):
    event_args['damage'] *= 0.9

  @event
  def event_spawn(self, event_args):
    event_args['player'].speed -= 0.1

class Warrior(GameObject):
  name = "Warrior"
  description = "Excels at close combat"

  items = [Shield()]

If you want to be “clever”, Python's decorators, metaclass protocol, descriptor objects, and superb reflection capabilities supply many opportunities to hook into class creation and behaviour. Unlike in C++ or Java, Python's classes are just ordinary objects, and as such certain game programming patterns like the type object pattern that avoid creation of extra classes are often unnecessary in Python.

  • Yeah my current implementation runs with metaclasses and decorating event callbacks, but I get constant feedback from users that they hate the "additional" Python boilerplate. Yaml seems awesome, any suggestions how to mix some Python with it? – Markus Meskanen Apr 11 '17 at 15:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.