Creative Scope and I7

I’m in the process of updating Secret Letter. Graeme did a great job with the code, but some of the things we asked him to do made the code somewhat difficult to update. We made a ton of changes to the story based on feedback for a 2.0 release and we were able to implement all except the changes to the concluding chapter.

We decided to open up the ending with more interactivity. Its original form was nearly entirely on rails. It was bad.

In my 5th attempt to make these changes, I decided to simply create a new project and redo the final chapter by itself. I’ve pulled code from the main project as needed.

In doing this, something is bugging me. I’m almost tempted to believe that code may be better off segregated, even if it means rewriting things several times. It might just be easier to read. For example, we have a half dozen descriptions for a character. This is really annoyingly ugly. What if instead, we could implement a new description of a character in a different part of the code?

Bobby is a man. “Bobby is a cool dude.”

During the fight scene, the description of Bobby is “Bobby is weak from fighting and clearly in need of help.”

During the flight scene, the description of Bobby is “Bobby looks determined.”

I don’t know I7 as well as I should, but I’m starting to think it would be easier to maintain a large piece of code if it were partitioned completely. The dependencies can really get out of hand, similar to an old-school hierarchical domain model in the world of object-orientation.

Thoughts?

David C.

I’m a little confused by this example, and by what you mean by partitioning.

Are you talking about something like, ‘the description of John is “this [if this]this [if that] that”’ etcetera?

Also, what dependencies are you talking about exactly?

Have you considered implementing characters as different objects in different parts of the game? You could have Bobby a kind and derive different Bobbies from that. If you have something that applies to Bobby everywhere in the game you can refer to the kind. For example:

[code]Bobby is a kind of man. The description of a Bobby is usually “Bobby is a cool dude.” The printed name of a Bobby is always “Bobby”.

Instead of attacking a Bobby: [this applies to Bobby everywhere]
say “He’s your ally!”

Fighting-Bobby is a Bobby. The description of fighting-Bobby is “Bobby is weak from fighting and clearly in need of help.”
Fleeing-Bobby is a Bobby. The description of fleeing-Bobby is “Bobby looks determined.”[/code]

Another way is just overriding the descriptions:

[code]Bobby is a man. “Bobby is a cool dude.”

Instead of examining Bobby when the fight scene is happening:
say “Bobby is weak from fighting and clearly in need of help.”

Instead of examining Bobby when the flight scene is happening:
say “Bobby looks determined.”[/code]
The catch in the latter method is that if you use Bobby’s description as a substitution (“Bobby’s status: [description of bobby]”) you’ll get the original description.

You can split it up by getting it into a rule structure. (A phrase is not a rulebook, but you can define a multi-rule phrase like this.)

The description of the rock is “[rock-desc location][run paragraph on]”.

To say rock-desc (R - room):
say “It’s a rock.” [general case]

To say rock-desc (R - Kitchen):
say “It’s a kitchen rock.”

To say rock-desc (R - Bathroom):
say “It’s a bathroom rock.”

Quite nice. How does it compare in terms of speed? I know that liberal use of Before/Instead/After can bog things down pretty quick, but I’ve also heard (I believe Jeff Nyman demonstrated it) that the compiler is able to optimize to some degree when such rules have no chance of firing. So what the best solution would be is confuzzling at times.

The problems with before/instead/after came up because (in some earlier release) every such rule was checked on every action – even the rules that had nothing to do with the current action. That’s the kind of speed issue you have to worry about.

That doesn’t apply here; the tests for which string to print are only checked when you actually print the rock description.

This is interesting, but I was thinking more like namespaces, where code is entirely cut off from other namespaces unless explicitly referenced.

I don’t want to pester people too much about this. I am not a good I7 programmer and I spent most of my programming hours on C#.

At some point in the next few months I should have time to get back into writing games and I will have more thoughts on the subject.

David C.

Interesting. While I agree with David in that it’d be nice to have namespace-like ways of partitioning the code, I have one tangential question that confuses the heck out of me regarding the code you demonstrated. It works when it comes to locations (an object that varies, I think), but I tried creating a mood property for my character and basing the character’s description on that instead. If I do that, the “to say” block defaults to outputting the general text every time. What gives?

I have no explanation. Apparently the compiler can build this kind of phrase-rule structure for a kind of thing, but not for a kind of value.

You could probably get it to work by switching over to an activity.

(And for those keeping track at home, this is why I think I7 needs a unified underlying rule mechanism.)

Maybe you’re bumping up against bug #199?

It might be related in the depths of the compiler, but it’s not the same symptom. If you look at the generated I6 code, you can see that compiler is building an appropriate tree of "if"s for one case (rooms) but not for the other case (kinds of value).

That’s quite intriguing. I was halfway convinced the error would be something elementary that I’d overlooked.

Oh, yes. I’ve read some of your posts on the subject. It’s undeniably interesting, even though (or perhaps because) some of it sounds like black magic: powerful, yes, but more than a little mind-bending.

I fear I may have to reach some higher plane of knowledge in I6 before I’m qualified to present an answer on that one. Such as actually being able to understand it, just for starters. :slight_smile:

(In this respect I7’s success may actually be a detriment. Teaching myself I6 at this point puts me in mind of trying to bridge a slowly widening chasm using matchsticks and glue.)

There may be a more elegant way, but something like this would work:

[code]The description of Bobby is “Bobby is a cool dude. [Bobby status] [Bobby mood]”

Bobby-status and Bobby-mood are texts that vary.

To say Bobby status: say Bobby-status.

To say Bobby mood: say Bobby-mood.

When the fight-scene begins:
Now Bobby-status is “Bobby is weak from fighting and clearly in need of help,”;
Now Bobby-mood is “but he still looks determined.”

When the fight-scene ends:
Now Bobby-status is “Bobby is weak from fighting,”;
if Bobby is injured:
Now Bobby-mood is “and stoic against the pain.”;
otherwise:
Now Bobby-mood is “but almost euphoric with relief.”[/code]

That doesn’t address the issue, I’m afraid. The solution you propose creates cross-dependencies that would scale exponentially with the size of the game. We want to reduce the number of potential breaks and keep the code manageable, whereas this does the opposite.

Zarf’s solution, had it worked for an object, would have been easy enough to extend:

A state is a kind of value. The states are humming, blipping, blopping, crashing, and burning.
The computer has a state. The computer is humming.

The description of the computer is "[comp-desc state][run paragraph on]".

To say comp-desc (R - state):
say "The machine moves." [general case]

To say comp-desc (R - humming):
say "The computer hummmmms in gentle reproach."

Adding a new description would simply entail entering a new comp-desc, which would override the default state.