Thursday 22 September 2011

Crass Commercialism

I've decided to bite the bullet and try my luck in the indie game market.

Not without a degree of trepidation, I must admit. But, I'm beginning to think that the only way I'll see stable employment from this point forward is to be my own boss. And if I'm going to spend all day sitting around writing software anyway, I might as well try and make it pay the bills.

So, the plan currently is to keep coding, but look at a commercial release of something. Probably still aim at the adult game market.I've got the coding skills; maybe some commercial incentive will get me to see a project through to completion for a change. Certainly it'll be nice to be able to work full time on something.

I'll also probably end up with adwords and a tip jar box on here at some point.

Plan A was "get a job", and that's pretty much failed. This is Plan B.

More details to come.

Saturday 17 September 2011

People Are Hard

Damn, but Inform gets frustrating when you try and do interactions with people.

A simple thing like fastening a collar around a slavegirl's neck falls foul of several rules.

In other news, I've decided to go professional with the games dev. Not sure of the details yet - I have a meeting which might make some funding available, so no hard and fast decisions until get done with that. Dangerous Game is one of the possible projects I might commercialise. Or it might end up being something completely new.

Meanwhile, I'm still working on The Doghouse. The story so far: You (as PC) have been summoned by your cousin Vinny and lumbered with looking after his new nightclub, "The Doghouse" while Vinny travels abroad for health reasons that are completely unrelated to the amount of money he owes to the Mob.

Of course with all that money owing, various extremely violent people will be displeased if you just walk out of the nightclub and get on with your life. So the sensible thing is to look around, work out the business plan, and get the club operational as soon as possible so you can get out before someone decides to put a contract on you too. Now if you could only work out why he put bedrooms adjoining the dance floor. Or jail cells in the basement...

You're aided in this (if that is indeed the correct word) by Einstein, the biggest and dumbest bouncer in the world. Einstein has had the plan explained to him by Vinny, but can't really remember much more than the "package is due today", although with the right questions, you might manage to jog his memory. And the arrival of the package will certainly answer a lot of questions.

So far I've coded up to the package arriving, (which has been great fun) and then hit a bit of a wall. So I hived off the "package" into it's own inform game with a view towards recombining the two when it's working.

I don't really want to release another "no-sex but loads of setup" file, so I'm going to keep plugging at the sexslave interactions, and hopefully release when there's something more to do than wander around and make wisecracks.

Monday 12 September 2011

The Doghouse

Inspired by Nuku's Flexible Society, I've been playing with Inform 7 again. I seem to be afflicted with more than my usual share of "Grasshopper Mind" at the moment.

Here's a start for something called The Doghouse. It's just a start at the moment, really. You'll need an Inform interpreter to play it. If you don't already have one, WindowsFrotz seems to work well enough.

Themes are going to be more or less my usual ones. There's not a lot of naughtiness in this yet, but you can get some idea of how it's going to develop...

Thursday 8 September 2011

Action and Action_Sleep

The action base class is pretty trivial
class Action
        attr_accessor :name
        attr_accessor :resistance

        def initialize(args)
                @name = args[:name]
                @resistance = args[:resistance] || 100
        end
end
That's a name, and a resistance value. In general if obedience exceeds resistance.

Of course, doing this in ruby, we don't really need a base class. So all this does is set a default resistance.

So, we have our first (and so far only) subclass Action_Sleep

class Action_Sleep < Action
        def initialize(args=nil)
                args = {} unless args
                args[:name] = "Sleep" unless args[:name]
                args[:resistance] = 35 unless args[:resistance]
                super(args)
        end
end

That defauts the name and changes the default resistance. I've left the args in so we can either have custom sleep actions for girls with strange sleep patterns, or else subclass it for something sleeplike later on.

What's missing here is the perform method. And this is where I get in a tangle.




#
#       two factors: obedience and tiredness
#
#       five outcomes:
#
#       disobedient and alert: will stay awake
#       disobedient and a bit tired: will try to stay awake
#       disobedient and very tired: fall asleep, mumbling defiance
#       obedient and tired: will go to sleep
#       obedient and alert: will try to sleep and pretend if need be
#
#       how to define "tired" then?
#       what do I want from tiredness?
#
#       I want to impose some limit on how long people can work
#       I want to be able to exceed that limit
#       I want to use sleep-dep to compel obedience
#
        def perform(actor)
                tiredness = 100 - actor.alertness
                obeidient = (actor.obedience > @resistance)
                tired = (tiredness > 40)
#
#               now, the simplest case is the obedient one
#
                if obedient
                        if tired
                                print "#{} sleeps soundly"
                        else
                                print "#{} lies still and pretends to sleep"
                        end
                        return
                end

#               so, these are the disobedient cases
#               simplest of which is if she's at zero alertness
#               in which case she falls asleep anyway
#
                if actor.alertness == 0
                        print "#{} mutters in her sleep"
                        return
                end

