Intelligent Hinting

Aaron A. Reed recently announced an open beta for his Intelligent Hinting extension for Inform 7. This is an amazing extension that intelligently figures out how to solve puzzles in Inform 7-based games with high-level puzzle annotations in your I7 project.

You have to define "puzzles" and "tasks" in your own game, at implementation-time, and the extension provides a >SUGGEST command which indicates the next action to be taken to solve the current puzzle. It's surprisingly smart: if you've defined that a cloak must be placed on a particular hook, it will automatically figure out how to move the player to find the cloak, pick it up, and move the player to the hook. Not only that, it even knows how to completely automatically find keys for locked doors that are between the player and either the cloak or the hook.

Not only is this a good feature for end-users, it also offers very important benefits to implementors of IF: It makes it trivial to automatically test if your work is winnable, and it makes it similarly trivial to generate a walkthrough to publish with your game automatically.

Inform 7 has a rich and descriptive world model, and it's great to see tools that are starting to really take advantage of it in very useful ways.

Twisted Show 3, Raffi Krikorian of Synthesis Studios

By the way, if you haven't listened to it yet, I recommend checking out the third episode of the Twisted Show, which is an interview of Raffi Krikorian of Synthesis Studios. I share space with Divmod in that back room :-)

by the way, if you have trouble with noise from the audio player at archive.org, try the .mp3 or .ogg version; they sound fine.

Planet Interactive Fiction

I just set up a Planet site for the community of Interactive Fiction bloggers. It's at http://wordeology.com/planet-if/ and it's called Planet IF.

Don't know what Interactive Fiction is? Emily Short explains it succinctly.

I'm not really a regular in the IF community, but I am a long-time reader and wanna-be author of IF. I want to see the medium grow in popularity and so I'll do what I can to help it out. So there you have it.

Twisted 8.1.0 prerelease 2

Hey all, I've put out the second prerelease of Twisted 8.1.0. This release includes a number of bug fixes, including for some unfortunate regressions in 8.0.1, as well as a few features.

  • Trial's performance was improved
  • Fixed a bug where Failures wouldn't be constructible involving Pyrex
  • Fixed a couple of reactor re-entrancy bugs introduced
  • Fixed the conch.insults bug where gnome-terminal wouldn't scroll when output reached the bottom of the screen.
And a bunch of other miscellaneous fixes. Please download this prerelease and give it a try with your applications.

Corotwine 0.2

As is my tradition, I'm doing extremely rapid releases of my software.

Here's Corotwine 0.2, which contains the following changes:

  • Returning from a connection-handling function now closes the connection
  • A bug was fixed in the example Chat server

The API documentation has been updated.

Please post any feedback.

Corotwine 0.1

I've just released Corotwine, a set of Coroutine APIs for Twisted. You can download Corotwine-0.1.tar.gz. There is very thorough API documentation.

Here's a complete example chat server. Start it up and telnet to port 1025 a couple of times and you'll be able to chat.


from twisted.internet import reactor
from twisted.internet.error import ConnectionClosed
from corotwine.protocol import gListenTCP, LineBuffer


class Chat(object):
def __init__(self):
self.clients = []

def handleConnection(self, transport):
transport = LineBuffer(transport)
self.clients.append(transport)
try:
try:
for line in transport:
for client in self.clients:
if client is not transport:
client.writeLine(line)
finally:
self.clients.remove(transport)
except ConnectionClosed:
return

from twisted.python.log import startLogging
import sys
startLogging(sys.stdout)

gListenTCP(1025, Chat().handleConnection)

reactor.run()

There are more examples in the corotwine/examples.py file.

Twisted 8.0.1 is out

Hey all. The release of Twisted 8.0 is finally done, and I was so excited about it that I just had to do another one: 8.0.1. The release announcement has been posted to the TM Labs blog.

Download and enjoy.

Twisted Isn't Specific

I was googling for some stuff related to Twisted and greenlet and I came across this post from last year by Jean-Paul Calderone: Twisted Isn't Specific. That subject is a reference to a quote in the Twisted.Quotes file:

<sayke> Acapnotic: don't make it twisted-specific
<dash> sayke: pffft
<dash> sayke: twisted isn't specific

