i7: instead ofs vs tables

The following is a simplification of how I cleaned up some code. It’s not specific to the attacking verb, but…

The “instead of attacking” used to have 40 different if-thens. Then I put it in a table, and it was so organized, I fixed a few bugs right away. I like this convenience. I want to start like this in the future, if I have, say, more than five if-thens in an instead/check rule.

However, I’m wondering if there’s a potential bad side to using tables for responses instead of the if-thens. Does it eat up significantly more memory? Is it potentially significantly slower with the table-searching? My suspicion is no, but I want to check off before I make wholesale changes.

I remember earlier topics about how tables are more efficient than lists, but I don’t know about them vs. if-thens.

[code]“Attacks” by Andrew Schultz

room 1 is a room. bo is a person in room 1. jo is a person in room 1. mo is a person in room 1. zo is a person in room 1.

instead of attacking:
if noun is a target listed in the table of attack-rej:
choose row with target of noun in table of attack-rej;
say “[nohit entry][line break]” instead;
say “No violence!”

table of attack-rej
target nohit
bo “No Bo.”
jo “M-m.”
mo “Don’t.”
yourself “You duck.”

test 1 with “attack bo/attack jo/attack mo/attack zo/attack me”[/code]

Tables are stored in a different part of memory from routines, but I don’t know which is more limited.

Tables will be slower and use a lot more memory. Keep to rules, but use multiple rules.

Thanks…this is what I was worried about. Maybe I should define something like attack-text instead? e.g. a thing has text called attack-text.

[code]a person has text called attack-text. attack-text of a person is usually “”.

room 1 is a room. bo is a person in room 1. attack-text of bo is “Bo says no.”. jo is a person in room 1. mo is a person in room 1. zo is a person in room 1.

instead of attacking:
if attack-text of noun is not “”:
say “[attack-text of noun]” instead;
[/code]

Just do this:

Instead of attacking bo: say "No Bo." instead.

Wow! I didn’t consider that’d be the easiest for Inform to read.

The thing is, I’m trying to make my code look neater, and I have the bad habit of throwing rules like this all over the place. So while this seems easiest for me, I’d have about 50 instead-of-attacking rules splattered throughout the code, and that’s gotten me in trouble before.

I suppose the best solution for me would be, in the future, to track these rules with a PERL script, to make sure I am lumping similar rules together in similar sections.

Thanks again!

Well when you have 50 of them you probably shouldn’t be using instead rules. Instead replace the standard rules for the attack action. Add a check rule for attacking yourself, and then some report rules to describe the effects. Kerkerkruip has probably got 50 report rules for its attack action.

Wasn’t that one of the requests that got implemented - you can say “Understand nothing as attack” and it detaches every synonym?

The original action does nothing, just unlist the block attacking rule and put in your own.

I think that, as a general rule, it’s best to jam as much stuff into the preamble of a rule as possible. The Inform compiler thinks a lot harder about rule preambles than it does about rule bodies. In this case, your original “Instead of attacking” rule was pretty terrible and error prone, as you discovered. “Instead of attacking Bo” is better. “Check attacking Bo” is even better, because it stays away from the (frequently huge and inefficient) Instead rulebook. “Check attacking Bo when the security guard can see the player” would be best, if it works (I have no idea). Basically, if you have a rule that says “if this other thing is also true, do stuff, otherwise ignore this rule”, then that test should probably be moved into the preamble (if it can).

Veterans, please feel free to contradict me here; if this is a mistaken belief I’d like to know soon!

I never realized how inefficient the “instead” rules were. I always just used them because I never bothered to wipe the block attacking rule–but I should. It is definitely easy enough.

Well, they’re not that inefficient that you’d have to go out of your way to avoid them. Also, you usually don’t need to remove the block attacking rule because any conditional check rules you write (Check attacking Bo: … or Check attacking when …:slight_smile: will always be more specific and take precedence over the block attacking rule.

The only case when you might want to remove the block attacking rule is when you want the action to succeed in some cases and go through the rest of the action rulebook, and sometimes not even then because you can conditionally ignore the block rule.