#
#               if she's not tired, she refuses to pretend to sleep
#
                if !tired
                        print "#{} makes rude gestures at the CCTV camera"
                        return
                end

#
#               now then: being tired will make her more inclined to
#               obey than she would be otherwise. Let's have a bonus #               from 1-20
#
                if actor.obedience + tiredness / 5 >= @resistance
                        print "#{} dozes, restlessly"
                else
                        print "#{} stares bleary-eyed at the camera"
                end
        end
That's still not got any changes to stats. Tiredness, obedience, resistance, none of them are moving at this point.

Next thing is to make it all compile and see how it runs.
 OK, Girl class now,
class Girl
        attr_accessor :name         # girl's name
        attr_accessor :obedience    # 100 == perfect obedience
        attr_accessor :alertness    # 0 == asleep, 100 == hyper
        attr_accessor :energy       # 0 == sick, 100 == fighting fit
        attr_accessor :actions      # action tabs - all possible actions
        attr_accessor :current      # currently selected action

#
#       set name from params, defaults for other stats
#       only one action (sleep) for now
#
        def initialize(args)
                @name           = args[:name]
                @obedience      = args[:obedience]      || 10
                @alertness      = args[:alertness]      || 100
                @energy         = args[:energy]         || 100
                @actions = {
                        :sleep => Action_Sleep.new({})
                }
                @current = @actions[:sleep]
        end
       
#      
#       call perform on the current action
#
        def do_shift(shift_id)
                @current.perform(self)
        end
end
Stats are 1 - 100 in range.
 That was simple too. Never mind, next one makes up for it

Wednesday 7 September 2011

Code: GirlList