The post is kind of relevant to some poking around I've been doing with integrating greenlet and Twisted again, but that's not really why I wanted to point it out on my blog. I just had a really good time reading it again. I think it's really well-written, and is fairly quotable. Just to warn you: this is one of those "quote posts" that contain more quotations than commentary, often perpetrated by ineffectual bloggers with nothing original to say. I'm sorry.

The email that Jean-Paul is responding to is by Andrew Dalke, and is about how he wants to magically replace the built-in Python socket module with something that switches to an event loop and allows other application code to run at the same time. This isn't terribly reliable, of course, and Jean-Paul gives a nice explanation of the dangers of implicit context switching (which applies to pre-emptive threading just as well as the controlled but still implicit switching of stackless or greenlet).
Consider this extremely trivial example:
  x = 0
def foo(conn):
global x
a = x + 1
b = ord(conn.recv(1))
x = a + b
return x
Clearly, foo is not threadsafe. Global mutable state is a terrible, terrible thing. The point to note is that by introducing a context switch at the conn.recv(1) call, the same effect is achieved as by any other context switch: it becomes possible for foo to return an inconsistent result or otherwise corrupt its own state if another piece of code violates its assumptions and changes x while it is waiting for the recv call to complete.
Asyncore was also brought up. It's often compared to Twisted, since in the past it was the only prevalent event system for Python. Twisted has pretty much obsoleted it by now, or so I like to think:
2) asyncore is smaller and easier to understand than Twisted, [-- Dalke]

While I hear this a lot, applications written with Twisted _are_ shorter and contain less irrelevant noise in the form of boilerplate than the equivalent asyncore programs. This may not mean that Twisted programs are easier to understand, but it is at least an objectively measurable metric.

Andrew goes on to talk about how great it would be if we could just use the existing built-in Python libraries for NNTP and POP3. That was pretty amusing, because those were some of the first protocol implementations (client and server) that Jean-Paul did for Twisted. And you know what? He had a reason for doing them with Twisted, instead of using the standard library versions:
Yet by using the Stackless socket monkeypatch, this same code works in an async framework. And the underlying libraries have a much larger developer base than Twisted. Want NNTP? "import nntplib" Want POP3? "import poplib" Plenty of documentation about them too. [-- Dalke]

This is going to come out pretty harshly, for which I can only apologize in advance, but it bears mention. The quality of protocol implementations in the standard library is bad. As in "not good". Twisted's NNTP support is better (even if I do say so myself - despite only having been working on by myself, when I knew almost nothing about Twisted, and having essentially never been touched since). Twisted's POP3 support is fantastically awesome. Next to imaplib, twisted.mail.imap4 is a sparkling diamond. And each of these implements the server end of the protocol as well: you won't find that in the standard library for almost any protocol.

He went on to compare the Twisted POP3 client documentation to the Python poplib. Neither were very good.

Jean-Paul even had a nice bit of wisdom about our culture as programmers in general:
I feel that using the phrase "just a" in the previously quoted text is an understatement. [-- Dalke]

I think you're right. We throw around "just" a lot in our line of work, don't we? :) Twisted does also account for a raft of platform-specific quirks and inconsistencies. I take this to be a good thing.

And what a classy closing.
I apologize for writing such a long message, but I didn't have time to write a shorter one.

pyOpenSSL 0.7a1

Jean-Paul Calderone has recently taken over maintenance of the pyOpenSSL project. He's doing development with bzr on launchpad.net/pyopenssl, but still maintaining the web site and downloads at pyopenssl.sf.net.

He's already fixed a bunch of bugs, like segfaults and things. There was a cool Open Space meeting at PyCon where he asked the community what kind of stuff they'd like to see in the bindings. I think he has plans for extending them a bit to make them more useful specifically for Twisted, but he's also very receptive to the community's patches and bug reports -- I think he's closed several bugs and patches since becoming maintainer.

Anyway, please go check out the new release - it's less buggy!

Another Twisted 8 pre-release

I just put out Twisted 8.0.0 pre-release 2 (that link is temporary and will definitely not last past the release of Twisted 8). The changes are in the NEWS file.

It comes with newly improved Windows IOCP support as well as support for easy_install. You can easy_install the main Twisted-8.0.0pre2.tar.bz2, but not the subprojects. When the final 8.0 release is out I'll register it on PyPI so that you can just type "easy_install Twisted" to get it.

Please check out this pre-release and report bugs.