2014-03-16

Plan G

Just a small update.

A few days back I stopped writing to work on building the world for Burn and I realized that it was really hard to do. Everything in the world has a displayed name and a unique identifier that is used for all kinds of stuff within the system. There are some simple checks done in the code to make sure that these identifiers don't intersect, but the corrective code also liked to change the identifiers while the displayed names were being edited. The end result was corruption of the data so I started to just manually edit identifiers in json. Managing hundreds of these identifiers for each person, place and verb becomes impossible after a while. So I've taken a step back to think about what the hell I'm doing.

The identifier doesn't need to be known by the player, but it also doesn't need to be known by the developer. The corrective code was there to prevent data issues, but it was a solution to a problem that shouldn't exist anyway. I was certain that other systems don't require any kind of management of identifiers like this but I hadn't really looked into any of them. I've been kind of stubborn about trying different game engines and I've even passed on working on projects that don't use Unity. Since I am basically trying to do things that have been done before I decided to look into how rooms are made in Inform, Adrift and Tads.


The process of creating a room in Inform7 seems to be as easy as writing 'Some Room is a room'. I don't know how it could be easier than that and Inform is pretty impressive to me. If I abandon ship on my system I'll definitely try Inform. Adrift doesn't look bad either. The most interesting thing to me is the map editor. Being able to visualize the world in 3d is pretty neat and I could see the advantage of it in the projects I've been working on. Looking at Tads 3... well... it looks like a pain in the ass to setup, but I take it a room is declared pretty easily along with it's description in a source code file. I haven't installed any of these tools, so these are just random observations from what I could find from a few searches.

There are great options out there but I have my reasons for building something new. I don't know if I've mentioned this about my system but it treats the world as something separate from things that are said about it and the state of it. Or in other words if you look at a person in the game, the description of that person should always match the state of the person. The person exists in a world manager and several descriptions of that person exist in a database that is separate from the person. The state of the person is also separate from the world and the descriptions so it's kind of like there are three subsystems working together to describe the person at any given time. Each system requires the other, but if the identifiers are screwed up it's basically a train wreck. The run time for the system works fine, it's just the design time part that is messed up right now. If I can just get the development tools working right I really believe the system will allow for some super interesting games.

I hope I can get this stuff sorted out and have Burn ready for testing by the end of the month. At the same time Burn is only a test project for the system so the system takes priority. Also once I finalize things I'll stop calling it "the system" and come up with a good name.