(I'm breaking these up by class to try and avoid Blogger lagging like it did yesterday)

It seems to me that everything I describe in this blog turns out at least three times as complicated when I write it all down than it was when it was in my head. For this reason, I'm reluctant to say that GirlList is simple and straight forward. I mean, I think it is, but I'm afraid if I say so, I'll invoke Murphy.

Anyway....
class GirlList

    def initialize
        @list = Array.new
    end

    def add(actor)
        @list.push(actor)
    end

    def do_shift(shift_id)
        @list.each { |x|
            x.do_shift(shift_id)
        }
    end
end

It's basically a wrapper around an array. Method to initialise the array, one to add girls, and one to evaluate each girl's performance in a shift.  I changed do_turn to do_shift at this level, as mentioned earlier, and I may yet lower the granularity further. But this'll do for now.

Why not just have an array? I'm not sure I have a good reason, except that I often find it's good to have an explicit list class. It gives me room to add processing when a girl is added or removed, for instance.

mmm... looks like this one really was that simple.

Code: TrainingCamp

A first cut of the TrainingCamp class looks like this:

class TrainingCamp
    def initialize
        @girls = GirlList.new
    end
  
    def do_turn
    #
    #    part of me wants to break this down, hour by hour
    #    I can see good things from that. Staggering
    #    changeovers for instance, means never risking
    #    having three girls gang up on you...
    #
        @girls.do_shift(Shift::Morning)
        @girls.do_shift(Shift::Afternoon)
        @girls.do_shift(Shift::Evening)
        @girls.do_shift(Shift::Night)
    end

    def add_girl(girl)
        @girls.add(girl)
    end
end
Again, nothing surprising there. I've added a method to add girls to the camp. The calling code looks like this this:
camp = TrainingCamp.new
camp.add_girl(Girl.new( :name => "Anne", :obedience => 51))
camp.add_girl(Girl.new( :name => "Betty" ))

while true
    camp.do_turn
    sleep 1
end
That'll let me run tests with one turn a second when the rest of the classes are working.

I also added a Shift class. Since that's just a holder for the shift constants, I'll we can deal with it here:
class Shift
    Morning        = "Morning"
    Afternoon     = "Afternoon"
    Evening        = "Evening"
    Night            = "Night"
end

I could just use the strings, but this way they get syntax checked and I can spot typos. I also had the impression that Ruby stored all strings as single instances, so passing strings around was no worse than passing ints, and that using strings was the preferred Ruby idiom for constants. But now I think on it, I may be getting that mixed up with Lua. Never mind, in any event, it saves me having a lookup table to convert int constants into strings

Tuesday 6 September 2011

Let's throw some UML at that...

So, let's look at how some of that breaks down into classes.

 

Nothing particularly earth shattering there. We have TrainingCamp as a top level class (at least as far as training is concerned) which contains a GirlList which abstracts a list of Girls in training. Eventually TrainingCamp is going to have a bit more to it, since it will need to manage available training equipment, training schedules and the like. But for now, it just keeps a list of girls.

The do_turn method in TrainingCamp executes one turn (which is to say one day) of training. That gets passed down to GirlList, which passes it on to each of the girls in the list. Thinking about it, I think I'll probably change to do_turn to do_shift or do_hour in Girl and GirlList. There are places we'll want to manage simultaneous actions - like two girls competing for the same resource, or sparring, or sex training for that matter. And the PC needs to be in the TrainingCamp as well, thinking about it ... but that can wait.


Anyway...





You'll note I'm not addressing mood state at all here. This is in the interests of starting simple. For now, I'm going to have a default, neutral mood and a single task - sleeping.

Some things to note

Each Action has a resistance. The basic rule is that if Girl.obedience > Action.resistance then the thing gets done. Every time a girl performs an action on demand, there's a chance that her resistance to that action will go down. And if she successfully refuses, it should probably have a chance to go up

I had thought of using the resistance value to model a girl's like or dislike of an action, but that's not going to work. Over time, resistance is going to drop to zero for everything she does, but I'd quite like there still to be things she liked and disliked. I'll need to think about that a bit.

The possible actions are stored in a hash called actions_list. Each girl will probably have the same actions (assuming no mutants, monstergirls or whatever) but they each get their own copy of the action table so we they can have their own resistance value. If the Action object gets too bit we'll need to split it to a global action table, and smaller one containing the girl-specific data. For now we'll just copy it.

Next thing, we'll try some code.

I'll finish this up tomorrow. I'm getting tired and Blogger is giving me a ten second lag on keyboard input at the moment. Ajax for the win.

Emotion Modelling

The heart of any training game is getting the girls to react believably to the training stimulus. However our simulation of the training process hasn't really changed since Pooolka write the first draft of Slavemaker.

In this post I'm going to talk a bit about the current state of that art, and what I see as good and bad about it. Then I want to explain what I want to do that's different, why I think that would be better, and some ideas on how I hope to get it done.

OK: State of the art. Basically all the games I'm familiar with work by  having different activities add points to some statistics, and subtract them from others. On balance, more points get added than subtracted, so it's possible to max out the girl's stats, while at the same time, the subtractions keep the game from becoming overly linear.

There's a lot that's good about that approach. It's simple, it's easy for the player to understand what's happening, and it gives a pretty good impression of a training process. It's simple, and it's Good Enough. These are strong points in favour.

As for drawbacks, there are two that spring to mind. One is that the system offers few surprises once you master the basics. You don't ever see a girl fly into a huff, and then slowly warm back out if it, for instance. You never see resistance suddenly crumble. You never see sullen obedience or apologetic defiance.

The other drawback is that it's very much a single trainee model. It doesn't allow for interaction with any other girls. Even in games like Whoremaster or Otherworld  that have multiple girls designed in from the start, they're still just running multiple parallel single player training.

So, then: What I want to achieve. I want to keep the keep the good parts of the original system so far as I can, while adding room for the girls to have emotional states that can change, usually predictably, sometimes not. I want to model relationships as well. Not the girl's relationship with her trainer, but also how she feels about each of the other slaves, her feelings for other masters and mistresses, and her feelings about the various tasks used in her training.

The hard part in this is going to be maintaining the simplicity and understandability of pooolka's model. In programming terms, it's a dead loss. We're going to need a lot of code and classes to manage these relationships. In terms of player interface, I think we can keep it more or less unchanged. As for understanding why the girls are behaving as they are, that's harder.

If a girl does unexpected things too often, then the game seems arbitrary and unfair. We can mitigate that a lot by making information available so the player can work out why in reterospect. But at the same time if we make too much information available, we lose the surprise when something unexpected does happen.

How to do it: I'll go into more detail in the next post, but basically I want to
have a state machine for different mental states, and to have that emotional state colour the way a girl reacts to a task. So if she's Defiant, then even if she obeys, she'll do it spitting curses at you. Or we might have an Submissive state where she does pretty much as she's told, and if for any reason she can't bring herself to obey, it'll be with apologies and pleas for mercy. Run either of them for too long and they'll transition to Tired, and not say anything apart from "need .. to ... sleep ..." or some such thing. Let them sleep and they'll jump back to their previous state.

Transitions are all going to be based on rules, and those rules will take account of  environmental and situational circumstances as well as attributes. So, for instance, you could have girl busy falling in love with their trainer, who has a bad day and ends up tired and hungry and gets given all the tasks she hates. If she gets enough negatives from all that, it's possible she might spike to an Angry state. She probably won't stay there long, because her stats are still ones for "falling-in-love". So the trainer gets an unexpected earful the next time he talks to her, followed by a fairly rapid cooling off afterward.

There are other things I'd like to do, too. Make effective training rely on rewards and punishment as well as simple repetition of a task, and allow the player to use things like hunger and sex drive as leverage to get obedience. But there's probably enough to be going on with here.

So, to summarise: I want to extend the basic pooolka model for training by adding emotional states that transition by well defined rules, but which are still capable of unexpected spikes, and I want to model relationships with people and with activities to provide extra variables to drive those state transitions. All of this with a user interface little different from the one
in slavemaker.

Next post I'll do some UML and maybe some code showing how I'm thinking of implementing all this.

Thursday 18 August 2011

Dangerous Game

Dangerous Game.
Platform: RPG Maker

The PC gets to join a club for the wealthy and privileged whose members regularly meet to hunt women. Each particpating hunter is expected to bring one girl to be released as quarry. It turns out there's an advantage to having your girl able to fight (since she can fight off the other hunters) and also being loyal to you (so she won't try and kill you). As a consequence a lot of the club activity is centred around slave training; both for combat skills and loyalty to their master.

