Thursday, January 28, 2016

Playing with Python 3 & Gtk (or What I did with my Summer Vacation)

Oh, yeah, I still have this blog thing.

As is fairly obvious to people who've seen my homepage, I take quite a lot of photographs. While I'm a big fan of using file system hierachies to categorise information, and it's fundamental to the way my Gallery software  works, there are nuances that are hard to represent with a single hierachy.

For years, I've used f-spot to maintain a tagged database of my photos, which makes various queries a lot simplere. Of course, f-spot has always been annoyingly buggy, and is now essentially dead and increasingly suffering from bit-rot. The official replacement, shotwell, is nice enough, unless you're the sort of person you cares about how the data is actually stored in the database, in which case it's not for you. (I shall not eloborate - the curious can easily shotwell's behaviour themselves). Since I'm the sort of that does care, shotwell's out. There is digikam, but Ive never hit it off with the KDE design philosophy, so that doesn't work well for me either.

Which of course leaves the traditional solution to minor inconviences with other people's software. Re-inventing the wheel. This does have a number of advantages. I can have something that just has the features I want, and drop a lot of stuff, such as all the image editing functionality, that there are better tools for. Furthermore, by writing in python 3, using gobject introspection and a pre-release of SQLObject, I can justify it both as a learning exercise (since I hadn't previously gotten beyond toy gtk3 programs), and also as testing SQLObject 3.

The net result of all this is Phototagger , something I'd actually decided to write in 2014 (but then as a python 2 program), but then didn't do any work on for more than a year, and which now represents far too much of my free time over the last month and a half or so.

There was a point early on where the actual code design was reasonably neat, but stuff got tangled as I worked around some questionable early choices without addressing the underlying problem, so a rewrite is on the cards at some point, but it now works pretty nicely.

The features are nothing special - photos can be added, tagged, tags can be edited and have various images assigned to them, and all that sort of thing. The search functionality is a bit limited - it doesn't allow constructing arbitary tag queries, but it covers the sort of queries I generally need.

Indivual photos can be viewed

And zoomed - this also supports mouse panning, which took a surprisingly long time to get right due to a misreading of the Gtk documentation.

As a learning experience, it was pretty useful. I got to play with some of the new Gtk 3 widgets, such as the Stack and FlowBox widgets, which are nifty, and work through some of the changes between Gtk 2 and Gtk 3. It's also given me a fair amount of confidence in SQLObject's python 3 support, although it doesn't stress the limits of SQLObject particularly.

As a tagging tool, it's now functional enough to replace f-spot for me, and has proved a great deal more stable. I now just need to rewrite a bunch of the tools I wrote to managing my f-spot database easier, and then I can finally move on.

Tuesday, July 22, 2014


As I've mentioned a few times, I spend a reasonable amount of my free time (and sometimes bits of my not free time ("compiling!")) working on Sutekh, our card manager for VtES.

As I've also mentioned, I created a fork of Sutekh called Thufir, which does the same thing for the defunct Dune CCG. While I got Thufir to a point I was happy with, I never really kep it up to date with Sutekh's developments, so the two code bases diverged rather rapidly.

Now we add the recent Android: Netrunner LCG into the mix. While there are a varierty of web-based card managers for A:NR, I find them clunky, and there's a dearth of other options. Maintaining a third fork of Sutekh also looked really unappealing, so I hatched a cunning plan to refactor Sutekh considerably, pulling a lot of non-VtES specific code into a nice, reasonably reusable basis for writing card management applications. I also reworked Thufir to use this new framework, fixing a lot of bugs and gaining a whole lot of new, useful features there. Of course, this all took time, and, as a result, I didn't get around to actually working on my A:NR app (called Whizzard).

Over the weekend, I decided to knuckle down and actually start working on this. Although there is still missing data and a bunch of features to hook up, it's moved past the vapourware stage really quickly, which gives me a warm fuzzy feeling about the refactoring work done on Sutekh.

Sutekh's base infrastructure is still not quite as self-contained as I'd like, which would avoid needing to duplicate code in the various repos, but I still haven't come up which a way of plugging the last couple of leaks I'm happy with, so I'll live with the current state of affairs until inspiration strikes.

Wednesday, February 5, 2014


Sometime towards the end of last year, I lost an argument about how traffic lights work with a minibus taxi. While I got off reasonably unscathed, my poor Honda didn't, which was a very sad experience.

Consequently, I spent some time looking for a suitable replacement. This took longer than I wanted, due to general end of year craziness, but eventually resulted in something I quite like.

Now that I have the licensing all sorted out, I hope to be able to enjoy the remaining good biking weather before winter sets in suitable style.

Sunday, April 21, 2013

Pyweek 16: Nemesis

So we've reached the end of another pyweek, and I've managed another game ("Bane's Befuddlement"), so it's time for my usual post-pyweek post.

Since most of the usual suspects were busy with other things, I ended up doing a solo entry for the first time. I also decided, on something of a poorly thought-out whim, to use kivy for this entry.

