Development Progress Report, week 23-24

I missed last week’s development blog post due to the pressure of other things, so I’ve got two weeks to cover.

On the narrative side, I’m nearing a long-awaited story milestone. The prologues are complete for each of the eleven protagonists, and all but two of them are written through to the end of the rather dense and complicated first day of the story proper. Once those last two characters are written through, that will represent a major milestone.

That brings us to (today), 88 scenes and 232,814 words. That’s more than Dune (the book), or Neverwinter Nights (the game) [This isn’t a competition!], but we’re not really into the full swing of things yet. That will be in the second Act, which is where the bulk of the narrative technology should start to shine (I hope!).

Continue reading Development Progress Report, week 23-24

Development Progress Report, weeks 20 and 21

There wasn’t a status report last week, because I was without electricity and an Internet connection, as a result of several days worth of getting the house rewired. Even this update is posted a day later than I’d intended.

That is past, and a lot got done during the rest of the time!

Continue reading Development Progress Report, weeks 20 and 21

Development Progress Report, week 19

Almost let the day get away from me without writing the update for Week 19. Project board says I’ve got 147 commits for the last 7 days, and closed all of my bugs (though a couple cosmetic ones turned up near the end of it).

Mostly this was an engine-work week again, so mostly working on Argus, rather than SNAFU, but SNAFU got some time as well.

Continue reading Development Progress Report, week 19

Development Progress Report, weeks 16+17

Coming out of the tangled and awkward mess that constitutes the usual (and I use the term advisedly), “festive season”, I’ve had my head down with a fairly major overhaul of the game-engine.

Once I started, it was hard to stop – particularly, since once I started, the engine was pretty much broken until I was mostly done. The primary work was converting to SDL (version 2, in case you’re wondering). I spent a couple hours figuring SDL out, then dove into the conversion.

The secondary work was just as interesting, as I started doing the necessary portability work to get the engine to build and run on other platforms.

Continue reading Development Progress Report, weeks 16+17

Show me the code: cpuid and popcount

 

So, modern CPUs have built-in functions for a lot of things, these days, which can offer you blisteringly fast access to some otherwise rather awkward and slow algorithms.

In my case, I wanted to access the CPU’s popcount function (count how many set bits there are in a value). The trick is that either the CPU supports it or it doesn’t, and different systems have different ways of testing if it does, and accessing it if it does. Of course if the CPU doesn’t support it, you still have to do it in software anyway.

So, I thought I’d write something extensible, and I thought I’d share.

Continue reading Show me the code: cpuid and popcount

Rewriting text output

Rendering text in a graphical environment is … let’s call it ‘involved’. Assuming you want to output a single line of text in a single typeface and colour, that’s pretty easy. The interface libraries will even probably be willing to word-wrap it for you.

If you want to do other things, like mix plain text with italics or bold or text in other colours, well suddenly you’ve got dozens of hoops to jump through.

Well, I did want that, so I had to work for it.

Continue reading Rewriting text output

Making inferences

Earlier on in the development of Argus, I made the decision to not bother checking if a character in the story already knew a piece of information before they ‘learned’ it.

My thinking at the time was that the act of looking up the information was essentially the same cost in time and resources as learning it. So, we may as well just learn it. If it altered what they knew, fine. If they already knew it, still fine. Nothing changed.

Then the knowledge inferences/assumptions system got more advanced. Story characters learn about each-other as the narrative progresses. Knowledge about the gender and approximate age-group of speakers is acquired by listeners, when the character speaks, and information is combined with other pieces of knowledge to determine, for example, just how characters should refer to each-other during the narrative.

Eventually the process of looking up lots of disparate pieces of knowledge, filling in with inferences and assumptions, and then producing a reference-model for referring to other characters (in a variety of levels of formality) started to get a bit expensive.

So, I finally bit the bullet, and added a method to the knowledge graph to test if something was already known before we tried to get a character to learn it. That way we can assess if knowledge the character consists of any new knowledge that might require updating their assumptions/inferences.

That means double the workload for any learning a character does (which happens a lot), but the reduction in reference-model updates actually pays back that cost almost fifty times over. The story can be processed even faster than before, with fewer spikes in CPU usage.

Overall, that’s a win.

It did lead me to code this peculiar little construct, though:

KnStore* KnStore::find(statement_t &statement, const std::wstring &p)
{
 if (statement.size() == 0 && this == nullptr)
   return (KnStore*)1;
...

DO NOT TRY THIS AT HOME!

Yes, I’m intentionally creating a bad pointer. I already had a find() method that is used to locate knowledge insertion points. Producing a contains() method (does the knowledge already exist) could use exactly the same logic (that is, call find() and test the returned pointer), but always ran off the end of the tree to a null KnStore instance, if and only if it was successful.

That was easy to subvert, and I can return a dummy pointer that no code path ever dereferences (I could also have thrown an exception, but at an additional cost).

Honestly, if I ever saw code like this in someone else’s software, that would immediately raise questions and not a few red flags. Surprisingly, in this case, it’s the perfect solution for a very specific problem.

 

Decoupling

As a result on doing some more work on Argus’ story compiler (which makes the module sound far more impressive than it actually is), I discovered that the early development prototyping had made the core engine code (the really portable workhorse library) far too tightly coupled with the platform-specific UI code.

That is, there were sections of the engine library that you couldn’t pull in without having to satisfy a lot of platform UI dependencies.

Thankfully, Observer patterns came to the rescue, and I was able to use these to decouple the engine library from having to have any direct knowledge or linkage to the UI module.

Well, mostly. Almost every case has been handled, but there’s still two parts left to do: The display of interstitial images, and managing the UI elements for character selection.

That’s all just a matter of dog-work, though. Sit down and actually cut the code. Bum on seat, code in editor.