Real early days on this as yet. Got an intro scene and a rough layout for the menu screen. The naked slavegirl, buttons, and rail are courtesy of redcape, who's put so much work into the look and feel of Otherworld.

We decided wanted to get away from the standard RPG/XP blue and white menu screen. I think we're succeeding.

This is more or less the idea I had for the Inform game I was talking about earlier. How it got to be RPG Maker, I have no idea, but I think i'm going to run with it. I can save Inform for another day :)

Wednesday 27 July 2011

Well, that was pretty revolting

Well, I left for a trip to Glasgow for a job interview, got back and spent all night and most of the next day getting intimate with the toilet bowl. I've just now had my first solid food in 36 hours (a slice of dry bread) and I'm in no particular hurry to try another.

So. Not a lot happened to report in that respect.

Meanwhile, if you don't know already, there's an alpha release of Otherworld going. Buggy as hell, but we're working on getting it into shape. I think that's mostly what I'll be doing between now and Friday.

Saturday 23 July 2011

Otherworld and ... other stuff

OK, so that was waaaay too long in between posts. I've been working on Otherworld, and for some reason wasn't comfortable posting about it in this blog. Don't ask me why, it makes no sense at all in retrospect.

So, I'l probably post a bit about some of the stuff I'm doing for that. No reason I can't meditate on Actionscript as well as C++.

Probably Inform7 as well. I've been looking at some of the adult based interactive text adventures out there: Valente and Fenoxo in particular. The whole transgender doesn't do anything for me I'm afraid, but they way they've been using Inform is a bit of an eye opener. So I've been playing around with something similar that plays more to my own particular interests. So expect a bit of that to show up as well.

(I know, I know ... another new project that'll last just long enough to look interesting and then get dropped in favour of the next shiny language. What can I say? It's how I learn things).

Monday 31 January 2011

Loading issues fixed

well, so far as loading chapter headings and background images goes, anyway. Still a lot of cases need adding.

Next I want to do the shuffle code. there's two parts to this: shuffling the narratives in a scene (or items in a narrative, or options in a choice, etc, etc, etc) and then there's re-arranging the treeview to reflect the change.

Let's get test cases for the Scene, Narrative and the rest, first.

Saturday 29 January 2011

A Test Case

SceneEdit, Boo. Test Case. Why isn't the image tag loading from XML?

        [Test]
        def load_background2():
                source = detab("""
                <scene name="GameStart" default="" desc="wibble wibble">
                 <narrative name="waking_up" desc="In which our hero ...">
                  <image path="data/images/foo.png" />
                  <image path="data/images/bar.png" />
                 </narrative>
                </scene>
                """)

                sr = StringReader(source)
                r = XmlReader.Create(sr)
                scene = Scene()
                scene.load(r)
/*
 *              make sure we have a narrative
 */
                Assert.AreEqual(1, scene.narratives.Count)
/*
 *              get the narrative, check the name
 */
                n as Narrative
                n = scene.narratives[0]
                Assert.AreEqual("waking_up", n.name)
/*
 *              now - it should have two narrative items attached
 */
                Assert.AreEqual(2, n.items.Count)


And that fails: there are zero items in the narrative. Also of interest is an error message in the test output saying "name image not handled". I missed that in the general output chatter when running the app itself.

A bit of grepping tracks that down to the Narrative class:

        def load(r as XmlReader):
                _name = gatt(r, "name")
                _desc = gatt(r, "desc")

                while r.Read():
                        if r.NodeType == XmlNodeType.Whitespace:
                                continue
                        if r.NodeType == XmlNodeType.EndElement:
                                if r.Name == "narrative":
                                        break
                                continue
                        if r.NodeType != XmlNodeType.Element:
                                print "unexpected node type: ${r.NodeType}"
                                break
                        if r.Name == "narrative":
                                break
                        if r.Name == "snippet":
                                sn = Snippet()
                                sn.load(r)
                                _items.Add(sn)
                                continue
                        print "name ${r.Name} not handled"


So I need to add a case to that loop for every tag I intend to read. Tedious, but at least I found it.

Incidentally, that's lousy O-O methodology. One of the basic ideas behind OO is that you have subclasses so you don't need to have ifs or switches like this. The trouble is that this kind of breaks down when you're reading text data.

The OO way to do it would be to have a factory method, typed as NarrativeItem that took the class name as a string and returned the appropriate item. You'd have a reader class specific to each tag and register them with the factory so it knew what objects mapped to what strings.

