Example 1: Battle Royal¶
Turberfield comes with a couple of examples. We will start with the simplest. What we learn here will set us up for the more advanced example later.
This is our first encounter with the Turberfield rehearsal tool. We will use it to preview the action in the first example.
Rehearsal¶
On Linux or MacOSX:
$ cd demo/battle
$ ~/py3.5/bin/turberfield-rehearse @rehearse.cli
On Windows 8.1:
> cd demo\battle
> start %USERPROFILE%\py3.6\Scripts\turberfield-rehearse @rehearse.cli
You can do this.
From now on, I’ll assume you know how to operate the command line on your computer. Further instructions will give the Linux form of commands only, and omit the prompt character.
Here’s what you should see in your terminal window. The dialogue is delivered incrementally. There’s also a sound effect at the appropriate point:
Scratchy
I hate the way you use me, Itchy !
Ol' Rusty Chopper
**Whack!**
Itchy
Uuurrggh!
Itchy.state = 0
Script file¶
Let’s take a peek at the file which generates the dialogue. You can open demo/battle/combat.rst to see it in full. Here’s the gist of it below.
.. entity:: FIGHTER_1
:states: 1
:roles: WEAPON
.. entity:: FIGHTER_2
:types: logic.Animal
:states: 1
.. entity:: WEAPON
:types: logic.Tool
[FIGHTER_1]_
I hate the way you use me, |fighter2| !
.. fx:: logic slapwhack.wav
:offset: 0
:duration: 3000
:loop: 1
[WEAPON]_
**Whack!**
[FIGHTER_2]_
Uuurrggh!
.. property:: FIGHTER_2.state 0
.. |fighter2| property:: FIGHTER_2.name.firstname
If you look at the yellow highlighted sections, you’ll see immediately how they correspond to lines of dialogue. Notice how they aren’t allocated to characters by name. Instead, the dialogue is written for generic roles. Part of Turberfield’s job is to match characters to those roles.
The script file also contains other sections which do not correspond to dialogue. They are called directives. I will explain those in the next section.
If names be not correct…
From now on, I’m going to start being precise in what I call things. I will avoid the words Actor and Character, since they suggest a human being.
In screenplay any thing, whether animate or inanimate, can have a voice. So Turberfield calls them Entities.
Entities can have attributes. An entity with a name attribute is called a Persona. An entity with state attributes is called Stateful. In addition to those, you can define your own types for your entities. So long as their types match, one entity can play the role of another entity.
References¶
Alongside the script file, there is a Python (.py) file. Python files are called modules. They supply the entities referred to in the script. You should take a look in detail at demo/battle/logic.py. Here below are its main features.
from itertools import repeat
from turberfield.dialogue.model import SceneScript
from turberfield.dialogue.types import Persona
from turberfield.dialogue.types import Stateful
class Animal(Stateful, Persona):
pass
class Tool(Stateful, Persona):
pass
references = [
Animal(name="Itchy").set_state(1),
Animal(name="Scratchy").set_state(1),
Tool(name="Ol' Rusty Chopper").set_state(1),
]
folder = SceneScript.Folder(
pkg=__name__,
description="Cartoon battle demo",
metadata=None,
paths=["combat.rst"],
interludes=repeat(None)
)
This file performs five tasks:
- Lines 1 - 5
- Import what we need from Python and Turberfield.
- Lines 8 - 12
- Define some types which are necessary for the scene.
- Lines 14 - 18
- Create some objects to be referenced by the script. We also give them a state at the same time.
- Lines 20 - 26
- Declare a folder object which contains our scene script file. There are several other elements here, and we’ll go into it properly later.
Type¶
A type is a concept from Python. You can create types with a class declaration in a Python module. In all these examples, we do no more than inherit behaviour from other base classes, hence the single pass instruction in the class body.
Notice that two of the entity declarations in the script file have a :types: constraint; Fighter 2 has to be some kind of Animal, and the Weapon a Tool.
State¶
The Battle Royal sequence makes use of state. Both fighters must be alive at the beginning of the scene. This is encoded as a simple integer state, which is set in the Python module when the references are created.
The entity declaration in the script file specifies the state must be 1 in order for a persona to be cast as one of the fighters in the scene.
A property directive in the scene file zeroes the state of the smitten fighter. We’ll look in more detail how this works in the Syntax guide.
Roles¶
By default, Turberfield’s rehearsal proceeds despite any unmatched entities. The lines will not be voiced for unmatched parts. If you want to be strict about only playing fully-cast scene files, you can specify that with an option.
In either case, if none of the entities in the scene can be cast, the entire scene is skipped.
An extra dimension to the casting of entities is the concept of roles. When roles are attached to an entity declaration it means that the persona which gets cast to play that entity becomes a candidate to play those other entities too.
In this way, a scene written as a montage of ensemble dialogue could still be delivered as a monologue were there to be only one persona available to deliver the lines.
Repeats¶
By default the rehearsal tool runs through the scene just once. To see the effect of roles in this example, we’ll need the scene to repeat. Launch the rehearsal again, this time specifying a repetition:
~/py3.5/bin/turberfield-rehearse --repeat=1 @rehearse.cli
And you should see the carnage play out, with one inevitable winner left standing:
Scratchy
I hate the way you use me, Itchy !
Ol' Rusty Chopper
**Whack!**
Itchy
Uuurrggh!
Itchy.state = 0
Ol' Rusty Chopper
I hate the way you use me, Scratchy !
Ol' Rusty Chopper
**Whack!**
Scratchy
Uuurrggh!
Scratchy.state = 0