This is (sort of) how my Python library Balladeer operates.
A Story object maintains a number of contexts, called Drama. Drama objects encapsulate both state and behaviour.
- In response to user input, the current Drama applies appropriate state transitions.
- The Drama generates objects of speech (Prologue, Dialogue and Epilogue).
- Using Drama state as the conditional criteria, the Story object selects more dialogue from scene files.
- Static dialogue is reformatted with variable substitution from the Drama object.
- The static dialogue is interleaved with the programmatic speech.
- The resulting stream (optionally) invokes event handlers on the Drama object.
- The Story selects one Drama to represent the next context in scope.
- The new Drama publishes the user commands now permitted by current state.
Both static and programmatic dialogue are expressed in SpeechMark format.