Really though, life's too short. Getting all that working and debugged is a task in its own right, and for something as minor as this, it just isn't worth it.

Of course, all that may change as the code evolves. For now though, we'll go with the old-fashioned approach.

Friday 28 January 2011

Shuffling Along

OK, time to look at the shuffle problem. First of all the verb needs to change to "move", if only on the buttons. "Shuffle" takes up too much space. (That said, I'm going to need another row of buttons before I'm done, but that for later).

The thing that stops this being trivial is that we need to be able to shuffle anything from menu choices to narratives.

I think I need some more test cases...

Thursday 27 January 2011

Shallow Bugs and Whoremaster

Well, there are that many bugs in this editing tool, if I hadn't doucmented the test suite as I went, I'd wonder if I ever tested it.

The thing is, short of some complicated and expensive software, there isn't a good way to repeatably test GUIs. (OK, it should be possible to do some tricks with NUnit and reflection, but I've never quite got that to work in practice).

Anyway, the theory is to put the application logic into a dll and test the hell out of that. The GUI code is to be as thin a wrapper around the dll as possible. But the GUI still needs testing - which is what I'm belatedly doing now, I suppose.

On the bright side, the bugs have generally been pretty superficial - which should be one payoff of the TDD phase. There shouldn't be any deep errors in the application logic, because I have tested the hell out of that.

On another note, I'm quite enjoying playing Whoremaster again. One of the drawbacks of developing a game is that somehow you never get to play it. You make changes and you test them, but somehow you stop playing for fun. Having had a break from the dev process, I'm starting to enjoy the game, and in doing so I#m starting to think about what I'd like to do to the source code.

I'm not about to break my sabbatical just yet but ... I'm starting to look forward to doing some work on the program again.

First Or Second Person

I keep alternating between wanting to write scenes in first and second person. So I thought I'd throw the question to the audience, as it were, and see what people think.

Both styles can be effective. The old Infocom style text adventures generally used second person narratives:
You are in a round room.

> PISS IN THE CORNER

Sorry, I don't understand "corner".

You are in a round room.

And that generally worked. The style was very much based on the pencil-and-paper role-playing games of the time, but you can tell a tale and get the player to identify with the protagonist. Of course you probably need to be a bit careful what words you put in the player's mouth, (and what thoughts you put in the players head!). Even then, games like Curses and Trinity play from the perspective of someone who definitely is not the player, and they still work very well.

Japanese style ADV games on the other hand tend to use first person, at least from the examples I can bring to mind. The dialog tends to be stream of consciousness from the MQ.

This is a very strange room I find myself in. It appears to be completely round.


It's all a bit confusing to me. They told me to take a piss in the corner, but there are no corners to piss in.


Maybe I could do it in the middle and claim the piss drained there. Maybe that would work. Or maybe they would see through my ruse and be angry with me.


It is a conundrum.
I think this possibly works better for ADV text. Second person seems a bit like constantly telling the player what to do. It's all right for descriptive text, as in Zork you have to say what happens to the player as the result of his choices. But then you get a lot more choice per text passage in Zork than you do in any ADV game.

Anyway, opinions anyone?

For example...

