Role-based interactive

I would like to have two to four players, or one person playing up to four roles, engage with my story, taking turns. This can be on the same computer/browser. I know that Inform does not lend itself to multi-player games, but can multi-role be accommodated? If not, can someone direct me to something that can. I have looked into Guncho, but that is a totally separate system and I prefer to stick with Inform 7.

This is tricky with Inform 7 but can be done. Review Recipe Book Chapter 5 and Recipe Book 5.6. Viewpoint as a start.

By default, the PC is a generic character called “Yourself” but you can change that at the beginning of the story and throughout play.

You’ll likely need to establish NPC characters in the story and switch viewpoints between them, either via rules cueing this at specific plot points, or an Every Turn rule that changes the player at set intervals using

now the player is Janine;

See the example Terror of the Sierra Madre in Recipe Book 5.6, also listed below:

Example: Terror of the Sierra Madre

Suppose we have a game where we want the player to control two different characters, swapping bodies from one turn to the next. First, the setting, and the two people who will alternately play:

"Terror of the Sierra Madre"

The Hay-Strewn Corridor is a room. "[if the player is Maleska]The horse stalls are empty: you have already drained the animals, and carried off their corpses. The house will not long sustain you now.

The window throws on the floor a bright square of malevolent sunlight[otherwise]The stalls for horses run down one side of the room, but the house has long stood empty. A square window without shutters looks out over the ranch, away toward the Sierras[end if]."

Teresa is a woman in the Hay-Strewn Corridor. "Teresa stands opposite you[if Teresa carries something], her fingers wrapped tightly around [a list of things carried by Teresa][end if]." Teresa carries a bulb of garlic and a cross.

Maleska is a man in the Hay-Strewn Corridor. "Maleska watches you from eyes entirely black." Maleska carries a skull.

If we tried the text above in Inform, we would find ourselves in the Hay-Strewn Corridor and confronted by both Teresa and Maleska. If “player” is not set to any named person, Inform creates a bland person called “yourself” to represent the player. To avoid this, we set “player” to the person we want to begin as. The player character is normally privately-named, so we’ll need to make sure “Maleska” still means what it should.

The player is Maleska. Understand "Maleska" as Maleska.

Now the Corridor contains just two people, and we arrive on the scene as Maleska, with only Teresa facing us.

At the end of every turn we will use the ‘now the player is…’ phrase. (This looks as if it simply changes the value of “player”: which it does, but it also carries out a complicated operation behind the scenes to effect the switch.)

Every turn:
if the player is Maleska, now the player is Teresa;
otherwise now the player is Maleska.

Our two characters already see the Corridor differently, but let’s differentiate them further:

Every person has a number called strength. The strength of Teresa is 3. The strength of Maleska is 5.

In this small example, strength is not used for anything, except that we will display it on the status line:

When play begins:
now the command prompt is "[bold type][player][roman type] > ";
now the left hand status line is "[player]";
now the right hand status line is "STR: [strength of the player]".

That last rule doesn’t quite do what we might have expected. When we print “[player]”, we find that Inform usually prints “yourself”. This is because Inform says “you” to mean Teresa when talking to the player-being-Teresa, and likewise for Maleska. We want to override that in this particular story, because the rapid switches of personality are otherwise hard to follow. So:

Rule for printing the name of Teresa: say "Teresa".

Rule for printing the name of Maleska: say "Maleska".

Test me with "look / look".
1 Like

A scheme like this might help to rotate:

Alice is a person in the Lab.
Bob is a person in the Lab.
Char is a person in the Lab.
Dave is a person in the Lab.

The PC list is always { Alice, Bob, Char, Dave }.
The PC number is initially 1.


To decide what person is the next PC:
  if the PC number is the number of entries in the PC list, now the PC number is 1;
  else increment the PC number;
  decide on entry PC number in the PC list;

When play begins: now the player is entry 1 in the PC list.
Every turn: now the player is the next PC; say "[We] [are] [printed name of player]."

