{"id":113376,"date":"2020-05-25T09:51:00","date_gmt":"2020-05-25T09:51:00","guid":{"rendered":"http:\/\/www.gamasutra.com\/view\/news\/363531"},"modified":"2020-05-25T09:51:00","modified_gmt":"2020-05-25T09:51:00","slug":"dreaming-spires-dynamic-narrative-layer-by-layer","status":"publish","type":"post","link":"https:\/\/sickgaming.net\/blog\/2020\/05\/25\/dreaming-spires-dynamic-narrative-layer-by-layer\/","title":{"rendered":"Dreaming Spires: Dynamic narrative, layer by layer"},"content":{"rendered":"<p><strong><i><small> The following blog post, unless otherwise noted, was written by a member of Gamasutra\u0092s community.<br \/>The thoughts and opinions expressed are those of the writer and not Gamasutra or its parent company. <\/small><\/i><\/strong> <\/p>\n<hr>\n<p><strong><a href=\"https:\/\/store.steampowered.com\/app\/1240050\/Pendragon\/\">Pendragon<\/a> is a narrative&nbsp;strategy&nbsp;game being made by <a href=\"http:\/\/www.inklestudios.com\">inkle<\/a>, the creators of <a href=\"http:\/\/www.inklestudios.com\/80days\">80 Days<\/a> and <a href=\"http:\/\/www.inklestudios.com\/heavensvault\">Heaven&#8217;s Vault<\/a>.<\/strong><\/p>\n<p>Our last game, the IGF-winning<em> <a href=\"http:\/\/www.inklestudios.com\/heavensvault\">Heaven\u2019s Vault,<\/a><\/em> was a 20+ hour&nbsp;adventure game that plays out differently for every player, and every time you play. It worked by combining a standard adventure game world with a highly contextual, dynamic dialogue system. The world provides the input &#8211; what do you find? In what order? &#8211; and the dialogue system spins it out into a narrative.<\/p>\n<p>For our next game, <a href=\"https:\/\/store.steampowered.com\/app\/1240050\/Pendragon\/\"><em>Pendragon<\/em><\/a>, we wanted to push that idea further. Is it possible to make the entire narrative out of contextual dialogue? Instead of tying the conversation engine to something rigid, like an adventure game world, we\u2019ve tied it instead to a procedurally-generated Chess-like strategy game. Boards, moves, pieces&#8230; and combinatorial explosion.&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" alt=\"A screenshot of Pendragon\" height=\"363\" src=\"https:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2020\/05\/dreaming-spires-dynamic-narrative-layer-by-layer.jpg\" width=\"646\"><\/p>\n<p>Here\u2019s how it works.<\/p>\n<p><strong>The Blueprint&nbsp;<\/strong><\/p>\n<p><em>Heaven\u2019s Vault<\/em>&#8216;s&nbsp;dialogue system consists of an enormous bucket of short conversations, tagged with what discoveries make them relevant, and a system for deciding what to say next.&nbsp;<\/p>\n<p>That system &#8211; which is driven by what the player finds in the world, and also what they talk about &#8211; is ultimately the thing responsible for delivering a coherent and engaging narrative across the game\u2019s 20h running time.<\/p>\n<p>A game of <em>Pendragon<\/em> &#8211; which is roughly as long to play through as <em>80 Days<\/em> &#8211; consists of a series of \u201cboards\u201d. Each board is created based on the required difficulty (which increases across the course of the game). It\u2019s given a setting type (\u201cweird forest\u201d, \u201ccrumbling ruin\u201d, \u201cvillage\u201d), and then populated with appropriate enemy pieces (\u201cwolf\u201d, \u201cbear\u201d, \u201crogue knight\u201d, \u201cblacksmith\u201d) that the hero party then attempt to fight, sneak and talk their way past.<\/p>\n<p>The system for the narrative is like <em>Heaven\u2019s Vault&#8217;s<\/em>: an enormous bucket of lines of dialogue, or lines of description, tagged with what\u2019s required to make them fire. But it\u2019s also quite a lot more structured too, with layers of content arranged from highly specific down to highly generic.&nbsp;<\/p>\n<p><strong>The Ground Floor: Responding to Game State<\/strong><\/p>\n<p>The basic tags are all tied to the gameplay. Who\u2019s moving? What kind of move are they making? What consequences does the move have on the game state? Which other pieces are involved in this move?&nbsp;<\/p>\n<p>We test these using a \u201cplay\u201d condition which takes three parameters &#8211; a description of the piece doing the move, a description of the move, and a set of things the move and piece mustn\u2019t be. Here are some examples:<\/p>\n<ul>\n<li><strong>play ( HEROES, ATTACK)<\/strong> &nbsp;\n<ul>\n<li>a hero piece is attacking someone<\/li>\n<\/ul>\n<\/li>\n<li><strong>play ( HEROES, (ATTACK, EXCHANGE) ) <\/strong>&nbsp; &nbsp;\n<ul>\n<li>a nervous hero piece is attacking someone, but is about to be captured in return<\/li>\n<\/ul>\n<\/li>\n<li><strong>play_not ( (NERVOUS, HEROES), ( ATTACK, EXCHANGE), LAST_PIECE)<\/strong> &nbsp;\n<ul>\n<li>a nervous hero piece is attacking someone, is about to be captured in return, but isn\u2019t the last piece on the hero team<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>Not every line has every kind of tag, and queries on tags can be highly specific &#8211; is Lancelot speaking, or Guinevere? &#8211; or they can be more general &#8211; Is the piece speaking someone confident, or someone nervous? Are they injured? Are they a knight, or a villager recruited to the cause?<\/p>\n<p><em>Pendragon<\/em> has a bank of about a thousand of these, arranged in rough priority order, with some additional tags to prevent close repetition of lines. These form the lowest level of the game\u2019s thinking &#8211; the fallback content.&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" alt=\"Another screenshot from Pendragon\" height=\"363\" src=\"https:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2020\/05\/dreaming-spires-dynamic-narrative-layer-by-layer-1.jpg\" width=\"646\"><\/p>\n<p><strong>The Mezzanine: Responding to Game Setting<\/strong><\/p>\n<p>The next layer is similar to the previous, except it\u2019s reserved for lines that reference the \u201cskin\u201d of a board more directly. This is done on a separate layer so it can be swapped in and out as required: there\u2019s no point processing dialogue about villagers when you\u2019re knee-deep in a snake-infested marsh.&nbsp;<\/p>\n<p>This layer uses all the same tags as before, but are only active is other conditions are met about the setting, or the piece being attacked; things like:<\/p>\n<ul>\n<li><strong>play(HEROES, ATTACK) &nbsp;&amp;&amp; is(victim(), BEAR)<\/strong> &#8211;\n<ul>\n<li>the knight slices through the bear<\/li>\n<\/ul>\n<\/li>\n<li><strong>play(WOLF, RETREAT) &amp;&amp; isLocation(FOREST) <\/strong>\n<ul>\n<li><strong>\u00e2\u20ac\u2039\u00e2\u20ac\u2039<\/strong>&nbsp;the wolf slinks a step back between the trees<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>Together these two layers give us playable locations, with a lot of colour:<\/p>\n<p><strong>Turn 1: LANCE advances<\/strong><br \/> LANCE: &nbsp; There\u2019s a wolf between the trees.<br \/> LANCE: &nbsp; I don\u2019t think it\u2019s seen me.<\/p>\n<p><strong>Turn 2: WOLF advances&nbsp;<\/strong><br \/> WOLF: &nbsp;Grrrr\u2026<\/p>\n<p><strong>Turn 3: LANCE holds position and draws his sword&nbsp;<\/strong><br \/> LANCE: &nbsp;Steady now. Watch the eyes\u2026<\/p>\n<p><strong>Turn 4: WOLF captures LANCE<\/strong><br \/> The wolf leaps, and Lancelot is knocked to the floor.<br \/> GWEN: Lancelot! No!&nbsp;<\/p>\n<p>But they still feel very much like barks; they lack the feeling of narrative because there\u2019s no continuity from one moment to the next. In the example above, it\u2019d be nice if Lancelot could, on Turn 3, curse and remark that the wolf has indeed seen him.&nbsp;<\/p>\n<p><strong>The Second Floor: What Just Happened?<\/strong><\/p>\n<p>The next layers of the stack introduce new ideas to move from describing the game state to creating a narrative around it, introducing ideas such as \u201cdid I just say X?\u201d \u201cDid I speak last?\u201d \u201cIs the piece I\u2019m attacking the one that moved on the last enemy turn?\u201d This allows you to set up simple chains of conversation, as follows:<\/p>\n<p><strong>Turn 1: LANCE advances<\/strong><br \/> LANCE: &nbsp; &nbsp;&nbsp; &nbsp;There\u2019s a wolf between the trees.<br \/> LANCE: &nbsp; &nbsp;&nbsp; &nbsp;I don\u2019t think it\u2019s seen me.<\/p>\n<p><strong>Turn 2: WOLF advances&nbsp;<\/strong><br \/> WOLF: &nbsp;&nbsp; &nbsp;Grrrr\u2026<br \/> GWEN: &nbsp;&nbsp; &nbsp;I think it\u2019s seen you, Lancelot.<\/p>\n<p><strong>Turn 3: LANCE holds position and draws his sword&nbsp;<\/strong><br \/> LANCE: &nbsp;&nbsp;&nbsp; &nbsp;I\u2019m not afraid\u2026<\/p>\n<p><strong>Turn 4: WOLF captures LANCE<\/strong><br \/> The wolf leaps, and Lancelot is knocked to the floor.<br \/> GWEN: &nbsp;&nbsp; &nbsp;Lancelot! No!<br \/> GWEN:&nbsp; &nbsp; &nbsp;You might be brave, but why are you so stupid?<\/p>\n<p>As with the tags for piece types, these \u201cwhat did I say recently\u201d queries can be quite generic; we aim to reuse content intelligently as much as possible and avoid writing entirely bespoke chains. The above sequence of moves &#8211; advance, advance, hold, capture &#8211; may only appear once in a hundred games, as the both the human and the AI player are free to make any valid move on their turn.<\/p>\n<p>It\u2019s important to find a balance between making triggers so specific they never fire, and so general they lose the sense of coherence.&nbsp;<\/p>\n<p><strong>The Third Floor: Dynamic Relationships&nbsp;<\/strong><\/p>\n<p>The next layer of our plot machine is reserved for dynamic plot: in-game events which are too significant not to be carried across the entire game. These are largely driven by relationships between characters.<\/p>\n<p>For instance, at the start of the game, Guinevere loves Arthur and Lancelot, Arthur loves Guinevere and so does Lancelot. These relationships are turned into tags &#8211; Guinevere is conflicted, Arthur is betrayed, Lancelot is dishonourable (and no one is happy.)&nbsp;<\/p>\n<p>The game then uses these tags to respond to events such as:<\/p>\n<ul>\n<li>An unrequited lover saves the object of their affections, who thanks them awkwardly&nbsp;<\/li>\n<li>A nasty, betrayed lover leaves their cheating partner to be killed&nbsp;<\/li>\n<li>A nervous, conflicted character can\u2019t choose between two people to help&nbsp;<\/li>\n<\/ul>\n<p>These relationships are also allowed to change across the course of the game. When a lover dies, a character may become broken-hearted. An unrequited lover may earn the respect and even love of their beloved by saving their life. Equally, love may turn to hate and jealousy, setting up new relationships to be responded to by the game.&nbsp;<\/p>\n<p>(Dynamic relations can then power gameplay effects: a character may obtain a devastating self-destructive move on the death of their lover, or a powerful burst of action on a declaration of unrequited love.)<\/p>\n<p><iframe loading=\"lazy\" allowfullscreen frameborder=\"0\" height=\"360\" src=\"\/\/www.youtube.com\/embed\/ZXueCoW9NVI?rel=0\" width=\"640\">[embedded content]<\/iframe><\/p>\n<p><strong>The Rest of the Entire Building: Generating Plot<\/strong><\/p>\n<p>All of the above forms the basic core loop for <em>Pendragon<\/em>, but as you might expect, it becomes invisible very quickly: players begin to skim over it. It\u2019s not the oatmeal problem &#8211; it\u2019s easy enough to provide a huge variety of responses (short, long, funny, sad, etc) &#8211; but rather it becomes clear that the text is only ever an output and never an input, and so the player learns that reading is optional, and will soon or later stop doing this.&nbsp;<\/p>\n<p>We first encountered this problem when developing<em> Sorcery!&#8217;s&nbsp;<\/em>combat:&nbsp;a&nbsp;Rock, Paper, Scissors-like simultaneous game, in which each round&nbsp;is converted into a procedurally assembled prose fight sequence as you play. We solved the irrelevance problem&nbsp;there by adding \u201ctells\u201d &#8211; the prose would include some text to suggest what the AI character was about to play on their next turn, so by reading it, you could make an informed guess about what to do next.&nbsp;<\/p>\n<p>(We really liked this system too! But reading reviews there\u2019s a clear gap between \u201cpeople who saw we were doing it\u201d and \u201cpeople who still ignored the text and found the combat too random.\u201d Next time in <strong>bold type,<\/strong> perhaps.)&nbsp;<\/p>\n<p>But for <em>Pendragon<\/em> that kind of solution is too simple: we need plot-construction, to carry our band of knights from the edges of Britain all the way to Arthur\u2019s side; we need world-building; and mysteries; and strange prophecies; and all the other things that combine to create a sense of mythology, character, and presence in the world.<\/p>\n<p><strong>Floors One Through Two Hundred: Scenes<\/strong><\/p>\n<p>Each \u201cnew board\u201d is assigned a scene. Scenes can be generic and repeatable (\u201cfight in a marsh\u201d) or highly specific (\u201cthe wood where Merlyn went missing\u201d). The scene then provides a top-level of dialogue barks, which are used before anything else is considered, and these can be very specific; setting up the level, discussing it; exploring it; while still handing control down to the lower levels.&nbsp;<\/p>\n<p>A discussion of, say, what happened to Arthur\u2019s fabled sword Excalibur, might be interrupted by a wolf mauling one of the main characters to death. Or it might proceed to its conclusion, with one character naming a monastery where the sword is rumoured to be held &#8211; which you can then travel to and visit, cueing another specific scene in which, perhaps, the sword will be found, if the stabby monks don\u2019t get you first.&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" alt=\"The intro text to a scene in Pendragon\" height=\"363\" src=\"https:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2020\/05\/dreaming-spires-dynamic-narrative-layer-by-layer-2.jpg\" width=\"646\"><\/p>\n<p>Conversations told this way are very fragile: they need to be interruptible, and be able to pick themselves up again if left half-finished; but this is a problem we already solved in <em>Heaven\u2019s Vault,<\/em> and we\u2019re employing the same knowledge tracking techniques we developed there.<\/p>\n<p>The logic behind deciding what scene to play when is quite subtle! As with <em>Heaven\u2019s Vault<\/em>, there is a game-wide \u201cstory manager\u201d whose job is to ensure interesting things happen, but not too often!&nbsp;<\/p>\n<p>The manager is aware across the wider game-loop as well, so a story that appears in a first play-through is less likely to reappear in the second if there\u2019s other content to explore: a feature we were unable to put into <em>Heaven\u2019s Vault <\/em>because of the fixed nature of the game world.&nbsp;<\/p>\n<p><strong>The Dream of Camelot!<\/strong><\/p>\n<p>And that\u2019s the whole of the castle; from base foundations up to turret-rooms, banqueting halls and bedchambers. We\u2019ve been throwing boulders at it for a while and it seems to be holding up!<\/p>\n<p>The Steam page is up, the wish-lists are trickling in, and we should have a playable demo along very soon. <a href=\"https:\/\/store.steampowered.com\/app\/1240050\/Pendragon\/\"><em>Pendragon<\/em><\/a> should be out in early summer!<br \/> &nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The following blog post, unless otherwise noted, was written by a member of Gamasutra\u0092s community.The thoughts and opinions expressed are those of the writer and not Gamasutra or its parent company. Pendragon is a narrative&nbsp;strategy&nbsp;game being made by inkle, the creators of 80 Days and Heaven&#8217;s Vault. Our last game, the IGF-winning Heaven\u2019s Vault, was [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":113377,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[20],"tags":[],"class_list":["post-113376","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-news"],"_links":{"self":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts\/113376","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/comments?post=113376"}],"version-history":[{"count":0,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts\/113376\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/media\/113377"}],"wp:attachment":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/media?parent=113376"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/categories?post=113376"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/tags?post=113376"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}