If there's no configuration set up, SceneEdit doesn't always default to the current folder. (actually, it should probably default to the one above on the assumption that it's been called from the tools sub folder.

If you edit the path and change it, the change is not reflected in the textbox

You can click +Narrative from the initial config screen and crash the tool - because the scene isn't set up as yet.

Dogfood, I tell you.

[edit]

Fixed them. Started a new scene, called it "waking up" hit tab ... and it crashed. This may take longer than I'd anticipated.

I think I'll just edit this post rather than spread the debug process over umpteen posts.

[edit]

Too many to log, all fairly simple. One that might take a bit more work: TreeView nodes aren't being set quite right. There's a nasty disorienting jump. Probably the result of a ham-handed fix to an earlier crash problem. (Scene needs to be a NarrativeItem - and I suspect Narrative will also need that distinction).

[edit]

No crash on narratives, but browsing for images doesn't use the game Resource folder as its root - which is the point of the config entry...

... the file browser doesn't do thumbnails for images - have to check the docs for that - I might be using it wrong ...

... and when I do find the image I need, the label in tree view is wrong...

[edit]

Save dialog uses the last image folder as default, which is wrong. Can fix that with two save dialog objects, perhaps. Seems wasteful, but should work.

On the bright side, it seems to be getting usable pretty quickly. There's hope yet :)

[edit]

Never did get around to making the shuffle buttons work...

[edit]

images and chapter headings don't appear to load. They save ok, but they don't appear in the loaded treeview. Let's review those test cases.

Also, specifying the XML file on the command line doesn't work

Wednesday 26 January 2011

Time To Eat Dogfood

If you're familiar with the idea of the "dogfood test", the title will make sense. If not it probably sounds a bit weird.

In software, the dogfood test is "does the developer use his own tools and/or products?" If a maker of dogfood thinks their product really is healthy, they'll be quite happy to eat it themselves. If not, you're entitled to ask "so what's wrong with it?" Similarly, you should expect a software house to use its own tools.

Which is a pain right now, because I need to convert all the text so far. I've got this neat GUI tool to do that (and spent way to long writing it) but what I really want to do is fire up vi and hand edit the XML.

The thing about that is ... you can always tell when a developer doesn't use his own tools. If you use a program, you tend to find and fix the problems as they occur. Eventually it gets to be more than just functional. It gets to be smooth. If you don't use it, then you tend to leave the rough edges in place.

So, if I want other people to use SceneEdit, I guess I better use it myself.

I expect there are dog food manufacturers who don't much care for the taste of dog food, come to think of it.

GuiStage

I'm chipping away at this in tiny little chubks at the moment. I get just so far and my concentration seems to go. Never mind, we do waht we can.

Today's exercise is to write the GuiStage class. A while back I wrote about using a "Stage" class to abstract the game engine and let me test the adv engine. I have a TestStage which works and using it I have a lot of tests (many of which need updating - the XML format changed during the SceneEdit develoment)

Anyway, now I need a GuiStage class. This being Lua, there isn't an actual base class to work from, so I'm going to adapt the Test version.

--[[
 * A Stage is where a Narrator might enact a Scene. So that's the
 * metaphor - a Stage is the interface that the Narrator class uses
 * to interact with the user (or test harness).
 *
 * in this case, we're interacting with the game GUI. Yayy!
--]]
module(..., package.seeall)

GuiStage = GuiStage or {}
GuiStage.__index = GuiStage

--[[
 * Create the object. Not sure what data we need to store
--]]
function GuiStage:new()
    self = { }
    setmetatable(self, GuiStage)
    return self
end

--[[
 *
 * This sets the background image for the adv window.
 *
--]]
function GuiStage:image(file)
end

--[[
 * This displays a message box
--]]
function GuiStage:text(string)
end

--[[
 * This called when a choice is displayed, to test the display
 * The result will be apparent from the text elements following the choice
--]]
function GuiStage:choice_show(options)
end

--[[
 * This called when a the result of a choice is required
 *
 * What we'll do is pop the value off the front of the input queue
--]]
function GuiStage:choice_result(item)
end

--[[
 * background image: not sure why this is here -
 * or what the difference is with the image method.
--]]
function GuiStage:set_background(filepath)
end


That's what I have to work to. I'm a little nonplussed to find I wrote two methods to set the background image. That said the set_background one doesn't seem to be used anywhere - test or production code. I'm tempted to use the name for the other method ... but that leaves too much code to fix and too many possible bugs if I miss something.

Anyway, that's my worklist.

Tuesday 25 January 2011

Finally!

At last, it's working. Or at least the introduction is - there are grat swathes still to write. The problem seems to have been with the event manager. I don't know what it was, but I ended up rewriting it using std::list.

Now, I can backtrack to test the XML format I was working on around Christmas, convert the story-so-far to XML, and then start to look at the lab screen again.

Monday 24 January 2011

Back into C++

Been a bit slow on the Conemaster front; I've been working on a generalised event format for Otherworld. I won't go into details here. If you're interested, check out the thread on the otherworlds board.

Meanwhile, back to C++. That can't find from namespace message seems to be harmless. It blows up on script because there's an event loop iteration before any window is displayed and the framework expects to find something with a script() method. I should probably add a dummy function into startup.lua just to silence that.

So why are those damn buttons not working? Best guess is a bug in the C++ framework. Doing some debugging, a click on the new button generates an event with an ID of 800 - but that isn't the ID under which the button is registered.

So, I need to dig a little deeper. This is all still catch-up stuff from before summer, really. I've been assuming the C++ was sound and all the problems lay in Lualand. Clearly that was an optimistic assessment...

Oh well, if it was easy, it wouldn't be any fun :)

Wednesday 19 January 2011

Lua and C++ - still

OK, one last chunter on this subject, and then it's high time I did some actual work.

Really, one thing that stands out from this is that I don't need to do much to the current setup. The prepare/run (I might call that init/run) approach works well for repeating events that need to be re-initialised. If the function isn't there it doesn't get called. The initial script doesn't have a namespace, but that's fixable, either by allowing a "" namespace meaning "look this up globally" or else by modding setup to use Setup or something similar. Or I could pass "_G" as a namespace, which would cause the lookup to use the global table.

I am a little worried that people will try and write functionality that runs when the chunk is executed, rather than when the functions it defines are executed. The problem there is that I'm not sure when a script/chunk will be executed, so the timing is undefined and subject to change.without notice. But writing the thing to execute when the script is parsed may well work for a lot of events. And of course, there's a pile of Lua that is supposed to work like that.

I guess I still don't have an entirely clear idea of how all this is going to work, despite writing way too many words on the subject.

Maybe the solution is to code some stuff up and see what happens. Getting ideas-on-paper is one thing, but this is turning into putting-off-work.

Tuesday 18 January 2011

Lua and C++: Lost in the wilderness

That was a longer break than I intended. I blame job hunting, real life, and a certain amount of Fallout 3. But let's not dwell on that.

I said I got very confused about how Lua worked with C++. I started thinking things like "well, if a chunk returns a function, then I should be defining functions. So I'd write a lua script like this:

function greeter()
      log("greeter script begin")
      message("Welcome to Clonemaster")
end

... and then wonder why it didn't work. Of course, it doesn't work for the same reason as it wouldn't work in a Lua script: the function is never called. When I run the Lua chunk I define the function, but need to also call it to make it run. If I'd just added one line to it, it would have been fine:

function greeter()
      log("greeter script begin")
      message("Welcome to Clonemaster")
end

greeter()


That seems so obvious in retrospect, but at the time, it cause me major headaches.

The other thing was the fact that Whoremaster needed the script exit so the SDL event loop could run. This meant that some things didn't happen when you asked them to happen. Message noxes just queued up, and that was fine. But image changes didn't happen until the script returned. So if you had three different images to illustrate those queued text boxes, they all be shown at once, at the end, and only the last one would be seen. Likewise, menus never got drawn until the script returned.

Eventually, I figured this out, and decided that what I needed was to have a separate namespace for each script, and for each one to have "prepare" and "run" methods.

Example = Example or {}

local stage = 0

Example.prepare = function()
        // set up the class variables ready for the script to run
        stage = 0
end

Example.run = function()
        // set up the class variables ready for the script to run
        stage = stage + 1
        if stage == 1 then
                // do stuff up to the first change of scenerey
        elseif stage == 2 then
                // do stuff up to the second...
        // ...
        end
end


The prepare idea was partly because necno's scripts in WM had a prepare method, and partly because I needed something to reset events when they were triggered.

Actually, that's probably still a pretty good event template for Clonemaster. It's just that I'm using scripts in a lot of other ways too, so I think I need to be a bit more flexible in how I call them.


One possibility which occured to me some time ago: if I can factor the SDL event loop into a C++ function, I could call it from inside the script. That would simplify a lot of the Lua architecture. It was too big a change for WM; for Clonemaster ... I'm worried that I'd need multiple invocations until it was ready to return to the script, and that in that time, the user would find a way of triggering another script, resulting in multiple embedded event loops, and some very hard to find errors. I still am, and I'm not going to do it for that reason...

Need to think about this a bit more..

Thursday 13 January 2011

Lua and C++: storing chuinks, functions, packages, modules

So: if we want to use a Lua chunk more than once, we need to keep track of where we can find it. Let's look at how functions work in Lua for a moment.

Normally, you define a lua function like this:

function foo()
    print "woof"
end

foo()


All fairly unremarkable. You can also create anonymous functions and assign them to variables:

foo = function()
        print "woof"
end

foo()


In actual fact, the two cases are identical. Just like in JavaScript/Actionscript (and probably a ton of other languages as well) if you write "foo()", the interpreter looks for a variable called "foo", checks to see if "foo"  contains a reference to a functions, and if it does, that function is called.

So, thinking about our C++ program, all we need to do is take that chunk and store it in  a global symbol. We can check that. First I want to split the loading and execution parts into their own funcs:

/*
 * load the string: the compiled code will be left in a "chunk"
 * (an anyonymous function) on the top of the stack
 */
int load(lua_State *L, string proggy)
{
        int rc = luaL_loadstring(L, proggy.c_str());
/*
 *      zero means success here
 */
        if(rc == 0) {
                return 0;
        }
/*
 *      report the error
 */
        cout    << "there was an error loading the script: <<"
                << lua_tostring(L, -1)
                << ">>"
                << endl
        ;
        return 1;
}

That's exactly the same code as before, just in its own func and with some extra comments and whitespace.

Similarly for the call part:

/*
 * call the function on top of the stack - bare minimum
 */
int call_top(lua_State *L)
{
        int rc;
/*
 *      run pcall: no args, no return, default handler
 */
        rc = lua_pcall(
                L,              // lua state
                0,              // number of arguments
                0,              // number of expected return values
                0               // error handler - use lua default
        );
/*
 *      a return of zero means everything worked OK
 */
        if(rc == 0) {
                return 0;
        }
/*
 *      the only other possible return (according to the docs) is one
 *      which means an error
 */
        cout    << "there was an error loading the script: <<"
                << lua_tostring(L, -1)
                << ">>"
                << endl
        ;
        return 1;
}

And then the main func gets a bit more manageable (and I can stop copying the include statements each time...)

int main()
{
        int rc;
        string prog = "print \"hello\"";
/*
 *      create a state for the lua interpreter
 */
        lua_State *L = lua_open();
/*
 *      set up the standard lua libraries
 */
        luaL_openlibs(L);
/*
 *      try and load the program - exit if it fails
 */
        if(load(L, prog) == 1) {
                return 0;
        }
/*
 *      call the chunk: it's on top of the stack
 */
        call_top(L);
/*
 *      shutdown the interpreter
 */
        lua_close(L);
        return 0;
}


Storing the chunk is easy:

/*
 * stores the function on top of the stack as global name
 * lua_setglobal pops a value from the stack, so the func will
 * no longer be there when this returns
 */
void save_chunk(lua_State *L, string name)
{
        lua_setglobal(L, name.c_str());
}


Looking it up again:

/*
 * stores the function on top of the stack as global name
 * lua_setglobal pops a value from the stack, so the func will
 * no longer be there when this returns
 */
void find_chunk(lua_State *L, string name)
{
        lua_getglobal(L, name.c_str());
}


It's fairly easy to see that these functions are just wrappers around the lua calls - and in fact they can be used to assign anything to a global name - whatever is on top of the stack. So normally I wouldn't bother with the functions, and I do so here purely for the sake of clearer explanations. (Hope it works).

Anyway:

int main()
{
        int rc;
        string prog = "print \"hello\"";
/*
 *      create a state for the lua interpreter
 */
        lua_State *L = lua_open();
/*
 *      set up the standard lua libraries
 */
        luaL_openlibs(L);
/*
 *      try and load the program - exit if it fails
 */
        if(load(L, prog) == 1) {
                return 0;
        }
/*
 *      chunk is on top of the stack - store it!
 */
        save_chunk(L, "hello");
/*
 *      lookup the chunk under global "hello" and then call it
 */
        for(int i = 0; i < 3; i++) {
/*
 *              need to find it before each call
 */
                find_chunk(L, "hello");
                call_top(L);
        }
/*
 *      shutdown the interpreter
 */
        lua_close(L);
        return 0;
}


And that now works as expected, printing "hello" three times. So we can parse a script and store itas a named function. But is that the best way to do things?


And this is where I started to get seriously confused...

Lua and C++: load and execute

OK. A couple of posts back I mentioned how luaL_dostring was mildly discouraged. I said I'd talk about that a bit more later. So let's do that.

The luaL_ functions are convenience functions in the Lua C API. There's nothing in them that is primitive: nothing in luaL_* that can't be done using a few calls to lua_* functions.

luaL_dostring is a case in point. The manual page is short and to the point.

int luaL_dostring (lua_State *L, const char *str); 
Loads and runs the given string. It is defined as the following macro:
     (luaL_loadstring(L, str) || lua_pcall(L, 0, LUA_MULTRET, 0)) 
It returns 0 if there are no errors or 1 in case of errors.
So the function basically does a load and and exec. That's not necessarily a bad thing, but you get some more options if you split load and exec. Specifically, you can load a big and complex lua script once, and then run it several times, without the overhead of parsing the string.

Of course, to do that you need to be able to fund the function once you've loaded it. luaL_loadstring is a convenience wrapper for lua_load (which is more complicated than most people will ever need), but you still need to look at lua_load to get the important datum:

Loads a Lua chunk. If there are no errors, lua_load pushes the compiled chunk as a Lua function on top of the stack
A "chunk" is what lua calls the compiled bytecode resulting from a load operation. As the manual says , the chunk is typed as a function. So to make it happen you need to call it. Usually with lua_pcall.  The "p" in pcall means "protected mode" which means that an error in the lua code can't crash the C++ program  Generally, you want all your calls to use protected mode.

So let's go back the simple hello program:

extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}

