Storylet Studio

External Inputs

External Inputs let you tell the testing tools about values that come from outside your story - things a host game, an operator, or an external system might set, rather than your own storylet outcomes. Once they're declared, Coverage and Simulate can reach and test content that depends on them, instead of treating it as unreachable.

External Inputs are a testing aid only. They never ship in a published storyworld and have no effect on a real playthrough; they exist so your tests behave like the real deployment.

The problem they solve

Your storyworld's state is normally driven by outcomes: a storylet plays, its outcome changes a property, and conditions elsewhere react. Both testing tools follow that same logic - Coverage plays random cards, Simulate plays the cards you click.

But some property values aren't set by any outcome. They're set by something outside the authored story:

  • In a single-player game, the game that embeds your storyworld often sets world properties directly - a chosen character class, a difficulty level, the in-world time of day, a score. Your outcomes never touch these; the game does.
  • In a multiplayer installation, an operator or an external system (a showtime scheduler, a building's show-control, an IoT trigger) sets @system properties - a venue phase, an "evening mode" switch, and so on.

If a storylet's condition depends on one of these - say @world.player_class == "mage" or @system.show_phase >= 2 - and nothing in your story ever sets that property, Coverage and Simulate can never satisfy the condition. The content looks like a dead branch, even though it would fire perfectly well in the real game once the host or operator sets the value.

An External Input is your way of saying: "this property gets set from outside, to one of these values." Declare it, and the testing tools can drive it.

Single-player and multiplayer: the same idea, two sources

The idea is identical in both cases; only who sets the value differs.

Who sets it in the real deployment Typical properties
Single-player The host game embedding the engine @world properties: class, difficulty, time of day, score
Multiplayer An operator console or an external/scheduled system @system properties: venue phase, evening mode

If you're building for both, declare the inputs your real deployment will provide. You don't have to use them - but without them, the test tools can't see past the externally-set gates, and your coverage report will under-count.

Where to find it

In the left-hand nav, open the Testing group and click External inputs. The page is on both the web app and the desktop app, and it applies to single-player and multiplayer storyworlds alike.

Declaring an input

Add an input and fill in three things:

  1. Property - the property the outside world sets. You can pick any declared property; world properties are the common single-player case, @system properties the common multiplayer one.
  2. When it changes:
    • Once, at the start - set a single time at the start of each test run. Use this for a choice that's fixed for a playthrough, like a character class or difficulty.
    • Recurring - may change during a run. Choose how often with a simple Rarely / Sometimes / Often setting. Use this for something that shifts over time, like a venue phase or the weather.
  3. Possible values - the set of values the outside world might set. This is the list the tools choose from.

The value list fills itself in

You usually don't have to think hard about the possible values:

  • For a true/false, enum, or flags property, the values come straight from the property's own definition.
  • For a number or text property, Storylet Studio scans your conditions and pre-fills the list with the values your content actually tests against. If a condition somewhere reads @world.score >= 50, the list is seeded with 49, 50, and 51 - the boundary and its neighbours - because those are the values that decide whether the gated content appears. You can edit the list freely.

So the only values that matter for testing - the ones your story distinguishes between - get tried, without you having to enumerate every possibility.

How Coverage uses External Inputs

When you run Coverage:

  • Each playthrough applies your Once-at-start inputs at the beginning, and fires Recurring inputs as turns pass, at the frequency you chose.
  • Content gated on those inputs is now reachable, so it gets exercised and counted instead of showing up as never-played.
  • Where a storylet still never fires because it depends on a property that nothing can set - no outcome anywhere writes it, and no External Input is declared for it - Coverage flags the row with a "no writer" chip that names the offending property (e.g. no writer (@world.phase)). That's a hint, not a bug to chase: you can make the row reachable either by giving some outcome a write to the property, or by declaring an External Input for it.

How Simulate uses External Inputs

When you simulate a single-player storyworld that has inputs declared:

  • Once-at-start inputs are applied when the simulation starts, so your draft begins in a realistic state.
  • An External inputs panel appears in the simulate controls. Each input has a Set... menu, so you can set its property to any of its declared values on the spot and see how the story reacts.
  • An Auto-drive toggle makes recurring inputs fire on their own as you advance turns, so the session behaves like the real deployment without you setting anything by hand.

In a multiplayer storyworld, simulate gives you a System (operator) panel instead: it lists your @system properties and lets you set them as an operator would - the multiplayer equivalent of driving an external input.

Things to keep in mind

  • Test-only. External Inputs live with your storyworld for testing but are never part of a published bundle. The real host game or operator is still responsible for setting the values in production.
  • More inputs, more runs. Each input you declare widens the space of situations to test. Coverage samples that space, so with several inputs you may want to raise the run count to cover the combinations.
  • Go easy on recurring frequency. A recurring input set to Often can dominate a run; start with Rarely or Sometimes unless you specifically want the value churning every few turns.