Elegant command-parsing in an OOP-based text game

前端 未结 5 1395
情话喂你
情话喂你 2021-02-09 01:52

I\'m playing with writing a MUD/text adventure (please don\'t laugh) in Ruby. Can anyone give me any pointers towards an elegant, oop-based solution to parsing input text? <

相关标签:
5条回答
  • 2021-02-09 02:19

    Split it into tokens as the format will always be:
    [command] [object1] ([refering] [object2])

    You could call method [command] on the [object1] in your room and pass it the [object2] if applicable.

    0 讨论(0)
  • 2021-02-09 02:26

    Ok. So you need a semantic ? (turn is an action, light an object, on an argument... (I relate to your comment to dbemerlin)).

    Why not defining a grammar ? humm... I guess lex and yacc are not a option ? (since it's not OOP at all, but what you want to do is to "compile" user input to produce something - executing some code who change the data of the room, and output a result)

    You can have an OOP design for your object and its action (like, all objects have a .describeMe() method ..) , and beside that, an input parser+compiler.

    Am I completely off the subject?

    Edit : after looking to the interpreter pattern pointed out by Marc Seeman, it seems to be the way to go in you want it in OOP. (but you will somewhat re-invent the wheel)

    0 讨论(0)
  • 2021-02-09 02:31

    The Interpreter design pattern is the most object-oriented approach to parsing that I'm aware of, but I'm sure compiler experts will point out algorithms that are more powerful.

    0 讨论(0)
  • 2021-02-09 02:35

    Sounds like you need a parser.

    Split the input string into tokens (words). Then feed the tokens, one at a time, to a state machine. I find that the push-down automata is rather intuitive and powerful way to write such an stm.

    0 讨论(0)
  • 2021-02-09 02:37

    For command interpreters, I'm rather fond of this simple, not all that elegant pattern. Patterns in dynamic languages tend to involve fewer boxes and lines than GOF patterns.

    class Thing
    
      # Handle a command by calling the method "cmd_" + command.
      # Raise BadCommand exception if there is no method for that command.
    
      def handle_command(command, args)
        method_name = "cmd_#{command}"
        raise BadCommand, command unless respond_to?(method_name)
        send(method_name, args)
      end
    
      def cmd_quit(args)
        # the code for command "quit"
      end
    
      def cmd_list(args)
        # the code for command "list"
      end
    
      ...
    
    end
    

    In this way, adding a new command is just adding a new method. No tables or case statements need to be adjusted.

    0 讨论(0)
提交回复
热议问题