Based on what happened with Mad Science (pyweek 14), I expected the solo entry to be something of struggle, and it does show in the end result. Artwork was obviously limited, since it's not my strong suite and I didn't want to spend a lot of time on the issue, but fortunately I was able to offset that somewhat by using one of the existing dungeon tile collections.

Probably the most crucial failing is ambition. Several of the past pyweek entries I'm been involved in have suffered from being overly ambitious (Nine Tales (pyweek 12) being the worst offender), so I aimed to avoid that pitfall this time. As a result,  I was under-ambitious. The game isn't that challenging, and is a bit bland. It's not without potential, but needed more time spent on the initial concept to really get something I would have been happy with.

There are several things I am happy with. I reaffirmed my belief in the importance of level editors for pyweek games. Even with the very simplistic one I wrote here, I was able to fill out the level content very quickly on Friday and Saturday as a result, and I rather like the careful level of stupid that AI achieves.

There are a few tricks about touch interfaces I need to learn. The most obvious one from this game is to avoid anything that goes too close to the edge of the screen - it's too easy to accidentally trigger one of the other buttons in that case.

As an exercise in working more with kivy, this was pretty successful. I'm still uncertain about how I feel about kivy. It's quite nice in some ways - being able to add a settings pane or a popup dialog with only a couple of lines of code - but it's also all sorts of magic in ways that really aren't helpful. The complicated import dance needed to ensure that we set the configured window size before creating the kivy window is just one example of this sort of thing. More annoyingly, the inability to hook in to the command-line argument parsing without some serious monkey patching is the sort of poorly thought out design that makes working with it painful.

Python's still a work in progress on android, and, while it's possible to use pyjnius to access the hardware, and to build apk's, both require more fiddling with building python for android than I was prepared to do during a pyweek, so, while the game runs OK on my phone, it's missing some features which would be very nice to have. There is enough work happening in this space that this should improve, though.

Windows packaging with kivy is a pain, and the recommended approach of using pyinstaller just failed horribly for me. I'm not sure if where to lay the blame for that, but debugging windows issues is not my favourite activity, and anyway not something I'm capable of doing at the end of a pyweek.

Thursday, November 22, 2012

Thoughts on the 2012 VTES Leagues

I had intended to blog about the league more, but that fell by the wayside, and got replaced by the game reports. I'll intend to do better for the next league.

Having now run two leagues, I think I can safely say it was a good idea. It's given a bit more structure to the local VTES games, and ensured that we keep having regular socials, which is needed to keep the game alive. It's also allowed me to fiddle with several deck ideas in fairly serious competition without the risks of a tournament.

Keeping the league running is fortunately fairly low-effort, and I've gotten a lot of the score management and tracking reasonably automated (working on which has been a useful "compiling" project). I'm not sure we've quite got the length of the league right yet - people seem to get a bit burnt out both times, so we should maybe shorten it a bit more, but I'd like to avoid long breaks in the game, simply to help keep interest up.

I'm not sure if it's accomplished my other goal of improving my play level. I have had a couple of games where I feel I've played really well, and made some good decisions in some somewhat non-obvious positions, but I've also made a number of really stupid errors, and thrown away a couple of potential game wins as a result.

On the other hand, I did manage to top both leagues, which suggests I'm doing something right. However, I partly topped the league by simply playing a lot more league games than everyone else. I feel somewhat guilty about that, as I feel I've been gaining an unfair benefit from the way the league rules were setup to not penalize people playing lots of games, and, as the main driver of the league, I'm partly responsible for the rules we chose.

Sunday, May 13, 2012

Pyweek 14: Mad Science

So we've reached the end of another pyweek, and managed yet another game ("Tomorrow, the World!!!"), so it's time for my usual post-pyweek post.

It's not one of the better entires I've been involved in, and I expect us to place very middle of the field this year. I think there's a decent concept here, but we didn't get enough content or game balance to have something that's really fun, and, as a result, much of the early game is a bit random and frustrating. There's nothing unfixable, but it needs a couple of days of people playing and extending the game to get to the point I'd actually be happy with it. It's got its entertaining bits, though, so I'm happy enough to throw it out there to be judged and see what happens.

Due to everyone being busy and / or being out of the country, we had a much smaller team than previous entries. I expected we would need to downscale as a result, but this proved to be more of a problem than I had actually anticipated. There just wasn't space for people to play the game much, which partly accounts for the issues, and there also much less opportunity to riff off other people's ideas to improve things. Everyone being busy in the day didn't help either. There were far fewer of the "ooh, a bunch of cool stuff has happened since I last worked on the game" moments, which also made it feel like more of a slog than past entries. The lack of people was most felt in the final Saturday finishing sprint, for which only 2 of us were available - most conversations were "I'm fixing X, can you look at Y?", and then silence for about 30 minutes while stuff happened. Given how the smaller team affected things, my respect for people doing successful solo entries has gone up even further.

I've now been involved 5 pyweek entries, and they've all been content heavy in various ways, so it's fair to call that as a definite trend. Given the games I enjoy playing, and the high value I place on being amusing, that's not surprising, but it's not a good feature for games with small teams.

