Amy Guy

Raw Blog

Thursday, May 24, 2012

Character sketching


Suddenly I find myself having to write some fiction to a deadline.  A deadline that isn't Nanowrimo, that is.  This isn't something I've had to do since my English language GCSE.  I deliberately avoided pursuing creative writing in any formal or academic manner, for fear the joy would be sucked from something I love; for fear it would become a chore, or an obligation.

But this semester I've imposed this on myself out of determination that my supposedly 'interdisciplinary' masters actually deviate from Web or software development at some point.  Not that making writing fiction a part of my final project has in any way reduced the programming.  Indeed, I've just added it on top of an already substantial project outcome.

But making an Interactive Fiction engine feels much more valuable if I actually write some fiction for it, doesn't it?

Suddenly, realistically, I have mere weeks to get this done.  My subconscious has been working on it since about December of last year, but I haven't had many committal thoughts.  So it's time to make (and justify) some decisions.

I already decided that, quite obviously really, the piece needs to revolve heavily around the city of Edinburgh.  (Obvious, as the reader will be experiencing it whilst wandering around the city, and I'm studying the affects of physical environment on immersion in a text).  As such, I figured doing research about local myths and legends, particularly stories relevant to specific places, is pertinent.  Look out for updates on that.  Historic and mythical local characters might be useful too.

Ian Rankin has famed the Edinburgh streets with his novels, but I'm no crime writer, nor mystery nor thriller.  I write science fiction and fantasy; imagining new worlds comes far more naturally to me than conjuring stories in this one.  And my time is too short to venture into an unfamiliar genre.  So this leaves me trying to figure out how to set a story on the real world streets of Edinburgh whilst maintaining a fantastical element so that I keep my sanity and confidence in the prose.

One potentially helpful aspect of Interactive Fiction, is that generally the stories are written in the second person.  The main character is a perspective taken by the user/reader/player.  This means there is a primary role that I don't have to develop too much as a character.  Just enough to fit in with the context of whatever plot starts to develop, but with adequate openness to allow the user to project themselves into the character's place.  Nonetheless, I'm going to need some attachment to this character in order to engage myself in the writing process.  I know from experience that I'm far less motivated to write about/for characters who don't interest me, but when I discover a character I feel really involved with, I miss them and desire to write more.

That's the interesting point, really.  I don't feel much as though I'm writing characters or their stories, but discovering them and learning about them through the writing process.  I've lost control of characters before; they've behaved unexpectedly or undesirably, sometimes even changing the whole course of a previously loosely planned plot. The same might apply to imaginary places or even objects.

Because I don't have time to find a fresh character, world, setting that I love, I have concluded that I need to hook this story back to something I've written in the past.  Something I'm already invested in.  This connection is only meaningful to me (until the glorious day the still unfinished, few-year-old novel gets published!) so it needs to be loose.  But enough to give me context.  The connection I have settled on is Milo's World, the subject of my 2008 Nanowrimo; my only successful attempt at reaching fifty thousand words in thirty days, though I have yet to write the ending to the story.  Also part three needs rewriting completely, those were dark days.  Not to mention the rest of it.  But that's neither here nor there.

The important thing is, I met a couple of characters with whom I had great fun.  I hung out with them for massive chunks of their childhoods.  I learnt what makes them tick, and I learnt their secrets.

The point-of-view character in Milo's World is Dusty.  I first met him as a four year old, and quickly discovered he had access to a secret world, where he regularly snuck off to play with a boy his own age, Milo, who seemed to live full-time in this world.  They had all sorts of innocent adventures, and gradually met other occupants.  I spent time with Dusty and Milo again aged eight, to find that not much had changed.  They had befriended some strange creatures, and were privvy to experiences they could not understand yet.  At age twelve, they were growing up.  Dusty has gained a few home-world friends, has developed an amazing talent for drawing caricatures, and his parents have long since assumed that he's over the 'imaginary friend' stage.  But his grip on their 'reality' is disjointed.  There are more kids around in Milo's world, living in a network of tunnels and working and playing together, and with the creatures of the world.  One species of creatures in particular have introduced curious technologies and ways of thinking.  When Dusty is sixteen years old, he is balancing regular high school drama with other-worldly adventures, but just barely.  He and Milo are working with one of the creatures to learn about a contraption that they played with in their youth, and have dubbed The Reality Machine.  Using it is hit and miss, and many of the things they find out about it, they learn the hard way.  When Milo's world and Dusty's home-world begin to bleed together through misuse of the Machine, things start to take a turn for the confusing.  Cue the hilarious, semi-cliffhanger ending, strongly linked with Dusty's drawing skills, I haven't written yet.

So where am I going with this?  In my Palimpsest story, Dusty is grown up.  Long since grown up.  He is old, mad-scientist-proffesor-ly, and living in a world that bears the consequences of his actions as a child.  Right away we have the existence of and ability to cross between alternative realities (via an understood and controllable Reality Machine, in case you hadn't cottoned).  Splendid.  I'm in my comfort zone already.  So how about... the playable character is Dusty's lab assistant.  Their age, gender, appearance, don't matter.  Their temperament matters probably only a little bit.  What matters is the fact that they have the ability to zip around in space and time.  Whaddya know?  Every single exciting era of Edinburgh's history is open to us to explore.

All I need now is a reason Dusty might have sent his assistant across to Edinburgh in our version of reality; something to pursue, something to figure out.  Or just a malfunctioning Reality Machine.

I call this a start.

As always, comments and suggestions welcome!

Thursday, May 17, 2012

Stylesheet organisation

About a year and a half ago I realised I needed to get a grip on how to organise my CSS.  I established a template, which I proceeded to change drastically with every new project.  I noticed recently that I've been reusing a version for the past few projects, with at the most only minor amendments to the general structure.  I also noticed how quickly I'm rolling out initial designs using this template.

I have finally reached the point where I figured out what I consistently reuse across projects, and finally have a stylesheet structure that makes such intuitive sense to me I can dart around and make changes with my eyes closed.  I find my stylesheets are much smaller, but even as they grow, I still know exactly where everything is.  I wish I had some statistics to quote about the amount of time spent scrolling through CSS looking for things.  I'm confident it is much reduced.

Some aspects of my workflow I developed through intuition; I made changes that felt right to me at the time, without really consulting anyone else's best practices.  Other things I picked up from here and there.  Every now and again I'd search for 'the right way' of doing this and find processes and systems that didn't gel with me (a primary example of this being the number of pre-built grid systems I tried and hated).  Eventually I would give up under the sheer number of contradicting points of view, but I probably picked up some subconscious inspiration on the way.

I hadn't thought much of this until Chris Eppstein talked about this at FOWD today.  A lot of the suggestions he demo'd are very similar to parts of my system (conceptually at least; he was discussing SASS and mine is raw CSS).  So I figured it's reached the point it is worth sharing.

First things first, I start with a basic Initializr stylesheet; a couple of minor tweaks, but then I largely accept the helper classes and IE fixes and hacks (no need to read this; it's just here for completeness):


/* ======================================================================
HTML5 Boilerplate CSS: h5bp.com/css
========================================================================== */

article, aside, details, figcaption, figure, footer, header, hgroup, nav, section { display: block; }
audio, canvas, video { display: inline-block; *display: inline; *zoom: 1; }
audio:not([controls]) { display: none; }
[hidden] { display: none; }

html { height: 100%, font-size: 62.5%; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; }
html, button, input, select, textarea { font-family: sans-serif; color: #222; }
body { height: 100%; margin: 0; padding: 0; font-size: 1em; }

::-moz-selection { background: #fe57a1; color: #fff; text-shadow: none; }
::selection { background: #fe57a1; color: #fff; text-shadow: none; }

a { color: #00e; }
a:visited { color: #551a8b; }
a:hover { color: #06e; }
a:focus { outline: thin dotted; }
a:hover, a:active { outline: 0; }

abbr[title] { border-bottom: 1px dotted; }
b, strong { font-weight: bold; }
blockquote { margin: 1em 40px; }
dfn { font-style: italic; }
hr { display: block; height: 1px; border: 0; border-top: 1px solid #ccc; margin: 1em 0; padding: 0; }
ins { background: #ff9; color: #000; text-decoration: none; }
mark { background: #ff0; color: #000; font-style: italic; font-weight: bold; }
pre, code, kbd, samp { font-family: monospace, serif; _font-family: 'courier new', monospace; font-size: 1em; }
pre { white-space: pre; white-space: pre-wrap; word-wrap: break-word; }
q { quotes: none; }
q:before, q:after { content: ""; content: none; }
small { font-size: 85%; }

sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; }
sup { top: -0.5em; }
sub { bottom: -0.25em; }

ul, ol { margin: 1em 0; padding: 0 0 0 40px; }
dd { margin: 0 0 0 40px; }
nav ul, nav ol { list-style: none; list-style-image: none; margin: 0; padding: 0; }

img { border: 0; -ms-interpolation-mode: bicubic; vertical-align: middle; }

svg:not(:root) { overflow: hidden; }

figure { margin: 0; }

form { margin: 0; }
fieldset { border: 0; margin: 0; padding: 0; }
label { cursor: pointer; }
legend { border: 0; *margin-left: -7px; padding: 0; white-space: normal; }
button, input, select, textarea { font-size: 100%; margin: 0; vertical-align: baseline; *vertical-align: middle; }
button, input { line-height: normal; }
button, input[type="button"], input[type="reset"], input[type="submit"] { cursor: pointer; -webkit-appearance: button; *overflow: visible; }
button[disabled], input[disabled] { cursor: default; }
input[type="checkbox"], input[type="radio"] { box-sizing: border-box; padding: 0; *width: 13px; *height: 13px; }
input[type="search"] { -webkit-appearance: textfield; -moz-box-sizing: content-box; -webkit-box-sizing: content-box; box-sizing: content-box; }
input[type="search"]::-webkit-search-decoration, input[type="search"]::-webkit-search-cancel-button { -webkit-appearance: none; }
button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; }
textarea { overflow: auto; vertical-align: top; resize: vertical; }
input:valid, textarea:valid {  }
input:invalid, textarea:invalid { background-color: #f0dddd; }

table { border-collapse: collapse; border-spacing: 0; }
td { vertical-align: top; }

.chromeframe { margin: 0.2em 0; background: #ccc; color: black; padding: 0.2em 0; }

/* ===============
    ALL: IE Fixes
   =============== */

.ie7 #title{ padding-top:20px; }

/*******************************************/
/*                                         */
/* My styles go here!                      */
/*                                         */
/*******************************************/

/* =============================================================================
   Non-Semantic Helper Classes
   ========================================================================== */

.ir { display: block; border: 0; text-indent: -999em; overflow: hidden; background-color: transparent; background-repeat: no-repeat; text-align: left; direction: ltr; *line-height: 0; }
.ir br { display: none; }
.hidden { display: none !important; visibility: hidden; }
.visuallyhidden { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; }
.visuallyhidden.focusable:active, .visuallyhidden.focusable:focus { clip: auto; height: auto; margin: 0; overflow: visible; position: static; width: auto; }
.invisible { visibility: hidden; }
.clearfix:before, .clearfix:after { content: ""; display: table; }
.clearfix:after { clear: both; }
.clearfix { *zoom: 1; }

/* =============================================================================
   Print Styles
   ========================================================================== */
 
@media print {
  * { background: transparent !important; color: black !important; box-shadow:none !important; text-shadow: none !important; filter:none !important; -ms-filter: none !important; } /* Black prints faster: h5bp.com/s */
  a, a:visited { text-decoration: underline; }
  a[href]:after { content: " (" attr(href) ")"; }
  abbr[title]:after { content: " (" attr(title) ")"; }
  .ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after { content: ""; }  /* Don't show links for images, or javascript/internal links */
  pre, blockquote { border: 1px solid #999; page-break-inside: avoid; }
  thead { display: table-header-group; } /* h5bp.com/t */
  tr, img { page-break-inside: avoid; }
  img { max-width: 100% !important; }
  @page { margin: 0.5cm; }
  p, h2, h3 { orphans: 3; widows: 3; }
  h2, h3 { page-break-after: avoid; }
}

My template is inserted into the appropriate point of the Initializr stylesheet.  I divide into five sections:

/* 0 Accessibility */

/* 1 Typography */

/* 2 Colours & borders */

/* 3 Spacing & layout */

/* 4 Images & video */

I start each section with empty media query clauses for 480px and up, 768px and up, 1024px and up, and 1200px and up.  By the time a project is done each section will typically have from one to six media query breakpoints in it, according to requirements.

0. Accessibility

A staple of this so far is:

/** 
 0 Accessibility
**/
.no-css {
 /* This class hides stuff that needs to be around for screenreaders or users with no CSS, but not in normal circumstances */
 position: absolute; left: -1000px;
}

Which I chuck in when I use visuals to enhance some content, to hide an appropriately positioned textual equivalent.

There's probably more useful stuff that should be here. I'm working on it. (Suggestions welcome!).

1. Typography

Not a lot going on here. Some obvious placeholders, plus a couple of classes I found myself needing over and over, which should be self explanatory (.win and .fail are applied to success or error messages; usually a form submission is involved).

/**
 1 Typography
**/

h1 {}
h2 {}
h3 {}
h4 {}

p {}
a { text-decoration: inherit; }
a:hover { text-decoration: underline; }

.note {
  font-size: 1em;
  font-weight: bold;
  text-align: right;
}

.wee {
  font-size: 0.8em;
}

.win, .fail {}


In typography, I strictly only include font stuff like faces, sizes, alignment, decoration and enhancements like text-decoration, font-weight.

2. Colours and borders

Border styles go here because they need to be defined before the border colours are. Otherwise, just colours go here:

/* Borders */
  .win, .fail { border: 2px solid; }

/* Dark */
  .dark { color: #2d2d2d;}
  .dark-bg { background-color: #2d2d2d; }
  .darker{ color: #000; }
  .darker-bg { background-color: #000; }

/* Primary Color */
  .color1 { color: green; }
  .color1-bg { background-color: green; }
  .color1-border { border-color: green; }
  .color1-texture { }

/* Secondary Color */
  .color2 { color: yellow; }
  .color2-bg { background-color: yellow; }
  .color2-border { border-color: yellow; }
  .color2-texture { }
  
/* Tertiary Color */
  .color3 { color: red; }
  .color3-bg { background-color: red; }
  .color3-border { border-color: red; }
  .color3-texture { }

/* Light */
  .light { color: #ccc; }
  .light-bg { background-color: #ccc; }
  .lighter { color: #fff; }
  .lighter-bg { background-color: #fff; }

.note { color: silver; }

.win {
  background-color: #E6EFC2;
  color:#264409;
  border-color:#C6D880;
}

.fail {
  background:#FBE3E4;
  color:#8a1f11;
  border-color:#FBC2C4;
}

After border styles, I start with the colour scheme, creating classes for text colours, background colours and border colours. It's unusual to need to go beyond a tertiary colour, and typically I only have primary and secondary. This leaves me with classes I can apply to any elements in my html templates, making it really quick and easy to experiment with different colour combinations. The color*-texture classes come in handy when I have textured backgrounds that match the colour scheme, and would include the background image (a repeating square of noise texture for example) and a background-colour as a backup.

Most of the time I don't want to be applying classes to everything to add colour though. I list elements that I'm confident aren't going to change in the mark-up which need colours applying to them, for example:

/**
    2 Colours and borders
**/

/* Primary colour */
  .color1, body { color: green; }
  .color1-bg, nav, footer { background-color: green; }

/* Secondary Color */
  .color2, nav { color: yellow; }
  .color2-bg, body { background-color: yellow; }

/* ...etc... */

I'm a fan of using off-white and off-black, so these are what I originally picked for my .light and .dark classes, which are always handy to have. Sometimes pure black and white are necessary too though, so the .lighter and .darker classes were born.

You can see .note, .win and .fail show up here too.

This pretty much means this is as long as the colours section will ever get. I don't apply colours anywhere else in the stylesheet, and it helps to ensure I stick to a colour scheme and don't get carried away with exceptions. Obviously, this also makes it super easy to change the colour scheme uniformly in a couple of seconds.

3. Spacing and grid

As I already mentioned, I have poked around with some of the existing flexible grid frameworks but none of them grabbed me. They all seemed to have too much. The minimalist system I came up with has answered all of my needs so far, although I wouldn't claim it's suitable for _every_ project in the world. It's also subject to tweaks, depending on the project of the moment.

I stick with Initializr's .wrapper class, which is 100% width until the viewport reaches 1024px, when it snaps to 900px wide. This is my default because it's been the most frequently appropriate so far. I have an ongoing project at the moment where the target audience are largely gamers, so capitalising on the excessive screen real estate they'll probably have means I stripped out this restriction in favour of a full width multi-column layout when the device allows.

I haven't yet had a need to go above five columns for my grid. I express my class names like fractions, and start off with only the 1/2, 1/3 and 2/3 ones taking up the correct proportion of the screen, with the others defaulting to 100%. This then changes for wider-than-small viewports, as you can see.

There are a few navigation list related things in there that I often find myself duplicating across projects (like a default centre-aligned stacked menu which progresses to a floating horizontal version). I pad my a elements (as opposed to their containing li elements) to enlarge the touch area for links. Plus some nth-child stuff for three column layouts, for keeping consistent row heights when the column heights are different.

/** 
 3 Spacing & Grid
**/

.wrapper {
 width: 100%;
}

/* Grid */
.w1of2 { width: 50%; float: left; }
.w1of3 { width: 33%; float: left; }
.w2of3 { width: 66%; float; left; }
.w1of1, .w1of4, .w1of5,
.w3of4, .w2of5, .w3of5, .w4of5 {
 width: 100%;
}

.inner {
 padding: 1em;
}

nav {
 max-width: 100%;
}

nav a {
 display: block;
 padding: 0.8em;
}

.inline { display: inline; }

.win, .fail {
  padding: 0.2em;
  display: block;
}


/* 3.1  */
 @media screen and (min-width: 479px){
  
  nav li { float: left; }
 }

/* 3.2  */
 @media screen and (min-width: 768px){
  .w1of2 { width: 50%; float: left; }
  .w1of3 { width: 33%; float: left; }
  .w1of4 { width: 25%; float: left; }
  .w1of5 { width: 20%; float: left; }
  .w2of3 { width: 66%; float: left; }
  .w3of4 { width: 75%; float: left; }
  .w2of5 { width: 40%; float: left; }
  .w3of5 { width: 60%; float: left; }
  .w4of5 { width: 80%; float: left; }

  .w1of3:nth-child(odd) { clear: none; }
  .w1of3:nth-child(3n-2) { clear: both; }
 }

/* 3.3  */
 @media screen and (min-width: 1024px){
  .wrapper {
   width: 900px;
   margin-left: auto; margin-right: auto;
  }
 }

Everything that goes in this section is to do with spacing: padding, margins, positioning, floating, wrapping... et cetera.

4. Images and video

Most projects call for tweaks to images that may or may not fit into the other sections of the stylesheet. Nonetheless, my brain copes better with I group them all together. Flexible YouTube video embed lives here too.

/** 
 4.0 Images and video
**/

.vid-holder {
 position: relative;
 padding-bottom: 56.25%;
 padding-top: 30px;
 height: 0;
 overflow: hidden;
}

.vid-holder iframe,  
.vid-holder object,  
.vid-holder embed {
 position: absolute;
 top: 0;
 left: 0;
 width: 100%;
 height: 100%;
}

/* Full width images on bigger than small screens are dumb. Reset this. */
@media screen and (max-width: 478px){
  .w1of1 img, .w1of2 img, .w1of3 img, .w1of4 img, .w1of5 img,
  .w2of3 img, .w3of4 img, .w2of5 img, .w3of5 img, .w4of5 img {
    width: 100%;
  }
}

And that's what I start all projects with. Here is it all assembled, with a few of the classes throw into the mark-up so you can see what's going on. If (when) I end up doing another major update, I shall probably write about it again.

Sunday, May 13, 2012

UI for IF


This is the first in an upcoming series of posts about my final project for my MSc by Research.  For those who don't know, my programme is Interdisciplinary Creative Practices, or ICP for short, and my main focuses so far have been on Interactive Fiction (IF) and the Web.  My final project needs a log book.  Traditionally such a thing would be compiled by me at the last minute based on notes scattered around my workspace, emails to myself and entries on Google Calendar and Tasks.  It's high time I got a grip on my organisation and did this properly, so blog posts tagged "icpLog" will help me keep a proper track of ongoing thoughts and progress.

For my final project, I endeavour to create in a "location-aware Interactive Fiction engine".  If at this stage you don't know what IF is, read this nice description by Emily Short.

Historically IF is programmed using one of several specialist languages along with specialist software packages.  The one I am most familiar with is Inform 7, a brilliantly simple but incredibly powerful natural language.. language.. which is perfect for non-programmers who want to create IF.  I haven't actually made anything myself with Inform yet (I plan to, in the name of research), but I have read a lot of source code and tutorials.

Similarly, IF is traditionally played/read on a user's computer, in their local environment.  The open source JavaScript IF interpreter, Parchment, brings playing IF to the Web; much more flexible and shareable, and enabling of many possibilities.

One such use of Parchment can be seen in Playfic, which appeared around March this year.  Playfic offers a fully in-browser Inform development environment for authors, similar to the Inform software the experienced would be used to running on their own machine.  And of course, an online read/play interface for the IF consumers.

This interface affords the user the chance to share their work-in-progress with the IF community.  The source code for all of the games can be viewed, making it really easy for newcomers to learn how to get started, and for anyone to figure out how a particularly creative experience or interesting quirk has been achieved.

One of the aims of my project when I laid out my ideas last October was to lower the entry barrier for prospective new IF authors.  Having spent several years weaving in and out of technical and non-technical environments or groups of people, it's plain to see that even Inform might be daunting to some.  Whilst it appears like uber high-level natural language to us programmers, for a writer, things like verbose if statements, oddly structured sentences and repetition of logic that would be inferred by a human from just a few words, can be pretty alien.

In other words, the programmer in me looks at Inform source code and sees prose; no complex syntax to remember, and logical and basic programming concepts.  The writer in me doesn't see prose; she sees awkwardly formed statements and struggles with maintaining the fluidity of a story whilst attempting interlace it with conditions and behaviours of things.

I'm sure if they work together, they can figure something out.

But more importantly, I'm sure my creatively split personality can offer some useful insights when it comes to designing my own online interface for IF authoring.

During a few weeks in April this year, I built the first iteration of Palimpsest, as my project is so named, around the requirements of some folk from the University of Edinburgh's English Literature department.  Concentrating on the 'location-aware' part and ignoring the 'Interactive Fiction' part, the current alpha allows the author to input bodies of texts and allocate them areas on a map.  The user, upon starting a particular 'experience' on their smart mobile device, could wander around a particular area and have these texts dynamically pushed to them, to read in the surroundings intended by the creator.  English Lit. are using this to deliver historical and contemporary literary works written or set in Edinburgh, as part of the celebration of 250 years of Edinburgh literature.  There's more work to be done for them before it meets all of their specifications, and it'll be premièred during the summer.  I built it on Google AppEngine with Python and jQuery and at the time of writing anyone can sign in and create an 'experience' for their own city, at http://palimpsest.rhiaro.co.uk.

It's time for the project to branch, as I must turn my attention to the IF side.  I will be pondering the source code of Nick Montfort's Curveship for inspiration about processing user input (one of my initial ideas was to adapt Curveship itself to add the location-aware aspect and a Web interface, but the complex narrative stuff that Curveship does goes waaay beyond my needs, and I think that would end up being more complicated than starting from scratch).

I will also be filling my flat with paper sketches of user interfaces for the authoring of Palimpsest works.  I need ways to model characters (playable and non-playable), locations and connections between locations (shouldn't be too hard, as this will be based on the real world), objects and their properties, and interactions with objects and characters.  I have so far concluded that I need a system of actions and consequences; I should be able to apply this to everything.  Most importantly, I need to a user to be able to input this information as if they were writing a story.  Obviously there will still be some differences; it may be a disjointed story, spread across a series of input fields.  But there won't be any degree of programming syntax, or unnatural prose.  The system needs to do that work, and help the author to put the right information in the right places to allow this.  For the programmatically-inclined, we could perhaps consider the writing of a traditional story (novel, etc.) as procedural writing, and the writing of a Palimpsest interactive piece as object-oriented writing.  Maybe.  We'll see how that analogy holds up as the project progresses.

In terms of functionality, all that I'm really changing compared to regular IF is stripping out the directional commands - north, south, east, west, and alternatives - and replacing them with physical movement.  The system will know where the rooms in a particular story are on a world map, and the wonderful HTML5 geolocation API will know where the player is (once they've given permission for Palimpsest to track their device).  I've already done this.  It works.  There are varying degrees of accuracy.  If you're in a building, you're looking at between fifty and two hundred metres of accuracy, depending on your device.  Outside, I had it accurate to three metres, and the average was five to ten.

Now all I need to do is... everything else.  The idea of building an IF engine from scratch is pretty daunting, especially given the huge complexity of actions people can squeeze out of languages like Inform.  Palimpsest will have nowhere near these capabilities, not at this stage, and I need to remember not to get hung up on that.  I'll probably leave out scoring, and whilst saving progress is a must, 'undo' won't be a priority.  With Inform you can create random events and complex algorithm-based behaviours of objects and characters.  That's not going to happen for Palimpsest this round.  I also can't shake the nagging inferiority I feel thinking about the usefulness of the Inform development environment in letting you visualise paths through your narrative to check for bugs and dead ends.  My subconscious will be working hard on a solution to that, but I can't hope too hard for it to be an outcome of this stage of the project.  Based on the actions-consequences idea, it would probably be feasible to generate a flow chart of some kind to help an author fish out paths through the narrative that don't work.

As anticipated, writing this post has helped my brain spin into ideas mode.  Likely before the day is out, I will post again with some doodles and diagrams and a more solid idea of how to make this UI work.

Comments, questions and suggestions welcome.