using namespace std;

#include <string>
#include <iostream>

int main()
{
        int rc;
        string prog = "print \"hello\"";
/*
 *      create a state for the lua interpretter
 */
        lua_State *L = lua_open();
/*
 *      set up the standard lua libraries
 */
        luaL_openlibs(L);
/*
 *      load the string: the compiled code will be left in a "chunk"
 *      (an anyonymous function) on the top of the stack
 */
        rc = luaL_loadstring(L, prog.c_str());
        if(rc == 1) {
                cout    << "there was an error loading the script: <<"
                        << lua_tostring(L, -1)
                        << ">>"
                        << endl
                ;
        }
/*
 *      call the chunk: it's on top of the stack
 */
        rc = lua_pcall(
                L,              // lua state
                0,              // number of arguments
                0,              // number of expected args
                0               // error handler - use lua default
        );

        lua_close(L);
        return 0;
}

 
And that works. So now I can write

        lua_pcall(L, 0, 0, 0);
        lua_pcall(L, 0, 0, 0);
        lua_pcall(L, 0, 0, 0);

And get "hello hello hello", right? Wrong. I get one "hello". The other two calls do nothing.

The problem is that the function has to be on top of the stack.The trouble is, to quote the manual:

All arguments and the function value are popped from the stack when the function is called
So by calling the chunk, we've lost it. It presumably still lives somewhere deep inside the luaState data, but I don't know any way to retrieve it.

So what we need to do is to make a note of where we can find it before we make the call....