On the upside, it was still fun. Coding for pyweek is always liberating, since it's much more important to have something close now than completely correct later. Having now done 3 pyweeks with mercurial, we've now also got the setup and workflow around that reasonably well sorted (which means we're almost certainly due to change to something else now), and past experience means that we're making a reasonable number correct design decisions early, so I'm quite happy with the final structure of the game.

Sunday, April 8, 2012

The Easter Egg Tournament

Ever since I heard of the idea of playing VTES for ante using easter eggs on the #vtes IRC channel, I've been keen to try the idea locally. So this year, I bit the bullet and generally chivied things along to get the event to happen.

We ended up with 8 players, although 2 only arrived late, so the first two rounds were 6 player games.

In the first game, I tried my weenie DEM/obf bleed deck, which didn't quite run properly. The table was Richard (Ahrimane wall) bleeding Dave (!Ventrue grinder with guns) bleeding me bleeding Simon (Black Hand bleed) bleeding Kevin (Enkidu) bleeding Hendrik (Osebo with 419 operations). I didn't draw any minions with obf or any obf masters for some time, and, combined with several Ministy's from Simon, that caused slowed down my deck considerably. I also lost a minion to a Kiss of Ra on an ill-thought out block attempt. I was able to oust Simon, but then, with the combination of some rushes from Enkidu, DOM bleed and a Smiling Jack in play, was duly ousted. Kevin failed to any significant damage to Dave's minions with Enkidu, and duly fell to the !Ventrue. Richard and Hendrik had spent most of the game tangling with each other, with Richard gradually losing to the potence combat, so Hendrik was able to oust Richard eventually. The end game got a little tight, ass Hendrik put a couple of minions into torpor, but ultimately wasn't able to get the critical action to burn Smiling Jack through and Dave took the table.

In the second game, I tried the Arika High Stakes deck I put together. The table was Richard (Group 4+5 Kiasyd) bleeding Dave (Group 4+5 Kiasyd) bleeding Simon (samedi wall) bleeding me bleeding Hendrik (Group2+3 !Tor with guns) bleeding Kevin (Group 2+3 !tor vote and bleed). The table was made interesting as Dave & Richard risked contesting, as did Kevin and Hendrik. Simon, at the end of a bounce chain, and with a wall'ish deck, walled up throughly, which caused me issues as I never got to cycle bounce out of my hand. I got a decent start, with Arika and an early Minion Tap, but drew few aggressive votes (although all the High Stakes), and, although I got Hendrik quite low on pool, I couldn't quite get what I needed to finish him off. Dave got a couple of bleeds on Simon, but failed on a lunge with Song of Pan and then failed to draw bounce and was ousted by Richard. I was able to minion tap a couple more times, and a voter cap off a High Stakes meant I was up to able to keep bringing minions out, and keep a healthy pool buffer. Hendrik ousted Kevin, thanks to a steady supply of Palle Grande bleeds, and then Richard was able to top-deck enough stealth to oust Simon. I was able to finally bounce a bleed from Richard onto Hendrik, and banish one of Hendrik's minions, but this was not enough to save Richard's Kiasyd from the !tor. At this point, I finally found my decks ousting package, and I was able to chomp through Hendrik's pool very efficiently for the last 2 VPs.

Caitlin and Adrian arrived for the final round, which saw us play two tables. Table 1 was Richard (Ahrimane wall) bleeding Dave (!Ventrue) bleeding Hendrik (Assamite) bleeding Adrian (Simon's Black Cat deck). I saw little of the game before the end game, but Hendrik held off Dave for quite some time before being ousted, while The brujah were able to tool up to a fair degree. Adrian then drew a couple of Frontal assaults which allowed him to put down Richard's minions and oust him. Adrian decked himself shortly afterwards, but with the hunting ground and the guns down, was nicely setup. In the end game, Dave was unable to cycle intercept to draw prevent and was thus on a losing proposition on every combat, and, after losing 3 minions to the Brujah guns, conceded.

The second table was Kevin (FoS temptation) bleeding Caitlin (Akunase wall'ish) bleeding Simon (DoC Choir / Bleed / Vote) bleeding me (Arika). I had a tricky game. And early Lily Prelude and bleed from Simon meant I only got Arika out, and, as I didn't see a Minion Tap or a Govern until quite late, I was stuck on 1 minion for most of the game. I did get a Legendary Vampire on Arika, which was very important, and, by steadily bleeding of 5, and a couple of votes and voter caps, was able to oust Kevin. Caitlin failed to do any significant damage to Simon, unable to get past the Daughters prevent and access to S:CE, and I was able to Minion Tap Arika and lunge with a Govern bleed for 7 to oust her. At this point, I erred, and decided to bring out a second minion, which left me too little pool to survive the daughters. I should also have remembered that I could have voted away the Command Performance, which would also have helped me. Still, 2 ousts with a single minion on the table was rather satisfying.

Overall, I think it was a success, and fun seemed to be had. I'll probably try to arrange something similar again next year.