Note
This page explains Balladeer's classic syntax, which is no longer maintained.
Refer to a more recent article for its replacement, Balladeer lite.
Properties
If you've done any Python programming, you may know what a property is. It's a way of giving an object a getter and a setter for an internal attribute.
It is intrinsic to Balladeer that a Drama and its Dialogue interact with each other. The main way they do this is via a property called state.
For this first example we'll treat that state as an integer value. In a future article though, we'll discover that it's much more flexible than that.
Green Bottles
We are going to create a version of the song 10 Green Bottles. You can find the full code example in the Balladeer repository.
drama.py
Here's a Drama class which on every turn reduces its integer state value by one:
class Bottles(Drama):
def interlude(self, folder, index, *args, **kwargs):
self.state = max(0, self.state - 1)
return self.facts
Interlude methods are expected to return a dictionary. Drama objects have a dictionary attribute called facts. So for simplicity that can be our return value here.
The state needs initially setting to 10, which we can do like this:
drama = Bottles().set_state(10)
song.rst
The dialogue needs access to the number of bottles, so we'll use a reStructuredText substitution to reference the drama state property:
.. |BOTTLES| property:: DRAMA.state
The main challenge to generating the lyrics correctly, is the way they change according to the number of bottles.
We use a condition directive to decide which form of words to use. Though state is an integer, in dialogue files everything is treated as a string.
Our conditional might look for an explicit string representation of the state integer, or we can define a regular expression instead. Regexes must be supplied inside parentheses, just as you see here:
.. entity:: DRAMA
:types: balladeer.Drama
.. |BOTTLES| property:: DRAMA.state
Song
====
Many
----
.. condition:: DRAMA.state ([^01]+)
|BOTTLES| green bottles, hanging on the wall.
And if one green bottle should accidentally fall,
There'll be...
One
---
.. condition:: DRAMA.state 1
|BOTTLES| green bottle, hanging on the wall.
And if one green bottle should accidentally fall,
There'll be...
None
----
.. condition:: DRAMA.state 0
No green bottles hanging on the wall.
Please take a moment to download the example and run this yourself.
This has been a simple case with which to start. In the next article we will complicate things slightly in order to learn more features of Balladeer.