{"id":22,"date":"2011-05-30T15:39:12","date_gmt":"2011-05-30T20:39:12","guid":{"rendered":"http:\/\/www.playwithlua.com\/?p=22"},"modified":"2020-05-22T13:23:50","modified_gmt":"2020-05-22T18:23:50","slug":"interactive-fiction-part-2","status":"publish","type":"post","link":"http:\/\/www.playwithlua.com\/?p=22","title":{"rendered":"Interactive Fiction (part 2)"},"content":{"rendered":"<p>I decided to clean up and refactor the code some from part one, although it still works the same way: we still have behaviors that various objects can become. I&#8217;m not going to go through every part of the code, but I will talk about how behaviors are designed, explain the parser, how commands are handled, and how a prop (the lamp) is implemented.<\/p>\n<h2>Behaviors<\/h2>\n<p>First, here&#8217;s how you create a behavior:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">Something <span style=\"color: #66cc66;\">=<\/span> behavior<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n<span style=\"color: #aa9900; font-weight: bold;\">function<\/span> Something<span style=\"color: #66cc66;\">.<\/span>methods<span style=\"color: #66cc66;\">.<\/span>whatever<span style=\"color: #66cc66;\">&#40;<\/span>self<span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">...<\/span> <span style=\"color: #aa9900; font-weight: bold;\">end<\/span><\/pre><\/div><\/div><\/div>\n\n<p><!--more--><\/p>\n<p>Behaviors are now tables that contain a table of methods (called <code>methods<\/code>), a table of every object tied to that behavior (called <code>all<\/code>), and functions called to initialize or tear down objects that are gaining or resigning that behavior (<code>on_become<\/code> and <code>on_resign<\/code>). To create a new object:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">blah <span style=\"color: #66cc66;\">=<\/span> new<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #66cc66;\">&#123;<\/span> a<span style=\"color: #66cc66;\">=<\/span><span style=\"color: #cc66cc;\">5<\/span> <span style=\"color: #66cc66;\">&#125;<\/span><span style=\"color: #66cc66;\">,<\/span> Something<span style=\"color: #66cc66;\">&#41;<\/span><\/pre><\/div><\/div><\/div>\n\n<p>This creates an object called <code>blah<\/code> that has a field &#8220;a&#8221; equal to 5, and two behaviors: Something and Object. That&#8217;s right, Object is a behavior, containing methods like <code>become<\/code> and <code>resign<\/code>, and every object we create behaves like an Object (unless they resign the Object behavior). We can resign things like so:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">blah<span style=\"color: #66cc66;\">:<\/span>resign<span style=\"color: #66cc66;\">&#40;<\/span>Something<span style=\"color: #66cc66;\">&#41;<\/span><\/pre><\/div><\/div><\/div>\n\n<p>Now blah behaves like an Object but not like a Something, so we can still call <code>become<\/code> (because that method is how an Object behaves) but not <code>whatever<\/code>.<\/p>\n<h2>Rulebooks<\/h2>\n<p>In order to respond to commands, we will have this idea of &#8220;rules&#8221;. A rule is simply a function that takes a command and returns either a response (a string to give the user) or nil. Rooms have rules, props have rules, the game has global rules, but they all behave the same way, so, let&#8217;s make a behavior for them:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">Rulebook <span style=\"color: #66cc66;\">=<\/span> behavior<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n&nbsp;\n<span style=\"color: #aa9900; font-weight: bold;\">function<\/span> Rulebook<span style=\"color: #66cc66;\">.<\/span>on_become<span style=\"color: #66cc66;\">&#40;<\/span>obj<span style=\"color: #66cc66;\">&#41;<\/span>\n   obj<span style=\"color: #66cc66;\">.<\/span>rules <span style=\"color: #66cc66;\">=<\/span> obj<span style=\"color: #66cc66;\">.<\/span>rules <span style=\"color: #aa9900; font-weight: bold;\">or<\/span> <span style=\"color: #66cc66;\">&#123;<\/span><span style=\"color: #66cc66;\">&#125;<\/span>\n<span style=\"color: #aa9900; font-weight: bold;\">end<\/span><\/pre><\/div><\/div><\/div>\n\n<p>Every object that behaves like a Rulebook must contain a list of rules, so we&#8217;ll add an empty one to it when it becomes a Rulebook. Now, a Rulebook has to be able to handle a command, by letting the rules that apply to it give their response:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\"><span style=\"color: #aa9900; font-weight: bold;\">function<\/span> Rulebook<span style=\"color: #66cc66;\">.<\/span>methods<span style=\"color: #66cc66;\">.<\/span>handle<span style=\"color: #66cc66;\">&#40;<\/span>rulebook<span style=\"color: #66cc66;\">,<\/span> command<span style=\"color: #66cc66;\">&#41;<\/span>\n   <span style=\"color: #aa9900; font-weight: bold;\">local<\/span> message <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #aa9900;\">nil<\/span>\n&nbsp;\n   <span style=\"color: #aa9900; font-weight: bold;\">for<\/span> _<span style=\"color: #66cc66;\">,<\/span> rule <span style=\"color: #aa9900; font-weight: bold;\">in<\/span> <span style=\"color: #0000aa;\">ipairs<\/span><span style=\"color: #66cc66;\">&#40;<\/span>rulebook<span style=\"color: #66cc66;\">.<\/span>rules<span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #aa9900; font-weight: bold;\">do<\/span>\n\t  message <span style=\"color: #66cc66;\">=<\/span> rule<span style=\"color: #66cc66;\">&#40;<\/span>rulebook<span style=\"color: #66cc66;\">,<\/span> command<span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #aa9900; font-weight: bold;\">or<\/span> message\n   <span style=\"color: #aa9900; font-weight: bold;\">end<\/span>\n&nbsp;\n   <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> message\n<span style=\"color: #aa9900; font-weight: bold;\">end<\/span><\/pre><\/div><\/div><\/div>\n\n<p>Note that we keep going even after a rule has responded; a well-designed Rulebook will only have one rule that applies to each command but more that one might need to be informed (think about a rule that increments a timer every turn but never gives a response, say). Later on we may need to let commands return more than just a response (like a flag saying whether any other rules should run) but this is fine for now.<\/p>\n<h2>Rooms<\/h2>\n<p>Rooms are about the same as before. However, we no longer keep the big global list of rooms, because the Room behavior does that itself, we just need to write a function to look up rooms by name:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\"><span style=\"color: #aa9900; font-weight: bold;\">function<\/span> Room<span style=\"color: #66cc66;\">.<\/span>find_by_name<span style=\"color: #66cc66;\">&#40;<\/span>_<span style=\"color: #66cc66;\">,<\/span> name<span style=\"color: #66cc66;\">&#41;<\/span>\n   <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> Room<span style=\"color: #66cc66;\">.<\/span>all<span style=\"color: #66cc66;\">:<\/span>select<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #aa9900; font-weight: bold;\">function<\/span><span style=\"color: #66cc66;\">&#40;<\/span>room<span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> room<span style=\"color: #66cc66;\">.<\/span>name <span style=\"color: #66cc66;\">==<\/span> name <span style=\"color: #aa9900; font-weight: bold;\">end<\/span><span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">&#91;<\/span><span style=\"color: #cc66cc;\">1<\/span><span style=\"color: #66cc66;\">&#93;<\/span>\n<span style=\"color: #aa9900; font-weight: bold;\">end<\/span><\/pre><\/div><\/div><\/div>\n\n<p>And tell the Room behavior to use that for its __index, so we can say something like <code>Room.Kitchen<\/code>:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\"><span style=\"color: #0000aa;\">setmetatable<\/span><span style=\"color: #66cc66;\">&#40;<\/span>Room<span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #66cc66;\">&#123;<\/span>__index <span style=\"color: #66cc66;\">=<\/span> Room<span style=\"color: #66cc66;\">.<\/span>find_by_name<span style=\"color: #66cc66;\">&#125;<\/span><span style=\"color: #66cc66;\">&#41;<\/span><\/pre><\/div><\/div><\/div>\n\n<p>Since all Rooms are also Rulebooks, we&#8217;ll make a quick function to make it easier to create them:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\"><span style=\"color: #aa9900; font-weight: bold;\">function<\/span> Room<span style=\"color: #66cc66;\">.<\/span>new<span style=\"color: #66cc66;\">&#40;<\/span>attrs<span style=\"color: #66cc66;\">&#41;<\/span>\n   <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> new<span style=\"color: #66cc66;\">&#40;<\/span>attrs<span style=\"color: #66cc66;\">,<\/span> Room<span style=\"color: #66cc66;\">,<\/span> Rulebook<span style=\"color: #66cc66;\">&#41;<\/span>\n<span style=\"color: #aa9900; font-weight: bold;\">end<\/span><\/pre><\/div><\/div><\/div>\n\n<h2>Props<\/h2>\n<p>Now we&#8217;re ready to do something that&#8217;s not just reorganization of the old code: props. &#8220;Prop&#8221; will be a behavior, obviously, and I&#8217;ve already said that all Props are Rulebooks. All Props also have a name, an article (which defaults to &#8220;a&#8221;, and is used in constructing messages, like &#8220;<em>a<\/em> boat and <em>some<\/em> water&#8221;), and a container. The container is the thing (either a Room or a Prop) that this Prop is inside, and it will be used later on to find all the props we can see. So, creating the Prop behavior:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">Prop <span style=\"color: #66cc66;\">=<\/span> behavior<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\nProp<span style=\"color: #66cc66;\">.<\/span>methods<span style=\"color: #66cc66;\">.<\/span>article <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #ff6666;\">&quot;a&quot;<\/span>\n&nbsp;\n<span style=\"color: #aa9900; font-weight: bold;\">function<\/span> Prop<span style=\"color: #66cc66;\">.<\/span>new<span style=\"color: #66cc66;\">&#40;<\/span>name<span style=\"color: #66cc66;\">,<\/span> container<span style=\"color: #66cc66;\">&#41;<\/span>\n   <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> new<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #66cc66;\">&#123;<\/span> name <span style=\"color: #66cc66;\">=<\/span> name<span style=\"color: #66cc66;\">,<\/span> container <span style=\"color: #66cc66;\">=<\/span> container <span style=\"color: #66cc66;\">&#125;<\/span><span style=\"color: #66cc66;\">,<\/span> Rulebook<span style=\"color: #66cc66;\">,<\/span> Prop<span style=\"color: #66cc66;\">&#41;<\/span>\n<span style=\"color: #aa9900; font-weight: bold;\">end<\/span><\/pre><\/div><\/div><\/div>\n\n<p>Note that we&#8217;re a Rulebook first and a Prop second. Since behaviors are applied in order, and the most-recently-applied takes precedence, this enables us to have Prop change how props handle commands. Also, notice that the default article &#8220;a&#8221; is put in <code>methods<\/code>. <code>methods<\/code> holds not just functions but anything that you want each object to be able to override.<\/p>\n<h2>Parser<\/h2>\n<p>Now, the parser. This is actually pretty simple. We want to take a string, like &#8220;give gold coin to merchant&#8221;, and turn it into a command. So, we have to decide what kind of grammar we&#8217;ll accept. The tricky part is that some things can be multiple words, like &#8220;gold coin&#8221;, and there are different forms of sentences that are valid, like we could also understand &#8220;walk north&#8221; or &#8220;drop brick&#8221;.<\/p>\n<p>There are four parts of speech we&#8217;ll try to capture:<\/p>\n<ol>\n<li>Verb: always in the first position, always one word, not optional.<\/li>\n<li>Preposition: can only be one of about 70 words, which we have a list of (like &#8220;under&#8221; and &#8220;to&#8221;). Marks the end of the second term, if there is one.<\/li>\n<li>Subject: everything between the verb and the preposition. This is what the verb will be done to.<\/li>\n<li>Object: everything after the preposition. This is more information that the verb\/subject needs to run.<\/li>\n<\/ol>\n<p>There are, of course, as many weird edge cases as you can think of, but what we&#8217;ll do is cheat: have rules in the game to rewrite these perverse commands into something that makes sense, like, if the verb is &#8220;turn&#8221; or &#8220;switch&#8221;, then the preposition (which is &#8220;on&#8221; or &#8220;off&#8221;) gets stored as the object. Anyway, here&#8217;s the little bit of code to do the parsing, courtesy of Lua&#8217;s <code>string.gmatch<\/code>:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\"><span style=\"color: #aa9900; font-weight: bold;\">function<\/span> Game<span style=\"color: #66cc66;\">.<\/span>methods<span style=\"color: #66cc66;\">.<\/span>parse<span style=\"color: #66cc66;\">&#40;<\/span>game<span style=\"color: #66cc66;\">,<\/span> str<span style=\"color: #66cc66;\">&#41;<\/span>\n   str <span style=\"color: #66cc66;\">=<\/span> str<span style=\"color: #66cc66;\">:<\/span>lower<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n   <span style=\"color: #aa9900; font-weight: bold;\">local<\/span> words<span style=\"color: #66cc66;\">,<\/span> term <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #0000aa;\">table<\/span><span style=\"color: #66cc66;\">.<\/span>new<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #aa9900;\">nil<\/span>\n   <span style=\"color: #aa9900; font-weight: bold;\">for<\/span> word <span style=\"color: #aa9900; font-weight: bold;\">in<\/span> str<span style=\"color: #66cc66;\">:<\/span>gmatch<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;%w+&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #aa9900; font-weight: bold;\">do<\/span> words<span style=\"color: #66cc66;\">:<\/span>insert<span style=\"color: #66cc66;\">&#40;<\/span>word<span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #aa9900; font-weight: bold;\">end<\/span>\n   <span style=\"color: #aa9900; font-weight: bold;\">local<\/span> command <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #66cc66;\">&#123;<\/span>game <span style=\"color: #66cc66;\">=<\/span> game<span style=\"color: #66cc66;\">,<\/span> verb <span style=\"color: #66cc66;\">=<\/span> words<span style=\"color: #66cc66;\">:<\/span><span style=\"color: #0000aa;\">remove<\/span><span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #cc66cc;\">1<\/span><span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">&#125;<\/span>\n&nbsp;\n   <span style=\"color: #aa9900; font-weight: bold;\">for<\/span> i<span style=\"color: #66cc66;\">,<\/span> word <span style=\"color: #aa9900; font-weight: bold;\">in<\/span> <span style=\"color: #0000aa;\">ipairs<\/span><span style=\"color: #66cc66;\">&#40;<\/span>words<span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #aa9900; font-weight: bold;\">do<\/span>\n\t  <span style=\"color: #aa9900; font-weight: bold;\">if<\/span> Game<span style=\"color: #66cc66;\">.<\/span>prepositions<span style=\"color: #66cc66;\">&#91;<\/span>word<span style=\"color: #66cc66;\">&#93;<\/span> <span style=\"color: #aa9900; font-weight: bold;\">then<\/span>\n\t\t command<span style=\"color: #66cc66;\">.<\/span>preposition <span style=\"color: #66cc66;\">=<\/span> word\n\t\t command<span style=\"color: #66cc66;\">.<\/span>subject <span style=\"color: #66cc66;\">=<\/span> term\n\t\t term <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #aa9900;\">nil<\/span>\n\t  <span style=\"color: #aa9900; font-weight: bold;\">elseif<\/span> term <span style=\"color: #aa9900; font-weight: bold;\">then<\/span>\n\t\t term <span style=\"color: #66cc66;\">=<\/span> term <span style=\"color: #66cc66;\">..<\/span> <span style=\"color: #ff6666;\">&quot; &quot;<\/span> <span style=\"color: #66cc66;\">..<\/span> word\n\t  <span style=\"color: #aa9900; font-weight: bold;\">else<\/span>\n\t\t term <span style=\"color: #66cc66;\">=<\/span> word\n\t  <span style=\"color: #aa9900; font-weight: bold;\">end<\/span>\n   <span style=\"color: #aa9900; font-weight: bold;\">end<\/span>\n&nbsp;\n   <span style=\"color: #aa9900; font-weight: bold;\">if<\/span> command<span style=\"color: #66cc66;\">.<\/span>preposition <span style=\"color: #aa9900; font-weight: bold;\">then<\/span>\n\t  command<span style=\"color: #66cc66;\">.<\/span>object <span style=\"color: #66cc66;\">=<\/span> term\n   <span style=\"color: #aa9900; font-weight: bold;\">else<\/span>\n\t  command<span style=\"color: #66cc66;\">.<\/span>subject <span style=\"color: #66cc66;\">=<\/span> term\n   <span style=\"color: #aa9900; font-weight: bold;\">end<\/span>\n&nbsp;\n   <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> command\n<span style=\"color: #aa9900; font-weight: bold;\">end<\/span><\/pre><\/div><\/div><\/div>\n\n<h2>Game command handling<\/h2>\n<p>After much thought, I decided that we needed multiple rulebooks for handling each command. We&#8217;ll try each rulebook in a certain order, and that should be sufficient to handle most of the cases of rules conflicting. So, there are five layers:<\/p>\n<ol>\n<li><code>Game.system_rules<\/code>: This holds things like &#8220;exit&#8221; and &#8220;save&#8221;, that you really don&#8217;t want to ever override. It goes first.<\/li>\n<li><code>Game.current_room<\/code>: The current room the player is in might have special conditions that should override everything else, like if it&#8217;s dark.<\/li>\n<li><code>Game.global_rules<\/code>: The game has global rules for handling things like movement, inventory, etc.<\/li>\n<li><code>subject<\/code>: The subject of the command gets to determine how it handles commands, if nothing else overrides it.<\/li>\n<li><code>Game.last_chance<\/code>: The game also has a set of last chance rules; if the command gets to here then it&#8217;s probably an error, so we&#8217;ll detect the common cases here and try to give a helpful error message.<\/li>\n<\/ol>\n<p>It seems a little over-complicated but in practice, most rules will go in the props or the room. The author should never have to touch system or last chance rules, and very rarely global rules.<\/p>\n<p>Props will do their command-handling a little differently: first they&#8217;ll try a list of rules, just like normal, but if that doesn&#8217;t yield a response they&#8217;ll send the command to a method named the same as the verb. This means that most of our code can be written with just <code>Prop.whatever.verbname<\/code>:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\"><span style=\"color: #aa9900; font-weight: bold;\">function<\/span> Prop<span style=\"color: #66cc66;\">.<\/span>methods<span style=\"color: #66cc66;\">.<\/span>handle<span style=\"color: #66cc66;\">&#40;<\/span>prop<span style=\"color: #66cc66;\">,<\/span> command<span style=\"color: #66cc66;\">&#41;<\/span>\n   <span style=\"color: #aa9900; font-weight: bold;\">local<\/span> resp <span style=\"color: #66cc66;\">=<\/span> Rulebook<span style=\"color: #66cc66;\">.<\/span>methods<span style=\"color: #66cc66;\">.<\/span>handle<span style=\"color: #66cc66;\">&#40;<\/span>prop<span style=\"color: #66cc66;\">,<\/span> command<span style=\"color: #66cc66;\">&#41;<\/span>\n&nbsp;\n   <span style=\"color: #aa9900; font-weight: bold;\">if<\/span> resp <span style=\"color: #aa9900; font-weight: bold;\">then<\/span> <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> resp\n   <span style=\"color: #aa9900; font-weight: bold;\">elseif<\/span> prop<span style=\"color: #66cc66;\">&#91;<\/span>command<span style=\"color: #66cc66;\">.<\/span>verb<span style=\"color: #66cc66;\">&#93;<\/span> <span style=\"color: #aa9900; font-weight: bold;\">then<\/span>\n\t  <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> prop<span style=\"color: #66cc66;\">&#91;<\/span>command<span style=\"color: #66cc66;\">.<\/span>verb<span style=\"color: #66cc66;\">&#93;<\/span><span style=\"color: #66cc66;\">&#40;<\/span>prop<span style=\"color: #66cc66;\">,<\/span> command<span style=\"color: #66cc66;\">&#41;<\/span>\n   <span style=\"color: #aa9900; font-weight: bold;\">else<\/span>\n\t  <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> <span style=\"color: #aa9900;\">nil<\/span>\n   <span style=\"color: #aa9900; font-weight: bold;\">end<\/span>\n<span style=\"color: #aa9900; font-weight: bold;\">end<\/span><\/pre><\/div><\/div><\/div>\n\n<h2>A prop<\/h2>\n<p>So now that that&#8217;s out of the way, let&#8217;s implement a simple prop, the lamp. It will support two verbs, &#8220;examine&#8221; and &#8220;turn&#8221;, so you can &#8220;turn on lamp&#8221; or you can &#8220;turn off lamp&#8221;, and you can see if it&#8217;s on or off with &#8220;examine lamp&#8221;. First make a prop:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">Prop<span style=\"color: #66cc66;\">.<\/span>new<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;lamp&quot;<\/span><span style=\"color: #66cc66;\">,<\/span> Room<span style=\"color: #66cc66;\">.<\/span>Bedroom<span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #808080; font-style: italic;\">-- It starts out in the bedroom<\/span>\nProp<span style=\"color: #66cc66;\">.<\/span>lamp<span style=\"color: #66cc66;\">.<\/span>turned_on <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #aa9900;\">false<\/span> <span style=\"color: #808080; font-style: italic;\">-- Record whether it's on or off<\/span><\/pre><\/div><\/div><\/div>\n\n<p>Now handle turning it on and off:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\"><span style=\"color: #aa9900; font-weight: bold;\">function<\/span> Prop<span style=\"color: #66cc66;\">.<\/span>lamp<span style=\"color: #66cc66;\">.<\/span>turn<span style=\"color: #66cc66;\">&#40;<\/span>lamp<span style=\"color: #66cc66;\">,<\/span> command<span style=\"color: #66cc66;\">&#41;<\/span>\n   <span style=\"color: #aa9900; font-weight: bold;\">if<\/span> command<span style=\"color: #66cc66;\">.<\/span>preposition <span style=\"color: #66cc66;\">==<\/span> <span style=\"color: #ff6666;\">&quot;on&quot;<\/span> <span style=\"color: #aa9900; font-weight: bold;\">then<\/span>\n\t  lamp<span style=\"color: #66cc66;\">.<\/span>turned_on <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #aa9900;\">true<\/span>\n\t  <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> <span style=\"color: #ff6666;\">&quot;You turn the lamp on.&quot;<\/span>\n   <span style=\"color: #aa9900; font-weight: bold;\">elseif<\/span> command<span style=\"color: #66cc66;\">.<\/span>preposition <span style=\"color: #66cc66;\">==<\/span> <span style=\"color: #ff6666;\">&quot;off&quot;<\/span> <span style=\"color: #aa9900; font-weight: bold;\">then<\/span>\n\t  lamp<span style=\"color: #66cc66;\">.<\/span>turned_on <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #aa9900;\">false<\/span>\n\t  <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> <span style=\"color: #ff6666;\">&quot;You turn the lamp off.&quot;<\/span>\n   <span style=\"color: #aa9900; font-weight: bold;\">end<\/span>\n<span style=\"color: #aa9900; font-weight: bold;\">end<\/span><\/pre><\/div><\/div><\/div>\n\n<p>And then a function to examine it:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\"><span style=\"color: #aa9900; font-weight: bold;\">function<\/span> Prop<span style=\"color: #66cc66;\">.<\/span>lamp<span style=\"color: #66cc66;\">.<\/span>examine<span style=\"color: #66cc66;\">&#40;<\/span>lamp<span style=\"color: #66cc66;\">,<\/span> command<span style=\"color: #66cc66;\">&#41;<\/span>\n   <span style=\"color: #aa9900; font-weight: bold;\">if<\/span> lamp<span style=\"color: #66cc66;\">.<\/span>turned_on <span style=\"color: #aa9900; font-weight: bold;\">then<\/span>\n\t  <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> <span style=\"color: #ff6666;\">&quot;The lamp is glowing brightly.&quot;<\/span>\n   <span style=\"color: #aa9900; font-weight: bold;\">else<\/span>\n\t  <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> <span style=\"color: #ff6666;\">&quot;The lamp is dark.&quot;<\/span>\n   <span style=\"color: #aa9900; font-weight: bold;\">end<\/span>\n<span style=\"color: #aa9900; font-weight: bold;\">end<\/span><\/pre><\/div><\/div><\/div>\n\n<p>That actually looks really straightforward, right? All the code to handle this is in one place, and it doesn&#8217;t need to worry about knowing about any other objects. If we really wanted to, we could make Lamp into a behavior even, just by making it define these two methods. Let&#8217;s try it out:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\"><span style=\"color: #66cc66;\">&gt;<\/span> <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> game<span style=\"color: #66cc66;\">:<\/span>input<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;examine lamp&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n    <span style=\"color: #ff6666;\">&quot;The lamp is dark.&quot;<\/span>\n<span style=\"color: #66cc66;\">&gt;<\/span> <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> game<span style=\"color: #66cc66;\">:<\/span>input<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;turn lamp on&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n    <span style=\"color: #ff6666;\">&quot;You turn the lamp on.&quot;<\/span>\n<span style=\"color: #66cc66;\">&gt;<\/span> <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> game<span style=\"color: #66cc66;\">:<\/span>input<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;examine lamp&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n    <span style=\"color: #ff6666;\">&quot;The lamp is glowing brightly.&quot;<\/span><\/pre><\/div><\/div><\/div>\n\n<p>Very simple.<\/p>\n<h2>What&#8217;s next?<\/h2>\n<p>The game engine works but it only really responds to those two commands. All the basic commands like walk, get, say, etc. need to be implemented, as well as concepts like darkness, open \/ locked doors, and so on. So there&#8217;s still a lot of work making an interactive fiction standard library, but the basic scaffolding of parsing and handling commands is there, as well as describing items and locations.<\/p>\n<p>If you want to write up any of that standard library, <a onclick=\"javascript:pageTracker._trackPageview('\/outgoing\/github.com\/randrews\/lua-if');\"  href=\"http:\/\/github.com\/randrews\/lua-if\">here&#8217;s the code so far<\/a>. Have fun!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I decided to clean up and refactor the code some from part one, although it still works the same way: we still have behaviors that various objects can become. I&#8217;m not going to go through every part of the code, but I will talk about how behaviors are designed, explain the parser, how commands are [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[],"_links":{"self":[{"href":"http:\/\/www.playwithlua.com\/index.php?rest_route=\/wp\/v2\/posts\/22"}],"collection":[{"href":"http:\/\/www.playwithlua.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.playwithlua.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.playwithlua.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.playwithlua.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=22"}],"version-history":[{"count":0,"href":"http:\/\/www.playwithlua.com\/index.php?rest_route=\/wp\/v2\/posts\/22\/revisions"}],"wp:attachment":[{"href":"http:\/\/www.playwithlua.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=22"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.playwithlua.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=22"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.playwithlua.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=22"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}