Archives

Tags

release art life update python licensing vegan xkcd guile conference cooking code blender beyond-javascript shared hosting identica robots pycon podcast hatecrime hy miro anniversary backups cookies money phone mediagoblin flourish campaign advocacy pelican orgmode foss sfxr diet zine politics talk firebug tech privilege interview creative-commons autonomous art gnome libre-graphics-meeting music pcf javascript contributor drawing cabbage kinda-mediagoblin meme family food tabletop freespeech libreplanet sqlite blog n900 php emacs free-culture biking recipe economics patents macros researchcation gimp boingboing openmoko cc0 firefox dustycloud lisp base64 personal chipy rsi frostcast deployment wedding uuid gpl security nouveau configuration robogoblins xudd speech recognition by-sa xmpp fsf

How Hy backported "yield from" to Python 2

By Christopher Allan Webber on Thu 20 November 2014

Hello everyone! Time for a bit of a diversion towards one of my favorite projects, Hy! (I'm an occasional committer, but the main mastermind behind the project is my good friend Paul Tagliamonte.) For those of you who don't know, Hy is a Lisp that transforms into the Python AST. Even more fun: you can import .hy files in .py files and .py files in .hy files! Crazy!

Now, when many people hear that, they say, "Huh what, why on earth would you do such a thing?" The usual response is something like, "Because it's fun!" But today, dear readers, I am going to show you a real... dare I say practical reason for using Hy. Because a cool feature just landed in Hy: a backport of "yield from" to Python 2.

Let's back up a bit. First, you might not know what "yield from" is or why it's cool. Well, Python has this thing called coroutines which allow you to do cool things, including suspending and resuming functions, which it turns out is really great for writing asynchronous code (sure, just wake me back up when we get the next network stanza, eh buddy?). Once you provide the ability to nest together coroutines by "delegating to subgenerators" (what "yield from" does that "yield" does not), this stuff starts to get really powerful. This feature is so useful that it's the basis of maybe the world's coolest asynchronous programming environment, asyncio. Only one problem: "yield from" didn't exist until Python 3.3... which means you can't use it with Python 2. Bummer!

Or can you? Time for our second bit of context. Ever hear of a Lisp programmer talk about something called a "macro"? No? Okay, think harder. Maybe it was in one of those conversations where you were talking about your favorite new your-pet-language feature, and the Lisp hacker was like, "Oh that's cute... yeah Lisp had that decades ago." And then you got really mad and brought up a bunch more features, and the Lisp hacker kept saying that Lisp had them before you were born, and "Oh yeah, and whatever features Lisp doesn't have, you can add really fast because Lisp has macros. You can basically program any feature with macros." Maybe you asked them, what the heck is a macro, and they said something inane like "it's a feature where you can program other features, or write code that writes code", but you barely remember, because at that point you just wanted to punch them in their smug little face. (And besides, you wondered, if you have higher order functions, isn't that enough?)

Well friends, today it is my face that you will want to do the punching to, because I'm about to show you how cool macros are and why having them makes Hy so awesome. But, after the face punching thing, you'll also thank me. (Also, please don't punch me in the face, this blogpost is not consent for face-punching.)

Enough with the talk. Time for examples! Let's look at some code. Say you have this Python 3.3+ code:

from awesomelib import IrcBot, bake_cookie, async

def irc_to_cookies(**connection_stuff):
    our_bot = IrcBot(**connection_stuff)
    yield from our_bot.open_connection()

    while True:
        message = yield from our_bot.get_next_message()

        if message.command == "bake_cookie":
            yield from async(bake_cookie())

Groovy. In our example above, we built a cookie baker that can be plugged into our awesomelib asynchronous network library and cookie baking pipeline system. (And of course, we wrote it in Hy, because we love Hy, and you can still run Hy code in vanilla Python.) We're feeling pretty good about this. We kind of wish we could run it in Python 2.X still, but Python 3.3+ is the future anyway, and no use worrying about the past really... right?

Our Hy example looks pretty similar:

(defn irc-to-cookies [&kwargs connection-stuff]
  (setv our-bot (apply IrcBot [] connection-stuff))
  (yield-from (.open-connection our-bot))

  (while True
    (setv message (yield-from (.get-next-message our-bot)))

    ;; If an irc user gives the "bake_cookie" command,
    ;; put a cookie in our ez_bake oven
    (if (= message.command "bake_cookie")
      (yield-from (async (bake-cookie))))))

But there's something magical... this code makes use of yield-from, which in Python 3.3+ Hy just uses the actual real built in "yield from" (or more accurately, ast.YieldFrom). But what about Python 2? Mere higher ordered function magic can't save us here. We need a way to implement a new feature.

Except oh right, this is a lisp, and we have macros! So why not write a macro for yield-from?

And it turns out that's exactly what paultag did:

(if-python2
  (defmacro/g! yield-from [expr]
    `(do (import types)
         (setv ~g!iter (iter ~expr))
         (setv ~g!return nil)
         (setv ~g!message nil)
         (while true
           (try (if (isinstance ~g!iter types.GeneratorType)
                  (setv ~g!message (yield (.send ~g!iter ~g!message)))
                  (setv ~g!message (yield (next ~g!iter))))
           (catch [~g!e StopIteration]
             (do (setv ~g!return (if (hasattr ~g!e "value")
                                     (. ~g!e value)
                                     nil))
               (break)))))
           ~g!return))
  nil)

This simple macro above is an implementation of yield-from which works in Python 2. The macro is more or less a function that writes new code to be expanded in place... allowing us to use basic building blocks of the language to build more complex features. Since in Lisp, code is a very simple, manipulatable data structure (lists!), we can literally write out code that writes code without too much trouble. (There's some magic going on with the ` character above, called backquoting... but it's best to read a tutorial on macros if it's not clear to you how the backquote is building the list of code there.) Hey look... we just brought a feature back to the future... as long as we're writing code in Hy, we can do subgenerator delegation with yield-from. Cool! That sure makes coroutines a lot more useful to those of us living in the past.

So wait, does this mean you can now use asyncio with Python 2? Well, not quite... asyncio is written in normal Python syntax, which means that it's using "yield from", not our more versatile "yield-from", and the library itself isn't written to support Python 2.7. So, no. (But, if asyncio was written in Hy, we could, even though Python 2.7 doesn't have "yield from"!)

The real goal of this article isn't to convince you to start backporting features to Python 2.X via Hy, though. Really, Python 3 is the future, write Python 3 code! But the point here is to get you thinking about how having macros allows you to implement new features now! Why wait for the features of Python 4.X? In Hy you can have them now! (Or even start prototyping them today!)

And that's worth getting excited about. And once you realize that, it's a bit easier to understand where lispers are coming from when they nerd out about how cool macros are. (Even if you still want to punch us in the face.)

(PS: think this is pretty cool? Hy is a really welcoming community, and there's a lot of fun stuff to do! Learn about language implementation and learn about lisp in a paradoxically fun and pythonic environment! We'd love to have you join in hacking with us!)

Javascript beyond Javascript (with Guile?)

By Christopher Allan Webber on Fri 15 August 2014

I'm learning more in my spare time / off normal hours about compilers and graph theory and reading various books on lisp. I have an agenda here, no idea if it'll happen; at the very worst I put a lot of tools in my toolkit that I should have had. But there is another reason... Well, this one's easiest to lay out point for point, so here goes:

  • Python is still my favorite language to write in day to day, but I guess that I keep feeling that any language that doesn't have a way to transcompile nicely to Javascript (or isn't Javascript itself) is unideal for writing really great web applications, for a simple reason: modern web applications are highly interactive, and I feel that a really stellar web application needs to share some code between the backend and the frontend. This becomes more obvious when writing dynamic templates or forms.

    While Python probably has hands-down the nicest asynchronous library in current development with asyncio, the above problem makes it feel like you can only do so much in the web world with it. (The Javascript Problem is a good page on the Haskell wiki which puts this all pretty nicely.)

    There's a lot lost by not being able to interweave applications between the frontend and the backend. Sadly, the best option in Python right now is to just give up and write entirely separate codebases in javascript that interact with your main codebase. But clients on the web are becoming thicker and thicker these days (even more so with technology like websockets and webrtc becoming prevalent), so this feels both weak and redundant.

  • You could say "just write javascript!" then, but let's face it, I don't really like Javascript. The language is getting better by leaps and bounds as time goes on, but a lot of the enthusiasm for the language still feels like Stockholm syndrome to me. But we're still left with Javascript. So what, then?

  • Transcompiling actually is becoming an increasingly appealing target. With asm.js this might not only be possible but actually very optimal. One only need look at the Unreal demo to see just how feasible transcompilation has become.

  • So okay, let's say we're doing some kind of transcompiling. We have two options, "transcompile wholesale", or "transcompile a subset that's acceptable for javascript and local evaluation". Obviously the former is desirable if possible, though the latter is a lot easier.

  • Indeed, transcompiling a subset has already been done, and well, by Clojurescript. I'm not really excited by anything too tied to the JVM, but still, pretty cool. Maybe good enough to get me into a hybrid Clojure/Clojurescript solution. But still... there's no asm.js target (maybe in the future?), and it feels like you're tossing out so much with Clojurescript, it really isn't the same language too much, just a very similarly overlapping language. I haven't tried it though... this is just from reading docs and watching talks :)

  • We could say maybe we could transcompile something like Python, but assuming we really want to have something like a template engine, we probably want to be writing in a full fledged version of the language, not a restricted subset. Python feels way too huge to expect for people to load in their browsers. So, what's more lightweight?

  • Let's continue in the lisp direction. Is there a way we can get a complete implementation in the browser, but of a language that's a bit more lightweight? How about Scheme? Scheme is notoriously simple to implement, maybe even too simple... and Javascript shares a lot of overlap with Scheme in design...

  • But which Scheme? How about Guile? Yes, Guile, GNU's extension language based on scheme.

Okay, wait, digression before we continue... I want to talk a bit more about Guile, because up until a few months ago my impression of it was still the somewhat-dismissive impression I had a few years ago. But I've come back to looking at Guile again. Largely this is thanks to Dave Thompson's Sly project. There is some seriously cool stuff going on with Sly, and that made me want to look into what's happening with Guile.

What I found is that Guile isn't the same thing it was a few years ago. For evidence of all the cool things that are happening under the hood, I point you to wingolog (warning: danger of being a real time sink; linking to Andy Wingo's blog has been described as "wingorolling" by a friend of mine). Guile isn't just an interpreter anymore, it has a sophisticated "compiler tower" since Guile 2.0. With the levels of abstraction that exist in Guile, could compiling to javascript/asm.js be a target? (What makes this feel extra appealing/feasible: Andy Wingo also works at his day job on improving javascript virtual machines, so maybe...?)

Well, better to ask Guile hackers themselves if it's possible... and I've pestered a number of them. The responses seem to be (and I may be representing incorrectly):

  • Getting the core language of Guile (which is of course scheme) ported over is not the hard part.
  • Making a subset of the language that works in Javascript is not too hard, but isn't too interesting. It would be much better to have the whole language work.
  • Overall, the most tedious part of porting guile to target any non-C target will be all of the library procedures currently implemented in C... however, gradually the Guile team is reducing the amount of C code in Guile and replacing it with Scheme code.
  • The problem is the runtime; you probably would want to re-use some higher level things like the allocator and garbage collector. Emscripten might do garbage collection correctly (guile relies on Boehm GC to do garbage collection); emscripten seems to provide a similar garbage collector? Tail calls are also a problem until at least es6 is common, and even then until they are optimized.
  • Maybe someone could try transcompiling Guile with emscripten as a test, but that probably wouldn't provide the right integration, and regardless, this would probably be a bit uncomfortable because emscripten relies on llvm, not gcc.
  • Targeting asm.js brings things more low-level, but the asm.js typedarray heap may not be appropriate; the guile-on-js heap and the javascript heap should really be the same.

Okay, so, that's a good number of problems that need to be overcome. Certainly it makes it feel like things are a ways off, but then again, it seems like there's strong interest. And it feels feasible... as an outsider to development. :)

But even assuming all the above are resolved, there are some other problems that I think scheme will always face adoption-wise:

  • I like lisp, and I like parentheses. I have emacs set up with rainbow-delimiters, smartparens, and highlight-parentheses (set up just to highlight the background, not the foreground, so it doesn't clobber rainbow-delimiters). Lisp's greatest enemy has never been its functional capability, but a general parenthesitis in the general population. This the big one, so let's come back to it in a moment.
  • Lots of scheme (lisp generally, but especially scheme) feels like it just is too in love with ideas that make it hard to approach. "car" and "cdr" are not good names but form the very basis of the language for historical reasons where even prominent lispers have had to backtrack to remember why. Linked lists as the core of lisp is great, but overuse of them is encouraged when other data types are much more appropriate: see teaching associative lists before hashmaps. While iteration tools are provided, there's simply too much emphasis on recursion. Recursion is powerful and awesome and necessary to solving many important computer science problems, but rarely needed by say, a web developer, and significantly harder to read and wrap one's mind around than iteration.
  • That said, these could be overcome with better introductory material. There seems to be interest in the guile world for this, thankfully!
  • Module names often look like robot serial numbers ("srfi-13") than anything human-readable and feel like they really need aliases.
  • The Guile community is very small, and does not seem to be very diverse. Outreach is greatly needed.

Returning to "parenthesitis", while I love lisp and all its parentheses, admittedly it's not the most readable language ever. I can wake up groggily at 5AM, be tossed a block of Python code, and even through blurry eyes, I can get a feel for what's happening in the code just by its structure. I can't say the same of any lisp.

But there's a way out of that situation! Guile's compiler stack is nicely set up so that another syntax can be laid on top of that. Guile's VM has semi-complete language implementations of ecmascript and some other languages on top of it. Recently Arne Babenhauserheide has written a whitespace to lisp preprocessor named wisp; I don't feel it really solves the problem by making things so much more readable, but it's a nice demonstration.

The most promising resolution I think would be to implement a syntax akin to Julia on top of Guile. If you haven't looked at Julia, it's a cool project: it has a python-like syntax with lisp-like power, and many other interesting features, including macros(!) in a language that is certified safe for those with parenthesitis. In fact, the language is largely built on top of scheme! So it might be nice to have a "sugarcoat" language that sits on top of Guile.

If all the above were achieved and a well developed web framework were written on top of Guile, it could be well positioned for writing web applications that are a joy to write, both on the backend and frontend.

One more thing: the complaint about "don't use emscripten" because it's built on top of llvm is an indication of how sorely needed a working javascript/asm.js compiler target is in GCC. ARM, X86, SPARC... these are all important compiler targets to have, but to advance user freedom where the user is today, the browser is the most important target of all.

Researchcation, concluded

By Christopher Allan Webber on Tue 03 June 2014

I just got done with a three week thing I've dubbed "researchcation". It's exactly what it sounds like, research + vacation.

It's hard for me to take time away from MediaGoblin right now and have it still meet its goals as a project. On the other hand, there's a lot that we have planned for the year ahead, but some of it I'm not really prepared enough for to make optimal decisions on. In addition, the last year and a half really have just not given me much of a break at all, and running a crowdfunding campaign (not to mention two over two years) is really exhausting. (Not that I'm complaining about success!)

I was feeling pretty close to burnout, but given how much there is to get done, I decided to take a compromise on this break... instead of taking a full fledged vacation, I'd take a "researchcation": three weeks to recharge my batteries and step away from the day to day of the project. In the meanwhile of that, I'd work on some projects to prepare me for the year ahead. A number of good things came out of it, though not exactly the same things I expected coming in. But I think it was worth the time invested.

My original plan going in was that I would work on two things: something related to the Pump API and federation, and something related to deployment. It turns out I didn't get around to the deployment part, but working on the federation part was insightful, though not in all the ways I anticipated. Though I've read the Pump API document and helped advise a bit on the design of PyPump (not to take credit for that, clearly credit belongs to Jessica Tallon generally, not me), there's nothing really like having a solid project to toss you into things, and I wanted to take a non-MediaGoblin-codebase approach to playing around with the Pump API.

I started out by hacking on a small project called PumpBus, which was going to be a daemon which wrapped pypump and exposed a d-bus API. I figured this would make writing clients easier (and even make it possible to write an emacs client... yeah I know). I got far enough to where I was able to post a message from emacs lisp, then decided that what I was working on just wasn't that interesting and wasn't teaching me much more than I already knew.

Given that there was both the "research" but also the "-cation" component to this, I figured the risks of failure were low, so I'd up the challenge of what I was working on a bit. I instead started working on something I've dubbed Pydraulics: a python-powered implementation of the Pump API. Worst came to worst I'd learn a few things.

I decided from the outset to keep a few assumptions related to pydraulics:

  • The end goal would be to have something that provided interfaces for object storage and retreival... not to wrap the database itself, but hopefully there would not be too many views, and maybe this could happen on a per-view basis. This way you could easily wrap Pydraulics around whatever application and use the storage/database it's already using. That's the end goal. (I didn't get there ;))
  • I'd keep things simple database-wise: assuming you're not providing your own interface, the default interface provided is postgres + sqlalchemy only. There's some new JSON-related features in Postgresql that are pretty exciting and would be appropriate here.
  • I'd use this as an oportunity to think about MediaGoblin's codebase. I decided I'd see how easy or hard it would be to split out components from MediaGoblin as I needed them into something I dubbed "libgoblin". For now, I'd allow this to be messy, but hopefully would give me a chance to think about what libgoblin should be.
  • I'd also use to think about where MediaGoblin fits as in terms of recent developments in asynchronous Python coding.

So, what came out of it?

  • Turns out SQLAlchemy does a nice job of making use of Postgres' built-in JSON support. Early tests seemed to indicate that this choice would pay off well. (Left me wondering: how hard would it be for someone to write a python API-compatible implementation of pymongo or something?)
  • I ended up spending a lot more time on the libgoblin side of things than I expected. I didn't realize that MediaGoblin had become such a self-contained microframework until this point. I wanted to port the MediaGoblin OAuth views over to Pydraulics to save time, but it turned out this required porting over a significant amount of MediaGoblin code over to libgoblin. I did get the oauth views working though!
  • Asynchronous stuff turned out to be interesting to explore, and I'll expand on what I've been thinking below.
  • I did end up getting a much, much stronger sense of the Pump API, which of course was the main goal, though the implementation of that is not yet complete.

Pondering asynchronous coding developments and MediaGoblin/libgoblin/pydraulics turned out to be fruitful. Mostly I have been looking at "what would it take for libgoblin to be usefully integrated into asyncio?"

This turns out to be a bit more challenging than it appears at the outset for one reason: mg_globals. mg_globals is a pretty sad design in MediaGoblin that I'd like to get rid of; basically it makes it easy to write functions that don't have to have the database session and friends, template environment and etc passed into them, because those are set on a global variable level. That works (but is nasty) as long as you're not in a multithreaded environment, but breaks as soon as you are. I recently created a ticket reflecting such, suggesting switching over to werkzeug context locals (Flask makes heavy use of this). Werkzeug's hack is clever, using thread locals so that even in a multi-threaded environment, the objects you're accessing are still globals, but they're the right globals.

But Werkzeug's solution is not good enough for integration with asyncio, where you might be doing "asynchronous" behavior in the same thread, suspending and resuming coroutines or coming back to tasks or etc. As such, it's almost guaranteed in this system that you'll be clobbering the variables another task needs.

What to do? I did research to see if anyone had ideas. It looks like you could do such a thing with Task.current_task() in asyncio, and that would be fairly equivalent. I think you'd need careful implementation though... if you're not paying close attention you might not attach the right things to the right subtask, and that whole thing just seems... fragile. But it still is a neat idea to play around with.

But here's some ideas that I think are neat all combined, related to this problem:

  • The idea that the request or asyncio task is the main object that you attach useful variables to, and you just pass that thing around as a "universal context" like crazy. (The downside: what happens when you aren't using asyncio, or don't need an http request, like in a migration script?)
  • I like the idea of the application being multi-instance'able, and then having requests and a local context as a layer on top of that. So you've got the "instantiated application" layer, and on top of that the "current request" layer, and at both levels you can have variables attached (like the database engine on the application level, but the database session on the request level). That's an awesome distinction.

But you don't really know whether or not some bit of code is using an asyncio task, a web request, or whatever to pass around. Here's the thing though: it doesn't really matter most of the time. With rare exceptions, you're just looking for $OBJECT.db or $OBJECT.templates or something. You just need some kind of object you can tack attributes on to.

So that's my idea in libgoblin/pydraulics: you have an application and you want to do something with it (handle a request, execute a task, etc), you can tack stuff onto that object. So either create a fresh context object to tack stuff onto or just start tacking things onto an object you have!

Currently, this looks like:

# Pydraulics -- Easy Pump API integration into your software.
#
# Copyright (C) 2014 Pydraulics contributors.  See AUTHORS.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# Large parts of this heavily borrowed from MediaGoblin.
# Copyright (C) 2011-2014 MediaGoblin contributors, see MEDIAGOBLIN-AUTHORS

class PydraulicsApp(object):
    """
    Pydraulics "basic" WSGI application
    """

    # ...

    def gen_context(self, request=None):
        """
        Generate or apply a context.

        If we have a request, use that as the context instead.
        """
        if request is not None:
            c = request
            c.app = self
        else:
            c = Context(self)

        c.template_env = jinja2.Environment(
            loader=self.template_loader, autoescape=True,
            undefined=jinja2.StrictUndefined,
            extensions=[
                'jinja2.ext.autoescape'])

        # Set up database
        c.db = self.Session()

        if request is not None:
            c.url_map = url_map.bind_to_environ(request.environ, server_name=self.netloc)
        else:
            c.url_map = url_map.bind(
                self.netloc,
                # Maybe support this later
                script_name=None)

Anyway, simple enough. Then you have request.db made, or if you've just got a command line script and you need the equivalent of that and you already have your instantiated application, just run application.gen_context(). Thus, for utilities that are working with this application and need a variety of instantiated things (the database and the template engine and so on and so on) it's easy enough to just accept "context" as the first argument of the function, then use context.db and etc. (I've considered using just "c" or "ctx" instead of "context" as the variable name since it seems so common and since it conflicts a bit with template context and friends, though that's not very explicit.) So, this seems good.

At one point I got frustrated with the massive amount of porting to libgoblin I was having to do and thought "I really should probably just use Django or Flask itself." However, I found that neither framework really addresses the asyncio stuff I was dealing with above, and once I got enough ported of libgoblin over, libgoblin-based development is very fast and comfortable.

That said, it took up enough time working through those things where I didn't complete the Pump implementation. That's okay, I've got enough to do what's required on my end from MediaGoblin (and we've got good direction and help on the federation end this upcoming year where the most important thing is that I have a good understanding). I still think pydraulics is a pretty neat idea, and I may finish it, though it'll be back-burner'ed for now.

However, libgoblin is something I'm likely to extract. I'm convinced that MediaGoblin is at a point where it's stable enough to know what works and doesn't about the technical design, so that gives me a good basis to know what to build from here. There are other applications I'd like to build which should mesh nicely with MediaGoblin but which really don't belong as part of MediaGoblin itself, and would be kind of hacky add-ons. Clearly this is not the most important development, but towards the end of the summer as we hopefully get the Python 3 branch merged, I will be looking towards this.

Aside from this, on the "-cation" end of things, I took some time to relax and also reapproach my health. I may have a separate post on that soon.

So, that's that. Overall it was productive, but again, not quite in the ways I was expecting. I feel okay about that though... I wanted to do some hacking and not feel deeply pressured or stressed about it... if that wasn't true, I think the "-cation" part wouldn't have held up. So I feel okay that I wandered a bit, and the other things I worked on / found I think are important anyhow, and have me much better prepared for the year ahead. Not to mention the most important part: I feel pretty refreshed and capable of taking it on!

What's next for the coming week? Well now that this is all over, I'm organizing plans so we can get rewards out the door and do project planning for the year ahead. We've got a lot of promises to fulfill. Better get to it!

Fifth wedding anniversary, the RPG

By Christopher Allan Webber on Fri 30 May 2014

We had an awesome wedding anniversary today... 5 years! Morgan didn't know I had planned something ahead of time. I'm not good at surprises, but this time I managed to pull off a surprise, and I think with massive style.

So, some context. First of all, a number of my friends and I, and I guess me especially, have kind of become tabletop role playing game nerds over the last year. We've been playing a wide variety of games, especially in Fate (the basis of which is under a free culture license!), from space adventures to crime dramas to German-esque fairytale stories to some rather silly holiday adventures, to large scale inter-kingdom dramas. Though we have played some games in the style of $STANDARD_FANTASY games (what most people think of when they think of tabletop RPGs), most of the stuff we've been playing has been more narrative even then, and less about straight up monster-killing dungeon crawling.

We have played some games in the category of $STANDARD_FANTASY though, and one in particular has a character that my spouse Morgan plays in, a sort of "professor of magic history" (yeah, people who know Morgan may notice some overlaps) who uses jewelry to actually power up her abilities, but isn't particularly innately magically inclined. Morgan is not really one for fancy jewelry, but she does like the engagement ring that I got her, which is a bit fancy. When she plays as this character, she actually dresses up for it, and wears some matching earrings as well.

So anyway, today we played a game in that universe, and I GM'ed (my brother and his girlfriend also participated, they were awesome). Morgan was arriving in a somewhat swashbuckling'y type city, so I compelled her that she probably would have to remove her ring (the source of half her magic) until she figured out a way to get some sort of protection from thievery in the city. I figured this would piss off Morgan... I didn't realize how much. "I'm not playing a game with you if you take away my jewelry." She eventually accepted the compel after encouragement from other players, but she was pretty fuming'ly mad about it. "You're making me take off my engagement ring on our anniversary?" (Morgan had thought I had accidentally planned this game on our anniversary without realizing it. She didn't realize that for once in our lives, I was being smooth about things.)

It was a good game generally. There was an artifact delivered, etc etc. By the end of the game, an NPC said "Oh, thanks, I think I have a jewel that matches yours... I can't really use it because it's for fire magic users only. Now where did I put that?"

In real life I shuffled through some drawers looking and pulled out a small beat up looking urn. "Careful, this thing is hot. Only fire magic users seem to be able to open it with no problem."

Of course her character did, and of course she was able to bypass the "smoke" (white tissue paper) no problem. And what was inside? A pendant that perfectly matches her ring. ("Conflict-free" in real life, supposedly, to the extent those things are true. Also, aside from her engagement ring, this is the only piece of jewelry I have ever bought Morgan. We're not really that much of jewelry-presents type people, but I think an exception here was successful.) Oh yeah, and in-game the pendant gave her a fate-point-activated fire shield that can give her an offensive-defense against people trying to pickpocket her or doing melee attacks.

It was a stunt for sure, but it worked. It extra worked because usually I am such a doofus, and I did piss off Morgan by compelling her earlier, and it looked like there were a bunch of bits that turned out to be just me making stupid mistakes that then turned around and made the end reveal awesome.

Somehow I pulled off that stunt, all the players seemed to have a good time generally, I didn't give it away beforehand (usually I'm not so successfully sneaky), and yes, my intentional-though-appearing-accidental pissing-off maneuvers really did make the final result more fun for everyone. Success!

Anyway, so that's that. Morgan told me I'm the best, and nerdiest, husband ever, so I'll gladly take all of that.

Happy fifth anniversary, Morgan. Here's to many more.

A sweet and savory cabbage recipe

By Christopher Allan Webber on Sat 24 May 2014

There's plenty of interesting things to talk about lately, and I'll get to them soon. I'm on something I've titled "research-cation" where I'm still kind of working, but it's also kind of like vacation, but really I'm mostly working on doing research for MediaGoblin's future.

In the meanwhile, I'm back in diet mode, basically because the MediaGoblin campaign was hard on my health. But also, the tooling I had in orgmode was never that great, so I've revamped org-diet. I might write a separate post on this... there's a lot of reasons why I did the revamp (it's not in master yet, but in the date-tree branch). I'm now doing daily uploads of my current health status which you can view here (yes, org-diet now is super flexible about generating reports).

I'm not going into details on that in this post, but I did recently just re-make one of my favorite recipes of all time with a number of adjustments. I forgot just how good it is. Anyway, here it is:

Ingredients Calories Quantity Total
head cabbage 290 1 290
tbsp olive oil 119 1 119
Westsoy baked tofu square 90 4 360
medium onion 44 1 44
can kidney beans 385 1 385
apple 71 2 142
tbsp nutritional yeast 25 2 50
tbsp vegetarian bullion 0 1.5 0
tbsp tamari / braggs liquid aminos 0 2 0
tbsp cornstarch 30 1/3 10
clove garlic 4 4 16
Total   8 177

This recipe is cheap, healthy, and most importantly, delicious. It has very few calories (a mere 177 calories... that's nothing!) but tastes pretty amazing. I usually start some rice in the rice cooker before I kick this off… put in two cups and that's a mere 120 calories on top of this. Only 297 calories! Despite that, it's quite filling. (Tasty, too!)

The nutritional yeast is optional, but I like it. You can use whatever bullion you like, but I like the Frontier Natural Products beef-ish tasting vegetarian bullion. Alternately, adding brewers yeast and a bit more salt is great.

You also don't have to use the westsoy baked tofu. You could use any other protein here. A lot of other kinds you have to fry up in advance though, and the westsoy stuff is already done and tastes great and I'm lazy. If you don't have tamari or liquid aminos, just up the bullion.

This makes 8 servings! It usually takes me about 50 minutes to make but I'm slow.

Okay, so! Here's my recipe. You're going to need a large pot, a large cutting board, and a large mixing bowl.

  • Get out a large cutting board and chop up cabbage. You want it in pieces probably, though if you prefer tiny ribbons that's fine. Set aside in mixing bowl.
  • Chop onions and, if you like, a couple cloves of garlic. Chop up the apples into chunks or wedges. Personally I like wedges.
  • Take your large pot, add the olive oil (or whatever oil really) and onion (also garlic if using). Saute that for a few minutes, until it starts to brown. Add apple and saute a bit longer, until the apple starts to brown a little.
  • Add a cup of water and stir around the ingredients for about two minutes.
  • Dump in the cabbage into the pot. It'll seem like a lot and like you'll never be able to stir this thing. (I told you to get a big pot!) Don't worry, it cooks down.
  • Add salt and pepper. Add some more water… I think I usually add about 1 more cup at this point. Stir around the cabbage in and out of the water as best you can for a minute or so. Then cover the pot and let it cook down for five minutes.
  • While the cabbage is cooking, chop the baked tofu into cubes, or tear it apart with your fingers if you get grossed out by cubes of tofu.
  • Return to the pot. The cabbage should be a bit more cooked down now, but not quite there. Add bullion, nutritional yeast, and tamari/liquid aminos. Open the kidney beans and pour the excess liquid right into the pot. Add more salt and pepper if you like. Now stir that stuff. Get that cabbage in and out of the broth!
  • At this point you need to let the cabbage cook down. I usually let it cook down a little bit less than half way. Stir it occasionally.
  • Stir together the cornstarch in 1/4 cup of water. You're trying to make a small slurry that'll thicken the broth into a kind of gravy.
  • Open the pot and pour the cornstarch in and add the tofu. Time to start stirring again. Stir stir stir!
  • Give it a few minutes and the sauce should thicken. The cabbage should become tender but not totally mushy. When you hit that point, stop cooking.
  • Serve with rice or some kind of grain. I usually put a tablespoon of cheap parmesan cheese on top too, but whatever you like, go for it.

Enjoy!