Tuesday, January 27, 2009

Yet more Vampire

(a further post in the "blog as a dump of deck notes" series)

So, at the social today, A had yet another stab at the Revolutionary Council Anarchs deck I'm trying to get to work. It's morphed a fair bit since the last attempts - I totally reworked the crypt, relying on Anarch Converts rather than trying to make Jack Drake work, which makes the crypt cheaper, although I still think the balance is a bit off. The existance of Herbert Westin, another 5-cap with OBF & PRE helps, but I'm still not completely happy with the crypt. I dropped the No Confidences, as just being to corner case, and replaced Anarch Manifesto's with Crypt Son's, since equiping them doesn't actually require an anarch, so can't be used to play Crimethinc. I'm relying on a smattering of tha in the crypt, and a bunch of discipline masters to boost my vampires.

In the first game, I was bleeding Andrew (playing old-school Toreador with some guns), bleeding Simon (Tremere) bleeding Richard (Guruhi PRE bleed) bleeding Marc (!Ventrue Wall/Bleed), with me starting. While I had a reasonable crypt draw (both Rennet and Herbert in the opening crypt), I had a sufficiently strange library draw that's it hard to say anything about the deck from it. I didn't draw a single Revolutionary Council, Effective Maangement or stealth card, and only drew 1 Crimethinc, immediately before I was ousted. Since I went through about 1/3 of my deck, that's fairly improbable (odds of around 1 in 1000, according to Sutekh (since I wrote that bit of the code, I'm reasonbly certain the maths is correct here)). Needless to say, the experience ended up being pretty annoying, and being hit by the occasionaly dominate bleed meant I was osuted without being able to put much pressure on Andrew. At this point, I went in search of some food, so I'm a bit hazy on the details of the rest of game, but, as I recall, Andrew having gradually built up, and, with Masika out to act as a repeat blocker, was able to defend himself well while bring out lots of small minions to whittle down Simon, with the occasional big presence bleed. Richard got several large bleeds through on Marc, but was unable to really get his pool farm going, due to having two Vessels Sudden'ed, which also stopped him burning Marc's blood dolls. Consequently, he was unable to survive a lunge by Simon, who soon fell to Andrew. Marc held on for a bit, but ultimately Andrew's minion superiority simply overwhelmed him.

In the second game, Andrew, playing a Ravnos deck (and starting) was bleeding Richard (Guhuri) bleeding me (Anarch Revolutionary Council) bleeding Marc (Nosferatu Rush combat) bleeding Simon (!Salburi). I had a much better library draw, and actually got some use out of the Poachers Hunting ground (until Andrew burnt Richard's hunting ground). I also managed to get three Revolutionary Councils off, although I had to direct 1 backwards to avoid being blocked. I was able to pressurise Marc quite successfully, but ultimately struggled to generate enough stealth. There were a couple of occasions where I was possibly 1 stealth card away from having the oust, but never quite drew the cards I needed. Having to juggle minions in and out of torpor because of Dragonbound being on the table also complicated things for me. I ultimately was ousted by Richard. Simon was able to oust Andrew via Fame, while Richard managed to strange day a bleed past Marc's 3-Raven spy Cock robin to oust him. Simon though, was eventually able to knock Richards minions down, diablerising Iniko and, had we not called the game at the point, would have probably been able to bleed through (although arguably the game was long past the timeout stage).

The major problem was the lack of stealth - I amybe need to rework the crypt a bit more so there is more OBF available, and run more different stealth cards - having the option of dropping the occasional Lost would make getting the votes to the table more likely. The problem is finding the space, though, as I need to have a number of slots for the Fee Stakes, I can;t reduce the vote push, since the anarch titlesjust aren't enough, and the defence package is already probably too weak. It needs more work, but it's much closer to a working deck idea than in the past, I feel.

Wednesday, January 14, 2009

Gtk+ lessons

I learnt of a couple of interesting gtk+ quirks over the last couple of days while hacking on Sutekh. Both rather surprised me, so are thus worth noting for future reference.

The first quirk is something I still don't fully understand. For various reasons[1] Sutekh uses strings to display the numbers with markup in the interface. I recently added a tweak so that these would sort numerically, rather than lexically. Since this involves stripping off the markup and converting to an integer, the sort is not lightning fast, but still acceptable. Unfortunately, adding the tweak the obvious way doubled the length of time to run the tests on the model, despite the model being unsorted by default. I've been unable to track down why this affects the tests so badly, since we shouldn't be using that code path at all. Fortunately, a simple lazy work-around exists, which is to tweak the sorting in a slightly less obvious way, and avoid it impacting the test suit.

The second quirk is something I do now understand, although the behaviour did surprise me. Sutekh is capable of generating very large gtk+ models (using "show all cards, show expansions + card sets" and editable options, it's easy to end up with a gtk.TreeStore containing more than 100000 entries). Loading these was unacceptably slow, with most of the time spent adding rows to the model, despite using the usual recommended tricks of disabling notifications and such while adding the rows.

It turns out that the underlying data structure for the gtk.TreeStore is glib's n-ary tree, g_node.
g_node, however, represents each list of children as a singly linked list from the parent. Consequently, appends into long lists are slow, since you have to walk to the end of the list. There's the obvious work-around, which is to insert thing in reverse using prepend, and it is indeed significantly faster, but you'd think this would be mentioned prominently in the docs, rather than requiring one to grub around in the glib code.

[1] i.e. We haven't got around to fixing this the right way yet.