Setting up a list of "qualities" or "parts" of people

New to the forum, not new to programming, relatively new to Inform.
I’m creating a sci-fi based game environment, and I would appreciate some assistance.

In this game, each person can have programs. There will be probably 30 programs by the time I’m done. Each program has a “rating” and can be either actively running or currently deactivated. There may end up being other qualities for each program later.

Each person (player & NPC people) can have a different rating # for each of their own programs. So for example, one person can have “Medic” with a rating 8. Another may have it at rating 2.

I have tried a few ways of doing this. I started with one of the examples for spells, had the player “carry” each program as if it were an item in their carry-all. Then NPCs had values like medic-rating which was a number, and I’d just assume if it had a number, it was also activated.

This breaks down in rulebooks and having the NPCs act on their own or being persuaded to act on the behalf of the player. It would be easier to use (oversimplified example) “the rating of medic of the actor” and have the same rule apply whether an NPC or the player were attempting to use it.

So I switched over to “parts of a person” – using a table of kinds, and assigning all these programs to every person (actually to every icon, which is a sub-kind of person). Now there’s Your Friend’s Medic, and The Evil Baddy’s Medic… and it works to an extent (although this may break again when there are many more NPCs in the game…).

So:

  1. I’m willing to try it yet-another-way even though I just spent a day re-doing the system to use parts of people. Combing through the rules and some of the finished examples, I can’t seem to find anything quite like what I’ve done.

  2. Alternatively – if this IS the best way to do it (I hope there’s a better way! a less memory-intensive way :wink: ) – I’m having particular trouble simply listing all of a player’s “parts” so that I can have a list of activated vs. deactivated programs. I’ve tried a bunch of things, but can’t figure this out – or even whether it’s possible.

I’d like a list of:
Medic (8)
Armor (3)

etc. – rather than:
Your Armor (3)
Your Medic (8)

(it would actually be messier, because the player is actually “Matrix Persona” so the list would be very ugly…)

I fought with the program until I finally got a list of “parts” of the person. That took a bit, because there were no documented examples of it. I gave up on trying to get it to give me the parent “kind” of the item it finds (which would be the base name of the program). This would certainly be easier…

Now, I’m trying to regex the names to strip out the actor’s name. This COULD be a bug… Given a clean inform document, I can’t get “Cleopatra’s” out of the output.

I can get the “printed name” into an indexed text variable. Regex refuses to parse the 's. I tried single-quote “'s (.?)", escaped-single-quote "'s (.?)”, and even the more risky non-specific \p punctuation catch-all “\ps (.?)". I can capture the s – "s (.?)” works fine – but not that darned apostrophe! Is it an HTML entity?!? The regexes fail when I try to include the apostrophe. If it’s an HTML entity, or other UTF-? character, shouldn’t it match on \p?

So here’s code that I’ve tried as proof-of-concept in a fresh document:

The Staging Area is a room.

Antony and Cleopatra are people in the Staging Area.

A program is a kind of thing.   
A program has a truth state called activated.  Activated is usually true.  A program has a number called rating.  Rating is usually 0.  some kinds of programs are defined by the Table of Matrix-Programs.

Table of Matrix-Programs
program	rating	activated
analyze	1	true

Getting programs is an action applying to nothing.
Understand "Programs" as getting programs.
Instead of getting programs:
	let thesethings be the list of programs incorporated by Cleopatra;
	showme thesethings;
	repeat with thisthing running through thesethings:
		if the activated of thisthing is true and the rating of thisthing is greater than 0:
			let printname be an indexed text;
			now printname is the printed name of thisthing;
			showme printname;
			if printname matches the regular expression "\ps (.*?)$": 
				showme text matching regular expression;
				showme text matching subexpression 1;
				change printname to the text matching subexpression 1;
				say "  [printname] ([rating of thisthing])[line break]";
			otherwise:
				say "Argh!";

It’s like magic – take out the ’ and everything is OK – put it back in and it’s all “Argh!” :slight_smile:

Whether there’s a better way or not, this could be a bug…or at least an “undocumented feature”? :slight_smile:

Seems regex \p doesn’t match single quotes:

Yep, apparently if you change to \P it DOES match the '. Again: “Argh!” but this time the Argh! message doesn’t come up. :wink: So ’ is not punctuation. hrm… [^\p\w]…this could get convoluted…

No clue on the regex stuff.

The other bit is a tricky problem, and this is a first stab - I’m sure someone will come along with something elegant shortly. But I’d be tempted to give people a table of skills. The skills could either be defined as values, or with text, and there’d be a column for the skill’s level/rating and for its activation.

Table of Normal Skills skill rating activation "medic" 5 true "armor" 3 false

Each person would probably need their own table, if everyone is constantly adjusting. If not, they could share a table.

A person has a table-name called skill table.  The skill table of a person is usually the Table of Normal Skills.  The skill table of Bob is the Table of Bob's Skills.