11 comments:

  1. Personally I7 has really won me over, mostly since it works much closer to how I actually think, and so programming makes a lot more sense to me. The big issue I find with I7 is scalability. I7 can handle hundreds and hundreds of rules pretty easily but it chugs when you have lots of objects with lots of properties. The big mistake a lot of people do is that they essentially take an object oriented approach rather than using the rule-based approach.

    ReplyDelete
    Replies
    1. I literally have no idea about using Inform but I would assume there is a way to break down an entire game's source code into multiple files that could be worked on separately. Twine was always sluggish for me with Hundreds of passages and links between them in the editor and I only realized that there was a multi file hack after I stopped using it. My editor scripts in Unity are sluggish right now with lots of rules, but I designed it to encourage using multiple files. Also rules in my system probably have a completely different meaning than in Inform. I'm kind of curious about how there are different approaches in Inform now.

      Delete
    2. Well, using separate source files is possible, since you can package your stuff up as an extension then include it in your source code, and there are various ways you can use external files, but I haven't really explored that, but the documentation presumes you are going to have essentially everything in the source file itself. There are ways to navigate to different parts of the source file but there's no separate compilation. That means a large project can take a bit of time to compile. My beefier computer takes 14 seconds to compile my current game. Extensions included, that's about 100,000 words long. I guess that's not long, but it's mostly just rules right now and not objects.

      Delete
    3. 14 seconds sounds bad if you have to make lots of small changes all the time and need to recompile everything to test them. I take it that editing the game generally isn't a problem though even with 100k words? With Twine I got to the point where I had too many passages displayed in the visual editor at once, so every action just lagged. I remember there was something about the algorithm used to add new passages that placed them far away from the actual location I was zoomed into in the story map. So then I had to slowly scroll way off into the distance to try and find the passage and drag it back to where it belonged. It became next to impossible to work with the lag but the build button was always fast enough. I still have a love/hate relationship with Twine, but I'm not looking back.

      Anyway I installed Inform and got far enough to see that there is a pretty neat testing thing built in. I hadn't even thought that far ahead with what I'm building now, but I'll add some kind of game testing to my distant future todos. I'm still not entirely sure about what you mean by object oriented vs rule-based approaches. When I hear object oriented I think of inheritance and instancing objects. I'm guessing you mean using rule-books to determine what to do, instead of trying to assess the state of an object directly to determine what to do? Again, I only understand a snippet of Inform and I think it's going to take me a while to dig through the docs.

      Delete
    4. I've had some fairly large source files, 80k+, and I7 handles it pretty smoothly. Oddly enough it's the commenting that lags. You can get around this by putting the end square bracket first. In any case, if editing is slow you can just take out some code and include it as an extension, so it's not a problem. You can also use the index to separate out bits that you are working on.

      I've only had a bit of experience with object based languages, so I'm no expert, but my understanding is this. With a rule based approach, separate cases are handled through rulebooks themselves. You have to specify how a rule handles what case. For example, if we were going to make a rulebook where the outcome determines whether someone dies from a fall, it might look something like this:

      Rule for lethal falling when the faller is landing on pillows: faller lives.

      Rule for lethal falling when the faller is landing on spikes: faller dies.

      Rule for lethal falling when the faller is going really fast: faller dies.

      As opposed to, say, having surfaces have a "falling lethality" property which determines life and death.

      Delete
    5. The last part is where I'm lost because I'm unsure how the property would be setup in Inform. In my mind I can see the scenario as code, but I have no idea how to translate that into Inform. I'm used to writing code so the natural language thing is ironically unnatural to me. I skimmed the docs and properties seem kind of complex to work with.

      That scenario would be kind of messy in Twine, or at least the way I was using it.

      In my 'the system' you would create some action that causes the player to fall, like 'Bad Guy, Check if he is getting closer'. When that action is taken a response is chosen from a huge collection of potential responses. So like the default thing would be:

      :: Rule Bad Guy Look Back
      You look back to see if you are still being chased, and the bad guy is gone. Unfortunately while not paying attention, you fell into a sewer drain.

      From there you can make a more specific response depending on any kind of player state. So if the player has a parachute equipped (yeah this makes no sense).

      :: Rule Bad Guy Look Back Parachute
      parachute = 1;
      You look back to see if you are still being chased, and the bad guy is gone. Unfortunately while not paying attention, you fell into a sewer drain. Good thing you brought your trusty parachute.

      Lets say the parachute is equipped but it's broken.

      :: Rule Bad Guy Look Back Parachute Malfunction
      parachute = 1;
      parachuteBusted = 1;
      You look back to see if you are still being chased, and the bad guy is gone. Unfortunately while not paying attention, you fell into a sewer drain. Good thing you brought your trusty parachute. You engage the parachute only to discover it has a large hole in it. Darn.

      All of the responses are sorted from most criteria to least so the closest match to the current state of the world is chosen. From there you could duplicate the responses and include different fall outcomes. If multiples rules have an equal amount of criteria, one is selected randomly and optionally with weights. That's where I would add landed on pillow and landed on spikes to the response. It's kind of a different way of looking at things, but I think it's pretty good.

      Delete
    6. Okay, well, if I were to do the same thing in Inform, the code would look something like this:

      [Code begins]

      The street is a room.

      The bad guy is a person in the street.

      The sewer drain is a thing in the street.

      The parachute is a thing in the street. The parachute can be fixed or busted. The parachute is fixed.

      Instead of examining the bad guy when the sewer drain is visible and the player is not carrying a parachute:
      say "You look back to see if you are still being chased, and the bad guy is gone. Unfortunately while not paying attention, you fell into a sewer drain.";
      end the story.

      Instead of examining the bad guy when the sewer drain is visible and the player is carrying a fixed parachute:
      say "You look back to see if you are still being chased, and the bad guy is gone. Unfortunately while not paying attention, you fell into a sewer drain. Good thing you brought your trusty parachute.";
      end the story.

      Instead of examining the bad guy when the sewer drain is visible and the player is carrying a busted parachute:
      say "You look back to see if you are still being chased, and the bad guy is gone. Unfortunately while not paying attention, you fell into a sewer drain. Good thing you brought your trusty parachute. You engage the parachute only to discover it has a large hole in it. Darn.";
      end the story.

      [Code ends]

      In theory, the code above should compile if you remove the space for tabs, but I haven't tested it yet. I hope that clarifies things a bit.

      Delete
    7. Thanks that helps a lot and I think based on that example that the rules do work the same way. That gives me some hope that I can write some kind of import/export tool for Inform. I can already see a few things that aren't one to one, but there is enough similarity that I could use variable and noun group naming conventions in my system to help with translation. I don't want to try and make up a new language to write content for my system, so being able to translate between other tools is pretty beneficial. I've been using tweecode from Twine but Inform source looks like a better fit.

      Sorry I guess I'm kind of thick but I'm still not understanding what the other way to set this up in Inform would look like. Assuming this is the rule based way, I am lost about the object oriented way. It's not a big deal because I obviously prefer the rule based way anyway.

      Delete
    8. You can have an object oriented approach in Inform, although it would be very awkward, and you'd still essentially be using rules. So let me take a recent example from my arousal extension for I7.

      [Rule based approach to arousal.]

      A person has a number called arousal. The arousal is usually 0.

      A body part is a kind of thing. A doohick is a kind of body part.

      The sensitivity rules are an object based rulebook producing a number.

      Carry out rubbing a doohick:
      [TAB]if the noun is enclosed by a person (called the individual):
      [TAB][TAB]increase the arousal of the individual by the number produced by the sensitivity rules for the noun.

      Sensitivity rule for a body part:
      [TAB]rule succeeds with result 5.

      [More object based approach.]

      A person has a number called arousal. The arousal is usually 0.

      A body part is a kind of thing. A doohick is a kind of body part.

      A body part has a number called sensitivity. The sensitivity of the doohick is 5.

      Carry out rubbing a doohick:
      [TAB]if the noun is enclosed by a person (called the individual):
      [TAB][TAB]increase the arousal of the individual by the sensitivity of the doohick.

      Delete
    9. I had to stare at the screen for a while, but now I get it (I think). The sensitivity is set explicitly in the object example, but rules allow you to take a bunch of stuff into account in order to set it. I'm guessing there would need to be a lot of if statements (not sure what they are called in Inform) to do that the object way. Then changing the logic would probably really suck as opposed to just adding a new rule. That is the same kind of problem I'm trying to avoid with my system. Here's how I'd set that up.

      Create a 'person' noun with a 'rub doohick' verb in the world editor.
      Generate a noun file for the runtime world system.
      Generate a rule file from the noun data. (this would make a single rule setup with criteria for the 'rub doohick' action on 'person')

      Open the rule editor and import the generated rule file.
      Add some response text to the rule to be displayed. (it's better to export the rule to a text file in tweecode format to write with something like word instead of writing directly in the Unity editor)
      Add context to the response of the rule. At runtime this adds the value of 5 to the variable 'personArousal'. ('personArousal' doesn't exist on the person object, it's just a piece of world state that exists at runtime)
      Generate the final runtime rule file and that's it.

      Assuming the player is in the same room as the person, they could select 'person' then 'rub doohick' and get back the right response. If I'm understanding the Inform Rules right the similarity between the systems is in the way multiple pieces of state can determine how things are handled, but not necessarily by working with objects directly.

      Delete
    10. Yeah, essentially. What I've found, just by experience, is that a lot of properties tend to slow I7 down quite a bit, so it's usually preferable to calculate them on the spot if possible, and to use rules instead of properties where you can.

      Delete