<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8734577</id><updated>2011-08-13T05:52:13.863-07:00</updated><category term='flash'/><category term='dom'/><category term='javascript'/><category term='web'/><category term='books'/><category term='fresno'/><category term='web developers'/><category term='web development'/><category term='firefox3'/><category term='os x'/><category term='art'/><category term='manhood'/><category term='open source'/><category term='creative commons'/><category term='chrome'/><category term='fundraising'/><category term='hypy'/><category term='firefox'/><category term='restore'/><category term='roleplaying'/><category term='addons'/><category term='announcement'/><category term='buffer'/><category term='srd'/><category term='memes'/><category term='python'/><category term='tips'/><category term='spam'/><category term='avi'/><category term='family'/><category term='video'/><category term='vim'/><category term='productivity'/><category term='launchpad'/><category term='dnd'/><category term='hg'/><category term='review'/><category term='prism'/><category term='openoffice.org'/><category term='backup'/><category term='humor'/><category term='anecdote'/><category term='linux'/><category term='d20'/><category term='extensions'/><category term='n3'/><category term='releases'/><category term='os'/><category term='politics'/><category term='fundable'/><category term='games'/><category term='penny arcade'/><category term='crpg'/><category term='bookmarks'/><category term='thumbnail'/><category term='gaming'/><category term='employment'/><category term='hiring'/><category term='goonmill'/><category term='obama'/><category term='ui'/><category term='decipher'/><category term='opinion'/><category term='software'/><category term='ipod'/><category term='rpg'/><category term='portland'/><category term='mac'/><category term='dates'/><category term='search'/><category term='unit testing'/><category term='swf'/><category term='greenpeace'/><category term='testing'/><category term='blogdoc'/><category term='ubuntu'/><category term='mercurial'/><category term='request'/><category term='pandora'/><category term='google'/><category term='money'/><title type='text'>Strong, dynamic</title><subtitle type='html'>Mostly about programming, mostly in Python.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>73</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8734577.post-617480930762931659</id><published>2009-10-30T07:37:00.001-07:00</published><updated>2009-10-31T08:49:44.208-07:00</updated><title type='text'>Behaving as a wave, not a particle</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;&lt;b&gt;UPDATE&lt;/b&gt;: Got one!  Thanks, the webs. :-)&lt;br/&gt;&lt;strike&gt;______________________________________&lt;/strike&gt;&lt;br/&gt;Dear Generousweb,&lt;br/&gt;&lt;br/&gt;I'd like an invitation to &lt;a href='http://wave.google.com/wave/'&gt;Google Wave&lt;/a&gt; so I can start porting my awesome &lt;a href='http://vellumbot-source.goonmill.org/'&gt;open source dicebot, Vellumbot&lt;/a&gt;, to the new platform.  (I've been talking about doing this since before it was cool--indeed, since before I knew Wave came with its own, apparently non-awesome dicebot.)&lt;br/&gt;&lt;br/&gt;Anyone out there interested in helping a brother out?&lt;br/&gt;&lt;br/&gt;Sincerely,&lt;br/&gt;&lt;br/&gt;Cory&lt;br/&gt;&lt;br/&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-617480930762931659?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/617480930762931659/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=617480930762931659' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/617480930762931659'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/617480930762931659'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2009/10/behaving-as-wave-not-particle.html' title='Behaving as a wave, not a particle'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-6062986306748663100</id><published>2009-09-19T00:37:00.000-07:00</published><updated>2009-09-20T00:38:10.128-07:00</updated><title type='text'>Hypy 0.8.4 released</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;The main focus of this release is a couple of minor bugfixes.&lt;br/&gt;&lt;br/&gt;&lt;div id='release-version-0-8-4-2009-09-19' class='section'&gt; &lt;h3&gt;Release Version 0.8.4 (2009.09.19)&lt;/h3&gt; &lt;p&gt;Bugfix release.&lt;/p&gt; &lt;ul class='simple'&gt;&lt;li&gt;It is now possible to construct an attribute-only search with None for search phrase.&lt;/li&gt;&lt;/ul&gt; &lt;/div&gt;&lt;strong&gt;&lt;br/&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-6062986306748663100?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/6062986306748663100/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=6062986306748663100' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/6062986306748663100'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/6062986306748663100'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2009/02/hypy-083-released.html' title='Hypy 0.8.4 released'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-5214069291995662434</id><published>2009-02-27T07:22:00.001-08:00</published><updated>2009-02-27T07:22:51.191-08:00</updated><title type='text'>Launched a new Google Group: hypy-discuss</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;More people are showing interest in the library, so we need a place to go to discuss things archivably: this &lt;a href='http://groups.google.com/group/hypy-discuss'&gt;Google Group for Hypy&lt;/a&gt; is it.&lt;br/&gt;&lt;br/&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-5214069291995662434?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/5214069291995662434/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=5214069291995662434' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/5214069291995662434'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/5214069291995662434'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2009/02/launched-new-google-group-hypy-discuss.html' title='Launched a new Google Group: hypy-discuss'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-1577420609458044736</id><published>2009-02-21T22:22:00.001-08:00</published><updated>2009-02-21T22:27:20.694-08:00</updated><title type='text'>Penny Arcade D&amp;D Podcast - this one has Wil Wheaton</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;&lt;a href='http://www.wizards.com/default.asp?x=dnd/4pod/20090218'&gt;&lt;img height='' src='http://www.wizards.com/dnd/images/podcast_papvp2_1th.jpg' style='max-width: 800px; float: right; margin-top: 10px; margin-bottom: 10px; margin-left: 10px;' title='podcast series 2 #1' alt='Gabe&amp;apos;s artwork for series 2 #1'/&gt;&lt;/a&gt;&lt;br /&gt;The &lt;a href='http://www.wizards.com/default.asp?x=dnd%2F4pod%2F20090218'&gt;newest series&lt;/a&gt; of PA D&amp;amp;D Podcasts has started out at the &lt;a href='http://www.wizards.com/default.asp?x=dnd%2F4pod%2F20090218'&gt;maximum level for funny&lt;/a&gt;.  I was literally - not figuratively, not "LOL" but literally by which I mean with my literal lungs - walking around laughing out loud at this in a supermarket.&lt;br /&gt;&lt;br /&gt;(&lt;a href='http://www.wizards.com/default.asp?x=dnd/drfe/20080530'&gt;First series starts here&lt;/a&gt;, but get a podcatcher and subscribe to the &lt;a href='http://www.wizards.com/dnd/rsspodcast.xml'&gt;feed&lt;/a&gt; you technophobe.)&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-1577420609458044736?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/1577420609458044736/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=1577420609458044736' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/1577420609458044736'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/1577420609458044736'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2009/02/penny-arcade-d-podcast-this-one-has-wil.html' title='Penny Arcade D&amp;amp;D Podcast - this one has Wil Wheaton'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-3374464692375891805</id><published>2009-02-21T13:20:00.001-08:00</published><updated>2011-03-26T15:24:29.344-07:00</updated><title type='text'>dpkg-origins: 0.9.1</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;Fixed a minor bug in dpkg-origins.  It would crash when a partially-configured but obsoleted package was found in the index.  (You might see this in dpkg -l as 'uc' or 'ic'.)  You would probably see this after a dist-upgrade, like I did.  Fixed this bug.&lt;br/&gt;&lt;br/&gt;(See this &lt;a href='http://strongdynamic.blogspot.com/2008/11/ubuntu-backup-tip-save-your-package.html'&gt;post about dpkg-origins&lt;/a&gt;.)&lt;br/&gt;&lt;br/&gt;Go get the &lt;a href='http://dl.dropbox.com/u/19400544/strongdynamic.blogspot.com/dpkg-origins'&gt;dpkg-origins script&lt;/a&gt;.&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;div class='zemanta-pixie'&gt;&lt;img src='http://img.zemanta.com/pixy.gif?x-id=3a9d8ea1-987e-4c66-b139-f006475d2bab' class='zemanta-pixie-img'/&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-3374464692375891805?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/3374464692375891805/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=3374464692375891805' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/3374464692375891805'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/3374464692375891805'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2009/02/dpkg-origins-091.html' title='dpkg-origins: 0.9.1'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-1882420413299100009</id><published>2009-01-20T21:52:00.001-08:00</published><updated>2009-01-20T22:01:54.752-08:00</updated><title type='text'>Hypy 0.8.2 released</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;A minor version release of Hypy.  No material bugs reported so far.  That's good for my users, but bad for me because I can't do more releases until bugs get reported for me to fix. :-)&lt;br/&gt;&lt;br/&gt;Some people would not have been able to easy_install release 0.8.1, so this release fixes that.&lt;br/&gt;&lt;br/&gt;Hypy is a fulltext search interface for Python applications.&lt;br/&gt;&lt;br/&gt;Homepage, downloads, everything: &lt;a href='http://goonmill.org/hypy/'&gt;http://goonmill.org/hypy/&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;&lt;u&gt;Release Version 0.8.2 (2009-01-20)&lt;/u&gt;&lt;br/&gt;&lt;ul&gt;&lt;li&gt;I was unconditionally importing ez_setup in my setup.py and that makes it hard to easy_install.  Don't do that.&lt;/li&gt;&lt;li&gt;No library functionality change, but now more users can install it.&lt;/li&gt;&lt;/ul&gt;&lt;br/&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-1882420413299100009?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/1882420413299100009/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=1882420413299100009' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/1882420413299100009'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/1882420413299100009'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2009/01/hypy-082-released.html' title='Hypy 0.8.2 released'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-7076035301915381662</id><published>2009-01-06T22:22:00.001-08:00</published><updated>2009-01-13T22:48:09.340-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='unit testing'/><category scheme='http://www.blogger.com/atom/ns#' term='anecdote'/><title type='text'>On demonstrating the value of unit tests to beginners</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;A little anecdote.  I'm slowly trying to get my team to wrap their heads around the idea that any new feature must be accompanied by unit tests as we near the point where they are absolutely required to write unit tests before they write code and the tests become part of the deliverable.  One thing I know is that if you haven't written a lot of unit tests yet, you don't really understand the value of them except very much in the abstract, so I am also trying to point out the value to him as we go.&lt;br/&gt;&lt;br/&gt;One of my developers is writing a function that uses the &lt;font face='Courier New'&gt;compiler&lt;/font&gt; module to inspect some Python code, it's not really important why.  He had just learned how to write some unit tests in Javascript and I was teaching him how to use the stdlib &lt;font face='Courier New'&gt;unittest&lt;/font&gt; module for his unit tests written in Python.   His implementation isn't written yet, he is just starting to figure out what the interfaces look like, which is a great time to start writing failing tests.&lt;br/&gt;&lt;br/&gt;I told him, start with this:&lt;br/&gt;&lt;br/&gt;&lt;small&gt;&lt;font face='Courier New'&gt;import unittest&lt;br/&gt;&lt;br/&gt;class MyTestCase(unittest.TestCase):&lt;br/&gt;  def test_myParseFunction(self):&lt;br/&gt;    assert 0&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;br/&gt;.. and run that test, which he did, and it failed, and I said "good".  I started pointing out to him ways he could make very minor modifications to his code to make it easier to test (not nearly enough has been written on the subject of making code easier to test, BTW--bloggers, get on it!).&lt;br/&gt;&lt;br/&gt;One of the improvements I asked him to make was to move some functions into another, more relevant module than the one he was working in.  He did that, then wrote version two of the unit test:&lt;br/&gt;&lt;br/&gt;&lt;font face='Courier New'&gt;&lt;small&gt;import unittest&lt;br/&gt;import mynewmodule&lt;br/&gt;&lt;br/&gt;class MyTestCase(unittest.TestCase):&lt;br/&gt;  def test_myParseFunction(self):&lt;br/&gt;    self.assertEqual(mynewmodule.myParseFunction("(python.code)"), [expected, output, structure]) &lt;/small&gt;&lt;br/&gt;&lt;/font&gt;&lt;br/&gt;Now, remember that he hasn't implemented myParseFunction yet.  So I asked him to run his failing test one more time.  And, a surprise to both of us, we got this:&lt;br/&gt;&lt;br/&gt;&lt;small&gt;&lt;font face='Courier New'&gt;[ERROR]: test_mymodule.MyTestCase.test_myParseFunction&lt;br/&gt;&lt;br/&gt;Traceback (most recent call last):&lt;br/&gt;  File "/usr/lib/python2.5/unittest.py", line 260, in run&lt;br/&gt;    testMethod()&lt;br/&gt;  File ".../test_mymodule.py", line 7, in test_myParseFunction&lt;br/&gt;    self.assertEqual(mynewmodule.myParseFunction("(python.code)"), [expected, output, structure])&lt;br/&gt;  File ".../mynewmodule.py", line 19, in myParseFunction&lt;br/&gt;    return compiler.parse(s)&lt;br/&gt;exceptions.NameError: global name 'compiler' is not defined&lt;/font&gt;&lt;/small&gt;&lt;br/&gt;&lt;br/&gt;What the.. oh right!  He imported compiler in the original module, but forgot to move it to the new module.  The unit test - so far, one line long and expected to fail in a relatively uninteresting way, had &lt;i&gt;already found a bug.&lt;/i&gt;  My favorite part was that it happened this way to someone learning &lt;i&gt;why&lt;/i&gt; we put so much value on unit tests.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-7076035301915381662?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/7076035301915381662/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=7076035301915381662' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/7076035301915381662'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/7076035301915381662'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2009/01/on-demonstrating-value-of-unit-tests-to.html' title='On demonstrating the value of unit tests to beginners'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-6018887856991186903</id><published>2008-12-15T16:28:00.001-08:00</published><updated>2009-01-13T22:48:22.324-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='open source'/><category scheme='http://www.blogger.com/atom/ns#' term='hypy'/><category scheme='http://www.blogger.com/atom/ns#' term='software'/><category scheme='http://www.blogger.com/atom/ns#' term='search'/><category scheme='http://www.blogger.com/atom/ns#' term='releases'/><title type='text'>Hypy 0.8.1 - Get your search on here.</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;Hypy is a fulltext search interface for Python applications. Use it to index and search your documents from Python code. Hypy is based on the estraiernative bindings by Yusuke Yoshida.&lt;br/&gt;&lt;ul&gt;&lt;li&gt;Fast, scalable&lt;/li&gt;&lt;li&gt;Perfect recall ratio by N-gram method&lt;/li&gt;&lt;li&gt;High precision by hybrid mechanism of N-gram and morphological analyzer&lt;/li&gt;&lt;li&gt;Phrase search, regular expressions, attribute search (including numeric and date comparisons), and similarity search&lt;/li&gt;&lt;li&gt;Simple and powerful API&lt;/li&gt;&lt;/ul&gt;Homepage, downloads, everything, etc.: &lt;a href='http://goonmill.org/hypy/'&gt;http://goonmill.org/hypy/&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;This is of course on pypi and can be installed with easy_install or pip.  You will need Hyper Estraier installed to use it.&lt;br/&gt;&lt;br/&gt;&lt;font face='monospace'&gt;Release Version 0.8.1 (2008.12.15)&lt;br/&gt;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~&lt;br/&gt;&lt;br/&gt;* Initial Public Opensourcing.&lt;br/&gt;&lt;br/&gt;&lt;/font&gt;&lt;font face='monospace'&gt;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~&lt;br/&gt;&lt;/font&gt;&lt;br/&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-6018887856991186903?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/6018887856991186903/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=6018887856991186903' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/6018887856991186903'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/6018887856991186903'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2008/12/hypy-081-get-your-search-on-here.html' title='Hypy 0.8.1 - Get your search on here.'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-6577904747470958905</id><published>2008-12-12T09:30:00.001-08:00</published><updated>2009-01-13T22:48:41.841-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='opinion'/><category scheme='http://www.blogger.com/atom/ns#' term='launchpad'/><category scheme='http://www.blogger.com/atom/ns#' term='ui'/><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><title type='text'>Sometimes good User Experience means ignoring sanity</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;Found on Launchpad's "register a project" page, this was one of four FAQ-ish bullet points:&lt;br /&gt;&lt;ul style='font-size: larger;'&gt;&lt;li style='margin-top: 1em;'&gt;&lt;strong&gt;Requesting Ubuntu CDs&lt;/strong&gt; is done at &lt;a href='https://shipit.ubuntu.com/' onclick='https://shipit.ubuntu.com/'&gt;shipit.ubuntu.com&lt;/a&gt;      &lt;input type='button' value='Oh, I want Ubuntu CDs'/&gt;  &lt;br /&gt;&lt;small&gt;(this      may sound weird to you, but a lot of people register projects asking      for CDs!)&lt;/small&gt;&lt;/li&gt;&lt;/ul&gt;I think this is a practical solution to a real, if insane, problem.  Nice touch on the button, too.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-6577904747470958905?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/6577904747470958905/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=6577904747470958905' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/6577904747470958905'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/6577904747470958905'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2008/12/sometimes-good-user-experience-means.html' title='Sometimes good User Experience means ignoring sanity'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-8985299234956463806</id><published>2008-11-12T16:25:00.000-08:00</published><updated>2009-01-13T22:48:56.310-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='memes'/><category scheme='http://www.blogger.com/atom/ns#' term='books'/><title type='text'>"phrase from nearest book" meme</title><content type='html'>&lt;a href="http://agiletesting.blogspot.com/2008/11/phrase-from-nearest-book-meme.html"&gt;From Agile Testing&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The meme:&lt;blockquote&gt;&lt;ul&gt;&lt;li&gt;Grab the nearest book.&lt;br /&gt;&lt;li&gt;Open it to page 56.&lt;br /&gt;&lt;li&gt;Find the fifth sentence.&lt;br /&gt;&lt;li&gt;Post the text of the sentence in your journal along with these instructions.&lt;br /&gt;&lt;li&gt;Don’t dig for your favorite book, the cool book, or the intellectual one: pick the CLOSEST.&lt;/ul&gt;&lt;/blockquote&gt;I am about to make a parody of myself, but this is honest to god page 56 sentence 5 of the closest book to me (apart from a pamphlet on health insurance which was not 56 pages long).&lt;br /&gt;&lt;br /&gt;"Magical weapons and other spells (such as &lt;span style="font-style:italic;"&gt;lightning bolt&lt;/span&gt;&lt;/span&gt;) inflict normal damage on him."&lt;br /&gt;&lt;br /&gt;Yes, I am reading from the D&amp;D &lt;span style="font-style:italic;"&gt;Rules Cyclopedia&lt;/span&gt;, a collection of all the Red box/Blue box D&amp;D rules, published 1991.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-8985299234956463806?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/8985299234956463806/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=8985299234956463806' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/8985299234956463806'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/8985299234956463806'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2008/11/phrase-from-nearest-book-meme.html' title='&quot;phrase from nearest book&quot; meme'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-6106300653684756592</id><published>2008-11-09T21:44:00.001-08:00</published><updated>2011-03-26T15:23:19.685-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='open source'/><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><title type='text'>Update to dpkg-origins installed package lister</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;Fixed a serious bug with dpkg-origins (see this &lt;a href='http://strongdynamic.blogspot.com/2008/11/ubuntu-backup-tip-save-your-package.html'&gt;post about dpkg-origins&lt;/a&gt;).  I forgot to have it check for status 'rc' packages.  These are packages that were installed and then removed.&lt;br /&gt;&lt;br /&gt;It now handles them correctly.  (That's what I get for testing on a brand-spanking-new installation of Ubuntu.)&lt;br /&gt;&lt;br /&gt;I've also put a version string into it: 0.9, because I'm actually using it myself in my backup plan now, which makes it near production ready!  Go get the &lt;a href='http://dl.dropbox.com/u/19400544/strongdynamic.blogspot.com/dpkg-origins'&gt;dpkg-origins script&lt;/a&gt;.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-6106300653684756592?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/6106300653684756592/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=6106300653684756592' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/6106300653684756592'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/6106300653684756592'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2008/11/update-to-dpkg-origins-installed.html' title='Update to dpkg-origins installed package lister'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-3222591324172990730</id><published>2008-11-04T08:56:00.001-08:00</published><updated>2009-01-13T22:49:25.261-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='opinion'/><category scheme='http://www.blogger.com/atom/ns#' term='politics'/><title type='text'>U.S. Citizens: Go Make History</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;Also, can I just say I'm really glad my polling place still uses black felt-tip pens and an optical scanner?  I trust these things way more.  No hanging chads, very nice paper trail.&lt;br /&gt;&lt;br /&gt;That is all.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-3222591324172990730?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/3222591324172990730/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=3222591324172990730' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/3222591324172990730'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/3222591324172990730'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2008/11/us-citizens-go-make-history.html' title='U.S. Citizens: Go Make History'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-2928583310489409669</id><published>2008-11-02T15:20:00.001-08:00</published><updated>2011-03-26T15:25:00.242-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='restore'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='backup'/><category scheme='http://www.blogger.com/atom/ns#' term='blogdoc'/><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><title type='text'>Ubuntu backup tip: save your package selections, including third-party, for later recovery</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;Today I wrote a little Python script which will pull a list of all of your installed packages, and then group them by Canonical-supplied, third-party PPA supplied, and manually installed .deb files.  This makes it a snap to automatically restore your package list if your system takes a dump, and even quickly put back your PPAs and manual debs as you go.&lt;br /&gt;&lt;br /&gt;It requires &lt;b&gt;python-twisted&lt;/b&gt; and &lt;b&gt;python-apt&lt;/b&gt; installed.  Here is the script: &lt;a href='http://dl.dropbox.com/u/19400544/strongdynamic.blogspot.com/dpkg-origins'&gt;dpkg-origins&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Recommended usage: Add this command to a script inside /etc/cron.daily:&lt;br /&gt;&lt;font face='Courier New'&gt;  dpkg-origins | mail -s "Package selections for `hostname -s` as of `date`" yourname@youremail.com&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;When calamity strikes and you need to restore, you can pipe this file directly:&lt;br /&gt;&lt;br /&gt;&lt;font face='Courier New'&gt;  cat selections.txt | sudo dpkg --set-selections &amp;amp;&amp;amp; apt-get -u dselect-upgrade&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;This will begin installing all of the Canonical-supplied packages in selections.txt.  All other packages are commented out, but the file itself contains instructions for restoring your PPA's; then you uncomment some more packages and run the above again.  Finally, at the very top of the file, you will find a commented-out list of the packages (and versions) which were installed directly from a .deb file; manually download and install those.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-2928583310489409669?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/2928583310489409669/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=2928583310489409669' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/2928583310489409669'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/2928583310489409669'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2008/11/ubuntu-backup-tip-save-your-package.html' title='Ubuntu backup tip: save your package selections, including third-party, for later recovery'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-8207806011767633353</id><published>2008-10-31T20:30:00.001-07:00</published><updated>2009-01-13T22:45:35.684-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='hiring'/><category scheme='http://www.blogger.com/atom/ns#' term='fresno'/><category scheme='http://www.blogger.com/atom/ns#' term='employment'/><category scheme='http://www.blogger.com/atom/ns#' term='decipher'/><category scheme='http://www.blogger.com/atom/ns#' term='web developers'/><title type='text'>Hiring in Portland and Fresno</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;Decipher is hiring web developers.  Decipher is &lt;i&gt;also&lt;/i&gt; paying people who know web developers - up to $1000 just for knowing someone who needs a job.  Details below.&lt;br /&gt;&lt;br /&gt;We're looking for a manual tester and test engineers in Fresno, CA.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Dice posting for our &lt;a href='http://seeker.dice.com/jobsearch/servlet/JobSearch?op=302&amp;amp;dockey=xml/b/c/bcd5cda94a400eab347f8b095db9f996@endecaindex&amp;amp;source=19&amp;amp;FREE_TEXT=python+javascript&amp;amp;rating=99'&gt;test engineer job&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;We're looking for web designers, people experienced with design and prototyping on the web, and software engineers in Portland, OR.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Posting for &lt;a href='http://seeker.dice.com/jobsearch/servlet/JobSearch?op=302&amp;amp;dockey=xml/0/e/0e8cf2c459457d5a0fc8ad417a400e98@endecaindex&amp;amp;source=19&amp;amp;FREE_TEXT=javascript&amp;amp;rating=99'&gt;Web Modeler/Prototyper&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href='http://seeker.dice.com/jobsearch/servlet/JobSearch?op=302&amp;amp;dockey=xml/3/e/3efff98c7c0b60bc828f6e8d306d12ef@endecaindex&amp;amp;source=19&amp;amp;FREE_TEXT=javascript&amp;amp;rating=99'&gt;Web Designer&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href='http://seeker.dice.com/jobsearch/servlet/JobSearch?op=302&amp;amp;dockey=xml/c/1/c18b514c4a8f7189b4960c4aeffa286f@endecaindex&amp;amp;source=19&amp;amp;FREE_TEXT=javascript&amp;amp;rating=99'&gt;Software Engineer&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;If you are one of these people, send us your resume!  If you know one of these people, &lt;i&gt;send us their resume!&lt;/i&gt;  We are paying referral bonuses of $250 if we hire your referral, and an additional $750 if they stay at Decipher for 6 months!&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-8207806011767633353?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/8207806011767633353/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=8207806011767633353' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/8207806011767633353'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/8207806011767633353'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2008/10/hiring-in-portland-and-fresno.html' title='Hiring in Portland and Fresno'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-3352280358991005773</id><published>2008-10-15T21:00:00.000-07:00</published><updated>2009-01-13T22:46:05.949-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='web development'/><category scheme='http://www.blogger.com/atom/ns#' term='rpg'/><category scheme='http://www.blogger.com/atom/ns#' term='dnd'/><category scheme='http://www.blogger.com/atom/ns#' term='goonmill'/><title type='text'>This is that part in the painting where God's finger touches Adam's</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;I've been making very exciting progress on Goonmill lately.  The user interface has undergone a complete overhaul, and I undertook a lot of interesting challenges in getting a precise, cross-browser layout with a maximum focus on GM usability.&lt;br/&gt;&lt;br/&gt;I've gotten it up to the point where I can use it myself by maintaing (with Tomboy) a Dogfood list, a list of everything I've noticed which would annoy me too much to use it.  As I go through and fix things, I would add to the list, so the list continually gets longer but the things remaining to fix still get shorter over time because I fix more than I find.&lt;br/&gt;&lt;br/&gt;As of this writing, that list is 39 items, with 33 crossed off.&lt;br/&gt;&lt;br/&gt;I really feel like Goonmill is going to become a useful resource to other people, and I'm looking forward to doing some blog posts or maybe even some kind of lightning talk somewhere on the application of Athena, Twisted and Prototype to a real, modern-look-and-feel web application with a purpose.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-3352280358991005773?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/3352280358991005773/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=3352280358991005773' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/3352280358991005773'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/3352280358991005773'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2008/04/this-is-that-part-in-painting-where-god.html' title='This is that part in the painting where God&amp;#39;s finger touches Adam&amp;#39;s'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-9176803082120174888</id><published>2008-10-13T17:45:00.001-07:00</published><updated>2009-01-13T22:46:26.208-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='art'/><category scheme='http://www.blogger.com/atom/ns#' term='creative commons'/><category scheme='http://www.blogger.com/atom/ns#' term='rpg'/><category scheme='http://www.blogger.com/atom/ns#' term='srd'/><category scheme='http://www.blogger.com/atom/ns#' term='goonmill'/><title type='text'>Goonmill - still seeking art - samples here!</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;I mentioned this &lt;a href='http://strongdynamic.blogspot.com/2008/06/goonmill-seeking-art.html'&gt;earlier&lt;/a&gt;: I am seeking samples of art for monsters in the System Reference Document for D&amp;amp;D 3.5. These must be openly-licensed, i.e. CC-BY, public domain or other non-restrictive license.  (It must allow derivatives and commercial uses.)  The purpose is to pile the artwork up until every monster in the books has free token art to go with it.  This will make it much easier to include with Virtual Gaming Tables, RPG management software, and the like, but I want it free enough that people can think of their own uses, and not have to worry about whether they are breaking copyright law.  Publish it with your module PDF?  Make a Flash game with it?  I don't see why not.&lt;br/&gt;&lt;br/&gt;I am publishing thumbnails of what I have so far, with a complete table of all the monsters.  I need images of 500+ of these monsters, but I have 165 covered so far!  A lot of them would be easy because there is so much repetition; for example, if I had one decent CC-licensed dragon, I could just recolor and reposition him and cover about 95 dragons in that list (not an exaggeration).&lt;br/&gt;&lt;br/&gt;There are 110 unique, freely-licensed images in the index below, and (because of duplication) they cover about 165 of the monster entries.&lt;br/&gt;&lt;br/&gt;The &lt;a href='http://goonmill.org/static/srd-monsters.html'&gt;sample page of my freely-licensed Monster Art&lt;/a&gt;.&lt;br/&gt;&lt;br/&gt;At the top of the page are thumbnails of all the images I have, culled from commons.wikimedia.org.  Below that is a table with all the monsters in the SRD, next to the filename of an image if it has one.  My top priority is getting the table filled; second priority is getting higher quality images and more variety for some of them.  Third priority is getting alternate images for as many as possible, so that a creator has a choice of which token to use.&lt;br/&gt;&lt;br/&gt;I will release the full archive (full-sized images) as soon as I get off my lazy butt and go get the attributions i need for some of those 110 images.  While they are all freely licensed, some of them do require attribution, and I owe it to the creators to at least provide that before I publish fully.&lt;br/&gt;&lt;br/&gt;The reason I am picking this back up again is the &lt;a href='http://www.encounteraday.com/2008/10/13/a-community-monster-manual/'&gt;Encounter-a-Day blog&lt;/a&gt; is throwing around the idea of a monster manual wiki (which I think should be named the Mob Manual), and I have offered this index to help out.&lt;br/&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-9176803082120174888?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/9176803082120174888/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=9176803082120174888' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/9176803082120174888'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/9176803082120174888'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2008/10/goonmill-still-seeking-art-samples-here.html' title='Goonmill - still seeking art - samples here!'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-619400390172903605</id><published>2008-10-06T22:15:00.001-07:00</published><updated>2009-01-13T22:46:50.638-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='pandora'/><category scheme='http://www.blogger.com/atom/ns#' term='opinion'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='prism'/><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><title type='text'>Prism on Ubuntu</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;I downloaded and started playing with &lt;a href='http://labs.mozilla.com/2007/11/prism-prototype-now-available-on-mac-and-linux/'&gt;Prism&lt;/a&gt;.  And it actually worked, which is cool.  There were only two setup steps:&lt;br/&gt;&lt;ol&gt;&lt;li&gt;Unpack the tarball in /usr/local/prism, or /opt/prism or something.&lt;/li&gt;&lt;li&gt;Symlink /usr/lib/firefox/plugins &amp;lt;- /usr/local/prism/plugins so Flash etc. works.&lt;br/&gt;&lt;/li&gt;&lt;/ol&gt;Unsurprisingly, there are still some problems.&lt;br/&gt;&lt;ul&gt;&lt;li&gt;The Refractor for Prism extension doesn't work very well.  Likely this is a problem with Refractor and not Prism, but what it does is it creates a shortcut icon on the desktop.  The shortcut runs your system Firefox, i.e. the same executable you are using Refractor for.  It doesn't ask for the location of the prism executable. It writes the webapp config to the wrong place, and it puts the wrong options into the Launcher.  That's kinda useless by itself. &lt;br/&gt;&lt;/li&gt;&lt;li&gt;Running /usr/local/prism/prism and then typing in a URL &lt;i&gt;did&lt;/i&gt; create a working shortcut, but unlike Refractor, it didn't automatically grab an icon from the website.  You can try, instead, using Refractor to create the launcher, and then editing the command line so it points to /usr/local/prism/prism, get rid of every option except the "-webapp xxx@xxx" arg, and then &lt;b&gt;move&lt;/b&gt; the webapp config dir it creates from ~/.webapps to ~/.prism/&lt;i&gt;$profile&lt;/i&gt;/webapps.  It's about the same amount of work as downloading the icon yourself.  Either way, the setup of a webapp is a bit of a mess right now.&lt;br/&gt;&lt;/li&gt;&lt;li&gt;You get a blank profile, so your fonts, addons, user stylesheets etc. are all missing.  You &lt;i&gt;might&lt;/i&gt; be able to fix this by copying a profile from ~/.mozilla/firefox to ~/.prism, and then running prism -ProfileManager, but I didn't experiment.&lt;/li&gt;&lt;/ul&gt;And one show-stoppingly dumb problem:&lt;br/&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Every prism application runs in the same process.&lt;/b&gt;&lt;/li&gt;&lt;/ul&gt;I created one for Pandora (which worked fine, once I symlinked Flash), and one for Google Reader.  Ran them both.  Pressed Ctrl+Q to quit one of them . . . and the other one shut down at the same time.  I mean, &lt;i&gt;what?&lt;/i&gt;  Isn't a big part of the point of prism to isolate your apps from one another?  If one of them crashes, they don't all crash, and that sort of thing?  That's lame, so sorry, I won't be using Prism yet.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-619400390172903605?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/619400390172903605/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=619400390172903605' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/619400390172903605'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/619400390172903605'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2008/10/prism-on-ubuntu.html' title='Prism on Ubuntu'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-1029762357808918453</id><published>2008-09-18T10:36:00.001-07:00</published><updated>2009-01-13T22:46:58.550-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='humor'/><title type='text'>Bankers of the world: A request</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;If you're planning to throw yourself on a ritual funeral pyre in the next few days, do you think you could carry the record of my mortgage with you?  Consider it a just atonement.&lt;br/&gt;&lt;br/&gt;Thanks!&lt;br/&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-1029762357808918453?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/1029762357808918453/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=1029762357808918453' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/1029762357808918453'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/1029762357808918453'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2008/09/bankers-of-world-request.html' title='Bankers of the world: A request'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-6032141102451959496</id><published>2008-09-17T09:35:00.001-07:00</published><updated>2009-01-13T22:38:56.947-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dates'/><category scheme='http://www.blogger.com/atom/ns#' term='request'/><title type='text'>People on the Internets: A request</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;Please put dates on your pages, such as release notes.  I can't tell how old your page is otherwise.  Thanks!&lt;br/&gt;&lt;br/&gt;- Committee of Citizens Concerned About Bitrot on the Internet&lt;br/&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-6032141102451959496?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/6032141102451959496/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=6032141102451959496' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/6032141102451959496'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/6032141102451959496'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2008/09/people-on-internets-request.html' title='People on the Internets: A request'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-5651189667588992427</id><published>2008-09-13T15:55:00.001-07:00</published><updated>2009-01-13T22:39:16.937-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='addons'/><category scheme='http://www.blogger.com/atom/ns#' term='extensions'/><category scheme='http://www.blogger.com/atom/ns#' term='announcement'/><category scheme='http://www.blogger.com/atom/ns#' term='chrome'/><category scheme='http://www.blogger.com/atom/ns#' term='google'/><title type='text'>Chrome to have Extensions "Next"</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;About a week ago, a senior VP at Google announced that yes, &lt;a href='http://news.cnet.com/8301-1001_3-10031764-92.html'&gt;they are going to be putting extension support into Chrome&lt;/a&gt;.  I'm relieved to hear it.&lt;br/&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-5651189667588992427?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/5651189667588992427/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=5651189667588992427' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/5651189667588992427'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/5651189667588992427'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2008/09/google-could-leverage-extensions-to.html' title='Chrome to have Extensions &quot;Next&quot;'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-6974865721328114767</id><published>2008-09-02T15:10:00.001-07:00</published><updated>2009-01-13T22:39:35.544-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='opinion'/><category scheme='http://www.blogger.com/atom/ns#' term='addons'/><category scheme='http://www.blogger.com/atom/ns#' term='extensions'/><category scheme='http://www.blogger.com/atom/ns#' term='chrome'/><category scheme='http://www.blogger.com/atom/ns#' term='google'/><title type='text'>Google Chrome - no extensions!</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;So, ugh.  &lt;a href='http://www.google.com/support/chrome/bin/answer.py?answer=95695'&gt;Chrome does not support extensions&lt;/a&gt;.  That means no Adblock Plus, no NoScript, no FireGPG, and all those other tweaks we all rely on to get through our day - for each of us, a different set of tweaks, adding up to thousands of features Google won't be developing on its own and therefore nobody will have.&lt;br/&gt;&lt;br/&gt;They &lt;i&gt;have&lt;/i&gt; to rectify this situation, or quickly see Chrome fork (or worse for them - an anti-Chrome developer groundswell).  I can only assume that this is a temporary situation.  To tell them what you think, and in the hopes that this situation is only temporary (it's a 0.2 browser right now, after all) go to the &lt;a href='http://www.google.com/support/chrome/bin/request.py?contact_type=feedback'&gt;support link&lt;/a&gt;.&lt;br/&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-6974865721328114767?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/6974865721328114767/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=6974865721328114767' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/6974865721328114767'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/6974865721328114767'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2008/09/google-chrome-no-extensions.html' title='Google Chrome - no extensions!'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-2302756042740693095</id><published>2008-09-01T21:21:00.001-07:00</published><updated>2009-01-13T22:40:41.962-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='dom'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><category scheme='http://www.blogger.com/atom/ns#' term='chrome'/><category scheme='http://www.blogger.com/atom/ns#' term='google'/><title type='text'>The most exciting part of Google Chrome</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;You've probably already heard about tomorrow's release of Google's browser project, &lt;a href='http://blogoscoped.com/archive/2008-09-01-n47.html'&gt;Google Chrome&lt;/a&gt;.  (&lt;a href='http://google.com/chrome/'&gt;This link&lt;/a&gt; is broken, but broken quite differently from other Google &lt;a href='http://www.google.com/404'&gt;404's&lt;/a&gt;.  It's a safe bet they are already proxying this page to some other server and will put something there When It's Ready.)&lt;br/&gt;&lt;br/&gt;There are many awesome in this, but I'd like to draw you web developers' attention to something that promises to be as exciting as the browser itself:&lt;br/&gt;&lt;br/&gt;Comic pages: &lt;a href='http://blogoscoped.com/google-chrome/9'&gt;page 9&lt;/a&gt;, &lt;a href='http://blogoscoped.com/google-chrome/10'&gt;page 10&lt;/a&gt;, &lt;a href='http://blogoscoped.com/google-chrome/11'&gt;page 11&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;These pages describe the testing apparatus used to develop Chrome.  It describes a continuous integration server that processes every build against a perfect rendering of tens of thousands of sites.  The perfect rendering is described as being "a schematic of what the browser thinks it's displaying".  I read this as being an internal data structure representing the rendered view.&lt;br/&gt;&lt;br/&gt;There are two reasons I love this.  First, it means that Google will be Ready on Day One to render the web.  It will be "another platform to support", but not to nearly the degree that (for example) Safari or IE7 is another platform to support.  This kind of testing apparatus can only lead to a more compliant, more reasonable platform.  (At the least, it should have only the same bugs Firefox does.  I wonder what they used to make their benchmark renderings?)  &lt;b&gt;Edit&lt;/b&gt;: I know Chrome is based on WebKit, I should clarify that, if they used Firefox for reference renderings, then their rendering bugs will match Firefox's.  Apparently WebKit already does this, but it wouldn't make much sense to use WebKit as the reference rendering for a test of WebKit!  So they must be using some other browser; Firefox would make sense.&lt;br/&gt;&lt;br/&gt;Second, it means we may finally get the holy grail of web testing: a headless DOM!  We currently have a test apparatus that consists of a big, fast Mac machine with a 1920px display and 4 VMware machines, running Selenium on multiple browsers.  Automating this is nightmarish, and completely unsuitable for agile development methodologies.  We only have one of these, so access to it has to be gated, and the barrier to entry to test your code is huge.  (You have to commit it, to start with.)  The web badly needs a way to test applications without a browser showing up on your desktop.  I just want to see green/red for the question "did my login page render the same way it did last time?"&lt;br/&gt;&lt;br/&gt;The phrase "schematic" tantalizingly hints at a test suite with the ability to tell you about test failures in a descriptive way.  I imagine seeing something like "div#nameEntry expected position:(258,317) got position(258,0)".  But now we've veered away from speculation into wishful thinking.&lt;br/&gt;&lt;br/&gt;This makes a big assumption that Google will release the code of the test apparatus.  But I'm betting they will, because it makes extremely good business sense.  If web devs start to rely on their test engine, their applications automatically support Chrome.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-2302756042740693095?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/2302756042740693095/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=2302756042740693095' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/2302756042740693095'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/2302756042740693095'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2008/09/most-exciting-part-of-google-chrome.html' title='The most exciting part of Google Chrome'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-4102174155759854952</id><published>2008-08-31T12:09:00.001-07:00</published><updated>2009-01-13T22:40:56.501-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='pandora'/><category scheme='http://www.blogger.com/atom/ns#' term='firefox'/><category scheme='http://www.blogger.com/atom/ns#' term='tips'/><category scheme='http://www.blogger.com/atom/ns#' term='blogdoc'/><title type='text'>Gnome/Firefox tip: Pandora as a Separate Application</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;&lt;b&gt;The problem:&lt;/b&gt; &lt;a href='http://pandora.com/'&gt;Pandora&lt;/a&gt; is more like a desktop application than a website.  It should stay open when you close your browser.  If you do web development, or your browser tends to crash a lot, or you just like to close Firefox sometimes, you probably don't want to lose your tunes.  Figure out a way to keep Pandora open when the rest of your web browsing session is gone.&lt;br/&gt;&lt;br/&gt;This is a walkthrough for Gnome/Compiz users for isolating Pandora from the rest of Firefox cleanly.  Much of this will be applicable to you if you don't use Compiz, and even if you don't use Gnome.&lt;br/&gt;&lt;br/&gt;This assumes Firefox 3.0.1/Linux, I can't vouch for command line options on any other version.&lt;br/&gt;&lt;br/&gt;When I refer to your Default Firefox Icon, I am talking about whatever means you usually use to launch Firefox, whether it's a toolbar icon, a menu icon, Alt+F2 "firefox", etc.&lt;br/&gt;&lt;b&gt;&lt;br/&gt;&lt;/b&gt;&lt;big&gt;&lt;b&gt;Create a Clean Pandora Profile&lt;/b&gt;&lt;small&gt;&lt;br/&gt;&lt;br/&gt;Start by shutting down all instances of firefox completely.  Then bring up a Terminal window and type:&lt;br/&gt;&lt;/small&gt;&lt;/big&gt;&lt;blockquote&gt;&lt;big&gt;&lt;small&gt;&lt;font face='Courier New'&gt;firefox -no-remote -ProfileManager&lt;/font&gt;&lt;/small&gt;&lt;/big&gt;&lt;br/&gt;&lt;/blockquote&gt;&lt;big&gt;&lt;small&gt;You'll get the small Profile Manager window.  Create a new profile, named 'pandora'.  You may, if you wish, clean it up.  I did all of the following:&lt;br/&gt;&lt;/small&gt;&lt;/big&gt;&lt;ul&gt;&lt;li&gt;&lt;big&gt;&lt;small&gt;moved all the controls to the menu bar line at the very top (right-click a blank space and "customize..."). &lt;/small&gt;&lt;/big&gt;&lt;/li&gt;&lt;li&gt;&lt;big&gt;&lt;small&gt;hid all the toolbars.&lt;/small&gt;&lt;/big&gt;&lt;/li&gt;&lt;li&gt;&lt;big&gt;&lt;small&gt;edit &amp;gt; preferences and changed the homepage to http://pandora.com/&lt;/small&gt;&lt;/big&gt;&lt;/li&gt;&lt;/ul&gt;&lt;big&gt;&lt;small&gt;Now quit from that firefox window.  Once again, run:&lt;br/&gt;&lt;/small&gt;&lt;/big&gt;&lt;blockquote&gt;&lt;font face='Courier New'&gt;&lt;big&gt;&lt;small&gt;firefox -no-remote -ProfileManager&lt;/small&gt;&lt;/big&gt;&lt;/font&gt;&lt;br/&gt;&lt;/blockquote&gt;&lt;big&gt;&lt;small&gt;Firefox makes your latest profile the default in all situations.  To fix that (you don't want Pandora as your default browser): Select 'default' (or your original profile) from the window that just appeared, and let firefox open.  Now your Default Firefox Icon won't open Pandora.&lt;br/&gt;&lt;br/&gt;&lt;/small&gt;&lt;/big&gt;&lt;b&gt;&lt;big&gt;Make a Launcher&lt;/big&gt;&lt;/b&gt;&lt;br/&gt;&lt;big&gt;&lt;small&gt;&lt;br/&gt;Right click on your Gnome menu panel, and "Add to Panel..."  Select Custom Application Launcher.  Enter the following:&lt;br/&gt;&lt;/small&gt;&lt;/big&gt;&lt;ul&gt;&lt;li&gt;Type: Application&lt;/li&gt;&lt;li&gt;Name: Pandora&lt;/li&gt;&lt;li&gt;Command: firefox -no-remote -P pandora&lt;/li&gt;&lt;li&gt;Comment: Opens in a separate Firefox process&lt;br/&gt;&lt;/li&gt;&lt;/ul&gt;&lt;big&gt;&lt;small&gt;(Only the Type and Command must match what I show above.)&lt;br/&gt;&lt;br/&gt;Leave that window open for now.  Re-launch Firefox using your Default Firefox Icon.&lt;br/&gt;&lt;br/&gt;Let's get a pretty icon for the launcher you're about to make.  In Firefox, visit: &lt;br/&gt;&lt;a href='http://pandora.com/favicon.ico'&gt;http://pandora.com/favicon.ico&lt;/a&gt; and save the file as ~/.mozilla/firefox/*.pandora/pandora.ico&lt;br/&gt;&lt;br/&gt;Now, go &lt;i&gt;back&lt;/i&gt; to your New Launcher window (you didn't close it, right? :) and click on the springy-looking icon to change the icon.  Choose the icon file you just saved as your icon.  Now finish/OK until you are out of the New Launcher window and you have a new launcher.&lt;br/&gt;&lt;br/&gt;&lt;b&gt;&lt;big&gt;Bonus Compiz Step: Place Windows Support&lt;/big&gt;&lt;br/&gt;&lt;/b&gt;&lt;br/&gt;The Compiz "Place Windows" plugin lets you put windows on a particular workspace automatically.  I want Pandora windows to automatically be placed on desktop 8, and other Firefox windows to automatically be placed on desktop 3.  &lt;i&gt;This was the trickiest part of the entire process.&lt;/i&gt;&lt;br/&gt;&lt;br/&gt;This isn't an explanation of how to use Place Windows (find that &lt;a href='http://wiki.compiz-fusion.org/Plugins/Place'&gt;elsewhere&lt;/a&gt;).  This is an explanation of why using Place Windows for the tricked-out Pandora profile is difficult, and how you can fix it.&lt;br/&gt;&lt;br/&gt;&lt;b&gt;Problem: &lt;/b&gt;Compiz requires you to identify the windows you want to place by window Class, Name, Title, Type, or a few other things.  For all firefox windows, Class, Name, Type and so on are the same; so if you want some firefox windows to go one place and some to go another, well, you can't do that with Place Windows unless you can differentiate them by title.  But firefox &lt;i&gt;always starts with the same title: "Mozilla Firefox".&lt;/i&gt;  Compiz only looks at the &lt;i&gt;initial &lt;/i&gt;title when it tries to place a window.&lt;br/&gt;&lt;br/&gt;&lt;b&gt;Solution: &lt;/b&gt;A plugin called &lt;a href='https://addons.mozilla.org/en-US/firefox/addon/8660https://addons.mozilla.org/en-US/firefox/addon/8660'&gt;MozFox&lt;/a&gt;.  This is a version of FireSomething, that plugin that lets you randomly name your browser "Fireslug", etc.  Bring up your Pandora profile using your new launcher icon, and visit the link above.  You will have to create an account and log in there because this is currently an "experimental" plugin.&lt;br/&gt;&lt;br/&gt;Install the plugin, and let the Pandora profile restart.  When it comes back up, Tools &amp;gt; Addons &amp;gt; MozFox &amp;gt; Preferences.  You will have to manually delete everything in the three lists.  (You can select multiple to delete at once, then right-click and "delete".  This is a pain in the butt.)&lt;br/&gt;&lt;br/&gt;Add to each list: "Pandora", "Fire", "fox".&lt;br/&gt;&lt;br/&gt;Now in the Place Windows plugin, set it up to match "title=Pandora.*".  (You must have Regex Matching on.)  Close out of that window, and restart Pandora.  When it comes back up, Compiz will automatically position it where you told it to go!&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;/small&gt;&lt;/big&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-4102174155759854952?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/4102174155759854952/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=4102174155759854952' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/4102174155759854952'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/4102174155759854952'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2008/08/gnomefirefox-tip-pandora-as-separate.html' title='Gnome/Firefox tip: Pandora as a Separate Application'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-7685395141720679481</id><published>2008-06-27T16:20:00.001-07:00</published><updated>2009-01-13T22:41:17.103-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='art'/><category scheme='http://www.blogger.com/atom/ns#' term='rpg'/><category scheme='http://www.blogger.com/atom/ns#' term='srd'/><category scheme='http://www.blogger.com/atom/ns#' term='gaming'/><category scheme='http://www.blogger.com/atom/ns#' term='d20'/><category scheme='http://www.blogger.com/atom/ns#' term='goonmill'/><title type='text'>Goonmill - seeking art</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;I am moving into the final phase before a first release of Goonmill.  I am seeking art for &lt;i&gt;any&lt;/i&gt; of the monsters found in the &lt;a href='http://www.d20srd.org/indexes/monsters.htm'&gt;D&amp;amp;D 3.5e SRD&lt;/a&gt;.&lt;br/&gt;&lt;ul&gt;&lt;li&gt;The art must be CC-licensed, public domain, or otherwise free to distribute for any purpose.  If CC licensed, it may be of the 'attribution' or 'no derivatives' types, but it must not be 'non-commercial'.  Goonmill is arguably a commercial effort, even if it is open source.&lt;br/&gt;&lt;/li&gt;&lt;li&gt;The more uncommon the creature for which you found art, the better.  I think I can cover orcs, humans, goblins, human skeletons, human ghosts, and human zombies pretty easily.  Variations are welcome.&lt;br/&gt;&lt;/li&gt;&lt;li&gt;You may of course contribute your own art to the cause, as long as you are willing to license it compatibly.&lt;/li&gt;&lt;li&gt;Honestly, I'm not that picky about quality or style at this point.  I am looking for 2d art, not models, though.  Feel free to render your models to 2d art.&lt;/li&gt;&lt;li&gt;Prefer an isometric viewpoint, but not required.&lt;br/&gt;&lt;/li&gt;&lt;/ul&gt;I am collecting this art for use with the D&amp;amp;D 3.5 SRD monsters.  It will be released freely once collected.  Goonmill will use it as part of the application, but in addition the entire database of art and creature stats will be available for use in other applications or for any other purpose.  The "any other purpose" part is why the art must not be CC-NC licensed.&lt;br/&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-7685395141720679481?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/7685395141720679481/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=7685395141720679481' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/7685395141720679481'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/7685395141720679481'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2008/06/goonmill-seeking-art.html' title='Goonmill - seeking art'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-3379983427342256250</id><published>2008-06-23T07:29:00.001-07:00</published><updated>2009-01-13T22:41:31.046-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='obama'/><category scheme='http://www.blogger.com/atom/ns#' term='manhood'/><category scheme='http://www.blogger.com/atom/ns#' term='spam'/><category scheme='http://www.blogger.com/atom/ns#' term='politics'/><title type='text'>Spam subject lines: A positive sign?</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;Actual spam subject line received today:&lt;br /&gt;&lt;blockquote&gt;Obama grows great length through herbal supplements&lt;/blockquote&gt;&lt;br /&gt;I think it's fair to say that your candidate is viewed in a positive light when he is used as a symbol of male virility.  I never got any "Kerry's dong will please your woman all night long", for example.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-3379983427342256250?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/3379983427342256250/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=3379983427342256250' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/3379983427342256250'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/3379983427342256250'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2008/06/spam-subject-lines-positive-sign.html' title='Spam subject lines: A positive sign?'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-7294733916495426835</id><published>2008-06-12T09:01:00.001-07:00</published><updated>2009-01-13T22:42:18.854-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='hiring'/><category scheme='http://www.blogger.com/atom/ns#' term='portland'/><category scheme='http://www.blogger.com/atom/ns#' term='employment'/><category scheme='http://www.blogger.com/atom/ns#' term='decipher'/><category scheme='http://www.blogger.com/atom/ns#' term='web developers'/><title type='text'>Decipher is Hiring</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;Dear lazyweb,&lt;br/&gt;&lt;br/&gt;If you want a job in R&amp;amp;D, and you have strong skills on all of the following, send your resume to the owner of this blog.  (If you have any trouble finding the email address, it's on my resume, which you can find on Google.)&lt;br/&gt;&lt;br/&gt;&lt;big&gt;Skills&lt;/big&gt;&lt;br/&gt;&lt;ul&gt;&lt;li&gt;Javascript&lt;/li&gt;&lt;li&gt;CSS&lt;/li&gt;&lt;li&gt;Linux development&lt;br/&gt;&lt;/li&gt;&lt;li&gt;Python&lt;br/&gt;&lt;/li&gt;&lt;/ul&gt;When I say strong, I mean, you really have recent experience building web apps with those skills, in combination.  We're in Fresno, and preference will be given to people who can work locally, but all resumes will be read.&lt;br/&gt;&lt;br/&gt;We are &lt;a href='http://www.decipherinc.com/'&gt;Decipher, Inc.&lt;/a&gt;&lt;br/&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-7294733916495426835?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/7294733916495426835/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=7294733916495426835' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/7294733916495426835'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/7294733916495426835'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2008/06/decipher-is-hiring.html' title='Decipher is Hiring'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-6300374444036743031</id><published>2008-06-05T17:09:00.001-07:00</published><updated>2009-01-13T22:42:37.132-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='fundable'/><category scheme='http://www.blogger.com/atom/ns#' term='money'/><category scheme='http://www.blogger.com/atom/ns#' term='family'/><category scheme='http://www.blogger.com/atom/ns#' term='greenpeace'/><category scheme='http://www.blogger.com/atom/ns#' term='fundraising'/><title type='text'>Greenpeace and Broadening Horizons</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;My stepson, Steven, is attempting to raise money for a semester learning from and about Greenpeace through their GOT program.  While I don't agree with everything GP does politically, I do support him learning and broadening his horizons and, well, I am a Green party member so I support things that contain green in the name, or things that are green, or things that encourage greenness.  Also, I like whales.  :-)&lt;br /&gt;&lt;br /&gt;Anyway, it's a serious program, and he's putting together &lt;a href='http://www.sendsteven.com/'&gt;a serious&lt;/a&gt; &lt;a href='http://sendsteven.blogspot.com/'&gt;web presence&lt;/a&gt; to raise the money to go.  He's also trying out &lt;a href='http://fundable.com/'&gt;Fundable&lt;/a&gt; on my suggestion, and I'd really like to see that succeed, because there's a few places I think Fundable could make a huge difference in this new, honor-system based economy we seem to be sailing into.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-6300374444036743031?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/6300374444036743031/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=6300374444036743031' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/6300374444036743031'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/6300374444036743031'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2008/06/greenpeace-and-broadening-horizons.html' title='Greenpeace and Broadening Horizons'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-3792944785455027172</id><published>2008-05-22T09:43:00.000-07:00</published><updated>2009-01-13T22:42:52.472-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='games'/><category scheme='http://www.blogger.com/atom/ns#' term='crpg'/><category scheme='http://www.blogger.com/atom/ns#' term='rpg'/><category scheme='http://www.blogger.com/atom/ns#' term='penny arcade'/><category scheme='http://www.blogger.com/atom/ns#' term='review'/><title type='text'>Review: Rain-Slick Precipice of Darkness Episode 1</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;Completed the game.  The first time through, it represented about 10 hours of gameplay for me, perhaps 6-7 for someone who actually plays video games often.  &lt;br /&gt;&lt;br /&gt;On a value-for-money basis, this is really good, especially when you include the enormous amount of value Penny Arcade has provided over the years; I bought this game without even downloading the trailer first, just because PA has earned that money either way.  Then, after I completed my &lt;i&gt;second&lt;/i&gt; playthrough, I realized that the value was pretty damn good.  I may play it again; I will at least go back to my savegame and try to find all the hidden concept art.  The game stands on its own merits, and I would have enjoyed playing it even if I didn't know much about Penny Arcade.  It's a lot of fun.&lt;br /&gt;&lt;h3&gt;Criticism&lt;/h3&gt;&lt;br /&gt;I have some criticisms, which I'll start with, but spoiler alert: they're all nitpicks.  I'll try not to include any actual game spoilers here.&lt;br /&gt;&lt;br /&gt;1) camera is somewhat frustrating at times.  I always had the sense that there was some cool stuff offscreen that I could get to if only I could see it.  It isn't that big a deal though; very rarely did I have any trouble seeing or navigating to the things the game needed me to see and navigate to.&lt;br /&gt;2) pathfinding AI was basically nonexistent.  You really only see this when you are trying to smash something to grab the combat bonus item inside, which you do by clicking on it so the player runs there.  My guy couldn't figure out how to get there if there was something more complicated than a lamppost in the way, and not even that if the lamppost was right next to him.  Oh well, it amounted to only a few extra clicks.  I never got stuck anywhere, either.&lt;br /&gt;3) It was a bit hard to navigate in some places, though.  This was particularly noticeable inside Anne-Claire's room, where, to reach her, you must either smash a box or find just the right detritus-free spot on the floor to click on.&lt;br /&gt;4) I wish it was longer.  I just wanted to play it more.  I would have paid double for a game 50% longer, and still felt it was a good deal.  Fortunately, it comes in episodes!  I &lt;i&gt;cannot wait&lt;/i&gt; for the next episode, and I will purchase it sight unseen again.  Based on plot points, I think there will be 4 episodes in total.&lt;br /&gt;&lt;h3&gt;Combat&lt;/h3&gt;&lt;br /&gt;Combat is challenging and fun, requiring skill and strategy simultaneously.  I'm not going to go into the details of the mechanics since there are plenty of reviews covering those.  Timing is important, but not always critical; you can get by most of the way without catlike reflexes.  There are lots of options at any point, and it definitely makes a difference which options you use in a given situation.  For example, in many places, if you choose the wrong character to attack a particular enemy, the combat will be much more dangerous and take much longer.  This is because creatures have particular resistances to certain kinds of attacks.  In some combats, for example, Gabe will shine, while in others he will be useless as an attacker, so you use his turn to activate healing and items instead.  The same also applies to which items you choose to use; some monsters have abilities that essentially nullify a particular item; but choose a different one and you can vanquish them quickly.  So, to win the game, you have to explore all the combat options.&lt;br /&gt;&lt;br /&gt;You also have to master the art of managing three characters at once, because if you waste time trying to decide what to do, the enemies will eliminate your opportunity to do it.  This isn't too hard after the first level's worth of battles, though.  The only thing really requiring fine reflexes was the 'block' maneuver, performed by hitting the space bar at exactly the right time in an attack sequence.  The time segment you have to block is different for every enemy attack, and most enemies have more than one, so you really have to watch the animations and practice.  You'll be an expert at this by the time you get to the last quarter of the game or so.  (The final boss would be really hard if you hadn't mastered the blocking skill by that point.)&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Exploration&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;The comparisons to ScummVM games are fairly accurate; the adventure portions of the game really feel like Day of the Tentacle, although not nearly as intricate.  The puzzles are my favorite kind: the kind that aren't really that difficult to solve.  I've always loved adventure games, but I've always been terrible at solving puzzles.  I've lately realized why I love them: adventure games reward you for exploring, and I love games in which exploration is a big factor.  I like poking around in all the odd corners of a game, and clicking on everything I see to find the hidden jokes and secrets.  Besides the hidden "concept art" which supposedly unlocks a bonus comic, there are also items in the game which can give you combat bonuses but aren't necessary to complete the game, and even some hidden combats.  At the risk of spoiling, I'll just say: if you get to the endgame with only T. Kemper and Anne-Claire as supplemental characters, you've missed something cool.  :-)&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Game Technology and Greenhouse&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;The game is out for 4 platforms simultaneously: PC, Mac, Linux, and Xbox.  This is pretty cool; nobody releases major games for Linux, never mind for all of those platforms at once.  As a software developer I appreciate the enormous difficulty they faced in accomplishing that; they obviously had to make some smart technology choices to succeed.  I ran into technical problems using the Linux version (pulseaudio sound was flaky); I eventually worked around them (shut down all music players, and run with "aoss" instead).  When I first encountered this problem, though, I just wanted to &lt;i&gt;play&lt;/i&gt;.  The multiplatform release came in handy here, and really demonstrated what I think will become the &lt;a href='http://www.playgreenhouse.com/about'&gt;Greenhouse ethos&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I'm using a Macbook Pro, and I have Leopard on this machine as well as Ubuntu Hardy.  So, I just downloaded another copy of the game, this time the Mac .dmg file.  I already had my license key for the Linux version.  After installing it on Leopard, I entered my Linux key, which Just Worked, and started the game up, and was playing immediately.  Greenhouse let me download multiple copies of the game for free and use my key in all of them with no hassles whatsoever.  Couple that with the simplicity of the initial purchase: You enter your credit card number, your license key displays in your browser immediately (and is emailed to you immediately), and the game starts downloading immediately.  They accomplished that (apparently) most difficult of feats for online software retailers: they made the game easier to buy than to pirate.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Humor and Characters&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;It's a &lt;i&gt;Penny Arcade game&lt;/i&gt;, so it really wouldn't be fair to review the game without talking about the humor in it.  You can't talk about humor without killing it though, so I'll keep this section short.  Here's the bottom line: if you like Penny Arcade, the game will be really funny.  During the run-up to the game, the guys put up a massive .wav file to test the playgreenhouse.com bandwidth, asking everyone to download it--smart QA strategy.  What was even smarter, though, was that the file was, in the style of their podcast, Gabe and Tycho talking about the making of the game.  One of the topics they discuss was that Tycho had to write descriptive text for every damn thing you can click on, even the crabs littering the boardwalk.  Well, the time was well-spent.  Click on everything you see; you'll be laughing a lot.&lt;br /&gt;&lt;br /&gt;The characters have great interactions with each other, and the dialog adds to the game, it doesn't detract.  It makes a difference when game dialog is written by someone who writes for a living &lt;i&gt;every day&lt;/i&gt;.  Jerry Holkins' wit shines through in every conversation tree.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Conclusion&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;4/5 asterisks: ****_&lt;br /&gt;&lt;br /&gt;As one forum denizen on Giant in the Playground said, "You can hit evil hobos with a rake so hard they literally explode.  What could not be awesome about that?"&lt;br /&gt;&lt;br /&gt;(Tycho just posted on the p-a site, saying "Thank you for letting me be your dungeon master."  God I'm jealous.)&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-3792944785455027172?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/3792944785455027172/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=3792944785455027172' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/3792944785455027172'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/3792944785455027172'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2008/05/review-rain-slick-precipice-of-darkness.html' title='Review: Rain-Slick Precipice of Darkness Episode 1'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-5717070291372136008</id><published>2008-03-28T07:55:00.000-07:00</published><updated>2009-01-13T22:43:01.045-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='humor'/><title type='text'>40,000 Coat Hangers</title><content type='html'>The court system put to its highest purpose.  That is to say: hilarious entertainment.&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;Judge: Tell me, Mr Chrysler, do these businessmen of yours also have Gideon Bibles by their bedside at home?&lt;/p&gt;  &lt;p&gt;Chrysler: Many of them, sir.&lt;/p&gt;  &lt;p&gt;Judge: And where do you get the Gideon Bibles from?&lt;/p&gt;  &lt;p&gt;Chrysler: Alas, they, too, have to be taken from hotels.&lt;/p&gt;  &lt;p&gt;Judge: Then why are you not also up on a charge of Bible-stealing?&lt;/p&gt;  &lt;p&gt;Chrysler: Because the Bibles do not belong to the hotels. They belong to the Gideon Society. And the Gideon Society has decided not to prosecute me, but to forgive me and tell me to go and sin no more.&lt;/p&gt;  &lt;p&gt;Judge: And have you sinned no more?&lt;/p&gt;  &lt;p&gt;Chrysler: Alas, no.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;/p&gt;This really is &lt;a href="http://www.srcf.ucam.org/%7Evy203/archives/2005/04/19/the-most-entertaining-trial-ever/"&gt;stellar stuff&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-5717070291372136008?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/5717070291372136008/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=5717070291372136008' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/5717070291372136008'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/5717070291372136008'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2008/03/40000-coat-hangers.html' title='40,000 Coat Hangers'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-8272793898900879935</id><published>2008-03-23T12:15:00.000-07:00</published><updated>2009-01-13T22:34:43.851-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='firefox'/><category scheme='http://www.blogger.com/atom/ns#' term='firefox3'/><category scheme='http://www.blogger.com/atom/ns#' term='web'/><category scheme='http://www.blogger.com/atom/ns#' term='bookmarks'/><title type='text'>My second-favorite FF3 feature</title><content type='html'>Now that &lt;a href="http://www.getfirebug.com/"&gt;most&lt;/a&gt; of &lt;a href="http://lifehacker.com/software/exclusive-lifehacker-download/better-gmail-2-firefox-extension-for-new-gmail-320618.php"&gt;my&lt;/a&gt; &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/26"&gt;extensions&lt;/a&gt; (with &lt;a href="http://karmatics.com/aardvark/"&gt;notable&lt;/a&gt; &lt;a href="http://firegpg.tuxfamily.org/?page=install&amp;amp;lang=en"&gt;exceptions&lt;/a&gt;) support FF3 without hax, I'm going to start using it fulltime.   My second-favorite* new feature: you can finally drag items in the Bookmarks menu.  Yes, Firefox bookmarks have finally (nearly) caught up to IE5 boomarks in usability.&lt;br /&gt;&lt;br /&gt;It's the little things that matter.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:78%;"&gt;* My favorite, of course, is the greatly expanded SVG support, so I can continue work on &lt;a href="http://goonmill.org/vellum/"&gt;Glass Vellum&lt;/a&gt;.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-8272793898900879935?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/8272793898900879935/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=8272793898900879935' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/8272793898900879935'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/8272793898900879935'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2008/03/my-second-favorite-ff3-feature.html' title='My second-favorite FF3 feature'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-818045705241800764</id><published>2008-03-22T09:03:00.000-07:00</published><updated>2009-01-13T22:34:23.989-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='video'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='blogdoc'/><category scheme='http://www.blogger.com/atom/ns#' term='ipod'/><title type='text'>iPod video for Linux</title><content type='html'>Google will tell you that you can convert video to iPod format in Linux using only VLC.  When lots of people tell you something on the Internet, and post howtos, this is often a good sign that lots of people on the Internet are idiots.  This is one of those times.  None of the howtos worked; I was getting either a corrupt file or no audio.  I am clearly not the only one, because every single howto I found that explained how to use VLC to transcode video, and there are quite a few, ALSO had commenters saying "um, the audio doesn't work".&lt;br /&gt;&lt;br /&gt;I finally discovered a solution, though, so it's sharing time.  Note that this is probably unnecessary if you just want to watch video podcasts, because gpodder works fine for that.  For non-podcast video, you almost always need to do a conversion.&lt;br /&gt;&lt;br /&gt;(Using Ubuntu, version &lt;strike&gt;Hammurabi&lt;/strike&gt;Hardy Heron.)&lt;br /&gt;&lt;br /&gt;For this meal, you will need these ingredients (aptitude install ..):&lt;br /&gt;&lt;code&gt;&lt;br /&gt;avidemux&lt;br /&gt;avidemux-cli&lt;br /&gt;vlc&lt;br /&gt;faad&lt;br /&gt;faac&lt;br /&gt;(every gstreamer plugins package you can find in main or in universe / multiverse)&lt;br /&gt;gtkpod-aac&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;The avidemux-cli package is optional; handy if you want to convert a whole directory full of files.  Note that you are going to install vlc, because it is one of the few players that will reliably play back these files.  You want it so you can test your output files before installing them on your ipod, but it may be considered optional.&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Open up the avidemux GUI, and open the file you want to convert.&lt;/li&gt;&lt;li&gt;Select menu item Auto &gt; IPOD&lt;/li&gt;&lt;li&gt;Confirm that video is being encoded with XVID4.  Optionally change the video bitrate to 1024 through the Configure button.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Audio encoding will still show "Copy".  Change it to "AAC".  Confirm through the configure button that the bitrate is 128.&lt;/li&gt;&lt;li&gt;Confirm that Format is MP4.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Save.  Encoding will begin.&lt;/li&gt;&lt;/ol&gt;&lt;span style="font-style: italic;"&gt;Optional: Batch Conversion.  &lt;/span&gt;When done, you may save this as a script with "File &gt; Save Project As ..." which allows you to do this from the command line.  However, I have already done the work for you.  To run it from the command line, get the shell script and .js file from &lt;a href="http://wiki.goonmill.org/AvidemuxScript"&gt;http://wiki.goonmill.org/AvidemuxScript&lt;/a&gt;.  If you save the shell script as "mp4", you can run it in a directory of AVI files, as&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    mp4 *.avi&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Test the converted file in VLC, making sure video isn't crappy and audio exists.&lt;br /&gt;&lt;br /&gt;Now copy it to the iPod.  You need gtkpod-aac installed for this, or you will get errors saying "compile gtkpod together with yadda yadda".  The package gtkpod-aac contains a binary that is already so compiled.  You can simply plug in the iPod, choose your model from the supported list in gtkpod, find the iPod in the tree at the left, pick "video inbox", and Add File there to add your file.  Save to copy to the ipod, and Eject the ipod.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-818045705241800764?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/818045705241800764/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=818045705241800764' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/818045705241800764'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/818045705241800764'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2008/03/ipod-video-for-linux.html' title='iPod video for Linux'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-5786130465156279268</id><published>2008-01-19T08:17:00.000-08:00</published><updated>2009-01-13T22:44:16.943-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='opinion'/><category scheme='http://www.blogger.com/atom/ns#' term='os'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='os x'/><category scheme='http://www.blogger.com/atom/ns#' term='mac'/><title type='text'>Gibbon takes Leopard</title><content type='html'>My lovefest for OS X is over.  I'm switching back to Linux.  It isn't a total loss, but it is a complete burnout for a software developer like me.  Some things I liked, some things I hated. . .&lt;br /&gt;&lt;br /&gt;What's OK:&lt;br /&gt;&lt;br /&gt;- Printing is pretty cool.  I really liked that printers were so easy to install.  OTOH, Ubuntu's printing stuff is almost as good; the only thing missing might be the icon that shows you what your currently-in-use printer actually looks like.  Printers seem to be self-healing in OS X as well, which means that they keep working even when they change IP addresses (something that happens with my printer at home).&lt;br /&gt;&lt;br /&gt;- FileVault.  Encryption is done well up to a point.  They succeeded in making it usable for the masses.  Then they halfway-blow it!  The screen saver and restart-from-suspend/hibernate do NOT require a password by default.  So if you do what most people do and just shut the laptop when you're done using it, all that encryption is useless because your filesystem is always sitting around in plain text.  FileVault should require you to password-protect those ways in.&lt;br /&gt;&lt;br /&gt;- OmniGraffle.  If they made a Linux version, I'd pay for it, and this is coming from someone who actually likes Inkscape already.&lt;br /&gt;&lt;br /&gt;- iTunes + iPod is pretty damn awesome.  Banshee is quite competitive, but to get the same package that OS X has on Ubuntu you need Banshee &lt;span style="font-style:italic;"&gt;and&lt;/span&gt; gpodder.  I like both of them, but they're not integrated, they don't work well with m4a feeds, so this is a clear Mac win, and no surprise.&lt;br /&gt;&lt;br /&gt;- VMWare fusion.  I love Unity mode for Windows.  I don't really use it enough to keep it around, though.  VirtualBox is a more-than-adequate replacement.  It lacks snapshots but makes up in overall speed.&lt;br /&gt;&lt;br /&gt;- Overall attractiveness.  Yep, it's pretty.  Ubuntu is about 90% of the way there.&lt;br /&gt;&lt;br /&gt;- Um... the hardware?  I really like the hardware.  I just would rather have something else installed on it.  OS X certainly comes with all the necessary MBP drivers, and all that hardware Just Works, so that's good.  But it's not as if somebody couldn't do the same with a MBP-targetted Ubuntu distribution.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;What's broken:&lt;br /&gt;&lt;br /&gt;- Terminal.  The tabs are horrible.. they won't display icons, they won't display the label of the terminal settings, they don't even obey the settings of Terminal.app itself.  The terminal emulation is frequently broken.  Readline is frequently broken.  ANSI colors are broken.  Terminal, you suck.   By all accounts, the alternatives are worse.&lt;br /&gt;&lt;br /&gt;- Python.  For FUCK's sake Apple, this is an embarrassment.  Either get it right or stop putting it on there by default.  Why do I have to install MacPorts Python every time to work around missing extensions like _bsddb?  Why do I get bus errors running simple things that work in Linux?&lt;br /&gt;&lt;br /&gt;- Instant Messaging.  Adium is the only decent multi-protocol option, and it doesn't support IRC and hides important options.  Adium actually is pretty damn close, but it's not all the way there.  XChat on the Mac is pretty crappy, and the other IRC alternatives were slow and worse.&lt;br /&gt;&lt;br /&gt;- Graphics software.  I refuse to pay for and use Photoshop.   Aperture is shipped on Leopard as crippleware, I say no to that guerilla tactic as well.   Gimp is a terrific piece of software, but it's unusable on a Mac.  Yes, you can run it in X11, and if you tried to, you would know what I mean by "unusable".&lt;br /&gt;&lt;br /&gt;- OpenOffice.  See previous post.  Oh my GOD this is terrible.  I refuse to pay for and use standards-raping MS Office, which is NOT an improvement over OpenOffice in functionality or performance anyway, even in the best of cases (running on Windows XP, for example).  OO.org works beautifully on Linux and on Windows; on OS X it vomits.&lt;br /&gt;&lt;br /&gt;- Media playback and use.   Linux just wins here.   Apple has nothing to offer over, say, VLC, which is why I installed VLC on the Mac.  It actually runs a treat there, BTW.   Apple's software respects region coding and all that other DRM and related rights-restriction bullshit, and I refuse to play that game.  VLC is able to redeem Apple here--I think.  It remains to be seen whether I can do something fair-use-y like rip my DVDs to the hard drive and play them with VLC, or use VLC to play out-of-region DVDs, but I'm beyond the point of wanting to give OS X a fair shake on this one.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;What changes to the OS X ecosystem would be required to win me back?&lt;br /&gt;&lt;br /&gt;- Fix OpenOffice.org.&lt;br /&gt;&lt;br /&gt;- Fix Python.  This is an absolute dealbreaker for me.&lt;br /&gt;&lt;br /&gt;I can put up with the rest of the problems, but those two are insufferable.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-5786130465156279268?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/5786130465156279268/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=5786130465156279268' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/5786130465156279268'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/5786130465156279268'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2008/01/gibbon-takes-leopard.html' title='Gibbon takes Leopard'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-3516026101459413936</id><published>2008-01-18T21:34:00.000-08:00</published><updated>2009-01-13T22:43:59.392-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='opinion'/><category scheme='http://www.blogger.com/atom/ns#' term='productivity'/><category scheme='http://www.blogger.com/atom/ns#' term='os x'/><category scheme='http://www.blogger.com/atom/ns#' term='openoffice.org'/><category scheme='http://www.blogger.com/atom/ns#' term='mac'/><title type='text'>OpenOffice.org on the Mac is shit</title><content type='html'>&lt;ol&gt;&lt;li&gt;OpenOffice.org X11 version:&lt;/li&gt;&lt;ol&gt;&lt;li&gt;Requires X11&lt;/li&gt;&lt;li&gt;Actually launches an xterm with a shell session when it runs&lt;/li&gt;&lt;li&gt;Makes you wait a minute before doing anything, then displays a useless "Command timed out" error message&lt;/li&gt;&lt;li&gt;Then runs some Java stuff before finally starting up&lt;/li&gt;&lt;li&gt;Doesn't take X11 with it when you shut it down&lt;/li&gt;&lt;li&gt;Draws menus as window decorations instead of at the top of the Desktop where it belongs in OS X (well, that's an X11 app for you)&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;li&gt;NeoOffice:&lt;/li&gt;&lt;ol&gt;&lt;li&gt;Utterly broken in Spaces.  Won't let you assign it to a particular Space, it just launches wherever you are.  Then, sometimes it won't even let you switch away from it, following you around like one of those web popups that just reopens every time it closes.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Doesn't adopt OS X keyboard shortcuts (e.g. Alt+Backspace doesn't erase a word)&lt;/li&gt;&lt;li&gt;Useless Aqua menu: just the NeoOffice menu item itself, not even so much as a "New &gt; Spreadsheet" menu.&lt;/li&gt;&lt;/ol&gt;&lt;li&gt;OpenOffice.org Aqua version:&lt;/li&gt;&lt;ol&gt;&lt;li&gt;All the icons are upside-down and pink&lt;/li&gt;&lt;li&gt;The clipboard doesn't work, even though the last update said the clipboard was finally fixed&lt;/li&gt;&lt;li&gt;By the way, the last update was July 2007.&lt;/li&gt;&lt;/ol&gt;&lt;/ol&gt;Then, just to kick you in the teeth a little, all three of these use different directory structures under ~/Library for storing your settings, so if you're persistent enough, like me, to try all three for due diligence, you have to reinstall your settings each time.&lt;br /&gt;&lt;br /&gt;And all three are slow.&lt;br /&gt;&lt;br /&gt;I don't get it.  OO.org is AWESOME on Windows.  It blazes in Ubuntu.  Why, despite THREE attempts, is it a steaming pile of shit on a Mac?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-3516026101459413936?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/3516026101459413936/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=3516026101459413936' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/3516026101459413936'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/3516026101459413936'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2008/01/openofficeorg-on-mac-is-shit.html' title='OpenOffice.org on the Mac is shit'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-4666747760911841252</id><published>2008-01-06T15:23:00.000-08:00</published><updated>2009-01-13T22:50:43.764-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='obama'/><category scheme='http://www.blogger.com/atom/ns#' term='politics'/><title type='text'>My one and only political post</title><content type='html'>This is my "techie" blog, so I'm not going to spend a lot of time doing politics on here.  In fact, I'm only doing one, this one, and I'm only doing it because I want to use this space to advertise my voter registration button.  There it is, over to the left, go ahead and click it if you aren't registered, or if you've moved, or if you are currently registered as the wrong party.&lt;br /&gt;&lt;br /&gt;I've been a registered Green for years, but I'm switching my affiliation to the Decline to State party for this election season.  In California I'm required to either vote in the primary of my party affiliation, or if I have Declined to State, I may vote in any.  I intend to remain a Green after this election, but I want to vote for Barack Obama.&lt;br /&gt;&lt;br /&gt;The button is there for you guys.  If you read this blog and don't consider yourself well-enough educated to get involved in politics, you might think you aren't up to the responsibility of voting.  I think this is one of the biggest reasons people don't vote in this country; they are aware that it is an important responsibility, and they don't want to screw it up.  (Witness Stephen Colbert's election coverage series, titled "Don't Fuck This Up, America".)&lt;br /&gt;&lt;br /&gt;An informed electorate is important to democracy.  However, I put it to you that, if you do register right now, you are far more likely to get informed.  No matter how ignorant of the issues you are right now, if you take the 2 minutes to get registered, I know you will be more informed in a month, and even better informed still in November.  You won't be able to help yourself.  You'll start conversations with people about how you just registered, and they'll start talking to you about issues.  Thus, the act of registration &lt;span style="font-style: italic;"&gt;itself&lt;/span&gt; catalyzes a better quality of democracy.&lt;br /&gt;&lt;br /&gt;Almost half of the primary elections are being held on Tuesday, Feb. 5, 2008, including California's primary.   If you aren't sure, check this &lt;a href="http://archive.stateline.org/flash-data/Primary/2008_presidential_primaries.pdf"&gt;PDF calendar&lt;/a&gt;.  Register, vote.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-4666747760911841252?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/4666747760911841252/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=4666747760911841252' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/4666747760911841252'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/4666747760911841252'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2008/01/my-one-and-only-political-post.html' title='My one and only political post'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-7961867968272698775</id><published>2007-11-01T11:42:00.000-07:00</published><updated>2007-11-01T11:47:50.368-07:00</updated><title type='text'>Limerick Minute</title><content type='html'>&lt;span style="font-weight: bold;"&gt;I once knew a man who said, "Though&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;It seems that I know that I know,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;  What I would like to see&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;  Is the eye that sees me,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;When I know that I know that I know."&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;- Unknown&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-7961867968272698775?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/7961867968272698775/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=7961867968272698775' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/7961867968272698775'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/7961867968272698775'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2007/11/limerick-minute.html' title='Limerick Minute'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-6710468573553931590</id><published>2007-10-15T22:18:00.001-07:00</published><updated>2008-03-08T19:24:29.112-08:00</updated><title type='text'>What is Goonmill?</title><content type='html'>I have written up a definition of Goonmill, so that application actually has a scope and we know when it's done.  See the &lt;a href="http://wiki.goonmill.org/DefiningGoonmill"&gt;DefiningGoonmill&lt;/a&gt; page in the wiki.&lt;br /&gt;&lt;br /&gt;It breaks the application into the user tasks you should be able to perform with a completed Goonmill.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-6710468573553931590?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/6710468573553931590/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=6710468573553931590' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/6710468573553931590'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/6710468573553931590'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2007/10/what-is-goonmill.html' title='What is Goonmill?'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-4675871761117475996</id><published>2007-10-14T12:08:00.000-07:00</published><updated>2007-11-14T21:36:27.184-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='vim'/><category scheme='http://www.blogger.com/atom/ns#' term='blogdoc'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='buffer'/><title type='text'>Vim: Run the current buffer as Python code</title><content type='html'>This uses the handy preview window feature of Vim.  Flagging a window as a preview window is useful because you can use pclose! to get rid of it, meaning you can reuse that vim real estate over and over for commands that produce output, and the output has to go somewhere.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;fu! DoRunPyBuffer2()&lt;br /&gt;pclose!  " force preview window closed&lt;br /&gt;setlocal ft=python&lt;br /&gt;&lt;br /&gt;" copy the buffer into a new window, then run that buffer through python&lt;br /&gt;sil %y a | below new | sil put a | sil %!python -&lt;br /&gt;" indicate the output window as the current previewwindow&lt;br /&gt;setlocal previewwindow ro nomodifiable nomodified&lt;br /&gt;&lt;br /&gt;" back into the original window&lt;br /&gt;winc p&lt;br /&gt;endfu&lt;br /&gt;&lt;br /&gt;command! RunPyBuffer call DoRunPyBuffer2()&lt;br /&gt;map &amp;lt;Leader&amp;gt;p :RunPyBuffer&amp;lt;CR&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;Backslash&amp;gt;+p is mapped to run the current buffer through a Python interpreter.  The output appears in a new window below the current one.&lt;br /&gt;&lt;br /&gt;The code to do this with another interpreted language, such as bash, is almost identical and left as an exercise for the reader.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-4675871761117475996?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/4675871761117475996/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=4675871761117475996' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/4675871761117475996'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/4675871761117475996'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2007/10/vim-run-current-buffer-as-python-code.html' title='Vim: Run the current buffer as Python code'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-5886089657415125038</id><published>2007-10-13T21:52:00.000-07:00</published><updated>2007-10-14T12:18:32.925-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='video'/><category scheme='http://www.blogger.com/atom/ns#' term='swf'/><category scheme='http://www.blogger.com/atom/ns#' term='blogdoc'/><category scheme='http://www.blogger.com/atom/ns#' term='thumbnail'/><category scheme='http://www.blogger.com/atom/ns#' term='flash'/><category scheme='http://www.blogger.com/atom/ns#' term='avi'/><title type='text'>Thumbnails from SWF video</title><content type='html'>I don't know if this'll ever be useful to anyone, but it was information I needed, and it was extremely hard to come by.&lt;br /&gt;&lt;br /&gt;Here's how you extract a thumbnail from an video stored in an swf file.  I'll leave the &lt;span style="font-family:courier new;"&gt;apt-get install&lt;/span&gt; dependencies as an exercise to the reader.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;#!/bin/bash&lt;br /&gt;SWF="$1"&lt;br /&gt;AVI="${SWF/swf/avi}"&lt;br /&gt;JPG="${SWF/.swf/%d.jpg}"&lt;br /&gt;flasm -x "${SWF}"&lt;br /&gt;mencoder -endpos 5 "${SWF}" -o /dev/null -nosound -ovc xvid -xvidencopts pass=1:turbo&lt;br /&gt;&lt;br /&gt;mencoder -endpos 5 "${SWF}" -o "${AVI}" -nosound -ovc xvid -xvidencopts pass=2:bitrate=1600&lt;br /&gt;&lt;br /&gt;ffmpeg -i "${AVI}" -an -ss 00:00:03 -t 00:00:01 -r 1 -y -s 120x90  "${JPG}"&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;BTW, this also converts the SWF to an AVI along the way, so if that's useful to you, great.  (Modify the endpos and get rid of -nosound if you really wanted the AVI.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-5886089657415125038?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/5886089657415125038/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=5886089657415125038' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/5886089657415125038'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/5886089657415125038'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2007/10/thumbnails-from-swf-video.html' title='Thumbnails from SWF video'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-7706832824101728097</id><published>2007-09-07T14:37:00.000-07:00</published><updated>2007-09-07T15:32:02.353-07:00</updated><title type='text'>Substitute Reading List</title><content type='html'>It's been a bit in vogue lately for people to post their reading lists.  I feel sad when I read them, because I don't have time to read any more, and I've always been a voracious and addictive reader until recently.  So what does a person do when they can't read any more?  They substitute something else.  Sometimes what's been substituted gives you a new dimension to appreciate, and you end up feeling as satisfied.&lt;br /&gt;&lt;br /&gt;Recently I have discovered the joys of podcast audio fiction, and I actually look forward to my drive to and from work every day, thanks to these.  Here is my substitute reading list for the last couple of months:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://escapepod.org/"&gt;Escape Pod&lt;/a&gt; - Every week, an amazing Science Fiction story via podcast.  The quality of the stories ranges from the good to the utterly unforgettable, and it is always worth listening.  I've listened to every single full and flash-fic episode, even going back through the archive to story #1.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://pseudopod.org/"&gt;Pseudopod&lt;/a&gt; - I am a huge horror buff thanks to my Dad's lifelong love of the stuff.  Pseudopod is a spinoff of Escape Pod, so expect the same with a horror twist.  The quality of stuff on Pseudopod is, if anything, of higher quality than Escape Pod, but maybe that's just my preference bias.    I've never missed an episode of this show.&lt;br /&gt;&lt;br /&gt;(BTW, I'm eagerly looking forward to &lt;a href="http://podcastle.org"&gt;Podcastle&lt;/a&gt;, another spinoff.  You can probably guess the theme without clicking on the link. :-)&lt;br /&gt;&lt;br /&gt;&lt;span class="down" style="display: block;" id="formatbar_CreateLink" title="Link" onmouseover="ButtonHoverOn(this);" onmouseout="ButtonHoverOff(this);" onmouseup="" onmousedown="CheckFormatting(event);FormatbarButton('richeditorframe', this, 8);ButtonMouseDown(this);"&gt;&lt;/span&gt;&lt;a href="http://podiobooks.com/title/eastern-standard-tribe"&gt;Eastern Standard Tribe&lt;/a&gt; podcast novel - I am a big fan of Cory Doctorow, and not merely because we have the same first name and last initial, spelled the same way.  I haven't finished this podcast yet, but I'm hooked already.  Be prepared to listen fast; Cory doesn't slow down, so you get a lot of story in a little time.  :-)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://podiobooks.com/title/the-corridor/"&gt;The Corridor&lt;/a&gt; podcast novel - This one, I have finished.  It's a thrill a minute, the writing is excellent, and the horror fantasy aspects are simultaneously imaginative and self-consistent, which is difficult to achieve.  As if that weren't enough, Zan has one of my all-time favorite reading voices.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://podiobooks.com/title/the-pocket-and-the-pendant/"&gt;The Pocket and the Pendant&lt;/a&gt; podcast novel - This one is aimed at young adults and, while it is a bit less consistent than The Corridor, it is well-written, exciting to listen, and entertaining.  Mark Jeffrey is also an excellent voice.&lt;br /&gt;&lt;br /&gt;(Not podcast audio, but . . . : )&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.flightcomics.com/"&gt;Flight&lt;/a&gt;, Volumes 1 and 2  - Graphic novel/anthologies.  Absolutely stunning art, in dozens of rich and evocative styles.  Tiny bundles of story on page after page.  Volumes 3 and 4 are out as well, I will be buying them ASAP.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-7706832824101728097?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/7706832824101728097/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=7706832824101728097' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/7706832824101728097'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/7706832824101728097'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2007/09/substitute-reading-list.html' title='Substitute Reading List'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-2113758782850114530</id><published>2007-08-21T21:21:00.000-07:00</published><updated>2009-01-13T22:44:47.522-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mercurial'/><category scheme='http://www.blogger.com/atom/ns#' term='hg'/><category scheme='http://www.blogger.com/atom/ns#' term='goonmill'/><title type='text'>Goonmill repo from scratch</title><content type='html'>In case you hadn't guessed by my last &lt;a href="http://strongdynamic.blogspot.com/2007/08/expunging-problem-file-from-mercurial.html"&gt;Mercurial post&lt;/a&gt;, I screwed up my Goonmill repository.  It's now back, with all the history intact but the one file I shouldn't have committed now purged.&lt;br /&gt;&lt;br /&gt;If you have a checkout, please get another checkout, you won't be able to update your existing one.&lt;br /&gt;&lt;br /&gt;We apologize for the inconvenience.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-2113758782850114530?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/2113758782850114530/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=2113758782850114530' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/2113758782850114530'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/2113758782850114530'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2007/08/goonmill-repo-from-scratch.html' title='Goonmill repo from scratch'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-5210255571919845682</id><published>2007-08-21T12:57:00.001-07:00</published><updated>2008-03-08T19:26:25.334-08:00</updated><title type='text'>Announcing a Playtools Mailing List</title><content type='html'>I have created a list for Playtools users and developers. &lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://goonmill.org/cgi-bin/mailman/listinfo/playtools"&gt;List info&lt;/a&gt; page&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt; (is also visible from the project's &lt;a href="http://goonmill.org/playtools/"&gt;home page&lt;/a&gt;.)&lt;br /&gt;&lt;br /&gt;I also added some branding to the Launchpad pages for &lt;a href="http://launchpad.net/goonmill/"&gt;both&lt;/a&gt; &lt;a href="http://launchpad.net/playtools/"&gt;projects&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-5210255571919845682?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/5210255571919845682/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=5210255571919845682' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/5210255571919845682'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/5210255571919845682'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2007/08/announcing-playtools-mailing-list.html' title='Announcing a Playtools Mailing List'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-1010725641956174608</id><published>2007-08-19T10:17:00.000-07:00</published><updated>2007-08-19T11:03:10.683-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='blogdoc'/><title type='text'>Expunging a problem file from Mercurial repo</title><content type='html'>&lt;a href="http://www.selenic.com/mercurial/wiki/"&gt;Mercurial&lt;/a&gt; is almost the perfect version control system: fast, lean, distributed, easily extensible and reliable.  It works by copying an entire repository, compressed, every time a clone needs to be made.  This is much more efficient than it may sound, and the time it takes to transfer a Mercurial repo is quite comparable to the time it takes to checkout a Subversion repository.&lt;br /&gt;&lt;br /&gt;The only time the system breaks down is if you lose your head and commit a large compressed database to the repository.  Since I'm still learning how everything in Mercurial works, I did this accidentally, and made several commits before I realized my repo was ballooning out of control due to this one file with only 7 commits.&lt;br /&gt;&lt;br /&gt;Here's how you recover.&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Make sure you fix this before anyone clones your repository from upstream.  The following procedure renders your repository unusable to anyone working on their own clone of it; they will have to clone a copy of the results and start fresh.&lt;/li&gt;&lt;li&gt;Get a list of all the commits that changed your file.&lt;br /&gt;&lt;code&gt;$ hg log -M -r0:tip --template "{rev} {files}\n" goonmill/srd35.db.gz&lt;br /&gt;11 goonmill/srd35.db.gz&lt;br /&gt;52 goonmill/srd35.db.gz&lt;br /&gt;59 goonmill/srd35.db.gz&lt;br /&gt;99 goonmill/alter3.sql goonmill/srd35.db.gz&lt;br /&gt;115 goonmill/srd35.db.gz&lt;br /&gt;160 goonmill/srd35.db.gz srd35.odb&lt;br /&gt;189 goonmill/srd35.db.gz&lt;/code&gt;&lt;/li&gt;&lt;li&gt;Export the entire repository as patches; use &lt;span style="font-family:courier new;"&gt;hg export&lt;/span&gt; to extract each one to a separate file.&lt;br /&gt;&lt;code&gt;$ mkdir ../Goonmill-revs; hg export -g -o ../Goonmill-revs/%r:%n-of-%N $(hg log -M --template "{rev} ")&lt;/code&gt;&lt;br /&gt;(Hundreds of patch files created)&lt;/li&gt;&lt;li&gt;Delete the ones that you found in step 2.  The reason I had you print {files} in that step was so that you could check to see if any other files would be affected by the new hole in the history.  For example, my commit 99 above changes another file.  Instead of deleting that revision, I will edit the patch so only the patch to the sql script is committed.&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:courier new;"&gt;"hg init&lt;/span&gt;" a new repository and use "&lt;span style="font-family:courier new;"&gt;hg import Goonmill-revs/*&lt;/span&gt;" to recreate.&lt;/li&gt;&lt;/ol&gt;You now have a new repository with the same revision history as before, but with your one problem file not contained in the repo history.  Next time, commit that database &lt;span style="font-style: italic;"&gt;uncompressed&lt;/span&gt;, because Mercurial does efficient binary diffs that don't work very well on compressed files but work great on uncompressed structured binary files like a database.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-1010725641956174608?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/1010725641956174608/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=1010725641956174608' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/1010725641956174608'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/1010725641956174608'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2007/08/expunging-problem-file-from-mercurial.html' title='Expunging a problem file from Mercurial repo'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-7071689076474380878</id><published>2007-08-16T00:50:00.000-07:00</published><updated>2008-03-08T19:26:48.394-08:00</updated><title type='text'>Playtools is Born</title><content type='html'>Per jml's suggestions:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The bug tracker and a project page live &lt;a href="http://launchpad.net/playtools/"&gt;on Launchpad&lt;/a&gt;, and the source link is prominently featured there too.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;There's a dedicated &lt;a href="http://goonmill.org/playtools/"&gt;home page&lt;/a&gt; on the website for it.  Anyone want to contribute a logo? :-)&lt;/li&gt;&lt;li&gt;The new name is "Playtools".&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;I've installed mailman, but I need to configure Apache correctly for it at an hour when I'm not falling asleep in my seat.&lt;br /&gt;&lt;br /&gt;Oh by the way, I &lt;a href="http://launchpad.net/goonmill/"&gt;gave Goonmill the Launchpad treatment&lt;/a&gt; as well.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-7071689076474380878?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/7071689076474380878/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=7071689076474380878' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/7071689076474380878'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/7071689076474380878'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2007/08/playtools-is-born.html' title='Playtools is Born'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-4630486991391286907</id><published>2007-08-14T00:11:00.001-07:00</published><updated>2008-03-08T19:22:54.737-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='n3'/><category scheme='http://www.blogger.com/atom/ns#' term='roleplaying'/><category scheme='http://www.blogger.com/atom/ns#' term='goonmill'/><title type='text'>D&amp;D Datahead Community, III</title><content type='html'>(&lt;a href="http://strongdynamic.blogspot.com/2007/08/d-datahead-community.html"&gt;Jump back to Part I.&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;In a database of typed columns in tables, you must have a single schema, hosted at one location. Someone must be gatekeeper of what goes into it, and how it gets extended. To be able to use the data, applications written for it must trust the gatekeeper. If something goes into it, it becomes part of all applications written against it, and an app developer can't reject that data without making special cases in the application (blacklisting). Worse, if something useful doesn't go into it, your application can never make use of that thing. Your application loses the freedom of choice; neither the application itself nor its users can decide whether to trust some data and not other data.&lt;br /&gt;&lt;br /&gt;An application built on published documents of triples, however, can be written so that both the application and the users of the application can choose which data to trust, by choosing from the list of URLs that the application loads as its data.&lt;br /&gt;&lt;br /&gt;This goes right to the heart of the Paper and Pencil RPG world. This is a world of publish-or-perish; companies must produce lots of supplements to the rules of existing games, or fail to make money. Players, meanwhile, do not have the wherewithal to buy all supplements everywhere, so they pick and choose which rules to buy, and which ones ultimately to use in play. Not all publishers are equally popular, not all suplements are equally popular. Some gamers play extremely old versions of the rules; some even adapt supplements of the new rules to the old rules (the P&amp;P version of a backport). And, any GM worth anything has his own set of House Rules, which he writes down only for the benefit of the rules lawyer in his group. In short, the RPG world is information anarchy.&lt;br /&gt;&lt;br /&gt;In order for an open source software community to form in this environment, some of this chaos must be reigned in so that GMs can make use of the software in the crazy scenarios that actually exist at &lt;span style="font-style: italic;"&gt;every&lt;/span&gt; game table. And I do mean every one; I have yet to meet a D&amp;D player who took the stock PHB/DMG/MM and played strictly by those rules and only by those rules.&lt;br /&gt;&lt;h4&gt;Supplements at the Application Level&lt;/h4&gt;The solution lies in a format that lets anyone publish their own rules.  N3 is the basis, not for tables, but for &lt;span style="font-style: italic;"&gt;documents&lt;/span&gt;, and documents can be published by anyone. But, unlike the pages of the &lt;a href="http://d20srd.org/"&gt;SRD&lt;/a&gt;, these documents are unordered. This lack of order actually becomes an asset in this context! Think about XML. In order to modify an XML document, you must parse it, insert your concept, and then re-emit it. This makes you a publisher of the entire set of facts the document is describing. Therefore, anyone who wants to build on the original document but include your facts, must derive from your document, and so on.&lt;br /&gt;&lt;br /&gt;In the unordered N3 format, however, all new facts just go on the pile. They can appear anywhere, even on another webserver. They do not have to be accompanied by a schema. In short, they are an explicit genuflection to the information anarchy of P&amp;P game publishing. If you want to write an application about my dragon, and include the fact that dragons have a caster level of 15, you don't have to republish my entire dragon, just publish this document:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;@prefix cdd: &amp;lt;http://thesoftworld.com/2007/monsters#&amp;gt;&lt;br /&gt;cdd:youngAdultGoldDragon :casterLevel 15;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;There, now anyone who wants to use a gold dragon and include its caster level in the facts about it, needs only whitelist my document and your new one at the same time.  The facts might be new lists of monsters.  They might be new rules to apply to already-published monsters--even in a blanket fashion: you can publish a statement such as "anything which is a monster has 15 Time Points", and now they do.  They might even be cancellation of some other whitelisted rules if, for example, you like some parts of one publication but not other parts.  An app can load any of these documents the developer wants to load, even cache them so they don't have to be requested over the Internet, but include only the facts that the application developer wants to include.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Or better yet, the ones the User wants to include.&lt;/span&gt; Because now that we've established these documents should be published somewhere, an application can simply collect all the documents it knows about and present them to the user as a list; the &lt;span style="font-style: italic;"&gt;user&lt;/span&gt; can now pick and choose which rules his creatures obey and which ones his creature ignores.  The user can even type in a new URL, and the application will fetch that document and include its facts, even though it didn't know about it before.&lt;br /&gt;&lt;br /&gt;Communities can vote on these publications, so they get "most popular" and "highest rated" rankings and can compete with each other.  &lt;span style="font-style: italic;"&gt;Any&lt;/span&gt; member of the community can publish material, and instantly see how his new monster or new rules plays with any other member's stuff.&lt;br /&gt;&lt;h4&gt;Next Steps&lt;/h4&gt;The technology, and in particular the standard, are only half-finished here, but they have a real application that needs them, which is Goonmill.  Goonmill is &lt;a href="http://goonmill.org/goonmill/"&gt;far more than half-finished&lt;/a&gt;; in fact, I've already partaken of its delicious dogfood, and used the statblocks in my own &lt;a href="http://nestofcandles.blogspot.com/"&gt;campaign world&lt;/a&gt;.  So I'm really not far from being able to publish real standards.  But already there are some documents online that yearn to be pounded on by brutal application developers until they do something sensible.  I am hosting them in what should be their &lt;a href="http://goonmill.org/2007/"&gt;permanent home&lt;/a&gt;, so developers will be able to link directly to these concepts and make use of them in their own applications.&lt;br /&gt;&lt;br /&gt;1. For Goonmill to continue, I now get to undertake converting a SQL database made from the SRD, into a series of N3 documents representing the same concepts as triples.  For monsters, the vast majority of the work has been done in Goonmill itself.  Converting monsters is simply a matter of rendering all 650-ish of them to N3 instead of HTML, a labor which will eventually become &lt;span style="font-family:courier new;"&gt;monster.n3&lt;/span&gt; at the above URL.  Two of those files are in use by the application already, &lt;span style="font-family:courier new;"&gt;family.n3&lt;/span&gt; and &lt;span style="font-family:courier new;"&gt;specialAbility.n3&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;2. I'll then use the same process to convert all spells, skills, items and feats found in the SRD.  When done, this will be a set of the core OGC documents, converted into a form that applications can easily load and understand, even access over the Internet.   I cannot change the license they are published under, which is the &lt;a href="http://en.wikipedia.org/wiki/Open_Gaming_License"&gt;OGL&lt;/a&gt;, but the OGL is a license that grants freedoms, not unlike the GPL as applied to game content.&lt;br /&gt;&lt;br /&gt;3. An archive form of the document standard will have to be brainstormed and spec'd out.  This format should allow us to zip/bundle N3 with a more prose-focused format like XHTML, so we don't have to crowbar a human-readable description of a red dragon into N3.&lt;br /&gt;&lt;br /&gt;4. Tools will have to be written so game developers, who may not want to know what the inside of Vim looks like, can convert their content to the N3 format.  But it need not be the publishers themselves who do this; any content which is OGC or CC-sharealike licensed can be easily converted by &lt;span style="font-style: italic;"&gt;any&lt;/span&gt; fan of the material.  It doesn't even have to be an application developer, just someone with a website who can publish mime-type "text/rdf+n3".  It also must be noted that one reason I chose N3 as my format was so that a person can create these documents &lt;span style="font-style: italic;"&gt;without&lt;/span&gt; a fancy XML editor, and by learning only a modicum of syntax.  (I was, and am still, a fan of the "&lt;a href="http://yaml.org/"&gt;YAML&lt;/a&gt;" syntax, and N3 is simpler to learn than that.)&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Conclusions&lt;/h4&gt;When these initiatives get under way in earnest--and I am not waiting for anyone's help, this is a banner I will take up for my own sake if nobody else is ready to jump in yet--others can and will write applications against it, including the data and even the N3 markup itself entirely within their applications, or loading them from their canonical site directly.  We will start to see the beginnings of actual cooperation among game software developers, and maybe an increase in the number of game software developers.&lt;br /&gt;&lt;br /&gt;As important, though, is that game developers take the opportunity to publish their game materials using a new standard that they've never had before.  If you are thinking about writing or publishing game content, talk to me about this format, because I want to give you all the technical help I can give.  I hope to publish some of my own game material this way to kick things off, which is really more like a #5 for next steps, since people will want to see how this thing really works when they consider whether to get on board.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-4630486991391286907?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/4630486991391286907/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=4630486991391286907' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/4630486991391286907'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/4630486991391286907'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2007/08/d-datahead-community-iii.html' title='D&amp;D Datahead Community, III'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-5457091830510383566</id><published>2007-08-12T12:13:00.000-07:00</published><updated>2007-08-15T21:48:07.204-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='n3'/><category scheme='http://www.blogger.com/atom/ns#' term='roleplaying'/><category scheme='http://www.blogger.com/atom/ns#' term='goonmill'/><title type='text'>D&amp;D Datahead Community, II</title><content type='html'>In my &lt;a href="http://strongdynamic.blogspot.com/2007/08/d-datahead-community.html"&gt;last post&lt;/a&gt; I discussed the goals of the projects I'm working on.  Pushing on, this post is about the means I am using to that end.&lt;br /&gt;&lt;br /&gt;A long-winded definition: &lt;span style="font-style: italic;"&gt;game software&lt;/span&gt; means software written to support paper-and-pencil games, board games, basically any kind of game that requires a bunch of friends to get together, learn the rules, and muddle through a session on their own.  In this discussion, &lt;span style="font-style: italic;"&gt;game software&lt;/span&gt; isn't about computer games, even CRPGs, although certain CRPGS (NWN comes to mind) lie on the border between that space and this one, especially where their construction toolkits are concerned.  In particular, &lt;span style="font-style: italic;"&gt;game software&lt;/span&gt; will mean software that helps Game Masters--GMs--create, recruit players for, publish modules for, and run their games.&lt;br /&gt;&lt;br /&gt;The idea at the center of this is that developers should be able to write software for their favorite games.  Enabling them to do so shouldn't be hard.  The game software community currently suffers from a lack of cooperation.  The open source "revolution" just hasn't found this niche yet.  Software publishers all seem to start from scratch, nobody writes frameworks or talks about best practices or forms committees.  Nobody standardizes anything.  Games software suffers and its developers spin their wheels.&lt;br /&gt;&lt;br /&gt;Goonmill will be my first attempt to make a standard for something.  Like a lot of standards, it builds on other standards.  In this case, it makes use of N3, shorthand for &lt;a href="http://en.wikipedia.org/wiki/Notation_3"&gt;Notation3&lt;/a&gt;.  N3 provides a wonderfully extensible data framework for this initiative.  So extensible that it seems to be completely &lt;span style="font-style: italic;"&gt;about extensibility&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Suppose I publish a document like this:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;:goldDragonYoungAdult&lt;br /&gt;p:cr 14;&lt;br /&gt;p:alignment c:lawfulGood;&lt;br /&gt;p:size c:huge;&lt;br /&gt;&lt;br /&gt;p:initiative +4;&lt;br /&gt;&lt;br /&gt;p:hitPoints "20d12+100";&lt;br /&gt;p:damageReduction [ c:magic 5 ];&lt;br /&gt;p:armorClass 27;&lt;br /&gt;p:immunity c:fire, c:paralysis, c:sleep;&lt;br /&gt;p:save [ c:fort +17 ], [ c:ref +12 ], [ c:will +16 ];&lt;br /&gt;&lt;br /&gt;p:speed [ c:ground "60 ft." ],&lt;br /&gt; [ c:flight "200 ft. (poor)" ],&lt;br /&gt; [ c:swim "60 ft." ]&lt;br /&gt;;&lt;br /&gt;p:bab +20;&lt;br /&gt;p:grapple +38;&lt;br /&gt;p:space "15 ft.";&lt;br /&gt;p:reach "10 ft. (15 ft. with bite)";&lt;br /&gt;p:melee [ a c:AttackGroup;&lt;br /&gt; c:claw (+29  "2d6+5");&lt;br /&gt; c:claw (+29  "2d6+5");&lt;br /&gt; c:bite (+29  "2d18+10");&lt;br /&gt; c:wing (+28  "1d8+5");&lt;br /&gt; c:wing (+28  "1d8+5");&lt;br /&gt; c:tail (+28  "2d6+15");&lt;br /&gt;];&lt;br /&gt;p:abilityScore [ c:str 31 ],&lt;br /&gt; [ c:dex 10 ],&lt;br /&gt; [ c:con 21 ],&lt;br /&gt; [ c:int 18 ],&lt;br /&gt; [ c:wis 19 ],&lt;br /&gt; [ c:cha 18 ]&lt;br /&gt;;&lt;br /&gt;.&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;I won't get into the subtleties of syntax here, just present the bare bones; if you're waiting to hear about the D&amp;D stuff, bear with me one little bit more.  The above is pretty readable and pretty easy to write with a text editor, as well, which gives it two marks up on XML.  The document above breaks down into a number of subject-verb-object statements.  On most of the lines above, you see only the verb-object part followed by a semicolon; this is because the subject in every case is :goldDragonYoungAdult.  Semicolons separate two S-V-O statements with the same Subject, so each of the following lines needs to give only a verb-object.  In a similar fashion, commas separate statements with the same Subject &lt;span style="font-style: italic;"&gt;and&lt;/span&gt; Verb, so only the Object is stated for the comma-separated groups.  () presents an ordered list, and [] presents an anonymous subject, so e.g. [ :foo :bar ] means "there exists some thing, whose :foo is :bar".&lt;br /&gt;&lt;br /&gt;However, the important thing here is that N3, like all triples formats, describes a set of unordered relations.  Unlike, say, a relational database which stores tables of strongly-typed columns with relations, N3 essentially stores &lt;span style="font-style: italic;"&gt;only relations&lt;/span&gt;.&lt;br /&gt;&lt;h4&gt;Why Does N3 Matter?&lt;/h4&gt;This has gotten pretty long--more tomorrow in &lt;a href="http://strongdynamic.blogspot.com/2007/08/d-datahead-community-iii.html"&gt;Part III&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-5457091830510383566?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/5457091830510383566/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=5457091830510383566' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/5457091830510383566'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/5457091830510383566'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2007/08/d-datahead-community-ii.html' title='D&amp;D Datahead Community, II'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-9093478157459345781</id><published>2007-08-10T21:29:00.000-07:00</published><updated>2007-08-10T21:32:18.564-07:00</updated><title type='text'>The Game Master Show</title><content type='html'>This isn't the "next post" I just promised.  I just wanted to point visibly at &lt;a href="http://thegamemastershow.com/"&gt;The Game Master Show&lt;/a&gt; and cheer.  I heard a tip, decided to listen to the podcast just now.  I'm 2/3 of the way through "Fred Hicks Spends My Money" and I'm already hooked on this podcast.  It's for gamers.  Check it out.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-9093478157459345781?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/9093478157459345781/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=9093478157459345781' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/9093478157459345781'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/9093478157459345781'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2007/08/game-master-show.html' title='The Game Master Show'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-4960811243845532832</id><published>2007-08-10T17:30:00.000-07:00</published><updated>2008-03-08T19:25:22.331-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='n3'/><category scheme='http://www.blogger.com/atom/ns#' term='roleplaying'/><category scheme='http://www.blogger.com/atom/ns#' term='goonmill'/><title type='text'>D&amp;D Datahead Community</title><content type='html'>One of my agenda items for &lt;a href="http://strongdynamic.blogspot.com/2007/08/goonmill.html"&gt;Goonmill&lt;/a&gt; is to build a better community for software nerds who like to roleplay, and are interested in software about roleplaying.  &lt;a href="http://goonmill.org/vellum/"&gt;Vellum&lt;/a&gt; is definitely aimed at this idea as well.&lt;br /&gt;&lt;br /&gt;With the software I'm creating, I have a few specific goals in mind.  Most important to me are:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;span&gt;&lt;span style="font-style: italic;"&gt;Develop tools for the community to use.&lt;/span&gt;  Part of community-building is connecting people, and the tools should help us do that.  In particular, they should help gamers build and then play games with each other.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&lt;span style="font-style: italic;"&gt;Bring together programmers who want to work on games.&lt;/span&gt;  This is entirely selfish.  I want to hear from the professional programmers who game, and help them implement their ideas for more gaming tools.  The tools should form a cloud of gaming-centric working parts, interlocking and building on each other.  This, in turn, strengthens my own offerings.&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;Stimulate interest in role-playing games.&lt;/span&gt;&lt;span&gt;  &lt;span style="font-style: italic;"&gt;Bring together gamers.  &lt;/span&gt;I'm passionate about them, and I know a lot of other people are also passionate about them.  Games are fun, and creative games are more fun.  There are a lot of people out there who played as kids and don't think they can find anyone who plays as an adult.  I'd like them to know that's not true.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&lt;span style="font-style: italic;"&gt;Make it possible for adult gamers with lives and jobs to still roll out a game quickly.&lt;/span&gt;  This goal is very personally applicable.  The tools should support, not dominate, our existing lifestyles.  I don't have 4 hours to spend for each hour gameplay.  A tool that saves me an a hour of prep will get me into 33% more games per week.&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&lt;span style="font-style: italic;"&gt;Profit?&lt;/span&gt;  No, really!  I hope to found a company dedicated to developing tools for the gamer, and games for the gamer.  People like me have disposable income, and no worthwhile hobby products to spend it on.&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&lt;span style="font-style: italic;"&gt;Build resources for would-be game publishers.&lt;/span&gt;  Putting out professional-quality playing materials takes time, but it's time some of us want to spend because we enjoy the act of creation and we want to present what we've created in a nice frame.  Or we want to sell it online.  Or we want to give it as gifts to our fellow gamers.  The tools should help us do that, in as many formats as possible: print, HTML, &lt;a href="http://iconvention.org/vgtcomp.php"&gt;VGT&lt;/a&gt;.&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;At first, the people I see using my tools are the GMs of the world.  We care about the creation.  We have our own ideas.  We have our own rules.  We have players who want &lt;span style="font-style: italic;"&gt;their&lt;/span&gt; ideas to make it into the game.&lt;br /&gt;&lt;br /&gt;In my next post, I'll talk about why the underlying data framework matters in the effort to serve this community, and what Goonmill is doing with it.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://strongdynamic.blogspot.com/2007/08/d-datahead-community-ii.html"&gt;Continue to part II.&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-4960811243845532832?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/4960811243845532832/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=4960811243845532832' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/4960811243845532832'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/4960811243845532832'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2007/08/d-datahead-community.html' title='D&amp;D Datahead Community'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-1105230086701893956</id><published>2007-08-08T07:31:00.000-07:00</published><updated>2007-08-15T21:52:11.534-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='roleplaying'/><category scheme='http://www.blogger.com/atom/ns#' term='goonmill'/><title type='text'>Goonmill</title><content type='html'>For the past few months I have been putting my extra few minutes into an application called "Goonmill".  This is software for generating &lt;a href="http://www.wizards.com/default.asp?x=dnd/dd/20060707a"&gt;MM4-format statblocks&lt;/a&gt; for monsters.  I wrote it as a tool I can use when scripting adventures to save the drudgery of looking up monsters, statting them out, and presenting them in a format convenient for use at the game table.&lt;br /&gt;&lt;br /&gt;Take a look at the &lt;a href="http://thesoftworld.com/goonmill/"&gt;online demo&lt;/a&gt;.  Features include:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Über-simple workflow.  Search, click, optionally tweak, repeat.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;A (nearly invisible) box near the top of the statblock is clickable and lets you enter a count.  When you do so, Goonmill rolls hit points for that many monsters, and displays them on the statblock.&lt;/li&gt;&lt;li&gt;Similar for naming the monster (next to the hit point box).&lt;/li&gt;&lt;li&gt;Similar for setting a custom alignment on the creature.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;A &lt;span style="font-style: italic;"&gt;ton&lt;/span&gt; of work has gone into generating &lt;span style="font-style: italic;"&gt;correct&lt;/span&gt; statblocks.  There are simpleparse parsers for a large number of the stats on the page, dedicated to reading the text from the original database (designed for old-format statblocks) and putting it into the much-more-picky new-format statblock.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Makes use of Nevow Athena for &lt;span style="font-style: italic;"&gt;everything&lt;/span&gt;, which means it feels a bit more like a desktop app than a web app.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;It's not perfect.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The search is crap and needs to be replaced--it's currently just a substring search on the beginnings of words.  There isn't even sorting of links by relevance.&lt;/li&gt;&lt;li&gt;Lots of little CSS/UI issues.&lt;/li&gt;&lt;ul&gt;&lt;li&gt;The (nearly invisible) boxes near the top need some rethinking so they aren't nearly invisible, and so they don't cause the line to overflow when you edit them.&lt;/li&gt;&lt;li&gt;Need a print version of the monster history, especially with the ability to print one monster per page for GMing.&lt;/li&gt;&lt;li&gt;It's not very pretty.  Someone with an eye for web aesthetics should polish it a bit.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;I'm not sure what to do with the possessions and spells, the only yellow (TODO) items left in the statblock.  I would like to create a whole workflow around those items, with UI for choosing manually and a button for generating sane values there.&lt;/li&gt;&lt;li&gt;Same goes for NPC characteristics.  I'd like to be able to just add class levels to a creature.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Same goes for making animal companions and familiars.&lt;/li&gt;&lt;li&gt;Same goes for using monster templates.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Data work: Output everything to a triplestore (N3 or similar) as an alternative to output to a statblock.  This would allow me to get rid of all the parsers and the sqlite part of the backend.  &lt;span style="font-weight: bold;"&gt;Better yet, this would allow anyone to publish their own classes, creatures, items, and spells, on their own websites, and use Goonmill to generate those creatures. &lt;/span&gt;Initial (manual) work has been done; a lot of the data already exists in N3 format, and there's a preliminary O3M (object-triplestore mapper) for making Python objects from this data format.  There's even a triplestore web sandbox built into Goonmill, for testing SPARQL queries against it.&lt;/li&gt;&lt;/ul&gt;This open source project needs developers!&lt;br /&gt;&lt;br /&gt;If you are a fan of role-playing games and a software developer, I need your help.  Any of the items in the above list are fair game right now.   Source access requires &lt;a href="http://www.selenic.com/mercurial/wiki/"&gt;Mercurial&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;hg clone http://goonmill-source.thesoftworld.com/&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Leave a comment if you want write access.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-1105230086701893956?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/1105230086701893956/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=1105230086701893956' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/1105230086701893956'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/1105230086701893956'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2007/08/goonmill.html' title='Goonmill'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-1747179790208292387</id><published>2007-07-17T19:22:00.000-07:00</published><updated>2007-07-17T19:45:25.900-07:00</updated><title type='text'>Reasons Why Some Podcast Players Suck</title><content type='html'>I am writing down a list of audio players I have recently tried in Ubuntu, together with the reasons why they suck.  I'm doing this because I have to keep track.  There are SO MANY sucky podcast audio players that I am now being forced to organize them by reason for sucking so I can figure out which one sucks the least.  My feature requirements are pretty light:&lt;br /&gt;&lt;br /&gt;- Actually plays podcasts.&lt;br /&gt;- Clear treatment of podcast subscriptions in the UI.  I should be able to update them, remove items from them, restore them to their default state, unsubscribe from them.&lt;br /&gt;- Ability to mark items visibly in some way.  I need to know whether I've already listened to an item AND whether I've downloaded it to a device or CD to listen to in the car; this requires at least three visible states.&lt;br /&gt;&lt;br /&gt;Rhythmbox:&lt;br /&gt; Podcast subscriptions are not visible in the interface anywhere, only items.  You can download, play or remove items, but you can't manipulate your subscriptions at all.  For example, &lt;span style="font-style: italic;"&gt;you can't remove a subscription&lt;/span&gt;.  This tells me the podcast interface is unfinished.  Also, automatically starts downloading items from a podcast, which annoys me.&lt;br /&gt;&lt;br /&gt;Banshee:&lt;br /&gt; Seemingly has all the features I need, but gaps in important functionality.  If you remove an item from a subscribed feed you can't get it back, ever, even by manually updating the podcast.   No easy way to tell the relationship between  a podcast file you downloaded and a file that shows up in your playlist; the playlist only shows metadata and won't let you look at the filename, which is sometimes important for serial podcasts.&lt;br /&gt;&lt;br /&gt;Quod Libet:&lt;br /&gt; The version in Ubuntu doesn't have the advertised "Audio Feeds" view which allows podcasts.  The version on &lt;a href="http://getdeb.net/"&gt;Getdeb&lt;/a&gt; doesn't either.&lt;br /&gt;&lt;br /&gt;Songbird:&lt;br /&gt; Holy overkill batman.  I need a podcast player, not a way of life.  Main issue is that, at least regarding the version in Getdeb, it doesn't seem to actually understand podcasts.  Yes, you can subscribe to them, but viewing them gives you the Firefox raw xml no-stylesheet view instead of the expected list-of-tracks.  (And where's the list-of-all-podcasts I would expect to find, while we're at it?)&lt;br /&gt;&lt;br /&gt;Amarok:&lt;br /&gt; Very slow.  Crashed at least once in my Gnome desktop.  Requires you to install xine plugins just to play mp3s; why the &lt;span style="font-style: italic;"&gt;hell&lt;/span&gt; wouldn't that be in the dependencies?  Confusing interface--I couldn't even figure out how to just view the file's metadata.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-1747179790208292387?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/1747179790208292387/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=1747179790208292387' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/1747179790208292387'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/1747179790208292387'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2007/07/reasons-why-some-podcast-players-suck.html' title='Reasons Why Some Podcast Players Suck'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-3944278907941714240</id><published>2007-03-19T20:13:00.000-07:00</published><updated>2007-03-19T20:17:08.546-07:00</updated><title type='text'>Blogging Hotline</title><content type='html'>Love it: (via &lt;a href="http://www.boingboing.net/2007/03/19/sticker_prototype_fo.html"&gt;BoingBoing&lt;/a&gt;)&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://boingboing.net/images/BLOGGERSTICKERprototype.gif"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; cursor: pointer;" src="http://boingboing.net/images/BLOGGERSTICKERprototype.gif" alt="" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-3944278907941714240?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/3944278907941714240/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=3944278907941714240' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/3944278907941714240'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/3944278907941714240'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2007/03/love-it.html' title='Blogging Hotline'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-3987396428123533647</id><published>2007-03-09T12:54:00.000-08:00</published><updated>2007-03-09T12:58:24.975-08:00</updated><title type='text'>Followup on Gmail</title><content type='html'>Regarding my last &lt;a href="http://strongdynamic.blogspot.com/2007/03/whats-frequency-gmail.html"&gt;Gmail-related post&lt;/a&gt;, I think I figured out what happens.  Gmail &lt;span style="font-style: italic;"&gt;seems&lt;/span&gt; to be adaptively changing its update frequency.  At night, when I don't get much if any email to that address, it updates once per hour.  During the day, when I get lots of email, it checks every few minutes.  If it hasn't updated recently, you can give it a kick in the pants by doing Settings link &gt; Accounts Tab &gt; Check Mail Now link (under "Get mail from other accounts").  I had to do this a few times, and Gmail seems to have increased its check frequency at the times of day that I normally receive email.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-3987396428123533647?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/3987396428123533647/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=3987396428123533647' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/3987396428123533647'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/3987396428123533647'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2007/03/followup-on-gmail.html' title='Followup on Gmail'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-237222912029614820</id><published>2007-03-03T11:34:00.000-08:00</published><updated>2007-03-03T12:17:57.847-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='blogdoc'/><title type='text'>VMware Upgrades Blogdoc</title><content type='html'>Regarding my &lt;a href="http://strongdynamic.blogspot.com/2007/03/joys-of-vmware.html"&gt;last post&lt;/a&gt;, I wanted to make note of a few issues I had, in blogdoc format.&lt;br /&gt;&lt;br /&gt;VMware has a cross-platform software package which helps guests function a little better.  It's required to get certain things, such as hgfs (filesystem for sharing files between guest and host) and cut/paste support between guest and host working.&lt;br /&gt;&lt;br /&gt;Kernel upgrades, and therefore distro upgrades, always cause problems with this stuff.  Here's some earned wisdom on these upgrades.  If you're planning to upgrade a VMware Ubuntu guest, I recommend printing it out, because you won't be able to Google for these answers if you wait until after you've upgraded ;-).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Networking Missing?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The first thing you should do after such an upgrade is "sudo modprobe pcnet32" if it isn't already installed.   This driver is required for basic (non-vmxnet-accelerated) networking and you'll be pretty frustrated without it.  If I understand things correctly, vmware-install.pl puts pcnet32 into /etc/modules.conf for you so it'll get loaded at the right time; but if something is wrong with your vmware-tools installation, it may not be present and you have to load it manually.  (It comes with your kernel, you don't need vmware tools at all to use it.)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Network Comes Up but Wrong IPs?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Kernel (or maybe it's just distro) upgrades always seem to re-enumerate the network devices, if your guest has more than one.  In plain English, your adapter "eth0" will become "eth1" and vice-versa.  This applies to you if, for example, you use both bridged networking to get onto the Internet from the guest and a private host-only network.  If you only have one network adapter in your guest, this probably isn't a problem for you.&lt;br /&gt;&lt;br /&gt;To solve this, you may have to update /etc/network/interfaces and /etc/dhcp3/dhclient.conf and adjust for the renumbering of your adapters.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;vmware-install.pl Didn't Work&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;You have to re-run this script every time you upgrade the kernel.  You will probably also have to run it if you upgrade the vmware application itself.  You will certainly have to run it if you upgrade your distro.  The fastest way to run it is "sudo ./vmware-install.pl defaults", which doesn't ask you any questions.&lt;br /&gt;&lt;br /&gt;The two most common problems I've had here are:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Script won't even attempt to compile because it can't find your Linux source.  Just run "sudo apt-get install linux-headers-$(uname -r)" first, and then "sudo ln -sf /usr/src/linux-headers-$(uname-r) /usr/src/linux".  Re-run the script, and it will find the Linux sources this time.  This step has to be done on every kernel upgrade, for reasons that will be obvious to anyone who has read this far.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Some kind of compile error.  The most recent one I had was that the 2.6.20 kernel wasn't yet tested with the vmxnet source, and a "wrong number of arguments" bug cropped up.  I found these &lt;a href="http://www.vmware.com/community/thread.jspa?threadID=62836"&gt;instructions to patch&lt;/a&gt; this problem. (I'll add this to the bottom, in diff -u format, in case the forum post drops off somehow.)&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;I want to make note here of a community-maintained patch which makes vmware work on any known kernel version.  This is apparently known as the &lt;a href="http://knihovny.cvut.cz/ftp/pub/vmware/"&gt;"any-any-update" patch&lt;/a&gt;.&lt;span class="down" style="display: block;" id="formatbar_CreateLink" title="Link" onmouseover="ButtonHoverOn(this);" onmouseout="ButtonHoverOff(this);" onmouseup="" onmousedown="CheckFormatting(event);FormatbarButton('richeditorframe', this, 8);ButtonMouseDown(this);"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Resolution Woes&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If you have a supported default resolution for your guest, you should be fine with "./vmware-install.pl defaults", which I believe will read your old config file and plug in the same resolution value you specified the first time you installed the tools.  However, I have a funky monitor resolution: 1280x768.  This is not one of the choices the script gives you, so I always have to manually tweak.  Fortunately, it seems to be enough to just copy a 1280x800 in xorg.conf to 1280x768 and then change the default resolution in your "Screen"/"Display"/"24"-bit depth section to "Modes" "1280x768".&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Mouse&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To get a mousewheel to work, I changed protocol "ps/2" to protocol "imps/2".&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;The 2.6.19/2.6.20+ vmxnet Patch&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;--- vmxnet.c.orig       2007-03-01 14:04:27.000000000 -0800&lt;br /&gt;+++ vmxnet.c    2007-03-01 13:57:29.000000000 -0800&lt;br /&gt;@@ -1055,7 +1055,11 @@&lt;br /&gt;vmxnet_netpoll(struct net_device *dev)&lt;br /&gt;{&lt;br /&gt;   disable_irq(dev-&gt;irq);&lt;br /&gt;+#if LINUX_VERSION_CODE &lt;&gt;irq, dev, NULL);&lt;br /&gt;+#else&lt;br /&gt;+   vmxnet_interrupt(dev-&gt;irq, dev);&lt;br /&gt;+#endif&lt;br /&gt;   enable_irq(dev-&gt;irq);&lt;br /&gt;}&lt;br /&gt;#endif /* VMW_HAVE_POLL_CONTROLLER */&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-237222912029614820?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/237222912029614820/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=237222912029614820' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/237222912029614820'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/237222912029614820'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2007/03/vmware-upgrades-blogdoc.html' title='VMware Upgrades Blogdoc'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-8284411522374883620</id><published>2007-03-03T11:14:00.000-08:00</published><updated>2007-03-03T11:34:04.944-08:00</updated><title type='text'>Joys of VMware</title><content type='html'>Yesterday I upgraded from Ubuntu Edgy Eft to Ubuntu Feisty Fawn (which is not yet released, usual disclaimers apply, don't use it or it will poison your hamster etc.)&lt;br /&gt;&lt;br /&gt;Upgrades are harsh environments for a computer; they're the computing equivalent of replacing the engine in your car.  Even in skilled hands, things can go wrong, and you don't want to get an error message telling you anything went wrong, even if it seems innocuous, because your computer might be about to give up the ghost completely.  (This is the computing equivalent of watching a mechanic walk over to you slowly from your car.  This man is a heavyset man in grease-blackened denims, wiping his hands with a red rag, looking down at the ground, walking slowly while he tries to get a read on how you're going to react to the news of your car's impending trip to the scrapyard.)&lt;br /&gt;&lt;br /&gt;Thus, before I began this process, so fraught as it is with the risk of doom, it was with great pleasure that I pushed the "snapshot" button on my VMware application.  If doom happens, I can just undo it.  (In this case, doom did not happen.  Feisty Fawn is running right now.  Ubuntu is really a joy.)&lt;br /&gt;&lt;br /&gt;You may not have used virtualization software yet.  You might be thinking about how slow it makes things, how you don't want to have even more complexity in your computing environment.  Forget all that.&lt;br /&gt;&lt;br /&gt;VMware is awesome.  I have allocated 512MB to my VMware instance, which is running on my solo-core uniprocessor laptop.  I can run all of my usual productivity applications, compile and build packages for software, run my D&amp;D software (most of which is written in Java).  I can even watch high-resolution video, with audio, and get a decent rate, and that's inside the guest.  If I wanted to play a fullscreen immersive game, I might use the host computer for that, but that's OK; that's what it's there for.  (I use a Windows host, mostly because it's the default OS of this laptop.)&lt;span style="font-size:130%;"&gt;&lt;span style="font-size:100%;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-8284411522374883620?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/8284411522374883620/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=8284411522374883620' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/8284411522374883620'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/8284411522374883620'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2007/03/joys-of-vmware.html' title='Joys of VMware'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-6018325678841900621</id><published>2007-03-02T09:41:00.000-08:00</published><updated>2007-03-02T09:51:21.645-08:00</updated><title type='text'>What's the frequency, Gmail?</title><content type='html'>I just set up Gmail's new fetcher feature, called "Mail Fetcher" or "Get mail from other accounts".  It acts as a POP &lt;span style="font-style: italic;"&gt;client&lt;/span&gt;, rertrieving POP3 email using your password from any account you want.  If you can prove that you own that sending address, you can then send email as that person.  Gmail has had this latter feature from some time.  In fact, you could simulate the whole thing by simply setting up a forward on the pop account in question.  The new POP client feature just makes it a little easier to label emails as being work-related or personal-related.&lt;br /&gt;&lt;br /&gt;Just had a question for the community.  Does anyone else use this feature?  If you do, have you figured out how to make Gmail check your email with a particular frequency?   It seems to be set to an hour now, which is painfully slow.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-6018325678841900621?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/6018325678841900621/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=6018325678841900621' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/6018325678841900621'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/6018325678841900621'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2007/03/whats-frequency-gmail.html' title='What&apos;s the frequency, Gmail?'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-5666799161338743767</id><published>2007-02-16T10:38:00.000-08:00</published><updated>2007-02-16T12:13:51.606-08:00</updated><title type='text'>Vista has arrived, SFW</title><content type='html'>So, the wife and I brought home a new desktop computer for her.  She didn't want a laptop for some reason.&lt;br /&gt;&lt;br /&gt;Due to market forces I don't need to rant about in this space, it had one of the 10 versions of Windows Vista on it.  She plugged it in, clicked through all the unenforceable license agreements (with her eyes closed, per my instructions . . .) required so lawyers have a reason to work for software companies.&lt;br /&gt;&lt;br /&gt;Then we had to set up networking.  Windows Vista, like &lt;span style="font-weight: bold;"&gt;every other version of Windows&lt;/span&gt;, has once again moved settings around for no good reason.  Another huge support nightmare for everyone in the world with a CRM system and a searchable support base, because their scripts will once again have to be updated so they can tell helpless customers the new locations of things.&lt;br /&gt;&lt;br /&gt;Course, that's no longer my problem.  Neither is it my problem that Windows now asks you to confirm everything you're doing that needs administrator access, but that's what I'm here today to rant about.&lt;br /&gt;&lt;br /&gt;You'd think, after developing Windows 3.1, WFW, Windows NT 3.51, Windows 95, Windows 98, Windows NT 4.0, Windows Me, Windows 2000, Windows XP, Windows 2003, and &lt;a href="http://www.penny-arcade.com/comic/2007/02/02"&gt;Windows AIDS,&lt;/a&gt; that Microsoft would have learned something about usability that works.  Somehow this lesson hasn't penetrated: &lt;span style="font-weight: bold;"&gt;Every interaction your software has with users trains them to do something.  You had better make sure it's training them to do the &lt;span style="font-style: italic;"&gt;right&lt;/span&gt; thing.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Let's take an example: The double-click.  MS trained users for years that double-click was how you opened everything.  Single click was for selecting.  Then they decided single-click was for opening, too.  Now all of us users trained to double-click are constantly opening things twice, by accident.  Thanks!  Then they had to give us a way to go &lt;span style="font-weight: bold;"&gt;back&lt;/span&gt; to the old way.  Nice job.&lt;br /&gt;&lt;br /&gt;The lesson users will be learning with Vista: When a program tells you it needs administrator access to do something, you click "Yes."  Doesn't matter why, just click it and make the dialog go away. &lt;span style="font-style: italic;"&gt; Changing the network settings?&lt;/span&gt;  "Yes."  &lt;span style="font-style: italic;"&gt;Opening the network settings dialog?&lt;/span&gt;  "Yes."  &lt;span style="font-style: italic;"&gt;Installing a program?&lt;/span&gt;  "Yes."  &lt;span style="font-style: italic;"&gt;Your web browser wants you to host some child pornography on your hard drive and launch a bittorrent tracker for it?&lt;/span&gt;  "Yes."&lt;br /&gt;&lt;br /&gt;After the tenth such context- and content-free question, you just click yes.  I'll be doing it too.  Windows will protect us!  "Yes."&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-5666799161338743767?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/5666799161338743767/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=5666799161338743767' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/5666799161338743767'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/5666799161338743767'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2007/02/vista-has-arrived-sfw.html' title='Vista has arrived, SFW'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-114659643468802719</id><published>2006-05-02T11:58:00.000-07:00</published><updated>2006-05-02T12:04:13.530-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='blogdoc'/><title type='text'>Quickie screen tip: always running screen</title><content type='html'>It's easy to set screen up so it automatically resumes your last session as soon as you log in.  If you don't like to manually type 'screen -&amp;lt;args&amp;gt;' after logging in, and you don't like screen sessions getting stranded by a killed terminal, try the following in your shell's user rc/profile:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;if ! echo $STY | cut -d. -f1 | xargs ps -p 2&gt; /dev/null | grep -i screen; then&lt;br /&gt;    exec screen -RR&lt;br /&gt;fi&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Credit to &lt;tt&gt;danieldg&lt;/tt&gt; on Freenode IRC for this approach.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-114659643468802719?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/114659643468802719/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=114659643468802719' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/114659643468802719'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/114659643468802719'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2006/05/quickie-screen-tip-always-running.html' title='Quickie screen tip: always running screen'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-114606976720491245</id><published>2006-04-26T09:26:00.000-07:00</published><updated>2011-03-26T13:39:05.950-07:00</updated><title type='text'>DM3</title><content type='html'>Thought I'd get this out there, since everyone else will too.&lt;br /&gt;&lt;br /&gt;Not that &lt;a href="http://homestarrunner.com/dman3.html"&gt;this game&lt;/a&gt; was &lt;em&gt;hard&lt;/em&gt;, mind you.  I solved the whole thing in about an hour.  But I like making maps, and inkscape is fun to use, so here you go: (walkthrough below)  If you don't see the svg map, try visiting the actual blog, and use firefox 1.5.&lt;br /&gt;&lt;img src="http://dl.dropbox.com/u/19400544/strongdynamic.blogspot.com/dm3.svg"&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;use claws (+1), get bone (+2), use bone (+3)&lt;/li&gt;&lt;li&gt;north, get flask&lt;/li&gt;&lt;li&gt;west, look inside log, get coins (+2)&lt;/li&gt;&lt;li&gt;(look inside log, get dank log insides :-)&lt;/li&gt;&lt;li&gt;e, e, talk to man, give coins to man (+2)&lt;/li&gt;&lt;li&gt;w, n, give corn to bird (+2)&lt;/li&gt;&lt;li&gt;n, talk to monk, get stein (+1), s (+3)&lt;/li&gt;&lt;li&gt;s, e, e, s, talk to barkeep, use stein (+2) - remember what Kigalonian looks like!&lt;/li&gt;&lt;li&gt;n, n, talk to kigalonian, choose the correct one (+2)&lt;/li&gt;&lt;li&gt;s, e, knock, ask for ketchup (+3)&lt;/li&gt;&lt;li&gt;w, w, w, w, look scrapbook, talk to hag, use ketchup on head (+2)&lt;/li&gt;&lt;li&gt;talk to hag, answer her questions (hope you read the scrapbook!) (+4)&lt;/li&gt;&lt;li&gt;e, e, s, give bird to troll (+2)&lt;/li&gt;&lt;li&gt;(look stream :-)&lt;/li&gt;&lt;li&gt;s, open door, use glove (+1)&lt;/li&gt;&lt;li&gt;get flask.  You know what to do here. (+6).&lt;span style="background-color: rgb(153, 255, 153);" name="textmarker_44" id="textmarked_40"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-114606976720491245?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/114606976720491245'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/114606976720491245'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2006/04/dm3.html' title='DM3'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-114413789111592382</id><published>2006-04-03T21:10:00.000-07:00</published><updated>2006-04-04T01:11:43.050-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='blogdoc'/><title type='text'>Nastier Than a Bear Holding a Shark</title><content type='html'>&lt;div class="document"&gt;&lt;p&gt;I have just finished setting up a Windows XP Pro box as a Subversion server.&lt;br /&gt;This is not a fun way to spend an evening.  Before you read this let me say&lt;br /&gt;the following things as loudly as possible:&lt;/p&gt;&lt;p&gt;&lt;em&gt;WINDOWS IS NOT A RECOMMENDED PLATFORM FOR A SUBVERSION SERVER.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;USE LINUX&lt;/em&gt; OR, what the hell, OS X would probably be okay too.&lt;/p&gt;&lt;p&gt;I will talk a little about why Windows is so bad later on.  However, Windows&lt;br /&gt;is what we had, and we needed a repo up ASAP, so I made do.  Fortunately&lt;br /&gt;Subversion keeps a database, and we will be able to copy that database to a&lt;br /&gt;non-toy computer in the future.  In the meantime, here's how to make it&lt;br /&gt;happen:&lt;/p&gt;&lt;div class="section"&gt;&lt;h3&gt;&lt;a id="install-sshd" name="install-sshd"&gt;Install SSHd&lt;/a&gt;&lt;/h3&gt;&lt;ol class="arabic simple"&gt;&lt;li&gt;Install &lt;a class="reference" href="http://cygwin.com/setup.exe"&gt;Cygwin&lt;/a&gt;.  Make sure the OpenSSH &lt;a class="footnote-reference" href="#id2" id="id1" name="id1"&gt;[1]&lt;/a&gt; package is checked.  You&lt;br /&gt;probably want to add a few other things.  My list of extras usually&lt;br /&gt;includes &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;zsh&lt;/span&gt;&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;zip&lt;/span&gt;&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;unzip&lt;/span&gt;&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;gcc-mingw&lt;/span&gt;&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;patch&lt;/span&gt;&lt;/tt&gt;, and&lt;br /&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;openssh&lt;/span&gt;&lt;/tt&gt;.&lt;/li&gt;&lt;/ol&gt;&lt;ol class="arabic simple" start="2"&gt;&lt;li&gt;Create local user accounts (or domain user accounts) for all the people&lt;br /&gt;you want to have making commits.  In Windows XP pro, the default&lt;br /&gt;is accounts with no password.  This is dumb.  Set passwords on all&lt;br /&gt;the accounts.  You can't log into SSH if you don't have either a password&lt;br /&gt;on the account or a public/private authorized_key pair on the account.&lt;br /&gt;Make these accounts local administrators.  If you don't think you can do&lt;br /&gt;that, then don't even bother with the rest of this solution.  You want Unix&lt;br /&gt;instead.&lt;/li&gt;&lt;li&gt;Launch the Cygwin prompt at least once.  Run:&lt;br /&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;mkpasswd&lt;/span&gt; &lt;span class="pre"&gt;-l&lt;/span&gt; &lt;span class="pre"&gt;&amp;gt;&lt;/span&gt; &lt;span class="pre"&gt;/etc/passwd;&lt;/span&gt; &lt;span class="pre"&gt;mkgroup&lt;/span&gt; &lt;span class="pre"&gt;-l&lt;/span&gt; &lt;span class="pre"&gt;&amp;gt;&lt;/span&gt; &lt;span class="pre"&gt;/etc/group&lt;/span&gt;&lt;/tt&gt;(In a Windows NT Domain/ADS environment, you probably want &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-l&lt;/span&gt; &lt;span class="pre"&gt;-D&lt;/span&gt;&lt;/tt&gt;.)&lt;/li&gt;&lt;li&gt;Add &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;C:\cygwin\bin&lt;/span&gt;&lt;/tt&gt; to your global &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;PATH&lt;/span&gt;&lt;/tt&gt; environment variable.&lt;br /&gt;Yeah, just do it.  It's in &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;My&lt;/span&gt; &lt;span class="pre"&gt;Computer&lt;/span&gt; &lt;span class="pre"&gt;&amp;gt;&lt;/span&gt; &lt;span class="pre"&gt;Proprties&lt;/span&gt; &lt;span class="pre"&gt;&amp;gt;&lt;/span&gt; &lt;span class="pre"&gt;Advanced&lt;/span&gt; &lt;span class="pre"&gt;&amp;gt;&lt;/span&gt;&lt;span class="pre"&gt;Environment&lt;/span&gt; &lt;span class="pre"&gt;Variables&lt;/span&gt;&lt;/tt&gt;.&lt;/li&gt;&lt;li&gt;Then run &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;ssh-host-config&lt;/span&gt;&lt;/tt&gt;.  You probably want to answer 'yes' to&lt;br /&gt;everything.&lt;/li&gt;&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;net&lt;/span&gt; &lt;span class="pre"&gt;start&lt;/span&gt; &lt;span class="pre"&gt;sshd&lt;/span&gt;&lt;/tt&gt; or start the service from the services applet.&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;div class="section"&gt;&lt;h3&gt;&lt;a id="test-ssh" name="test-ssh"&gt;Test SSH&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;I suggest logging in as one of your users using just ssh, and make sure you&lt;br /&gt;see some kind of shell.&lt;/p&gt;&lt;/div&gt;&lt;div class="section"&gt;&lt;h3&gt;&lt;a id="install-subversion-and-make-svnserve-your-bitch" name="install-subversion-and-make-svnserve-your-bitch"&gt;Install Subversion and Make &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;svnserve&lt;/span&gt;&lt;/tt&gt; Your Bitch&lt;/a&gt;&lt;/h3&gt;&lt;ol class="arabic simple" start="7"&gt;&lt;li&gt;Install &lt;a class="reference" href="http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91&amp;amp;expandFolder=91&amp;amp;folderID=0"&gt;Subversion&lt;/a&gt;.&lt;/li&gt;&lt;/ol&gt;&lt;ol class="arabic" start="8"&gt;&lt;li&gt;&lt;p class="first"&gt;Create a repository somwhere, using &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;svnadmin&lt;/span&gt;&lt;/tt&gt;.  Now, there're a couple&lt;br /&gt;of things that need to be true about this repository.&lt;/p&gt;&lt;ul class="simple"&gt;&lt;li&gt;It needs to be owned by the Administrators group, including&lt;br /&gt;subdirectories/folders.&lt;/li&gt;&lt;li&gt;It needs to be writable by them, including subdirs/folders.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Both of these things are accessed through the Security Tab, and then the&lt;br /&gt;Advanced button, when you right-click on the folder.  If you don't have a&lt;br /&gt;security tab, go into Tools&amp;gt;Folder Options&amp;gt;View&amp;gt; and uncheck &amp;quot;Simple&lt;br /&gt;File Sharing&amp;quot;.&lt;/p&gt;&lt;p&gt;You may be scratching your head and thinking &amp;quot;But all your users are&lt;br /&gt;administrators.. why can't they write to the folder regardless?&amp;quot;  You, my&lt;br /&gt;friend, understand Unix.  Unfortunately, you don't understand Windows,&lt;br /&gt;wherein permissions activate and deactivate apparently at random.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p class="first"&gt;If you've ever configured svn+ssh access to a repository on Unix, you know&lt;br /&gt;about the umask problem as described in the box at the bottom of this&lt;br /&gt;&lt;a class="reference" href="http://svnbook.red-bean.com/en/1.1/ch06s05.html"&gt;svnbook page&lt;/a&gt;.  There's a different problem on Windows, but it's solved&lt;br /&gt;the same way, with a very similar shell script.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;blockquote&gt;&lt;p&gt;In Cygwin's sshd, you get a very limited set of directories in your PATH.&lt;br /&gt;It does not match the list in your global environment; it is apparently&lt;br /&gt;compiled into sshd.  There are a couple of different ways to modify it, but&lt;br /&gt;they aren't global and/or they don't apply when using ssh to tunnel svn.&lt;br /&gt;The solution is this shell script:&lt;/p&gt;&lt;pre class="literal-block"&gt;#!/bin/sh&lt;br /&gt;cd /cygdrive/c/Program\ Files/Subversion/bin&lt;br /&gt;# change the following line so that -r points to where you are&lt;br /&gt;# keeping your subversion repositories.  This keeps your URLs shorter.&lt;br /&gt;./svnserve -r C:/SUBVERSION &amp;quot;$&amp;#64;&amp;quot;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;!--  --&gt;&lt;blockquote&gt;&lt;p&gt;You need to name this script &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;svnserve&lt;/span&gt;&lt;/tt&gt; with no extension, put this into&lt;br /&gt;your &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;C:\WINDOWS&lt;/span&gt;&lt;/tt&gt; directory, and, using Cygwin,&lt;br /&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;chmod&lt;/span&gt; &lt;span class="pre"&gt;a+x&lt;/span&gt; &lt;span class="pre"&gt;/cygdrive/c/WINDOWS/svnserve&lt;/span&gt;&lt;/tt&gt;.&lt;br /&gt;What you are doing is routing around the broken PATH and directing svn to&lt;br /&gt;run the binary from its own directory.  Note also the argument &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-r&lt;/span&gt;&lt;span class="pre"&gt;C:/SUBVERSION&lt;/span&gt;&lt;/tt&gt;.  That's a &lt;em&gt;FORWARD SLASH&lt;/em&gt;.  This argument is optional, but&lt;br /&gt;it's extremely handy.  Use it when you want shorter URLs.&lt;br /&gt;For example, if you did:&lt;/p&gt;&lt;pre class="literal-block"&gt;mkdir C:/REPOS&lt;br /&gt;cd C:/REPOS&lt;br /&gt;svnadmin create Foostuffs&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;!--  --&gt;&lt;blockquote&gt;If you want your url to be &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;svn+ssh://foostuffs.com/Foostuffs&lt;/span&gt;&lt;/tt&gt;, then use&lt;br /&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-r&lt;/span&gt; &lt;span class="pre"&gt;C:/REPOS&lt;/span&gt;&lt;/tt&gt;.&lt;/blockquote&gt;&lt;ol class="arabic simple" start="10"&gt;&lt;li&gt;Make &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;svnserve.exe&lt;/span&gt;&lt;/tt&gt; in &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;C:\Program&lt;/span&gt; &lt;span class="pre"&gt;Files\Subversion\bin&lt;/span&gt;&lt;/tt&gt; executable by&lt;br /&gt;everyone.  It isn't world executable by default.&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;div class="section"&gt;&lt;h3&gt;&lt;a id="test-svn" name="test-svn"&gt;Test svn&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Try &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;svn&lt;/span&gt; &lt;span class="pre"&gt;co&lt;/span&gt; &lt;span class="pre"&gt;svn+ssh://foostuffs.com/Foostuffs&lt;/span&gt;&lt;/tt&gt; and see what happens.  If&lt;br /&gt;you're trying this on a Windows client, you will want to find somebody else's document&lt;br /&gt;on setting up svn+ssh client access from Windows.&lt;/p&gt;&lt;/div&gt;&lt;div class="section"&gt;&lt;h3&gt;&lt;a id="why-windows-sucks" name="why-windows-sucks"&gt;Why Windows Sucks&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Well, we've already covered the problems with the broken PATH on Windows,&lt;br /&gt;which forces us to use the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;C:\WINDOWS\svnserve&lt;/span&gt;&lt;/tt&gt; kludge, and the requirement&lt;br /&gt;that your users be local Administrators.  In addition to that, this&lt;br /&gt;configuration is just plain flaky and slow.  Performance is sluggish or&lt;br /&gt;sometimes just stops altogether, for reasons from the computer going to sleep&lt;br /&gt;(watch out for that) to having the wrong &amp;quot;Optimize for background apps&amp;quot;&lt;br /&gt;setting, to just weird behavior in general.  SSH is also slow under Cygwin,&lt;br /&gt;which makes SVN slow.&lt;/p&gt;&lt;p&gt;Tomorrow I'll be setting up Bugzilla on the same box, assuming this pile of&lt;br /&gt;cards hasn't fallen over by then.&lt;/p&gt;&lt;table class="docutils footnote" frame="void" id="id2" rules="none"&gt;&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;&lt;tbody valign="top"&gt;&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id1" name="id2"&gt;[1]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;(Why am I not using conch?  Conch doesn't work on Windows.  If&lt;br /&gt;you disagree, feel free to send me instructions or patches and I&lt;br /&gt;will try them.  Really.  I don't like Cygwin sshd.)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-114413789111592382?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/114413789111592382/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=114413789111592382' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/114413789111592382'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/114413789111592382'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2006/04/nastier-than-bear-holding-shark.html' title='Nastier Than a Bear Holding a Shark'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-114192627670484334</id><published>2006-03-09T09:40:00.000-08:00</published><updated>2006-03-14T14:00:32.286-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='blogdoc'/><title type='text'>Quickie setuptools</title><content type='html'>Here's a one-liner shell script to install PJE's setuptools, for Googling goodness.  Nearly everyone, I hope, has wget.  (There's also a version that uses only python by importing urllib2.  I like this one.)&lt;br /&gt;&lt;br /&gt;&lt;code&gt;wget -O - http://peak.telecommunity.com/dist/ez_setup.py | python -&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;strike&gt;If you're on Windows, you probably then want to do ..&lt;br /&gt;&lt;br /&gt;&lt;code&gt;cd c:\python24\scripts&lt;br /&gt;ren easy_install-script.py easy_install.py&lt;br /&gt;exemaker easy_install.py&lt;/code&gt;&lt;/strike&gt;&lt;br /&gt;&lt;br /&gt;Edit:&lt;br /&gt;Look for "easy_install.exe" in the C:\python24\scripts directory if you're on Windows.  You probably want to copy it to somewhere in your binary PATH.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-114192627670484334?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/114192627670484334/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=114192627670484334' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/114192627670484334'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/114192627670484334'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2006/03/quickie-setuptools.html' title='Quickie setuptools'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-114067689706335448</id><published>2006-02-22T22:34:00.000-08:00</published><updated>2006-02-22T22:41:37.073-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='blogdoc'/><title type='text'>Down with the Man</title><content type='html'>Ringtones are outrageously expensive.  My stepdaughter wanted to put some custom ones on her Razr which you might not even be able to download, and I happen to be decent with Audacity.  I wanted to put a note on here so the next visitor to google.com would do better than I did.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Make sure your MP3 file is encoded at a 22kHz sample rate.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If you don't do that, you will get the message "File type not recognized" from your Motorola Razr phone.&lt;br /&gt;&lt;br /&gt;You will see a lot of stupid nonsense about making an mp3 file and then renaming it to .MID.  I didn't do that, I just figured out where the project sample rate button was in Audacity.  (Hint: It's in the bottom left corner.)  Then export as an MP3, transfer to the phone using one of many methods, and off you go.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-114067689706335448?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/114067689706335448/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=114067689706335448' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/114067689706335448'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/114067689706335448'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2006/02/down-with-man.html' title='Down with the Man'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-113322996750874216</id><published>2005-11-28T17:16:00.000-08:00</published><updated>2011-03-26T11:51:12.660-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='blogdoc'/><title type='text'>Stupid Nevow Tricks</title><content type='html'>Actually, this stupid &lt;a href="http://divmod.org/trac/wiki/DivmodNevow"&gt;Nevow&lt;/a&gt; trick is pretty damn clever.&lt;br /&gt;&lt;br /&gt;So, you want to write a db-backed app with a web frontend.  You plan to have, let's say, 60k users registered and you want them to be able to send one another a message via a webform by entering first and last real name as the recipient.&lt;br /&gt;&lt;br /&gt;This could be a real pain.  In the old days you'd need a separate form just to look up the user in the database first, then you can start the message sending bit.  Not any more.&lt;br /&gt;&lt;br /&gt;Check out &lt;a href="http://svn.twistedmatrix.com/cvs/sandbox/moonfallen/name_complete_demo/"&gt;this demo&lt;/a&gt;.  This uses Divmod's &lt;a href="http://divmod.org/trac/wiki/DivmodAxiom"&gt;Axiom&lt;/a&gt; as the database backend, and Nevow's new LivePage API called "athena" to drive the frontend.  I'm very impressed with the power and performance of the Axiom database so far, and it holds up beautifully in this example.  LivePage works wonderfully with it for a very compelling combination.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;What does it do?&lt;/h3&gt;&lt;br /&gt;The demo database contains a single table with 10k names in it.  (Locally I experimented with a 60k name database before trimming the fat for the checkin; performance did not suffer one iota.)  The names are randomly generated from US Census data.  When you start the demo and point your web browser at it (see the &lt;span style="font-weight: bold;"&gt;README.txt&lt;/span&gt;) you'll see a field.  Type a name into this field; if part of what you typed has a database hit, you'll see the possible completions:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://dl.dropbox.com/u/19400544/strongdynamic.blogspot.com/typeahead2_68120970.png"&gt;&lt;img style="border: thin solid black; cursor: pointer;" src="http://dl.dropbox.com/u/19400544/strongdynamic.blogspot.com/typeahead1_68120968.png" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;.. until you get a unique match, at which point it fills in your text field for you:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://dl.dropbox.com/u/19400544/strongdynamic.blogspot.com/typeahead2_68120970.png"&gt;&lt;img style="border: thin solid black; cursor: pointer;" src="http://dl.dropbox.com/u/19400544/strongdynamic.blogspot.com/typeahead2_68120970.png" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;You can, of course, also click a name in the menu.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;What's neat?&lt;/h3&gt;&lt;br /&gt;A lot of the interesting part is in JavaScript, so make sure you look at &lt;span style="font-family:courier new;"&gt;typeahead.html&lt;/span&gt;.   In particular, &lt;span style="font-family:courier new;"&gt;selectRange&lt;/span&gt; handles selecting the untyped portion of the text field, and &lt;span style="font-family:courier new;"&gt;complete&lt;/span&gt; handles filling in the field and the options in the &lt;span style="font-family:courier new;"&gt;select&lt;/span&gt; element.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Nevow&lt;/h4&gt;&lt;br /&gt;The Nevow stuff is pretty straightforward.  You create a LivePage instance as your page.  Then you create elements capable of talking to the server as LiveFragments, and stuff them into the page.  Here's the whole LiveFragment for the input field.  This renders the input box and has a single method to handle a callRemote from JavaScript.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;class TypeAheadFieldFragment(athena.LiveFragment):&lt;br /&gt;  docFactory = loaders.stan(T.input(type="text", id="typehere", **athena.liveFragmentID))&lt;br /&gt;  allowedMethods =  { 'loadCompletion' : True }&lt;br /&gt;&lt;br /&gt;  def loadCompletion(self, typed):&lt;br /&gt;      assert type(typed) is unicode&lt;br /&gt;      if typed == u'':&lt;br /&gt;          return None&lt;br /&gt;      q = Person.name.like(typed, u'%')&lt;br /&gt;      matches = theStore.count(Person, q)&lt;br /&gt;      if matches &lt;= 10:&lt;br /&gt;          return [p.name for p in theStore.query(Person, q)]&lt;br /&gt;      else:&lt;br /&gt;          return None&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The matching JavaScript is nice and simple:&lt;br /&gt;&lt;code&gt;  var node = $('typehere');&lt;br /&gt;  var typed = node.value;&lt;br /&gt;  var d = Nevow.Athena.refByDOM(node).callRemote('loadCompletion', typed);&lt;br /&gt;  d.addCallback(complete);&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;(Again, be sure to read the rest of the JavaScript on the page.)&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Axiom&lt;/h4&gt;&lt;br /&gt;Axiom is damn bloody simple to use.  The demo doesn't really show off much in the way of Axiom features, but it does show off how simple your ORM code can be.  A couple of things stood out for me.&lt;br /&gt;&lt;br /&gt;One was that Axiom's latency is very very low indeed.  At the place where I do the query I treat it as non-blocking, and for me on my one laptop it had better be.  In fact, if this demo works at all it has to be non-blocking; a person typing would quickly get ahead of the database otherwise.  The speed of Axiom at returning a list of 10 names from a list of 10k names is impressively subsecond.  Now, I'll be the first to acknowledge that what works nice and fast for me on my laptop might not be so fast when you've got 10k live users banging away on their keyboards, but it establishes that this low latency is at least &lt;em&gt;possible&lt;/em&gt; to achieve.  I'll leave the macho scaling stuff to others.&lt;br /&gt;&lt;br /&gt;The other was that Axiom's batch performance is pretty darn good.  I left in the &lt;span style="font-family:courier new;"&gt;batchInsert&lt;/span&gt; function in &lt;span style="font-family:courier new;"&gt;namedb.py&lt;/span&gt;.  The function I used to to import the original 60k names took about 7 seconds to run using Store's &lt;span style="font-family:courier new;"&gt;transact&lt;/span&gt; method.  Be sure to use &lt;span style="font-family:courier new;"&gt;.transact()&lt;/span&gt; if you're going to be manipulating a bunch of rows at once though; before someone (I think JP?) pointed out that Axiom had transactions, I was trying to do the 60k inserts by creating 60k Items at one per second.  It's worth highlighting that the &lt;span style="font-family:courier new;"&gt;transact&lt;/span&gt; method is so simple to use that as soon as I knew about it I was using it with no explanation whatsoever.  Simplicity is beauty.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;MochiKit&lt;/h4&gt;&lt;br /&gt;Another surprise winner here was MochiKit.  I've heard so many good things about it, but until now only used it indirectly through LivePage.  Even if I didn't already know who wrote it, it would have been obvious that this JS library was written by an artful Python hacker.  I made use of MochiKit.DOM for constructing the items in the select widget, but I was particularly impressed with MochiKit's "bookmarklet debugging".  Getting complex scripts to work in JavaScript is nothing short of horrifying for me, but having the log messaging and viewing facilities in such a nice format cut in half the time it would have taken me to get the JS right.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-113322996750874216?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/113322996750874216/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=113322996750874216' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/113322996750874216'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/113322996750874216'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2005/11/stupid-nevow-tricks.html' title='Stupid Nevow Tricks'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-112741719316815135</id><published>2005-09-22T11:05:00.000-07:00</published><updated>2005-09-22T12:29:26.920-07:00</updated><title type='text'>Pydispatcher</title><content type='html'>I thought I'd give a shout-out here to &lt;a href="http://pydispatcher.sf.net/"&gt;pydispatcher&lt;/a&gt;.  It was written by a gent named Pat O'Brien, whom I've met and had lunch with, and it's coming in very handy for Vellum.  I've refactored Vellum to use it, and it's remarkably simple and robust.  Where it comes in handy is building code where lots of things need to know when program state changes, and need to know where those events came from to decide whether to use them.&lt;br /&gt;&lt;br /&gt;The essence is:&lt;br /&gt;&lt;pre&gt;   def receiver(sender, arg1, arg2):&lt;br /&gt;     if sender=='ninja':&lt;br /&gt;       print arg1, arg2&lt;br /&gt;&lt;br /&gt;   def otherReceiver(arg1, arg2):&lt;br /&gt;     if arg1=='oNOerror': sys.exit(1)&lt;br /&gt;&lt;br /&gt;   dispatcher.connect(receiver, "foo")&lt;br /&gt;   dispatcher.connect(otherReceiver, "foo")&lt;br /&gt;   ...&lt;br /&gt;   dispatcher.send('foo', sender='ninja', arg1='yaysuccess', arg2='whatever')&lt;br /&gt;   dispatcher.send('foo', sender='phb', arg1='oNOerror', arg2=123)&lt;br /&gt;&lt;br /&gt;   #==&gt; yaysuccess whatever&lt;br /&gt;   #==&gt; eek, error&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Signals can be any (hashable?) python object, as can senders.&lt;br /&gt;&lt;br /&gt;Even if you think this is a bad way to design an app (signals going all over the place, confusing the call stack), you might find it useful if you don't &lt;span style="font-style: italic;"&gt;know&lt;/span&gt; how to design your app.  Do it with the event dispatch mechanism first, then look for all the places where signals are sent, and figure out how to get them upstream in the call stack from the code handling them.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-112741719316815135?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/112741719316815135/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=112741719316815135' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/112741719316815135'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/112741719316815135'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2005/09/pydispatcher.html' title='Pydispatcher'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-111954309514719493</id><published>2005-06-23T09:11:00.000-07:00</published><updated>2005-06-23T09:11:48.000-07:00</updated><title type='text'>Prohibited from using the wagon</title><content type='html'>Oh, BANDwagon.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://blogsurvey.media.mit.edu/request"&gt;&lt;img src="http://blogsurvey.media.mit.edu/images/survey-science.gif" alt="Take the MIT Weblog Survey" style="border:none"&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-111954309514719493?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/111954309514719493/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=111954309514719493' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/111954309514719493'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/111954309514719493'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2005/06/prohibited-from-using-wagon.html' title='Prohibited from using the wagon'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-111876905268264779</id><published>2005-06-14T09:49:00.000-07:00</published><updated>2011-03-26T11:57:31.343-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='blogdoc'/><title type='text'>Vellum is a Gnome Canvas Application</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://dl.dropbox.com/u/19400544/strongdynamic.blogspot.com/Vellum%20screen%20shot%2C%202005.06.13_19128089.jpg"&gt;&lt;img style="float: right; margin: 0pt 0pt 10px 10px; cursor: pointer; width: 448px; height: 338px;" src="http://dl.dropbox.com/u/19400544/strongdynamic.blogspot.com/Vellum%20screen%20shot%2C%202005.06.13_19128089.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;I have successfully made the switch from PyGame to Gnome Canvas in Vellum. While it has been by no means seamless, most of my problems were due to misunderstanding how it works, and general unfamiliarity with graphic programming in general and making drawing tools in particular.&lt;br /&gt;&lt;br /&gt;Vellum maps now have scrollbars, which I never managed to implement in PyGame because it doesn't have a scrolling concept. It's not really meant for use with a toolkit, so this shouldn't be surprising.  With Gnome Canvas, the scrollbars were the source of most of my problems. I was using GTK's Viewport widget, and dropping my Canvas in that to get scrollbars. In short, when it's in a Viewport, Canvas isn't double-buffered and it doesn't get the advantage of its infinite-width scrolling areas. In fact, resizing large scroll areas inside a Viewport is VERY slow. It was only when I realized that Canvas has native support for moving scrollbars around that I threw out the Viewport widget and got the performance that Canvas promises. Now the app is very fast, drawing is double-buffered and graphic operations take place near instantly.&lt;br /&gt;&lt;br /&gt;After adding the working scrollbars I gave Vellum two new tools.&lt;br /&gt;&lt;ol&gt;   &lt;li&gt;There's a Pan tool, selectable by clicking on the hand icon in the toolbar. Pan allows you to drag the map around freely without having to reach for the scrollbars. This gives you finer control over what portion of the map you're looking at. I like Pan tools.&lt;/li&gt;   &lt;li&gt;There's a Magnify tool. This works like the magnify tool in Gimp. Click the Zoom button, then click somewhere in the canvas and drag. You get a rectangle which shows you what the inscribed area will be. When you release, the Canvas zooms in and centers on the area you inscribed with your rectangle. This tool will be one of the ones I use the most, as it allows a user to focus on particular aspects of a map or combat.&lt;br /&gt;&lt;/li&gt; &lt;/ol&gt; I will be adding keyboard shortcuts for all these tools in due time. For now I'm going to be taking pride in the fact that I've added a new application area to my repertoire of things I know how to program: Graphic editing applications.&lt;br /&gt;&lt;br /&gt;This also represents another minor milestone for Vellum.  &lt;span style="font-style: italic;"&gt;The GUI actually does something useful&lt;/span&gt;. Granted, it's basically a crippled image viewer at this point, but look at it in context. There's now a way for a GM to share a map with his clients: create a .map file and put it in the server. The clients can connect and get that map, which happens automatically after they type in the right address. And everyone can scroll around or zoom to parts of the map that are interesting, which gives them a shared frame of reference for IRC-based games. It's certainly not earth-shattering, but it's something to dogfood.&lt;br /&gt;&lt;hr /&gt;I promised in my last post to provide more details on how I got Gnome Canvas to compile on Windows. There's really no special magic. If you want to see how it's done:&lt;br /&gt;&lt;tt&gt;&lt;br /&gt;svn co svn://svn.berlios.de/vellum/sandbox/corydodt/canvas&lt;br /&gt;&lt;/tt&gt;&lt;br /&gt;There's a shell script in there to build libgnomecanvas and another one to build gnomecanvas-bindings. Ignore the libgnomecanvas one, as the binaries are checked into that directory as well (no special magic is required to build the C library runtime, it turns out). README.txt will fill in the rest. You just run the shell script, which invokes the code generator (&lt;span style="font-style: italic;"&gt;I know&lt;/span&gt;, I didn't write it), compiles the two C files and links them.&lt;br /&gt;&lt;hr /&gt;&lt;i&gt;Edit: Original post said I switched from "PyGTK", not from "PyGame" which is what I meant.&lt;/i&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-111876905268264779?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/111876905268264779/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=111876905268264779' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/111876905268264779'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/111876905268264779'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2005/06/vellum-is-gnome-canvas-application.html' title='Vellum is a Gnome Canvas Application'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-111809434685913391</id><published>2005-06-06T14:41:00.000-07:00</published><updated>2005-06-06T14:53:42.580-07:00</updated><title type='text'>Gnome Canvas on Win32</title><content type='html'>Compiled libgnomecanvas and its bindings successfully (no errors or warnings!), ran a demo with it.  Have yet to test text rendering or anything moderately complex with it, so cross your fingers.  So far, though, lookin' gooood.  It's compiled "native" (without Cygwin) so it'll be distributable without Cygwin.&lt;br /&gt;&lt;br /&gt;Props to muntyan @ irc.gimp.org for guidance.&lt;br /&gt;&lt;br /&gt;Details to come.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-111809434685913391?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/111809434685913391/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=111809434685913391' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/111809434685913391'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/111809434685913391'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2005/06/gnome-canvas-on-win32.html' title='Gnome Canvas on Win32'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-111787464830019812</id><published>2005-06-04T01:39:00.000-07:00</published><updated>2005-06-04T01:46:04.806-07:00</updated><title type='text'>Why Hacks are Bad</title><content type='html'>So, Pygame in a GTK window is a dead end. It requires the SDL window hack (see vellum/gui/frontend.py for implementation details). This works, with a lot of kludgity, in Python 2.3. I just discovered that it's completely broken again in Python 2.4 if you're on Windows. This, combined with the fundamental problem that you can only have one Pygame window in your program (not "at a time"; ever) makes Pygame a total dead end for Vellum. Maybe I can try to make gnomecanvas bindings compile again. (Sigh of a thousand hurricanes.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-111787464830019812?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/111787464830019812/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=111787464830019812' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/111787464830019812'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/111787464830019812'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2005/06/why-hacks-are-bad.html' title='Why Hacks are Bad'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-111605547121473466</id><published>2005-05-14T00:24:00.000-07:00</published><updated>2011-03-26T11:45:10.603-07:00</updated><title type='text'>Vellum Early Screenshot</title><content type='html'>&lt;div style="float: right; margin-left: 10px; margin-bottom: 10px;"&gt; &lt;a href="http://dl.dropbox.com/u/19400544/strongdynamic.blogspot.com/Vellum%20Early%20Screenshot_13643684.jpg" title="photo sharing"&gt;&lt;img src="http://dl.dropbox.com/u/19400544/strongdynamic.blogspot.com/Vellum%20Early%20Screenshot_13643684.jpg" alt="" style="border: solid 2px #000000;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style=" margin-top: 0px;font-size:0.9em;" &gt;  &lt;a href="http://dl.dropbox.com/u/19400544/strongdynamic.blogspot.com/Vellum%20Early%20Screenshot_13643684.jpg"&gt;Vellum Early Screenshot&lt;/a&gt; &lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;Vellum is really coming along now.  The initial work integrating GTK with Pygame at a basic level is done.  I can download and display icons.  More importantly, I have the framework of the object model for representing these things in the program, and a clear understanding of the requirements.&lt;br /&gt;&lt;br /&gt;In addition, on the IRC bot side, VellumTalk steadily gets smarter and better.  It now understands how to subscribe an irc nick to its private messages channel, so the GM can see the results of all players' secret die rolls (with context).  I'm currently in the process of rewriting the whole parsing mess in IRC using pyparsing, and that's going swimmingly.&lt;br /&gt;&lt;br /&gt;This is the fun part, when development steadily accelerates and things change visibly very quickly.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-111605547121473466?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/111605547121473466/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=111605547121473466' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/111605547121473466'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/111605547121473466'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2005/05/vellum-early-screenshot.html' title='Vellum Early Screenshot'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-111466353029768714</id><published>2005-04-27T20:15:00.000-07:00</published><updated>2005-04-27T21:45:30.300-07:00</updated><title type='text'>Vellum</title><content type='html'>Some interesting challenges in the newest project. Check out &lt;a href="http://vellum.berlios.de/"&gt;http://vellum.berlios.de/&lt;/a&gt; and the project page. Nothing much there yet, but you'll be able to find our source code. So far what we've got is a sandbox with some fine work on a very interesting character model by Aaron Lehmann, and a trunk with some rudimentary GUI code and a surprisingly useful IRC bot I spent a few hours on.&lt;br /&gt;&lt;br /&gt;The goal of the project is to have a non-intrusive RPG client. (See previous post if you think RPG means Rocket-Propelled Grenade.) These are the target features:&lt;br /&gt;&lt;ul&gt;   &lt;li&gt;An HTTP server to deliver data files such as map graphics and character icons&lt;/li&gt;   &lt;li&gt;A graphical client capable of displaying a map with obscurement, icons, scaling, targetting arrows, and other visual effects&lt;br /&gt;  &lt;/li&gt;   &lt;li&gt;A PB server for realtime communication with the GUI clients&lt;br /&gt;  &lt;/li&gt;   &lt;li&gt;An IRC bot, integrated with HTTP and PB, to assist combat interactions, die rolls, and character management.&lt;/li&gt;   &lt;li&gt;Export filters for various character generation programs, in particular &lt;a href="http://pcgen.sf.net/"&gt;PCGen&lt;/a&gt;.&lt;br /&gt;  &lt;/li&gt;   &lt;li&gt;Every component cross-platform.  Runnable on Windows, Linux, Mac, hey maybe a PDA too.&lt;/li&gt; &lt;/ul&gt; What works:&lt;br /&gt;&lt;ul&gt;   &lt;li&gt;There's an HTTP server.  It delivers files.&lt;/li&gt;   &lt;li&gt;There's a PB server.  Right now it only delivers lists of filenames that are served by the HTTP server, along with their checksums and metadata.&lt;/li&gt;   &lt;li&gt;There's a GUI client.  It's written in GTK.  It starts up, has a widget to specify the PB server to connect to, and when it connects it receives the list of files and requests those as well, and verifies their checksums.&lt;br /&gt;  &lt;/li&gt;   &lt;li&gt;There's an export filter for PCGen which writes (most of) the character data as &lt;a href="http://yaml.org"&gt;YAML&lt;/a&gt;.  YAML is almost perfectly-suited for this data format.&lt;/li&gt;   &lt;li&gt;There's a rich character model.  It isn't connected to anything yet, but it's capable of applying a variety of effects to various combat roles.  For example, it knows about ability scores and equipment, and how to calculate armor class based on these things.  (This is more complex than it sounds.  Take a look at the code.)&lt;/li&gt;   &lt;li&gt;There's an IRC bot.  It has already proven useful, as we played a full 4.5-hour game session using only the VellumTalk bot and a web server for maps.  It remembers "aliases" right now&lt;br /&gt;  &lt;/li&gt; &lt;/ul&gt; I don't know how far away from a release we are, but I'm pretty happy about the progress so far.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-111466353029768714?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/111466353029768714/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=111466353029768714' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/111466353029768714'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/111466353029768714'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2005/04/vellum.html' title='Vellum'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-110295947340188256</id><published>2004-12-13T09:10:00.000-08:00</published><updated>2004-12-13T09:44:56.706-08:00</updated><title type='text'>PPFRPG4L,Y</title><content type='html'>&lt;h3&gt;Paper/Pencil Fantasy Role-Playing Games for Life, Yo&lt;/h3&gt;Or at least until everyone has wearable computing.  I'm flexible on the actual dead trees.&lt;br /&gt;&lt;br /&gt;I've been DM'ing this &lt;a href="http://wizards.com/default.asp?x=dnd/welcome"&gt;game&lt;/a&gt; for 17 years now and someone &lt;span style="font-style: italic;"&gt;finally&lt;/span&gt; made a cartography program that is flexible enough and produces good-enough-looking results for artistic nitwits like myself.  &lt;span style="font-style: italic;"&gt;And&lt;/span&gt; it's powerful enough to produce the frequently-quite-unusual-and-challenging maps I like to produce for my games.  It's &lt;a href="http://www.dundjinni.com/"&gt;Dundjinni&lt;/a&gt;. The best part is the ease-of-use, oh and the user art, oh and the cross-platformality, oh and the actually-quite-surprisingly-good builtin adventure authoring tools. The tools have automatic statblock generation, give you lots of places to organize text, include room-by-room authoring, and produce printable pages that actually look good.&lt;br /&gt;&lt;br /&gt;The neatest part of the authoring tools is that they're actually integrated with the mapmaking, which is surprising given the raster-based nature of Dundjinni. The way it works is you paint the map layout, stamp objects on the map, and Dundjinni remembers what the object is. This sounds trivial, but remember that Dundjinni is &lt;span style="font-style: italic;"&gt;not&lt;/span&gt; tile-based; everything is done with stamping PNGs into place, and you can even use an eraser on the stamped images to shape them or remove parts of them as desired. Dundjinni apparently remembers the bit pattern (in technical terms I think this would be known as collision area) for every single object on the map, even if the object is not contiguous. It's almost a given that you can move around, rotate, resize, and edit each object after it has been placed on the map, but then DJ takes this concept a step further and remembers that objects have certain categories they fall into, with game-rules implications: Right-click on a treasure chest, and you can create a list of treasure items to put into it; right-click on a "token" (monster icon) and you can fully edit its D20 stats and description, or load the stats from the included database of d20-SRD (and other) monsters.&lt;br /&gt;&lt;br /&gt;Then as a final step, you use any of the paint tools--paintbrush, bucket fill, marquee, whatever--and create a visible (to the map maker) colored region that corresponds to one numbered room or encounter. Every object that overlaps that region, even partially, is listed in the room's contents. For example, when the adventure prints out, monsters in that region will have their statblocks appear in the description of that room. You can even have more than one room overlapping a single object, which makes sense for doors, for example.&lt;br /&gt;&lt;br /&gt;This is all brilliant, and works together terribly well. DJ is still obviously a young product, and could use some usability and performance enhancements, but they absolutely worked on the right things for their version 1.0 and created an insanely useful DM tool.&lt;br /&gt;&lt;br /&gt;I expect an open-source version of DJ will show up in 3-4 years or so.&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-110295947340188256?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/110295947340188256/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=110295947340188256' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/110295947340188256'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/110295947340188256'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2004/12/ppfrpg4ly.html' title='PPFRPG4L,Y'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-110037619151314417</id><published>2004-11-13T09:40:00.000-08:00</published><updated>2004-11-13T14:21:03.630-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='blogdoc'/><title type='text'>Making XML Suck Less</title><content type='html'>&lt;a href="http://xmlsucks.org/"&gt;XML sucks&lt;/a&gt;. It's axiomatic these days, except to those corporate code-jockeys who happily implement everything their pointy-haired bosses tell them is buzzword compliant. (Many, I'm sure, do it to keep their job; just as many, I feel, probably do it because they believe their own bullshit.)&lt;br /&gt;&lt;br /&gt;One of the corrollaries of "XML Sucks" is "the great tools are what make XML suck less." And the pro-XML faction firmly believe that XML is what makes it possible to implement those great tools. I hold to another point of view. XML Sucks, the tools for processing XML suck, and XML makes it harder to implement those tools. But it is possible to write tools that don't suck, and that &lt;span style="font-style: italic;"&gt;would&lt;/span&gt; make XML suck less.&lt;br /&gt;&lt;br /&gt;There are a few bright points.  Frameworks like &lt;a href="http://nevow.com/"&gt;Nevow&lt;/a&gt; make XML generation both elegant and idiot-proof. Tools like &lt;a href="http://utidylib.berlios.de/"&gt;uTidylib&lt;/a&gt; and &lt;a href="http://www.crummy.com/software/BeautifulSoup/"&gt;BeautifulSoup&lt;/a&gt; make it possible to clean up other peoples' garbage. And some of the standards for XML are actually useful. CSS is simply an awesome way to change the appearance of a rendered document. &lt;a href="http://www.relaxng.org/"&gt;Relax-NG&lt;/a&gt; provides a way to define a valid XML format without the awfulness of a DTD or the brain-numbing pedantry of a schema, and even has a &lt;a href="http://www.relaxng.org/compact-tutorial-20030326.html"&gt;compact form&lt;/a&gt;. (An aside: the word "compact" gets applied to a lot of XML-related technologies. It's actually code for "you don't have to use that awful XML crap to write this, you can use a more sensible syntax instead." Examples: XSLTXT, Relax-NG compact.) And then there's &lt;a href="http://www.zvon.org/xxl/XPathTutorial/General/examples.html"&gt;XPath&lt;/a&gt; which provides a concise way to get a set of nodes from a document, and is extensible.&lt;br /&gt;&lt;h3&gt;Extending XPath&lt;br /&gt;&lt;/h3&gt;I want to use XPath on a project I'm working on. (If it goes anywhere, I'll blog about that too.) To use XPath, you generally have to provide some extension functions. This is because XPath's set of core functions, while sensible, can't do some basic operations. That other standards support. For example, you can interact with a CSS stylesheet by multiclassing nodes, like this:&lt;br /&gt;&lt;code&gt;&amp;lt;div class="important"&amp;gt;1. You should turn your car on before attempting to drive it.&amp;lt;/div&amp;gt;&lt;br /&gt;&amp;lt;div class="dangerous"&amp;gt;2. If you drop a lit match in the gas tank, bad things will happen.&amp;lt;/div&amp;gt;&lt;br /&gt;&amp;lt;div class="important dangerous"&amp;gt;3. Don't drink and drive.&amp;lt;/div&amp;gt;&lt;br /&gt;&amp;lt;div class="dangerous important"&amp;gt;4. Use tire chains when driving on an icy road.&amp;lt;/div&amp;gt;&lt;br /&gt;&amp;lt;div class="not-important"&amp;gt;5. Your glove compartment can be used to store maps.&amp;lt;/div&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;This applies both the important and dangerous styles to the node last node, whatever that means. In CSS, it probably specifies an appearance, but other applications acting on the same file may also want to get those classes. XPath can't select a node that uses classes in this way. Consider how we might select the nodes with class 'important'.&lt;br /&gt;&lt;code&gt;//*[@class='important']                # only matches (1), not (3) or (4)&lt;br /&gt;//*[starts-with("important", @class)]  # only matches (1) and (3)&lt;br /&gt;//*[contains("important", @class)]     # matches (1), (3) and (4) .. oops, and (5) too.&lt;/code&gt;&lt;br /&gt;After trying libxml2 and having it crash the Python interpreter on me (this is the second time I've given it a try; there won't be a third) I installed pyxml 0.8.3. First thing I had to do was figure out how to implement an extension function for using regular expressions, such that:&lt;br /&gt;&lt;a name="_above"&gt;&lt;/a&gt;&lt;code&gt;//*[&lt;span style="font-style: italic;"&gt;func&lt;/span&gt;("\bimportant\b", @class)]&lt;/code&gt;&lt;br /&gt;returns the nodes I want, by regular expression selection.&lt;br /&gt;&lt;br /&gt;First I learned that namespaces in XPath are, quite naturally, XML namespaces.  Therefore, to call &lt;code&gt;func&lt;/code&gt; I needed to define a namespace, analogous a Python module, for it to live in. I chose an arbitrary URL at a hypothetical developer.berlios.de website for the hypothetical project I'm working on: "http://bypath.berlios.de/2004/11/bypath". This string is itself the namespace; when you want to refer to the namespace, you use an alias, called a prefix.&lt;br /&gt;&lt;br /&gt;Then I wrote the first version of my extension function:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;def simpleSearchRe(ctx, expr, input):&lt;br /&gt;    return re.search(expr, input) is not None&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Some things to note. &lt;code&gt;simpleSearchRe&lt;/code&gt; takes three arguments, not two. The first argument is the XPath evaluation context object, which pyxml always passes to extension functions. &lt;code&gt;simpleSearchRe &lt;/code&gt;returns True or False, not a string or a node or a nodelist or something else; so it can be used to filter nodes in an XPath expression in exactly the manner I demonstrated &lt;a href="#_above"&gt;above&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Once you have an extension function and a namespace, making the actual XPath binding is simplicity itself.  The code:&lt;br /&gt;&lt;code&gt;xpath.g_extFunctions.update({...})&lt;/code&gt;&lt;br /&gt;The dict you pass maps a (namespace, function-name) tuple to the actual function.  Example:&lt;br /&gt;&lt;code&gt;xpath.g_extFunctions.update({("http://bypath.berlios.de/2004/11/bypath", "simple-search-re"): simpleSearchRe})&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Unfortunately the above implementation of simpleSearchRe is too naïve for my desired use.  For example, this works:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;//*[by:simple-search-re('\bimportant\b', string(@class))]&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;but not my example.  This returns a RuntimeError:&lt;br /&gt;&lt;code&gt;//*[by:simple-search-re('\bimportant\b', @class)]&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Since developers familiar with XPath will expect both to work, I had to dig deep to find out what was happening.  Finally I learned that @class becomes a list of nodes with one item, and my function tries to treat it like a string.  There's a big gotcha: a bug in pyxml makes it appear that my code isn't even being called, because &lt;code&gt;simpleSearchRe&lt;/code&gt; does not appear in the traceback call stack anywhere.  In fact what's happening is my code is raising a simple TypeError, and pyxml then eats that error and issues its own, in a different part of the code.&lt;br /&gt;&lt;br /&gt;This revised version worked:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;def simpleSearchRe(ctx, expr, input):&lt;br /&gt;    # convert a node, nodelist or a string to a string&lt;br /&gt;    input = xpath.Conversions.StringValue(input)&lt;br /&gt;    return re.search(expr, input) is not None&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The full module, demonstrating how one extends pyxml's xpath with new functions:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;from xml.dom import minidom&lt;br /&gt;from xml import xpath&lt;br /&gt;import re&lt;br /&gt;&lt;br /&gt;# define a namespace&lt;br /&gt;BYPATH_NAMESPACE = 'http://bypath.berlios.de/2004/11/bypath'&lt;br /&gt;&lt;br /&gt;# define a function capable of coercing its arguments to strings and &lt;br /&gt;# operating on them&lt;br /&gt;def simpleSearchRe(ctx, expr, input):&lt;br /&gt;    # convert a node or a string to a string&lt;br /&gt;    input = xpath.Conversions.StringValue(input)&lt;br /&gt;    return re.search(expr, input) is not None&lt;br /&gt;&lt;br /&gt;# add the function to the global list of extension functions, bound to &lt;br /&gt;# an xpath name in an xml namespace&lt;br /&gt;xpath.g_extFunctions.update({(BYPATH_NAMESPACE, 'simple-search-re'): &lt;br /&gt;                             simpleSearchRe})&lt;br /&gt;&lt;br /&gt;# test doc&lt;br /&gt;doc = minidom.parseString('&amp;lt;y class="aa bb"&amp;gt;&amp;lt;x class="b a c"/&gt;&amp;lt;/y&amp;gt;')&lt;br /&gt;&lt;br /&gt;# create a context which knows about our namespace&lt;br /&gt;ctx = xpath.CreateContext(doc)&lt;br /&gt;ctx.setNamespaces({'by':BYPATH_NAMESPACE})&lt;br /&gt;&lt;br /&gt;xeval = lambda expr: xpath.Evaluate(expr, context=ctx)&lt;br /&gt;&lt;br /&gt;# tests&lt;br /&gt;print xeval('//*')&lt;br /&gt;print xeval(r'//*[by:simple-search-re("\ba\b", string(@class))]')&lt;br /&gt;print xeval(r'//*[by:simple-search-re("\ba\b", @class)]')&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-110037619151314417?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/110037619151314417/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=110037619151314417' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/110037619151314417'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/110037619151314417'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2004/11/making-xml-suck-less.html' title='Making XML Suck Less'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-109985112304840172</id><published>2004-11-07T09:25:00.000-08:00</published><updated>2004-11-11T13:54:04.253-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='blogdoc'/><title type='text'>Experiments in Writing an Offline Blog</title><content type='html'>I did a very strange thing yesterday. I wrote a blog. At least, it might look like a blog if you allowed certain liberties, such as the fact that most blogs don't force you to upload a static HTML file in order to publish a post. I will try to explain why I did this, but I'm going to tell you up front that the explanation will not be satisfying and largely amounts to "because I could". I will also explain how I did it, and that will be more interesting if you have a problem in the same category as mine.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The Problem&lt;/h3&gt;As the author of &lt;a href="http://pbp.berlios.de/"&gt;PBP&lt;/a&gt;, I have to keep the front page updated with news items. Until now I've been doing this by editing an HTML file by had. Well, I hate editing XML by hand, and while HTML at least is supported by editors, they never get the markup quite right. The editor I'm using right now to generate this blog entry is doing ugly things like using font style attributes and making guesses about where my line breaks should go. For prose on my blog, that's acceptable, but I expect a certain precise format for my "professional" projects.&lt;br /&gt;&lt;br /&gt;Frustrated with the errors I was constantly making getting the news file just right, I decided to make news entries something much simpler to type. I've been doing a lot of successful experimenting with &lt;a href="http://yaml.org/"&gt;YAML&lt;/a&gt; lately, and although I had previously decided it was more appropriate for "data" formats than "document" formats (whatever you think that means) I figured news entries were brief enough and structured enough that YAML might be appropriate.&lt;br /&gt;&lt;br /&gt;I also needed a way to render the YAML to HTML.  Well, I already had this, in &lt;a href="http://nevow.org/"&gt;Nevow&lt;/a&gt;. Of course, you can't run your own webserver on BerliOS, and Nevow isn't really appropriate for CGI yet, and in any case I have no need yet for this level of control. I just needed a way to generate the static HTML file that I was at the time generating by hand.&lt;br /&gt;&lt;br /&gt;When I was done I wanted a tool I could run on a YAML file, which would plug my news items into a template and give me an HTML document suitable for posting on the web. Then in the future, when I want to edit my news items, I only have to edit a YAML file. As YAML is much more readable and writeable than XML and need contain only the dynamic part of the page (the news items) instead of all of it, this would less onerous a chore. As a bonus, if I made a formatting mistake, I should get a parse error instead of hiding the problem behind a web browser's sorta-error-correcting rendering engine.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The Implementation: An "Offline Blog"&lt;/h3&gt;The implementation for this is available in PBP's svn repository, which you can check out with the command&lt;br /&gt;&lt;pre&gt;svn co svn://svn.berlios.de/pbp/trunk pbp&lt;/pre&gt;I will refer to parts of this by their location relative to the root of the working copy, so (for example) &lt;span style="font-family:courier new;"&gt;/doc/pbp.xhtml&lt;/span&gt; refers to &lt;span style="font-family:monospace;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;svn://svn.berlios.de/pbp/trunk/doc/pbp&lt;/span&gt; in the repository and &lt;span style="font-family:courier new;"&gt;pbp/doc/pbp.xhtml&lt;/span&gt; in the working copy.&lt;br /&gt;&lt;br /&gt;Step one was getting Nevow to render a static HTML file. Fortunately this is easy. There are two ways to do it. One is the newly-added &lt;span style="font-family:courier new;"&gt;Page.renderSynchronously&lt;/span&gt; method, which returns a rendered HTML file. The other is to start and stop a reactor and use plain old callbacks to finish rendering. The former method is fine if you are sure you'll never need to execute anything asynchronously while publishing the file (therefore needing real deferred handling), but I figured I would go ahead and use the reactor in case I ever made a GUI out of this.&lt;br /&gt;&lt;br /&gt;First I designed a template: &lt;span style="font-family:courier new;"&gt;/doc/pbp.xhtml&lt;/span&gt;. I won't go into the details of Nevow templates, and this one is completely unremarkable. Only two interesting things will be plugged in: the latest released version, which appears in the template as &lt;span style="font-family:courier new;"&gt;&amp;lt;n:slot name='latest' /&amp;gt;&lt;/span&gt;, and the news items, which appear as &lt;span style="font-family:courier new;"&gt;&amp;lt;n:invisible render='news' /&amp;gt;&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Then I needed some data to put into the template. I had to learn up a bit on YAML, but I came up with &lt;span style="font-family:courier new;"&gt;/doc/news.yml&lt;/span&gt; with very little trouble. (Tip: To use &amp;gt;-style folding, you need to indent &lt;span style="font-style: italic;"&gt;everything &lt;/span&gt;in the block, even paragraph separators.  A paragraph separator is actually a line containing only &lt;span style="font-style: italic;"&gt;n &lt;/span&gt;blank spaces between two paragraphs, where &lt;span style="font-style: italic;"&gt;n &lt;/span&gt;is the number of spaces the preceding paragraph is indented.) The YAML document contains two items, "release:" which contains the version of the most recent release, and "news:" which is a sequence of all the news items, ever. Each news item in turn is a map of three items, "date:", "title:", and "c:" which stands for content. The important thing to see is how &lt;span style="font-style: italic;"&gt;simple&lt;/span&gt; it is to add new items to this file, and how extremely readable the file is. And since it's done with YAML, I didn't have to write my own parser for the format, as &lt;a href="http://www.pyyaml.org/cgi-bin/trac.cgi"&gt;PyYaml&lt;/a&gt; already exists.&lt;br /&gt;&lt;br /&gt;To parse this file into native Python data types is just one call:&lt;br /&gt;&lt;pre&gt;ydata = list(yaml.loadFile(yamlfile))[0]&lt;/pre&gt;&lt;span style="font-family:courier new;"&gt;yaml.loadFile&lt;/span&gt; returns a stream of YAML documents, and is designed for streaming data. I turn this generator into a list with &lt;span style="font-family:courier new;"&gt;list()&lt;/span&gt; and take the first (zero'th) item from it, as there is only one YAML document there.&lt;br /&gt;&lt;br /&gt;To go with the template I needed a &lt;span style="font-family:courier new;"&gt;rend.Page&lt;/span&gt; subclass, which is &lt;span style="font-family:courier new;"&gt;news2html.Page&lt;/span&gt; in &lt;span style="font-family:courier new;"&gt;/doc/news2html.py&lt;/span&gt;. I pass &lt;span style="font-family:courier new;"&gt;ydata&lt;/span&gt; to the &lt;span style="font-family:courier new;"&gt;Page&lt;/span&gt; and the news items and release version are extracted in &lt;span style="font-family:courier new;"&gt;Page.render_news&lt;/span&gt; and &lt;span style="font-family:courier new;"&gt;Page.render_download&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Now there was just one problem left to solve. I wanted to be able to put links in my HTML documents, of the form &lt;span style="font-family:courier new;"&gt;&amp;lt;a href='...'&amp;gt;blah blah&amp;lt;/a&amp;gt;&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;A Secret Friend&lt;/h3&gt;I considered several possibilities for the problem of HTML linking. One was to have a sequence of links as an item at the top of the YAML document, and make references to that, but this would have significantly increased the work typing each entry, even the ones without links... and most of the entries do not have links. I chose instead to make a small concession to the Wiki way of doing things and write links like this: &lt;span style="font-family:courier new;"&gt;[I am the text around the href which is http://foo.com/bar]&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;To do this I needed a parser. Let it be said that I have never had any luck writing my own parsers for anything, and even extremely simple parses like this have stymied me in the past. I don't know but for some reason I &lt;span style="font-style: italic;"&gt;suck&lt;/span&gt; at parsing.  It can be said to be my Achilles heel, the thing I dread doing more than anything else.&lt;br /&gt;&lt;br /&gt;Perhaps that will no longer be true. At the suggestion of deltab on IRC, I looked into an undocumented feature of Python's &lt;span style="font-family:courier new;"&gt;sre&lt;/span&gt; module, &lt;span style="font-family:courier new;"&gt;sre.Scanner&lt;/span&gt;. This provides a simple scanning interface which lets you define tokens with regular expressions--a common tactic in parsing-helper modules--and then bind them to callbacks. You create a Scanner object initializing it with a list of the tokens, in the order that they should be matched. There were only three interesting tokens for me: bracketed links, "[[" which I intended to allow as an escape for the [ character, and everything else. The code to emit &amp;lt;a&amp;gt; links is below:&lt;br /&gt;&lt;pre&gt;def got_char(scanner, token): return token&lt;br /&gt;&lt;br /&gt;def got_bracket(scanner, token): return '['&lt;br /&gt;&lt;br /&gt;def got_link(scanner, token):&lt;br /&gt;   # strip start and end brackets&lt;br /&gt;   token = token[1:-1]&lt;br /&gt;&lt;br /&gt;   words = token.split()&lt;br /&gt;   url = words[-1]&lt;br /&gt;   rest = ' '.join(words[:-1])&lt;br /&gt;&lt;br /&gt;   return T.a(href=url)[rest]&lt;br /&gt;&lt;br /&gt;tokens = [(r'\[\[', got_bracket),&lt;br /&gt;     (r'\[[^\]]+\]', got_link),&lt;br /&gt;     ('.', got_char),&lt;br /&gt;     ]&lt;br /&gt;scanner = sre.Scanner(tokens)&lt;br /&gt;...&lt;br /&gt;scanner.scan(para)&lt;/pre&gt;&lt;br /&gt;If you look at my code in news2html.py, you'll see that I later on added scanning to fix double and single quotes, turning them into double and single “smart” quotes.&lt;br /&gt;&lt;br /&gt;As finishing touches, I added the command line option &lt;span style="font-family:courier new;"&gt;--count&lt;/span&gt; to control how many news items will appear in the generated page, and allowed an additional command line parameter to control which template is used to generate the HTML page.&lt;br /&gt;&lt;h3&gt;Next Steps&lt;/h3&gt;RSS! I added a &lt;span style="font-family:courier new;"&gt;--output&lt;/span&gt; command line option, and for my next project I'll be using news2html to generate a feed for PBP. Not that many people will notice or care, but when it's this easy why not make it available for those who do?&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-109985112304840172?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/109985112304840172/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=109985112304840172' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/109985112304840172'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/109985112304840172'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2004/11/experiments-in-writing-offline-blog.html' title='Experiments in Writing an Offline Blog'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-109961291829856452</id><published>2004-11-04T15:23:00.000-08:00</published><updated>2004-11-06T11:15:38.676-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='blogdoc'/><title type='text'>apt-get install antidote</title><content type='html'>&lt;h3&gt;New Distro #73&lt;/h3&gt;OK, so I've started to play with Ubuntu. Kick-ass distribution. Installed without a hitch on a server, a desktop machine, 4 Sony laptops and one Dell laptop. And by 'installed' I mean: got the screen resolution, sound, and network cards right, first try, &lt;span style="font-style: italic;"&gt;no human intervention&lt;/span&gt;. Two different kinds of wireless network cards in that group, and the server's network card is a funky dual Intel one that no other distribution has picked up yet out of the box. Knoppix couldn't even do that.&lt;br /&gt;&lt;br /&gt;There's one small problem, and it is small (smaller than I thought it was, even): not all Debian packages are available out of the box. They only support a subset (a large subset) of Debian's recent vintage packages.&lt;br /&gt;&lt;br /&gt;I needed winbind, first thing, and that package is not in Ubuntu. So I did what I have been told time and again never to do: I added the Debian sid archive to &lt;span style="font-family:courier new;"&gt;/etc/apt/sources.list&lt;/span&gt; and fired up Synaptic to install the winbind package. This went off without a hitch, but on my next upgrade I ended up upgrading &lt;span style="font-weight: bold;"&gt;hundreds&lt;/span&gt; of packages to sid, since sid is now slightly more recent than Ubuntu for very uninteresting reasons.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Oops&lt;/h3&gt;This messed up Ubuntu's nice desktop layout.  Realizing I didn't want to keep it that way, I then &lt;span style="font-weight: bold;"&gt;removed&lt;/span&gt; the sid repositories from sources.list and then downgraded to the Ubuntu versions of a few of the desktop packages using an old apt trick:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;$ sudo apt-get install gnome-system-tools=1.0.0-0ubuntu7&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This was fine, got my desktop back to pretty again. I knew I still had loads of "foreign" packages installed on my system, but I resolved not to think about it too hard.&lt;br /&gt;&lt;br /&gt;But pretty soon I needed another package. This one happened to be python-dev. The Python package structure in Debian (and therefore Ubuntu) is a rat's nest of weird, exact-version dependencies. If you try to mix repositories on Python, you will end up reinstalling hundreds of packages, even using the trick above. Wait, that's an exaggeration: in my case, the number was actually &lt;span style="font-weight: bold;"&gt;76&lt;/span&gt; &lt;span style="font-weight: bold;"&gt;packages&lt;/span&gt; that had to be reinstalled because I • already had Debian's sid version of Python installed and • needed to install one from Ubuntu. In order to use the apt trick above to fix this problem, I would have had to look up the most recent Ubuntu version of all 76 of those packages (using &lt;span style="font-family:courier new;"&gt;apt-cache showpkg&lt;/span&gt;) and then type each one on the command line. If I'm smart, maybe I could write a little Python code to help me build the list, but it would still be a monstrous pain in the ass.&lt;br /&gt;&lt;br /&gt;I have torn my hair out on this issue many times before, when I did things like install Debian sarge and then install everything from backports.org, or try to add one sid package to a woody system and end up installing hundreds of unwanted packages. My conclusion has always been: you can't go back. You're stuck with your mixed repositories, and you'll end up upgrading everything under the sun. Hope everything keeps working right! :-)&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;You Can Go Home Again&lt;/h3&gt;Turns out that's not true.  The solution turns out to be quite simple.  There's a file called &lt;span style="font-family:courier new;"&gt;apt_preferences&lt;/span&gt; by the man page.  It's in &lt;span style="font-family:courier new;"&gt;/etc/apt/preferences&lt;/span&gt;. It controls where you get packages from, and under what conditions, when you have multiple sources in sources.list. It makes filters by combining groups of three facts:&lt;br /&gt;&lt;ul&gt;   &lt;li&gt;What packages the filter applies to, with "Package:"&lt;br /&gt;&lt;/li&gt;   &lt;li&gt;Where those packages come from, with "Pin:"&lt;br /&gt;&lt;/li&gt;   &lt;li&gt;How high a priority you want to set for the filtered packages, with "Pin-Priority:"&lt;br /&gt;&lt;/li&gt; &lt;/ul&gt; Basically you say, "for these packages, if they're coming from this location, install them with this much priority." You can, for example, use &lt;span style="font-family:courier new;"&gt;apt_preferences&lt;/span&gt; to set a priority of 0 which says "Don't install the package from here, ever." I wanted just the opposite, the most forceful priority possible. A priority &gt; 1000 says "Install packages from this location, no matter what, even if they're less recent than the one already installed." Used like this, it forces Ubuntu to downgrade everything on your system to the version in Ubuntu:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Package: *&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Pin: release a=warty&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Pin-Priority: 1001&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Once you've made this setting, just do an &lt;span style="font-family:courier new;"&gt;apt-get upgrade&lt;/span&gt;. I don't promise it'll be smooth as glass; packages aren't tested for downgrading, let alone downgrading across distributions. At worst you will have to run it a few times, and possibly manually select a few packages to remove completely to prevent conflicts, but it does work. I just used it to downgrade 466 packages from sid to warty. :-)&lt;br /&gt;&lt;br /&gt;So &lt;span style="font-style: italic;"&gt;then &lt;/span&gt;they tell me about the &lt;span style="font-family:courier new;"&gt;universe &lt;/span&gt;repository, which is where I &lt;span style="font-weight: bold;"&gt;should&lt;/span&gt; have found winbind. . .&lt;br /&gt;&lt;h3&gt;By the Way&lt;/h3&gt;Don't forget to change your &lt;span style="font-family:courier new;"&gt;apt_preferences&lt;/span&gt; &lt;span style="font-style: italic;"&gt;back&lt;/span&gt; to the way it comes out of to the box (missing). Just delete it when you're done. Otherwise, you won't get security updates, because &lt;span style="font-family:courier new;"&gt;warty/security&lt;/span&gt; doesn't match the Pin you specified in &lt;span style="font-family:courier new;"&gt;apt_preferences&lt;/span&gt;.  Once you've gotten rid of the &lt;span style="font-family:courier new;"&gt;preferences &lt;/span&gt;file, do another &lt;span style="font-family:courier new;"&gt;apt-get upgrade &lt;/span&gt;and you'll re-get the most recent security updates.&lt;br /&gt;&lt;h3 style="font-style: italic;"&gt;Update&lt;/h3&gt;&lt;br /&gt;In addition to &lt;span style="font-family:courier new;"&gt;universe&lt;/span&gt;, I recently learned how to enable the &lt;span style="font-family:courier new;"&gt;multiverse&lt;/span&gt; repository and I feel it deserves a mention because useful things like browser plugins live there. Add this to your &lt;span style="font-family:courier new;"&gt;sources.list&lt;/span&gt;:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;deb http://archive.ubuntu.com/ubuntu/ warty multiverse&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-109961291829856452?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/109961291829856452/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=109961291829856452' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/109961291829856452'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/109961291829856452'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2004/11/apt-get-install-antidote.html' title='apt-get install antidote'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8734577.post-109785458821587840</id><published>2004-10-15T08:35:00.000-07:00</published><updated>2004-10-15T20:30:59.386-07:00</updated><title type='text'>My Blog</title><content type='html'>I created an account so I could comment on other blogs :-)  Dunno if I will ever use this.&lt;br /&gt;&lt;br /&gt;Maybe I'll publish my &lt;a href="http://freemind.sf.net"&gt;mind&lt;/a&gt; &lt;a href="http://twistedmatrix.com/trac/infogreater/trac"&gt;map&lt;/a&gt; here or something.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8734577-109785458821587840?l=strongdynamic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://strongdynamic.blogspot.com/feeds/109785458821587840/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8734577&amp;postID=109785458821587840' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/109785458821587840'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8734577/posts/default/109785458821587840'/><link rel='alternate' type='text/html' href='http://strongdynamic.blogspot.com/2004/10/my-blog.html' title='My Blog'/><author><name>Cory</name><uri>http://www.blogger.com/profile/16763371844879659730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos7.flickr.com/9622756_84df9c2807_o.jpg'/></author><thr:total>0</thr:total></entry></feed>