The nasty bit about this is that the readability gets a bit squirrelly:

[code]The description of a person is usually “[skills of the item described]”.

To say skills of (target - a person):
sort the skill table of the target in activation order;
repeat through the skill table:
if the activation entry is true:
say “[skill entry in sentence case]: [rating entry]”;
say line break;
if target is a medic:
say “[The target] is a medic.”

Definition: a person is a medic if the rating corresponding to a skill of “medic” in the skill table of it is greater than 3 and the activation corresponding to a skill of “medic” in the skill table of it is true.
[/code]

But if you built up phrases, it might not be so bad. For instance, you could have something like this to toggle off a skill:

To deactivate (ability - some text) on (target - a person): if the ability is a skill listed in the skill table of target: now the activation corresponding to a skill of ability in the skill table of the target is false;

And once you’ve got that layer in place, it’s much easier to write.

After looking: deactivate "medic" on Bob;

You could also consider having a table per skill, with the list of people and their skill level - it just depends on how it makes sense to you. Again, you’d probably want a layer of definitions in place to make the code easier to read.

(the entire test code from above in one nice dump):

[spoiler][code]The Lab is a room. Bob is a man in the Lab.

Table of Normal Skills
skill rating activation
“medic” 5 true
“armor” 3 false

Table of Bob’s Skills
skill rating activation
“medic” 8 true
“armor” 5 true

A person has a table-name called skill table. The skill table of a person is usually the Table of Normal Skills. The skill table of Bob is the Table of Bob’s Skills.
The description of a person is usually “[skills of the item described]”.

To say skills of (target - a person):
sort the skill table of the target in activation order;
repeat through the skill table:
if the activation entry is true:
say “[skill entry in sentence case]: [rating entry]”;
say line break;
if target is a medic:
say “[The target] is a medic.”

Definition: a person is a medic if the rating corresponding to a skill of “medic” in the skill table of it is greater than 0 and the activation corresponding to a skill of “medic” in the skill table of it is true. [/code][/spoiler]

I know why.

I just found that ’ is in the \w set. So that \w matches “don’t”. Oy. Couldn’t it be in both? And still no idea why I can’t match ’ or ’ directly…

Ok – thank you! First, I like that the skills are not going to interfere with the namespace of the rest of the document – that’s pretty good! When I started with the modification of the “Magic” example, it made me have to jump verbal hoops to name other things in the game… I am not the one dictating the names of the “programs” in this “game” – it’s a playing aid for a role-playing game.

Sometimes the skills will change during game play, so they may need their own tables… OR the table-per Program idea… Thinking about that. If there are 50 actors, there will be 50 tables – thankfully I might never have to actually see them. :slight_smile: They could be generated inside the game itself, I would imagine. But better 50 tables @ 30 entries each for 50 actors than 1500 items for 50 actors!!!

Quite livable, actually. Although I don’t know if I need that Definition statement, there are others that I might need.

How and when it is best to do so is apparently some of the learning curve of Inform :slight_smile:

Thank you for your quick response!! I’m glad there’s an alternative that’s going to be less hungry for memory. I’ll see if anyone has something more eloquent, but this is much better than what I was up to…and might work for other things in my game, too. Too many “attributes” to keep track of on the player & NPCs…

A table is probably the most logical way to go - you essentially have a three (or four) way relation, which is awkward to represent with anything other than a table.

My preference is to have one big table, but whatever works for you in practical terms.

This is not tested, but it might look something like this:

[code]Table of Skills
actor skill proficiency activation
Yourself medic 8 on
Bob plumbing 2 off
Sheila flamethrower 11 on

To decide which number is the current proficiency of (actor - a person) at (task - a skill):
Repeat through the table of skillls:
if the actor entry is the actor and the skill entry is the task and activation entry is on, decide on proficiency entry;
Decide on 0.
[/code]

Unless the skills are actually objects in the game, like computer chips, I’d recommend making them a kind of value. You’ll also want to create phrases for setting the proficiency and activation, and maybe for increasing and decreasing the proficiency. You can define a conditional relation to check whether a person has a particular skill activated, or even to compare the proficiency with a global variable or phrase result.

Ok, settling through awkward vs. sleek, I did this to match the apostrophe and it worked:

			if printname matches the regular expression "<^A-Za-z\d\p>s (.*?)$": 

While I probably won’t need to use the regex after all (thanks to wonderful help on alternatives…), someone else might eventually want to list someone’s parts and need the regex…so I thought I’d put it out there. If anyone ever needs it, they might also want to add the hyphen character to the exclusion: “<^A-Za-z\d\p->s (.*?)$”

Well, you can represent many-fold relations as lists; despite the related drawbacks, I believe that is currently the best way to implement them in I7.

The nice thing about this is a person can have a list, whereas no thing can have a table. That makes generalizing the code much simpler.