(Every Turn for demo purposes: I’m assuming you’ll end up with something more complicated to manage switching: for instance, you probably don’t want to make a role burn their sole turn to learn that they can’t take the desk because it’s fixed in place.)

3 Likes

Thanks, this is helpful. I was considering something like this, but will each PC take on the role of the player temporarily. Also, I have to consider things like different locations when I switch roles. I think that individual inventories will be ok because each PC can have their own carryall, right?

There’s a wrinkle I didn’t get into. I7 automatically creates a “yourself” object. “The player” is a person variable. Inform abhors a vacuum, so variables can’t have null values: in the case of objects, they will default to the first object of that kind created, so the player always defaults to yourself. In my code above, the player variable is set to Alice when play begins, but you can’t stop I7 from creating the yourself object, and the current value of the player variable can’t ever be offstage, so an extra person would be hanging out in the Lab.

So my code snippet would better have been:

When play begins:
now the player is entry 1 in the PC list;
now yourself is offstage;
follow the note object acquisitons rule; [explained below]

There’s nothing very special about the yourself object – it’s just another person object. So you could say, instead:

The printed name of yourself is "Alice".
Understand "alice" as yourself.
The PC list is always { Yourself, Bob, Char, Dave }.

and then not send yourself to nowhere. But then you have to remember to not use “Alice” in your code but always “yourself”. I think it’s easier to just let the yourself object sit offstage.

Locations and inventories will be associated with the respective people objects. The value of the player variable determines who’s the actor for any commands the user issues, and who the actor is shapes the game’s output for the command, for instance, “look” is relative to that actor’s position. If you look through the Standard Rules, you’ll see a bunch of things qualified “if the actor is the player” but they’re nearly all about details of what to output or about the context of the data that’s being considered to see what gets output.

I can think of one edge-case that becomes a little odd. The game prints the initial appearances of objects in the room that aren’t “handled”. Things enclosed by the yourself object are handled before we get to the When Play Begins rules; a thing the player takes become handled; the next to last thing in the turn sequence is the Note Object Acquisition rule, which marks anything the player encloses as handled.

Handled isn’t considered on a per-person basis: a thing either has it or doesn’t have it. So if Alice becomes the player in a when play begins rule, we should make sure whatever she encloses is handled. And then we probably shouldn’t switch players in an every turn rule, but in a rule we add as the last turn sequence rule, to ensure the inventory of whoever the player was gets handled before the switch. But if you never use things’ initial appearances, this becomes a non-issue.

Exactly when in the turn sequence the player value switches offers other opportunities for complications, depending on how you build things. If you switch in an every turn rule, you’re already past the first time the game considers whether any scenes should start, but there will be another one toward the end of the turn sequence. So it could be the case that the player is always a different person between those two checks. Does that matter? Not if you’re not using scenes. If you are, then maybe.

2 Likes

Each NPC has their own inventory, and if you set it up right, the PC just Quantum Leap body-jumps into each character wholesale wherever they are and with whatever they have on them.

That’s what I did in my Cragne Manor Room: Jessica was an NPC in a different section of the map with her own clothes, her own books, her own descriptions, and I just had to change the player to her (and a bunch of stuff with story tense and prop manipulation…etc)

2 Likes

Or just

The player is initially Alice.

(The word “initially” is unnecessary.) This doesn’t prevent the yourself object from being created though.

2 Likes

well, I’m toying with the concept of a PC whose polymorph into other person, but I’m still experimenting; anyway, the yourself can be turned into either a named/fleshed character or into a normally off-stage Ringbearer (of the Ring of Impdom, my debug-enabling item…), but on the latter, I must figure how to deal with the for-release dummied version when the not-for-release Ringbearer is active…

Best regards from Italy,
dott. Piergiorgio

Wow, Zed,
Thanks much for this. There’s a lot to think about here. I7 is already a bit tricky for me. This could be my quicksand.

Hi All,