[code]New York City is a room.

Spidey is a man in New York. Mary Jane is a woman in New York.

A program is a kind of value. The programs are armor, medic, and web-slinging.

Everyone has a list of programs called the skillset.
Everyone has a list of numbers called the proficiency.
Everyone has a list of truth states called the activation.

The skillset of Spidey is {armor, medic, web-slinging}. The proficiency of Spidey is {4, 2, 8}. The activation of Spidey is {true, false, true}.

Mary Jane has skillset {medic}. She has proficiency {6}. She has activation {true}.

Understand “detail [something]” as detailing. Detailing is an action applying to one thing.

Check detailing something which is not a person: say “Only people have programs.” instead.

Carry out detailing someone (called the subject):
if the skillset of the subject is empty, say “[The subject] [if the subject is singular-named and the subject is not the player]is[otherwise]are[end if] an empty vessel.” instead;
repeat with L running from 1 to the number of entries in the skillset of the subject:
say “[entry L of the skillset of the subject]: [entry L of the proficiency of the subject]”;
if entry L of the activation of the subject is false, say " (deactivated)";
say line break.[/code]

The only downside here is that those lists are independent. Keeping them synchronized is up to you; if you add, remove, or reorganize items in one list, you have to make sure to perform the exact same sequence of actions on the two other lists as well.

Obviously, all of that “entry X of” code can get tedious, so you can define some shortcut phrases to get the related variables from a program of a given person:

[code]
To decide whether (mope - a person) has installed (requirement - a program):
if the requirement is listed in the skillset of the mope, yes;
otherwise no.

To decide whether the (requirement - a program) of (mope - a person) is active:
unless the mope has installed the requirement, decide no;
repeat with L running from 1 to the number of entries in the skillset of the mope:
if entry L of the skillset of the mope is the requirement, decide on entry L of the activation of the mope.

To decide what number is the training of (mope - a person) in (requirement - a program):
unless the mope has installed the requirement, decide on 0;
repeat with L running from 1 to the number of entries in the skillset of the mope:
if entry L of the skillset of the mope is the requirement, decide on entry L of the proficiency of the mope.[/code]

Apparently a thing can have a table-name though. I can have different tables for different parent classes (i.e. different kinds of “people” in the game can have different base sets of skills or programs depending on what they are – then I only need to give them a customized table if they diverge from the default – or even have it check the master table for a default if they don’t have a listing in their personal table, but I don’t think I’ll go that far).

Where it’s ok when there’s a few items to synchronize, it also begins to degrade when you have to list 30+ of these into each of the lists. Much too easy to throw the list off by forgetting a number or truth_state.

Here’s another way it COULD be done with a list, not saying it’s a bright idea, but it replicates the idea of a multi-dimensional array:

Everyone has a list of indexed texts called skillsets. The skillset of Spidey is {"armor/4/true", "medic/2/false","web-slinging/8/true"}.
Then parse the text with regex’s. The only bonus being that you keep related information indexed/together at all times – and it’s still sort-able (only imperfectly, on skillname) without throwing everything off.

I don’t see how that’s any better or worse than a table, however. I want the code to be human-usable, so the tables are more convenient. I’m coding a base extension so that people can create their own environment around the plug-in environment. I don’t think it’s reasonable to ask people to deal with several lists versus one table per person.

I’m still looking at your contribution from the angle of how I can use it for other things in my game environment. I just don’t think the 30 programs are it. There may be other things it makes more sense in, in which case I’ll try it out.

An icon is a kind of person. An icon has a table-name called stat table.	The stat table of an icon is usually the Table of Icon Stats.

Table of Icon Stats
stat	rating	activation	is-attack	is-program
"analyze"	0	true	false	true
"browse"	0	false	false	true
"edit"	0	true	false	true


To say programs of (target - an icon):
	sort the stat table of the target in activation order;
	repeat through the stat table:
		if the is-program entry is true and the activation entry is true and rating entry is greater than 0:
			say "[stat entry in sentence case] ([rating entry])[line break]";

The parser is choking on the sort statement. Probably because “stat table” is not a table at all – it’s a table-name?

It’s one of those instances where I can be sitting there all night trying to figure out the correct wording to refer back to the actual table rather than the table-name assigned to the person. I’ll give it a go, but if anyone knows I’d sure appreciate the help. For now I’ve just removed the sort statement and gotten it to parse.

I think you need to change “repeat through the stat table” to “repeat through the stat table of the target.”

ETA: And I don’t think you need to worry about referring to the actual table rather than to the table-name; I’m pretty sure that when you refer to the stat table of an icon you’re referring to the table, not to the table-name, even though you had to declare it as a table-name.

When I removed the sort line, I did change the following line accordingly.

Actually, in one of my test documents the sort worked, so it must be something else that’s wrong with the code I tried. I’ll look at it again.