New to Inform7 and this forum. I saw this interesting discussion on the player switching between NPCs. The sample mentioned (Terror of the Sierra Madre) does not appear to work for me; When I look at Teresa I get “You see nothing special about Teresa.”; when I look at Maleska I get “As good-looking as ever.”, no matter whether the player is currently Teresa or Maleska, which looks to me like the description of the “player” is always associated with Maleska. I think I can fix this adding something like:

The description of Teresa is "[if the player is Teresa]I should have brought a wooden stake[otherwise]Her neck looks juicy[end if]."
The description of Maleska is "[if the player is Maleska]Oh my I am very thirsty[otherwise]He looks with a VERY thirsty look at me[end if]."

Or am I missing something? Is there a better way to handle a player switching between NPCs?

1 Like

Congratulations! You’ve uncovered your first I7 undocumented weirdness. Terror of the Sierra Madre says:

If “player” is not set to any named person, Inform creates a bland person called “yourself” to represent the player. To avoid this, we set “player” to the person we want to begin as.

And this is a fib, as I said above: it always creates a yourself object. But because I had set the player to Alice in a when play begins rule, instead of in an assertion, I had missed noticing weird details. It turns out that setting the player variable in an assertion is a very different thing from doing so within a rule/phrase/etc.

When an assertion says, e.g., the player is Maleska, as the Terror of the Sierra Madre does, then so far as all the things asserted about yourself and Maleska at the start of game, they are the same object. If you try asserting The description of yourself is "foo". The description of Maleska is "bar". The player is Maleska. you’ll get a compiler error about the contradiction.

The description of yourself defaults to “As good-looking as ever” (in the Standard Rules) so that becomes true of Maleska, because anything asserted about yourself in an assertion at the beginning of the game applies to Maleska.

Despite all this, a “yourself” object still exists. Its printed name is updated to “your former self” and player commands can refer to it as any of “your former self”, “my former self”, “former self”, “former” (try saying showme former self as Maleska or Teresa).

But rules or phrases that referred to yourself would really be referring to the yourself object, i.e., a different object from what yourself meant in the assertions. (We basically never refer to yourself, we refer to the player so in practice this doesn’t come up.)

So it’s appropriate to set Maleska’s description, just as you have. “As good-looking as ever” isn’t dynamically associated with anything; it’s just the description the player object gets by default at the start of the game if nothing else was assigned. If the example didn’t say The player is Maleska. but said When play begins: now the player is Maleska. then Maleska would have no description and examining Maleska would get the “nothing special” message, same as for Teresa.

3 Likes

Small print: Another thing it’s easy to miss if you’re dipping into I6 is that when you assert The player is Maleska in source code, Maleska is created as privately-named (via Standard Rules: The yourself is privately-named) and is therefore created with no name property at all at the I6 level. Hence the need to write Understand "Maleska" as Maleska - which allows Maleska to be referred to in the game.

Ordinarily, Understand "Maleska" as Maleska would add the word ‘Maleska’ to the array of dictionary words in the I6 ‘name’ property, but for a privately-named object, rather than creating a name property, instead the compiler creates a parse_name property. Parse_name properties are routines usually used to process more complex name-recognition code than simply word-matching entries in the name property, but in this instance the routine simply matches ‘Maleska’ and returns true.

In play, it makes no difference that “Maleska” is being recognised by a parse_name routine rather than by matching to a word in the name property.

However, Maleska carries through the game this odd stigma of having been created during compilation as the initial player object, however many times the player subsequently switches between player objects, and being oblivious to this could cause odd things to happen if the game has I6 code that attempts to reference or manipulate the name property.

Obviously, if Maleska is created as an ordinary object then set as the player object during before play begins... he will not carry this stigma (and doesn’t need the Understand "Maleska" as Maleska).

2 Likes

Now, is better that the yourself object is kept unused and creating the actual PC as ordinary object, accepting the overhead and (important in the .z8 context) memory allocation of an unused object ?

Best regards from Italy,
dott. Piergiorgio.