<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Kooneiform</title>
	<atom:link href="http://kooneiform.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://kooneiform.wordpress.com</link>
	<description>writing  +  text  +  games</description>
	<lastBuildDate>Tue, 03 Nov 2009 06:40:13 +0000</lastBuildDate>
	<generator>http://wordpress.com/</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<cloud domain='kooneiform.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://www.gravatar.com/blavatar/b7bfdea260bb55838222f494beb2a4e7?s=96&#038;d=http://s.wordpress.com/i/buttonw-com.png</url>
		<title>Kooneiform</title>
		<link>http://kooneiform.wordpress.com</link>
	</image>
			<item>
		<title>The IGF cometh</title>
		<link>http://kooneiform.wordpress.com/2009/11/02/the-igf-cometh/</link>
		<comments>http://kooneiform.wordpress.com/2009/11/02/the-igf-cometh/#comments</comments>
		<pubDate>Tue, 03 Nov 2009 06:00:58 +0000</pubDate>
		<dc:creator>georgek</dc:creator>
				<category><![CDATA[games]]></category>

		<guid isPermaLink="false">http://kooneiform.wordpress.com/?p=409</guid>
		<description><![CDATA[The IGF main competition entries are up, bigger by a third than last year (which was bigger by a third than the year before apparently). Will it be bigger and badder though? Such remains to be seen, but there definitely were some that caught my eye:
7 Nights: &#8220;&#8221;7 Nights&#8221; shows that a quality AAA-style 3D [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=kooneiform.wordpress.com&blog=108553&post=409&subd=kooneiform&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p><a href="http://www.igf.com/index.html">The IGF</a> main competition entries are up, bigger by a third than last year (which was bigger by a third than the year before apparently). Will it be bigger and <strong><em>badder</em></strong> though? Such remains to be seen, but there definitely were some that caught my eye:</p>
<p><strong>7 Nights</strong>: &#8220;&#8221;7 Nights&#8221; shows that a quality AAA-style 3D first person shooter can be deployed on the web and could be created in about 7 MB.</p>
<p>This is also the first videogame in the world that was created and tested while on public transportation (Seattle Sound Transit Routes 545 &amp; 577)&#8221;. Represent!</p>
<p><strong>78641</strong>: &#8220;Saluton!! GZ Storm is now proudly to present – 78641 – the classic Esperanto-language adventure game now playing first time in Language English!!!&#8221;</p>
<p><strong>A Slow Year</strong>: &#8220;A Slow Year is a collection of four games, one for each season, about the expereince of observing things. Played on the Atari Video Computer System (aka Atari 2600), the game invites sedate observation and methodical action.</p>
<p>A Slow Year is a kind of videogame chapbook, a set of &#8220;game poems&#8221; that attempt to embrace maximum expressive constraint and representational condensation. The game will be available for PC and Mac in a custom Atari emulator, and for Atari as a limited edition cartridge and poetry set.&#8221;</p>
<p><strong>Achron</strong>: &#8220;Achron is the first &#8220;meta-time strategy&#8221; game. It is a real-time strategy game where all players can simultaneously travel through time, change the past, preview the future, and send their forces through time to when they are needed.&#8221;</p>
<p><strong>ARGH: Augmented Reality Ghost Hunter</strong>: &#8220;ARGH is an augmented reality game that lets you use your Ghost Goggles to discover ghosts in your actual environment.</p>
<p>Players collect different ghosts located in physical locations all over the world. Explore the REAL WORLD and experiment with the time of day and time of year to discover the phantoms that share our space.&#8221;</p>
<p>Good lord I&#8217;m not even out of the a&#8217;s. </p>
<p><strong>edit</strong>: Too bad, no parser IF this year. Looks like a few games you could call IF though. </p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/kooneiform.wordpress.com/409/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/kooneiform.wordpress.com/409/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/kooneiform.wordpress.com/409/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/kooneiform.wordpress.com/409/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/kooneiform.wordpress.com/409/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/kooneiform.wordpress.com/409/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/kooneiform.wordpress.com/409/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/kooneiform.wordpress.com/409/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/kooneiform.wordpress.com/409/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/kooneiform.wordpress.com/409/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=kooneiform.wordpress.com&blog=108553&post=409&subd=kooneiform&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://kooneiform.wordpress.com/2009/11/02/the-igf-cometh/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/edacead2fb1ad30f1bf7cf21d1bbea55?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">kooneiform</media:title>
		</media:content>
	</item>
		<item>
		<title>hey there&#8217;s an IFComp!</title>
		<link>http://kooneiform.wordpress.com/2009/10/31/hey-theres-an-ifcomp/</link>
		<comments>http://kooneiform.wordpress.com/2009/10/31/hey-theres-an-ifcomp/#comments</comments>
		<pubDate>Sat, 31 Oct 2009 18:36:01 +0000</pubDate>
		<dc:creator>georgek</dc:creator>
				<category><![CDATA[IF]]></category>

		<guid isPermaLink="false">http://kooneiform.wordpress.com/?p=403</guid>
		<description><![CDATA[I have only two weeks to play the games. Luckily there&#8217;s just 24 this year. Instead of posting here I think I&#8217;ll keep everything at the Intfiction forums. 
       <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=kooneiform.wordpress.com&blog=108553&post=403&subd=kooneiform&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>I have only two weeks to play the games. Luckily there&#8217;s just 24 this year. Instead of posting here I think <a href="http://www.intfiction.org/forum/viewtopic.php?f=32&amp;t=838">I&#8217;ll keep everything at the Intfiction forums</a>. </p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/kooneiform.wordpress.com/403/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/kooneiform.wordpress.com/403/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/kooneiform.wordpress.com/403/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/kooneiform.wordpress.com/403/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/kooneiform.wordpress.com/403/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/kooneiform.wordpress.com/403/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/kooneiform.wordpress.com/403/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/kooneiform.wordpress.com/403/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/kooneiform.wordpress.com/403/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/kooneiform.wordpress.com/403/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=kooneiform.wordpress.com&blog=108553&post=403&subd=kooneiform&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://kooneiform.wordpress.com/2009/10/31/hey-theres-an-ifcomp/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/edacead2fb1ad30f1bf7cf21d1bbea55?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">kooneiform</media:title>
		</media:content>
	</item>
		<item>
		<title>off the mud wire: MiniBoa and playing Maiden Desmodus</title>
		<link>http://kooneiform.wordpress.com/2009/09/07/off-the-mud-wire-miniboa-and-playing-maiden-desmodus/</link>
		<comments>http://kooneiform.wordpress.com/2009/09/07/off-the-mud-wire-miniboa-and-playing-maiden-desmodus/#comments</comments>
		<pubDate>Mon, 07 Sep 2009 20:04:54 +0000</pubDate>
		<dc:creator>georgek</dc:creator>
				<category><![CDATA[muds]]></category>

		<guid isPermaLink="false">http://kooneiform.wordpress.com/?p=393</guid>
		<description><![CDATA[MiniBoa, a minimal Python socket and telnet package
Jim Storch, author of the in development BogBoa, has kindly packaged his socket and telnet modules into a minimal, Python, single-threaded asynchronous telnet server called MiniBoa (think SocketMUD), much to my own delight! The cool thing is, as far as I&#8217;ve found, MiniBoa is the first such package [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=kooneiform.wordpress.com&blog=108553&post=393&subd=kooneiform&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p><strong>MiniBoa, a minimal Python socket and telnet package</strong></p>
<p><a href="http://bogboa.blogspot.com/">Jim Storch</a>, author of the in development <a href="http://code.google.com/p/bogboa/">BogBoa</a>, has kindly packaged his socket and telnet modules into a minimal, Python, single-threaded asynchronous telnet server called <a href="http://code.google.com/p/bogboa/downloads/list">MiniBoa</a> (think SocketMUD), much to my own delight! The cool thing is, as far as I&#8217;ve found, MiniBoa is the first such package to be made available in Python. Up to now your choices were to strip out something from an existing codebase, or use something like Twisted &#8212; which is great, but for learning purposes not the best for people like me. Not only is this a good learning tool but if you want to start writing a mud in Python for fun this is a great solution for the networking side. </p>
<p><strong>Maiden Desmodus</strong><br />
<br />
For the last few weeks I&#8217;ve been playing <a href="http://www.maidendesmodus.com">Maiden Desmodus</a> with my first character &#8212; the first time in a couple years probably that I&#8217;ve done more than just login to a mud to chat or check a place out. As I&#8217;ve found MD suits my casual drop-in play very well, aided in no small part by its Flash client, but also by the somewhat episodic nature of the gameplay. Every other day or so I can drop in and complete a task (a quest in other words, usually a fetch or kill task but sometimes something more involved). Skill progression is time-based on a decreasing power curve so this also encourages playing at the front of the curve if you don&#8217;t have a lot of time (or money, as MD allows you to buy skill progression blessings). Anyway, my physician is level 5!</p>
<p>The game itself is quite fun, and as a pleasant surprise does most of the things that I personally like in a mud. The world is well done and not filled with generic races or silly fantasy names. Its setting is a refreshing mix of dark medievalish fantasy and more Elizabethan to Victorian era stuff (quite a broad cut I know but I like that sort of thing). The skill and guild system is interesting, and the combat is on the shorter and less spammy side thank God. The players also seem to be a good group on the whole. So while I don&#8217;t see myself putting a whole lot of time or money into the game right now  (maybe if I had started playing ten years ago), it&#8217;s definitely worth it to keep playing my character (give Caturige a shout if you see him!). </p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/kooneiform.wordpress.com/393/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/kooneiform.wordpress.com/393/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/kooneiform.wordpress.com/393/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/kooneiform.wordpress.com/393/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/kooneiform.wordpress.com/393/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/kooneiform.wordpress.com/393/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/kooneiform.wordpress.com/393/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/kooneiform.wordpress.com/393/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/kooneiform.wordpress.com/393/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/kooneiform.wordpress.com/393/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=kooneiform.wordpress.com&blog=108553&post=393&subd=kooneiform&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://kooneiform.wordpress.com/2009/09/07/off-the-mud-wire-miniboa-and-playing-maiden-desmodus/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/edacead2fb1ad30f1bf7cf21d1bbea55?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">kooneiform</media:title>
		</media:content>
	</item>
		<item>
		<title>more on messages (a roguelike in Python #17)</title>
		<link>http://kooneiform.wordpress.com/2009/08/17/more-on-messages-a-roguelike-in-python-17/</link>
		<comments>http://kooneiform.wordpress.com/2009/08/17/more-on-messages-a-roguelike-in-python-17/#comments</comments>
		<pubDate>Mon, 17 Aug 2009 20:26:51 +0000</pubDate>
		<dc:creator>georgek</dc:creator>
				<category><![CDATA[roguelike]]></category>

		<guid isPermaLink="false">http://kooneiform.wordpress.com/?p=390</guid>
		<description><![CDATA[Up to now message handling (what gets printed to the message log) was just adding a message string to the log wherever something in the code warranted it. This was simple at first, but required checks to make sure a monster wasn&#8217;t initiating a message (like &#8216;you can&#8217;t go that way&#8217; &#8212; seemed like a [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=kooneiform.wordpress.com&blog=108553&post=390&subd=kooneiform&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Up to now message handling (what gets printed to the message log) was just adding a message string to the log wherever something in the code warranted it. This was simple at first, but required checks to make sure a monster wasn&#8217;t initiating a message (like &#8216;you can&#8217;t go that way&#8217; &#8212; seemed like a bug until I understood what was going on!).</p>
<p>So I&#8217;ve taken the next step to something a little more involved. Here&#8217;s what the message class looks like now;</p>
<pre class="brush: python;">
class Log(object):
    def __init__(self):
        self.history = [&quot;Go!&quot;]
        self.cursor = 0

    def add(self, message, enactor, *string):
        for handler in enactor.handlers:
            if isinstance(enactor.handlers[handler], Messages):
                script = enactor.handlers[handler].script

                if message in script:
                    if string:
                        self.history.append(script[message] % string)
                    else:
                        self.history.append(script[message])
                    self.cursor += 1

            break

    def set_cursor(self, line_number):
        self.cursor = line_number
</pre>
<p>Adding a message now requires the message (which isn&#8217;t the message itself as I&#8217;ll explain), the enactor who initiated it, and an optional string to pass into the message. Using this method looks like this:</p>
<pre class="brush: python;">
game.log.add(&quot;got something&quot;, enactor, target.name)
</pre>
<p>You can see that before anything gets added to the log I check if there&#8217;s a handler in the enactor&#8217;s handlers that is of type <strong>Messages</strong>. This class is a parent class that doesn&#8217;t really do anything, but allows me to subclass off it with handlers that actually do something &#8212; namely, add scripts to the enactor. For example:</p>
<pre class="brush: python;">
class Messages(object):
    def __init__(self):
        self.script = {}

class PlayerMessages(Messages):
    def __init__(self, gid):
        self.gid = gid
        self.script = {
                        &quot;move failed&quot;       : &quot;You can't go that way.&quot;,
                        &quot;opened something&quot;  : &quot;You opened the %s&quot;,
                        &quot;closed something&quot;  : &quot;You closed the %s&quot;,
                        &quot;command not found&quot; : &quot;Try again!&quot;,
                        &quot;got something&quot;     : &quot;You get the %s&quot;,
                        &quot;used inventory item&quot; : &quot;You used inventory item %s&quot;}

    def update(self):
        pass
</pre>
<p>By checking for an instance of Messages I can create many different message subclasses with different scripts, and attach these to actors depending on what messages I want them to have. Once the add method finds a Messages subclass, it checks if the message is in the script, and if so adds it to the log &#8212; with another check if the optional string was passed in as an argument or not. </p>
<p>This should get more interesting once I have messages for other actors &#8212; I can customize a standard message for each script. </p>
<p>I think I can extend this to be able to attach multiple scripts to the same actor &#8212; I&#8217;ll have to change the conditional check in the add method to create a list of handlers that are Messages subclasses, and then run through each handler&#8217;s script to find if a particular message is in there. There could be a problem though if I attach two subclasses that have the same type of message in their scripts &#8212; I&#8217;ll probably just have to add the first one that matches if that case arises. </p>
<p>Also I&#8217;ve been playing around with the UI some more.</p>
<p><img src="http://kooneiform.files.wordpress.com/2009/08/paneselect.png?w=375&#038;h=280" alt="paneselect" title="paneselect" width="375" height="280" class="aligncenter size-full wp-image-391" /></p>
<p>I dropped the idea of the alt key + a number as a secondary use for inventory items &#8212; I&#8217;ll probably have enough to do just adding single uses for items! I also mocked up a pane selection scheme, where the tab key cycles through each pane and highlights it (the inventory pane is highlighted in that screenshot). When you highlight a pane you&#8217;ll get some additional functionality &#8212; scrolling through the message log, examining inventory items, examining things in the viewport, and scrolling through the journal pane (the pane to the right). </p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/kooneiform.wordpress.com/390/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/kooneiform.wordpress.com/390/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/kooneiform.wordpress.com/390/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/kooneiform.wordpress.com/390/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/kooneiform.wordpress.com/390/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/kooneiform.wordpress.com/390/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/kooneiform.wordpress.com/390/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/kooneiform.wordpress.com/390/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/kooneiform.wordpress.com/390/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/kooneiform.wordpress.com/390/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=kooneiform.wordpress.com&blog=108553&post=390&subd=kooneiform&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://kooneiform.wordpress.com/2009/08/17/more-on-messages-a-roguelike-in-python-17/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/edacead2fb1ad30f1bf7cf21d1bbea55?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">kooneiform</media:title>
		</media:content>

		<media:content url="http://kooneiform.files.wordpress.com/2009/08/paneselect.png" medium="image">
			<media:title type="html">paneselect</media:title>
		</media:content>
	</item>
		<item>
		<title>sometimes I like to go through every line of code and just change something</title>
		<link>http://kooneiform.wordpress.com/2009/08/12/sometimes-i-like-to-go-through-every-line-of-code-and-just-change-something/</link>
		<comments>http://kooneiform.wordpress.com/2009/08/12/sometimes-i-like-to-go-through-every-line-of-code-and-just-change-something/#comments</comments>
		<pubDate>Thu, 13 Aug 2009 06:46:16 +0000</pubDate>
		<dc:creator>georgek</dc:creator>
				<category><![CDATA[roguelike]]></category>

		<guid isPermaLink="false">http://kooneiform.wordpress.com/?p=388</guid>
		<description><![CDATA[Usually it&#8217;s for a good reason, to fix something I did earlier for no reason, or maybe for a bad reason that I didn&#8217;t understand at the time.
Up to now I&#8217;ve been passing objects around by referring to the object itself (I guess this is passing by reference? I think this is what Python does [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=kooneiform.wordpress.com&blog=108553&post=388&subd=kooneiform&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Usually it&#8217;s for a good reason, to fix something I did earlier for no reason, or maybe for a bad reason that I didn&#8217;t understand at the time.</p>
<p>Up to now I&#8217;ve been passing objects around by referring to the object itself (I guess this is passing by reference? I think this is what Python does by default). However when you save the game state with yaml (and perhaps with the pickle module too, though I haven&#8217;t investigated this), it saves every reference as the actual object data. For example, if you had an attribute on every thing that referenced a map object, that whole map object including its map array would be saved once for each thing. </p>
<p>That in itself wasn&#8217;t a problem, as you can clear data that you don&#8217;t need to save in your saving routine before you exit the game. However my future plans for the game include a lot of cross-referencing between objects, and I do want to be able to save that state without saving the same object data over and over. </p>
<p>So now instead of passing objects around by reference, each object has a unique game id (the <strong>gid</strong>). This gets created in a thing&#8217;s __init__ method like so:</p>
<pre class="brush: python;">
class Thing(object):
    def __init__(self, name, x, y, properties, *handlers):
        self.gid = id(self)
        while self.gid in game.gids:
            self.gid = self.gid + 1
        game.gids[self.gid] = self
</pre>
<p>The reason for the while loop is if I create a thing after a game has been saved and reloaded, there is a slim chance that a new gid could match an old gid (as I&#8217;m just using Python&#8217;s id() function to create the number). If that does happen, I create a new gid until I have a unique one. </p>
<p>Of course this is not as simple as what I was doing before (though saving is actually a little simpler, as I just save a single dictionary of gids and re-use it when I load it back in). Every time I want to look up a thing&#8217;s properties I need to look up the thing&#8217;s object first in the gids dictionary. Nevertheless I think it&#8217;ll pay off in the long run. </p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/kooneiform.wordpress.com/388/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/kooneiform.wordpress.com/388/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/kooneiform.wordpress.com/388/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/kooneiform.wordpress.com/388/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/kooneiform.wordpress.com/388/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/kooneiform.wordpress.com/388/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/kooneiform.wordpress.com/388/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/kooneiform.wordpress.com/388/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/kooneiform.wordpress.com/388/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/kooneiform.wordpress.com/388/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=kooneiform.wordpress.com&blog=108553&post=388&subd=kooneiform&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://kooneiform.wordpress.com/2009/08/12/sometimes-i-like-to-go-through-every-line-of-code-and-just-change-something/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/edacead2fb1ad30f1bf7cf21d1bbea55?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">kooneiform</media:title>
		</media:content>
	</item>
		<item>
		<title>more of what you see (a roguelike in Python #16)</title>
		<link>http://kooneiform.wordpress.com/2009/08/08/more-of-what-you-see-a-roguelike-in-python-16/</link>
		<comments>http://kooneiform.wordpress.com/2009/08/08/more-of-what-you-see-a-roguelike-in-python-16/#comments</comments>
		<pubDate>Sat, 08 Aug 2009 23:22:41 +0000</pubDate>
		<dc:creator>georgek</dc:creator>
				<category><![CDATA[roguelike]]></category>

		<guid isPermaLink="false">http://kooneiform.wordpress.com/?p=382</guid>
		<description><![CDATA[
Things are getting to the point where this is less of a demo and more of what I want to do in the game itself. I may or may not write a more complete tutorial based on the demo &#8212; I think there&#8217;s more than enough here for people to get familiar and get started [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=kooneiform.wordpress.com&blog=108553&post=382&subd=kooneiform&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p><img src="http://kooneiform.files.wordpress.com/2009/08/dianamessages.png?w=400&#038;h=300" alt="dianamessages" title="dianamessages" width="400" height="300" class="aligncenter size-full wp-image-381" /></p>
<p>Things are getting to the point where this is less of a demo and more of what I want to do in the game itself. I may or may not write a more complete tutorial based on the demo &#8212; I think there&#8217;s more than enough here for people to get familiar and get started with libtcod in general.</p>
<p>I&#8217;ve put in a rudimentary message log in the bottom pane of the display. That skull on the right is from the libtcod package &#8212; I&#8217;m thinking about using the right-hand pane to display images like character portraits, text of signs, books, conversations maybe? The top pane will contain game information views, like inventory and so on. </p>
<p>The command set right now is very simple &#8212; bump to open things (I&#8217;ll extend this to mean operate something that isn&#8217;t otherwise openable), press x to pick things up. Control + direction closes things (or will turn something &#8216;off&#8217;). Control by itself will act on a thing in the same cell as you. I still mean to work in throwing  things, and using things in inventory, but I&#8217;m going to keep the command set simple. I&#8217;d like to use &#8216;z&#8217; for taking an action with something in hand, but allow using anything in inventory (which will be limited) by selecting its inventory number (I think this is what Chickhack does if I remember correctly, I liked it at the time). Control + z then could be used as an undo/rewind, but that&#8217;s so far off I&#8217;m not really thinking about it at the moment. </p>
<p>I&#8217;m going back and forth right now about extending this command set and keeping it simple. I&#8217;m leaning toward keeping it simple, both as a creative constraint and to keep the project size small. The one thing that bugs me about this is I&#8217;d like multiple uses of things (for example, you have a potion you could either drink or throw at something). I may have to accept single-use items if I keep the command set limited. One possibility to open options up a bit is to use inventory-keys for an item&#8217;s primary use (so hitting &#8216;1&#8242;  and then &#8216;enter&#8217; drinks the potion if that&#8217;s inventory item #1) and pressing &#8216;1&#8242; then &#8216;z&#8217; does an item&#8217;s secondary action, which could be throw. In the end I may save multiple-uses for another project&#8230;I don&#8217;t want things to get too convoluted. </p>
<p><strong>update</strong>: don&#8217;t want it too convoluted?&#8230;where&#8217;s the fun in that? I&#8217;ve started trying something I think could work &#8212; using number keys for primary use of the item, and Alt + number for the secondary use. I may be able then to hijack Alt + x as a drop key if I ever want one. </p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/kooneiform.wordpress.com/382/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/kooneiform.wordpress.com/382/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/kooneiform.wordpress.com/382/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/kooneiform.wordpress.com/382/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/kooneiform.wordpress.com/382/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/kooneiform.wordpress.com/382/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/kooneiform.wordpress.com/382/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/kooneiform.wordpress.com/382/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/kooneiform.wordpress.com/382/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/kooneiform.wordpress.com/382/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=kooneiform.wordpress.com&blog=108553&post=382&subd=kooneiform&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://kooneiform.wordpress.com/2009/08/08/more-of-what-you-see-a-roguelike-in-python-16/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/edacead2fb1ad30f1bf7cf21d1bbea55?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">kooneiform</media:title>
		</media:content>

		<media:content url="http://kooneiform.files.wordpress.com/2009/08/dianamessages.png" medium="image">
			<media:title type="html">dianamessages</media:title>
		</media:content>
	</item>
		<item>
		<title>the social space of mudders</title>
		<link>http://kooneiform.wordpress.com/2009/08/04/the-social-space-of-mudders/</link>
		<comments>http://kooneiform.wordpress.com/2009/08/04/the-social-space-of-mudders/#comments</comments>
		<pubDate>Wed, 05 Aug 2009 07:03:25 +0000</pubDate>
		<dc:creator>georgek</dc:creator>
				<category><![CDATA[muds]]></category>

		<guid isPermaLink="false">http://kooneiform.wordpress.com/?p=379</guid>
		<description><![CDATA[I don&#8217;t write much about muds anymore as I haven&#8217;t been playing muds. Nearly all of them are far less suited to casual play that I would like. Nevertheless I still read the various forums, and right now there&#8217;s a long thread over at Mudbytes about a new moderation system the admins there are considering [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=kooneiform.wordpress.com&blog=108553&post=379&subd=kooneiform&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>I don&#8217;t write much about muds anymore as I haven&#8217;t been playing muds. Nearly all of them are far less suited to casual play that I would like. Nevertheless I still read the various forums, and right now there&#8217;s a <a href="http://www.mudbytes.net/index.php?a=topic&amp;t=1910">long thread over at Mudbytes</a> about a new moderation system the admins there are considering implementing. Read on if you&#8217;re curious, but fair warning that this may be interesting only to a very few people. </p>
<p>If you don&#8217;t follow muds, there are three main sites with forums: The Mud Connector, Top Mud Sites, and Mudbytes. Mudbytes is a relative newcomer, in some sense taking the role that MudMagic used to fill (a site which is now closed), indeed, as is often the case with community sites, it got its start partly due to people leaving MudMagic. All things considered I&#8217;d say that Mudbytes is the most vibrant discussion forum currently going. Particularly in the last few months it seems to have gained some new members, and while in my opinion it used to be focused on DIKU-derived codebases, lately it&#8217;s seen a more interesting range of discussion from programming to design. </p>
<p>All of this is a long preamble of context to frame why I&#8217;m posting this. I would have posted in the thread linked above but I felt it wouldn&#8217;t have served much purpose really, and what I&#8217;m trying to do here is get some thoughts out there to figure something out. For the record my nick on Mudbytes is Idealiad. </p>
<p>So what the Mudbytes admin are proposing is a system of moderation with a dedicated forum to contain &#8216;moderation threads&#8217; &#8212; basically reference threads created when any disciplinary action takes place. The basic idea is to create a transparent system so that threads aren&#8217;t derailed with moderation disputes, and make it easier to reference moderation actions without digging up threads all over the forum. Also new moderators would be put in place to do the actual work of modding. The idea for this is derived from another forum with a similar system. </p>
<p>This is all in response to some recent issues with people getting suspensions and threads getting locked over some troll threads and responses that apparently are against various Mudbytes rules. People were crying foul over what they saw as heavy-handed moderation and wanted more transparency and accountability in how the modding went down. </p>
<p>So the proposal thread has developed in an interesting way. First of all my response was against the idea of a moderation sub-forum, but for the idea of new mods. My main beef with the separate sub-forum is that I think it creates an atmosphere of antagonism rather than cooperation. I&#8217;ll try to explain my reasons for thinking that. </p>
<p>I think the &#8216;community energy&#8217; of a site is relatively fixed. How the community chooses to spend that energy influences the tone and direction of the site, how its members will treat each other and how new members will integrate into the established community. So when the community spends its energy in creating an infrastructure to deal with infractions, it is taking away energy from other things. </p>
<p>I have to admit my main influence on this thinking is the time I spend on TIGSource. TIGS is not without moderation of course. People there have been banned and threads locked. In general though, I get the sense that the atmosphere of TIGS is much, much different than that of Mudbytes (to be fair it&#8217;s also a much larger site, and so personal disputes don&#8217;t tend to involve the whole community like they do at Mudbytes, so their impact is somewhat diluted in the grand scheme of things). In essence TIGS spends its community energy on, for lack of a better word, &#8216;positive infrastructure&#8217;. An effort is made to keep things moving in a positive direction. When people trend the other way there is an effort by others to steer the ship to its original course. </p>
<p>As a result of this comparison, I got frustrated with Mudbytes. What I&#8217;d like to see is a similar focus on positive infrastructure, and less on what is in effect an infrastructure for litigation. </p>
<p>What could be the reasons for this difference? My first thought was that it has to do with the nature of mudding itself. Muds are games that primarily are social spaces. Unlike the majority of games on TIGS, a mud is <em>in itself</em> a social space. You certainly can have a community based around a game on TIGS, but this idea of a social space is quite different. There is a long tradition of large hierarchies running muds, with all the rules, sometimes formal and sometimes informal, you would expect in any community. By their nature then, mudders are used to all sorts of frameworks for maintaining this social space, and these frameworks are going to mirror what we see in society at large &#8212; judicial and political systems &#8212; and when the time comes to moderate another social space which they are a member of, like Mudbytes, they&#8217;re going to turn to these same rules and frameworks as the tools they&#8217;re comfortable with. </p>
<p>It&#8217;s not surprising then that in that Mudbytes thread people are not really arguing about the need for such a system of moderation (with one or two exceptions), but instead debating what seems to me more and more elaborate systems of moderation and their finer points of implementation. In essence the die already is cast.</p>
<p>The thing here though is that I think people like this. Whether there is a sub-forum for moderation or not it doesn&#8217;t really matter &#8212; the community at Mudbytes already is oriented toward this way of being. They like going back and forth over who&#8217;s trolling who, what should be modded or shouldn&#8217;t, and all the finer political points in between, and will continue to do so no matter what kind of system is set up.  It&#8217;s kind of like people who go for student government or model UN. In that case a system with more transparency is probably better than a system with less, don&#8217;t you think? </p>
<p>So in the end I guess I have to accept this community for what it is if I want to participate in it. I don&#8217;t know if it&#8217;s possible for it to <em>be </em>different, more like TIGS or something like it. In effect its social space already is dictated by the social habits of the mudders themselves, and I don&#8217;t see in the near future those habits changing very much at all. </p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/kooneiform.wordpress.com/379/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/kooneiform.wordpress.com/379/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/kooneiform.wordpress.com/379/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/kooneiform.wordpress.com/379/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/kooneiform.wordpress.com/379/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/kooneiform.wordpress.com/379/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/kooneiform.wordpress.com/379/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/kooneiform.wordpress.com/379/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/kooneiform.wordpress.com/379/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/kooneiform.wordpress.com/379/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=kooneiform.wordpress.com&blog=108553&post=379&subd=kooneiform&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://kooneiform.wordpress.com/2009/08/04/the-social-space-of-mudders/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/edacead2fb1ad30f1bf7cf21d1bbea55?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">kooneiform</media:title>
		</media:content>
	</item>
		<item>
		<title>things (a roguelike in Python #15)</title>
		<link>http://kooneiform.wordpress.com/2009/07/31/things-a-roguelike-in-python-15/</link>
		<comments>http://kooneiform.wordpress.com/2009/07/31/things-a-roguelike-in-python-15/#comments</comments>
		<pubDate>Sat, 01 Aug 2009 02:08:30 +0000</pubDate>
		<dc:creator>georgek</dc:creator>
				<category><![CDATA[roguelike]]></category>

		<guid isPermaLink="false">http://kooneiform.wordpress.com/?p=375</guid>
		<description><![CDATA[I haven&#8217;t really spent much time yet figuring out what a thing from the Thing class is, so far defining it as an object with a name, speed, position, and maybe a handler for field-of-view or dumb AI. Furthermore the character used to represent it on screen simply was based on its name. Since I [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=kooneiform.wordpress.com&blog=108553&post=375&subd=kooneiform&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>I haven&#8217;t really spent much time yet figuring out what a thing from the Thing class is, so far defining it as an object with a name, speed, position, and maybe a handler for field-of-view or dumb AI. Furthermore the character used to represent it on screen simply was based on its name. Since I knew I wanted to better define a Thing and start figuring out how I want to represent it visually, I&#8217;ve started hacking on <strong>Thing</strong>. </p>
<p>First of all <strong>Thing</strong>&#8217;s parameters have changed. The __init__ now looks like this:</p>
<pre class="brush: python;">
class Thing(object):
    def __init__(self, name, x, y, properties, *handlers):
        self.name = name
        self.x = x
        self.y = y
        self.properties = properties
        self.handlers = {}
        if not None in handlers:
            for string in handlers:
                handler = eval(string)
                self.handlers[string] = handler(self)

        self.things = []
        self.stage = None

        self.char_type = self.get_char_type()
</pre>
<p>As you can see I got rid of the speed parameter, which is now included in <strong>properties</strong>. A thing therefore looks like this in its yaml definition file:</p>
<pre class="brush: python;">
- iron-barred window
- 35
- 12
- speed : normal
  kind :
  - window
  state :
  - none
-
</pre>
<p>That definition gives the thing&#8217;s name, x, and y attributes. The next item in the list is a dictionary containing the keys <strong>speed</strong>, <strong>kind</strong>, and <strong>state</strong>. This dictionary is passed into a new instance of a thing as <strong>properties</strong>. The last blank list item is <strong>handlers</strong>. </p>
<p>It&#8217;s all very provisional right now as I figure out how to define a thing. But here&#8217;s a closer look at the last statement in __init__, <strong>self.char_type = self.get_char_type()</strong>.</p>
<p>Here&#8217;s that function:</p>
<pre class="brush: python;">
 def get_char_type(self):
        name = ''
        if self.name in player.ui.char_types:
            name = self.name
        else:
            name_tokens = self.name.split(' ')
            for token in name_tokens:
                if token in player.ui.char_types:
                    name = token

        if not len(name):
            for kind in self.properties['kind']:
                if kind in player.ui.char_types:
                    name = kind

        for state in self.properties['state']:
            state_modifying_name = ' '.join([state, name])
            if state_modifying_name in player.ui.chars:
                return state_modifying_name
            if len(name):
                return name
            else:
                return 'unknown'
</pre>
<p>What I&#8217;m trying to do is find the visual symbol for a thing (its char_type) based on its name, kind, and state (if any). This is of course not very straightforward and I may have to choose a different method. Whenever a thing&#8217;s state changes, its symbol may change as well. There is also the possibility, not accounted for in this code yet, that a thing may have a combination of states that modify its name or kind producing a unique visual symbol. I think I can get this to work but it&#8217;ll require some experimentation. </p>
<p>In the meantime I&#8217;ll explain how this works. The player.ui.char_types list looks like this:</p>
<pre class="brush: python;">
        self.char_types = ['player', 'unknown', 'ground', 'wall', 'window', \
        'lamp', 'knife', 'door', 'portal']
</pre>
<p>So the first thing the get_char_type function asks is if the thing&#8217;s self.name is in that list; if so, it assigns it to the local variable <strong>name</strong>, previously set to an empty string allowing it to be referenced later in the function. If the thing&#8217;s self.name is not in the list we break up the name into its tokens (parts), and if one of those are in the list, we assign <em>that </em>to name. Keep in mind that name may still be empty at this point. </p>
<p>Next, if <strong>name </strong>is empty, we see if the thing&#8217;s kind is in the list of char_types, and if so, assign that to <strong>name</strong>. </p>
<p>Finally we combine whatever state the thing might have with its name, and check if that&#8217;s in the list. This takes care of things like &#8216;closed door&#8217;. If there&#8217;s a match we return it. If not, we see if name is non-empty (there was a successful match earlier) and return that. Lastly if name is still empty, it&#8217;s not in the list of char_types and so we call it &#8216;unknown&#8217;, which gets the question mark symbol when drawn to the screen. </p>
<p>Some notes after the cut on how to find symbols for combination of states. </p>
<p><span id="more-375"></span></p>
<p>I&#8217;m imagining things like an object that&#8217;s an &#8216;open broken door&#8217;. (perhaps this door can&#8217;t then be closed and/or locked). I would have to find this symbol (if I do indeed try to represent this with a unique symbol) in the dictionary of ui.chars when I draw it to the screen. Given the code above this isn&#8217;t going to happen, as it only searches for individual states, not a combination &#8212; how then could I find the right symbol?</p>
<p>First of all it seems like I don&#8217;t want to depend on an exact match, as I would have to reorder every combination of words in the string &#8212; i.e., &#8216;broken open door&#8217; and &#8216;open broken door&#8217;. What I really want to do is compare the list of states + name (&#8216;open broken door&#8217;) with the &#8216;list&#8217; of the key (a string, really) into ui.chars (for example, say the key actually is the string &#8216;broken open door&#8217;). </p>
<p>If I convert the string to a list by splitting on the space (<strong><em>string</em>.split(&#8216; &#8216;)</strong>), then find the difference of the two sets like this:</p>
<pre class="brush: python;">
difference = set.difference(set(a), set(b))
</pre>
<p>If the two strings in any order are different from each other, <strong>difference </strong>will be non-empty. </p>
<p>This alone doesn&#8217;t solve the problem where a thing has multiple states and only one of them in combination with its name matches a key in ui.chars. For example, if a door has the states &#8216;open&#8217; and &#8216;pickled&#8217;. If the key is &#8216;open door&#8217;, &#8216;open pickled door&#8217; won&#8217;t match it using a difference of sets. But maybe &#8216;pickled&#8217; isn&#8217;t applicable to the visual symbol for the door at all, and it <em>should </em>match as &#8216;open door&#8217;. </p>
<p>One possible preliminary test is to create a list of states + name, then check if each word of a key&#8217;s string is in this list. If so, this should match if the states + name in its entirety doesn&#8217;t match any other key. For example:</p>
<pre class="brush: python;">
list = thing.properties['state'] + [name]

for key in player.ui.chars.keys():
    key_list = key.split(' ')
    for item in key_list:
        if item in list:
            print 'match'
....
#etcetera
</pre>
<p>Perhaps more trouble than its worth. For certain effects/states I&#8217;m going to want to just color the character anyway, rather than having a separate symbol for every combination of thing and its state. Still, this could work well for updating a thing&#8217;s symbol on a dynamic basis as states change. Have to try it out and see. </p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/kooneiform.wordpress.com/375/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/kooneiform.wordpress.com/375/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/kooneiform.wordpress.com/375/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/kooneiform.wordpress.com/375/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/kooneiform.wordpress.com/375/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/kooneiform.wordpress.com/375/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/kooneiform.wordpress.com/375/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/kooneiform.wordpress.com/375/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/kooneiform.wordpress.com/375/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/kooneiform.wordpress.com/375/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=kooneiform.wordpress.com&blog=108553&post=375&subd=kooneiform&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://kooneiform.wordpress.com/2009/07/31/things-a-roguelike-in-python-15/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/edacead2fb1ad30f1bf7cf21d1bbea55?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">kooneiform</media:title>
		</media:content>
	</item>
		<item>
		<title>pystil</title>
		<link>http://kooneiform.wordpress.com/2009/07/28/pystil/</link>
		<comments>http://kooneiform.wordpress.com/2009/07/28/pystil/#comments</comments>
		<pubDate>Wed, 29 Jul 2009 07:54:08 +0000</pubDate>
		<dc:creator>georgek</dc:creator>
				<category><![CDATA[IF]]></category>
		<category><![CDATA[Interactive Fiction]]></category>
		<category><![CDATA[writing]]></category>
		<category><![CDATA[pystil]]></category>

		<guid isPermaLink="false">http://kooneiform.wordpress.com/?p=371</guid>
		<description><![CDATA[
I&#8217;ve been thinking for a while about something like a drawing tool for writers&#8230;something like Alchemy that I would write in Python, maybe using pyglet. I&#8217;ve always wanted to make tools as well as make games, but they seemed beyond my capabilities somewhat&#8230;I have some specific UI ideas I&#8217;d like to try in the software [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=kooneiform.wordpress.com&blog=108553&post=371&subd=kooneiform&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p><img src="http://kooneiform.files.wordpress.com/2009/07/pystilmockup.png?w=480&#038;h=360" alt="pystilmockup" title="pystilmockup" width="480" height="360" class="alignleft size-full wp-image-372" /></p>
<p>I&#8217;ve been thinking for a while about something like a drawing tool for writers&#8230;something like <a href="http://al.chemy.org/">Alchemy</a> that I would write in Python, maybe using pyglet. I&#8217;ve always wanted to make tools as well as make games, but they seemed beyond my capabilities somewhat&#8230;I have some specific UI ideas I&#8217;d like to try in the software flesh (mainly &#8212; bigger text for godsake, though it may turn the tool into one only I would use). A couple of new developments inch me closer to my goal. It&#8217;s beginning to look like Nick Montfort&#8217;s <em>nn</em>, now known as <a href="http://www.curveship.com">Curveship</a>, will have <a href="http://nickm.com/post/2009/07/introducing-curveship/">a release later this year</a>. And then over at MudBytes in a thread where someone asked for help naming a mud framework/IDE written in Python, I thought of the name pystil. So&#8230;a narrative/text generation player/maker? Who knows.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/kooneiform.wordpress.com/371/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/kooneiform.wordpress.com/371/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/kooneiform.wordpress.com/371/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/kooneiform.wordpress.com/371/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/kooneiform.wordpress.com/371/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/kooneiform.wordpress.com/371/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/kooneiform.wordpress.com/371/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/kooneiform.wordpress.com/371/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/kooneiform.wordpress.com/371/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/kooneiform.wordpress.com/371/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=kooneiform.wordpress.com&blog=108553&post=371&subd=kooneiform&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://kooneiform.wordpress.com/2009/07/28/pystil/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/edacead2fb1ad30f1bf7cf21d1bbea55?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">kooneiform</media:title>
		</media:content>

		<media:content url="http://kooneiform.files.wordpress.com/2009/07/pystilmockup.png" medium="image">
			<media:title type="html">pystilmockup</media:title>
		</media:content>
	</item>
		<item>
		<title>stages (a roguelike in Python # 14)</title>
		<link>http://kooneiform.wordpress.com/2009/07/26/stages-a-roguelike-in-python-14/</link>
		<comments>http://kooneiform.wordpress.com/2009/07/26/stages-a-roguelike-in-python-14/#comments</comments>
		<pubDate>Mon, 27 Jul 2009 01:05:16 +0000</pubDate>
		<dc:creator>georgek</dc:creator>
				<category><![CDATA[roguelike]]></category>

		<guid isPermaLink="false">http://kooneiform.wordpress.com/?p=367</guid>
		<description><![CDATA[A few days ago I got to the point where I wanted to add switching levels and a get command. Adding the get command led me to consider how I would represent inventory in the code, and I thought simple, every thing has a list of things it holds.
The new code is after the jump, [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=kooneiform.wordpress.com&blog=108553&post=367&subd=kooneiform&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>A few days ago I got to the point where I wanted to add switching levels and a get command. Adding the get command led me to consider how I would represent inventory in the code, and I thought simple, every thing has a list of things it holds.</p>
<p>The new code is after the jump, but first some explanation. </p>
<p>My thought was that a level is simply a thing that holds the things inside it. OK, I was thinking this is good, because I had wanted to have different kinds of levels in the game, like airships, giant woolly mammoths and so forth, and this would potentially make it straightforward to have a giant woolly mammoth walking around that the player could jump on and explore. So I decided a level would be a kind of handler that gets attached to a thing and adds the functionality of a map.</p>
<p>As you can tell I&#8217;m not too concerned with representing scale at this point &#8212; I don&#8217;t think I will be at any point really, this is a game after all. Regardless, I decided to call a level handler a <strong>Stage</strong>. </p>
<p>You can see in previous postings of the demo that I managed the map in a single <strong>World </strong>object. So I needed to do some heavy rewriting, and this led me to reconsider the handler/thing structure altogether. As a result I threw out the <strong>Brain </strong>class and now add handlers directly to a <strong>Thing</strong>. I think this is simpler overall.</p>
<p>At one point I got sidetracked by the magic of Python&#8217;s __getattr__. This is an attribute on every object, that&#8217;s executed when the interpreter doesn&#8217;t find the attribute it&#8217;s looking for as a result of a call on a property or function. So I was doing things like calling <em>thing.foo</em> where <em>foo </em>was actually an attribute on a handler, not the thing itself. However this proved to be more trouble than it was worth (since, as far as I could tell, __getattr__ expects you to return a value when called, and I decided this was too much hassle). The easier solution for me was to rewrite things so that wherever I call an attribute of a handler, I access it through a dictionary of handlers on the thing, like this:</p>
<pre class="brush: python;">
            cells = stage.handlers['Stage'].cells_get(self.thing, self.fov_radius)
</pre>
<p>A little verbose, but easier in the end, and maybe clearer overall. </p>
<p>Saving the game now means saving the stages in a game. I&#8217;ll need to revise this in the future to account for stages within stages though. Switching stages means removing the thing from its current stage and adding it to the new stage. By keeping track of the player&#8217;s current stage I know what to draw to the screen. Currently I only update things in the player&#8217;s stage, so this will need to be changed in the future so time doesn&#8217;t freeze on a stage when the player leaves it. And finally, getting and dropping things means removing and adding the thing to the things that are getting it or receiving it.</p>
<p>There&#8217;s a crude inventory display in the upper part of the UI at the moment, but there&#8217;s only one thing to get. </p>
<p>Things are now kept in a file by stage, which is named like <em>stage_name</em>.things, and the maps are in <em>stage_name</em>.map. </p>
<p><strong>addendum</strong>: With all this talk of stages, it may seem as if something is being left out &#8212; namely procedural generation of levels! And for the moment this is true, but as I think I&#8217;ve mentioned before I&#8217;m not going to focus on generating levels until I have a better idea of what I want the game to be. So for now I&#8217;m sticking with hardcoded content to give me a base to test on. </p>
<p><span id="more-367"></span></p>
<pre class="brush: python;">
#!/usr/bin/python

'''
libtcod OO python tutorial
This code modifies samples_py.py from libtcod 1.4.1. It shows a '@'
walking around a scrolling map with a source of light giving simple FOV.
It's in the public domain.
'''

#############################################
# imports
#############################################

import os
import random
import yaml
import cProfile
import libtcod.libtcodpy as libtcod

#############################################
# profile
#############################################

PROFILER = cProfile.Profile()

#############################################
# constants
#############################################

PROFILE = False
SAVING = True

#############################################
# thing
#############################################

class Thing(object):
    def __init__(self, name, x, y, speed, properties, *handlers):
        self.name = name
        self.x = x
        self.y = y
        self.speed = speed
        self.properties = properties
        self.handlers = {}
        if not None in handlers:
            for string in handlers:
                handler = eval(string)
                self.handlers[string] = handler(self)

        self.things = []
        self.stage = None

    def set_position(self, dx, dy):
        self.x = self.x + dx
        self.y = self.y + dy

    def set_name(self, name):
        self.name = name

#############################################
# handlers
#############################################

class Stage(object):
    def __init__(self, thing):
        self.thing = thing
        self.cell_types = {
                            ' ' : ['ground', 'transparent', 'walkable'],
                            '#' : ['wall']}
        self.width = None
        self.height = None
        self.state = []

        name = self.thing.name + '.map'
        self.load(name)

    def load(self, name):
        file = open(name, 'r')
        for line in file:
            line = line.strip(' \n')
            line_data = []
            for cell in line:
                line_data.append(self.cell_types[cell])
            self.state.append(line_data)

        self.width = len(self.state[0])
        self.height = len(self.state)

        file.close()

    def update(self):
        pass

    def cells_get(self, thing=None, radius=None):
        cells = []

        r = 0
        if radius:
            r = radius

        y_start = 0
        x_start = 0
        y_end = self.height
        x_end = self.width
        if thing:
            y_start = max(thing.y - r, 0)
            x_start = max(thing.x - r, 0)
            y_end = min(self.height, thing.y + r + 1)
            x_end = min(self.width, thing.x + r + 1)

        for y in range(y_start, y_end):
            for x in range(x_start, x_end):
                cells.append((x, y))

        return cells

    def cell_has_monster(self, x, y):
        for thing in self.thing.things:
            if (thing.x, thing.y) == (x, y) and (thing.name == 'monster' or thing.name == 'player'):
                return True

    def cell_is_unwalkable(self, x, y):
        if not 'walkable' in self.state[y][x]:
            return True

    def cell_has_closed_door(self, x, y):
        for thing in self.thing.things:
            if (thing.x, thing.y) == (x, y) and thing.name == 'closed door':
                return True

    def cell_type_get(self, x, y):
        return self.state[y][x][0]

    def cell_add_property(self, x, y, property):
        self.state[y][x] = self.state[y][x] + [property]

#############################################
# do things
#############################################

class Fov(object):
    def __init__(self, thing):
        self.thing = thing

        self.fov_map = None
        self.fov_radius = 2
        self.fov_map_to_world_coordinates = []

    def update(self):
        stage = self.thing.stage

        if stage == player.thing.stage:
            self.fov_map_to_world_coordinates = []
            cells = stage.handlers['Stage'].cells_get(self.thing, self.fov_radius)
            cell_first = cells[0]
            cell_last = cells[len(cells)-1]

            difference_right = cell_last[0] - self.thing.x
            difference_bottom = cell_last[1] - self.thing.y
            difference_left = self.thing.x - cell_first[0]
            difference_top = self.thing.y - cell_first[1]

            fov_map_size_x = difference_right + difference_left + 1
            fov_map_size_y = difference_bottom + difference_top + 1

            self.fov_map = libtcod.map_new(fov_map_size_x, fov_map_size_y)

            for i in range(len(cells)):
                x, y = cells[i]
                fov_map_x = i % fov_map_size_x
                fov_map_y = i // fov_map_size_x
                cell = stage.handlers['Stage'].state[y][x]
                if 'walkable' in cell and 'transparent' in cell:
                    libtcod.map_set_properties(self.fov_map, fov_map_x, fov_map_y, True, True)
                elif 'walkable' in cell:
                    libtcod.map_set_properties(self.fov_map, fov_map_x, fov_map_y, False, True)
                elif 'transparent' in cell:
                    libtcod.map_set_properties(self.fov_map, fov_map_x, fov_map_y, True, False)

                for thing in self.thing.stage.things:
                    if thing.name == 'window' and (x, y) == (thing.x, thing.y):
                        libtcod.map_set_properties(self.fov_map, fov_map_x, fov_map_y, True, False)

                    if thing.name == 'closed door' and (x, y) == (thing.x, thing.y):
                        libtcod.map_set_properties(self.fov_map, fov_map_x, fov_map_y, False, False)

                if (x, y) == (self.thing.x, self.thing.y):
                    fov_x_focus = fov_map_x
                    fov_y_focus = fov_map_y

                self.fov_map_to_world_coordinates.append(((fov_map_x, fov_map_y), (x, y)))

            libtcod.map_compute_fov(self.fov_map, fov_x_focus, fov_y_focus, self.fov_radius, True)

            if self.thing.name == 'player':
                for i in range(len(cells)):
                    x, y = cells[i]
                    fov_map_x = i % fov_map_size_x
                    fov_map_y = i // fov_map_size_x
                    cell = stage.handlers['Stage'].state[y][x]
                    if (libtcod.map_is_in_fov(self.fov_map, fov_map_x, fov_map_y) and
                        not 'discovered' in stage.handlers['Stage'].state[y][x]):
                        stage.handlers['Stage'].cell_add_property(x, y, 'discovered')

class AI(object):
    def __init__(self, thing):
        self.thing = thing
        self.choices = ['north', 'south', 'west', 'east']

    def update(self):
        if self.thing.stage == player.thing.stage:
            choice = random.randint(0, 3)
            command_name = self.choices[choice]
            game.command.do(command_name, self.thing)

#############################################
# player
#############################################

class Awesome(object):
    def __init__(self):
        self.ui = UI()
        self.view = View()
        self.input = Input()
        self.name = ''
        self.thing = None

    def create(self, stage):
        self.thing = Thing('player', 26, 15, 'normal', '', 'Fov')
        stage.things.append(self.thing)
        self.thing.stage = stage
        self.thing.handlers['Fov'].fov_radius = 5

class UI(object):
    def __init__(self):
        self.width = 55
        self.height = 30
        self.state = self.splash

        self.dialog = libtcod.console_new(30, 10)
        libtcod.console_set_background_color(self.dialog, libtcod.light_grey)
        libtcod.console_set_foreground_color(self.dialog, libtcod.black)
        libtcod.console_clear(self.dialog)

        self.top = libtcod.console_new(53, 3)
        libtcod.console_set_background_color(self.top, libtcod.light_grey)
        libtcod.console_set_foreground_color(self.top, libtcod.white)
        libtcod.console_clear(self.top)

        self.bottom = libtcod.console_new(53, 3)
        libtcod.console_set_background_color(self.bottom, libtcod.light_grey)
        libtcod.console_set_foreground_color(self.bottom, libtcod.white)
        libtcod.console_clear(self.bottom)

        self.right = libtcod.console_new(21, 20)
        libtcod.console_set_background_color(self.right, libtcod.grey)
        libtcod.console_set_foreground_color(self.right, libtcod.white)
        libtcod.console_clear(self.right)

        self.main_menu_options = ['new game', 'load saved game']
        self.main_menu_cursor = 0
        self.load_game_selected = ''
        self.load_game_cursor = 0
        self.save_games = []

        self.chars = {
                        'player'    : '@',
                        'monster'   : '?',
                        'ground'    : ' ',
                        'wall'      : '#',
                        'window'    : libtcod.CHAR_DHLINE,
                        'lamp'      : 'l',
                        'knife'     : 'k',
                        'open door' : '-',
                        'closed door'   : '+',
                        'portal'    : 'O'}

        self.cell_colors = {
                            'wall' : libtcod.Color(67, 65, 52),
                            'ground' : libtcod.Color(145, 140, 140),
                            'dark': libtcod.Color(1, 1, 1),
                            'lit': libtcod.Color(255, 255, 33),
                            'visible': libtcod.Color(254, 254, 233),
                            'discovered': libtcod.Color(50, 50, 100)}    

        font = os.path.join('fonts', 'arial12x12.png')
        libtcod.console_set_custom_font(
                                        font,
                                        libtcod.FONT_LAYOUT_TCOD |
                                        libtcod.FONT_TYPE_GREYSCALE,
                                        32,
                                        <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_cool.gif' alt='8)' class='wp-smiley' /> 

        libtcod.console_init_root(
                                    self.width,
                                    self.height,
                                    'Python Demo',
                                    False)
        libtcod.console_set_background_color(0, libtcod.dark_grey)
        libtcod.mouse_show_cursor(False)
        libtcod.console_credits()

        self.states = {
                        'splash'    : self.splash,
                        'main_menu' : self.main_menu,
                        'new_game'  : self.new_game,
                        'load_game' : self.load_game,
                        'gameplay'  : self.gameplay}

    def change_state(self, state):
        self.state = self.states[state]

    def draw(self):
        self.state()

    def splash(self):
        libtcod.console_clear(0)
        libtcod.console_set_foreground_color(0, libtcod.white)
        libtcod.console_print_center(0, self.width//2, self.height//2-4, libtcod.BKGND_NONE, &quot;A Python Demo&quot;)
        libtcod.console_flush()

    def main_menu(self):
        libtcod.console_clear(0)
        libtcod.console_set_foreground_color(0, libtcod.white)
        libtcod.console_print_center(0, self.width//2, self.height//2-4, libtcod.BKGND_NONE, &quot;A Python Demo&quot;)

        for i in range(len(self.main_menu_options)):
            option = self.main_menu_options[i]
            if i == self.main_menu_cursor:
                cursor = '&gt;'
            else:
                cursor = ' '
            libtcod.console_print_left(0, 20, self.height//2+i, libtcod.BKGND_NONE, &quot;%c%s %s%c&quot; % (libtcod.COLCTRL_1, cursor, option, libtcod.COLCTRL_STOP))

        libtcod.console_flush()

    def new_game(self):
        libtcod.console_clear(0)
        libtcod.console_clear(self.dialog)
        libtcod.console_print_left(self.dialog, 2, 5, libtcod.BKGND_NONE, &quot;%cTell me your name, hunter. %c&quot; % (libtcod.COLCTRL_1, libtcod.COLCTRL_STOP))
        libtcod.console_print_center(self.dialog, 15, 8, libtcod.BKGND_NONE, &quot;%c%s_%c&quot; % (libtcod.COLCTRL_1, player.name, libtcod.COLCTRL_STOP))

        libtcod.console_blit(
                                self.dialog,
                                0,
                                0,
                                30,
                                10,
                                0,
                                (self.width - 30)/2,
                                10,
                                200)
        libtcod.console_flush()

    def load_game(self):
        libtcod.console_clear(0)
        libtcod.console_clear(self.dialog)
        libtcod.console_print_center(self.dialog, 15, 1, libtcod.BKGND_NONE, &quot;%cTell me your name, hunter. %c&quot; % (libtcod.COLCTRL_1, libtcod.COLCTRL_STOP))

        i = self.load_game_cursor
        game = self.save_games[i].split('.')[0].replace('_', ' ')

        libtcod.console_print_center(self.dialog, 15, 4, libtcod.BKGND_NONE, &quot;%c&gt; %s%c&quot; % (libtcod.COLCTRL_1, game, libtcod.COLCTRL_STOP))
        libtcod.console_print_center(self.dialog, 15, 8, libtcod.BKGND_NONE, &quot;%cup/down to select%c&quot; % (libtcod.COLCTRL_1, libtcod.COLCTRL_STOP))

        libtcod.console_blit(
                                self.dialog,
                                0,
                                0,
                                30,
                                10,
                                0,
                                (self.width - 30)/2,
                                10,
                                200)
        libtcod.console_flush()

    def gameplay(self):
        libtcod.console_clear(0)
        libtcod.console_clear(self.right)
        libtcod.console_clear(self.top)

        libtcod.console_print_left(self.right, 1, 1, libtcod.BKGND_NONE, &quot;HJKL move around&quot;)
        libtcod.console_print_left(self.right, 1, 4, libtcod.BKGND_NONE, &quot;%s&quot; % player.name)
        libtcod.console_print_left(self.right, 1, 5, libtcod.BKGND_NONE, &quot;in %s&quot; % player.thing.stage.name)

        libtcod.console_print_left(self.right, 1, 7, libtcod.BKGND_NONE, &quot;game turn: %d&quot; % game.time.turns)
        libtcod.console_print_left(self.right, 1, 9, libtcod.BKGND_NONE, &quot;%s&quot; % game.message.text)

        libtcod.console_print_left(self.top, 1, 1, libtcod.BKGND_NONE, &quot;%s&quot; % player.thing.things)

        libtcod.console_blit(
                                player.view.screen,
                                0,
                                0,
                                player.view.width,
                                player.view.height,
                                0,
                                1,
                                5,
                                255)

        libtcod.console_blit(
                                self.top,
                                0,
                                0,
                                53,
                                3,
                                0,
                                1,
                                1,
                                255)

        libtcod.console_blit(
                                self.bottom,
                                0,
                                0,
                                53,
                                3,
                                0,
                                1,
                                26,
                                255)

        libtcod.console_blit(
                                self.right,
                                0,
                                0,
                                21,
                                20,
                                0,
                                33,
                                5,
                                255)
        libtcod.console_flush()

class View(object):
    def __init__(self):
        self.width = 30
        self.height = 20
        self.anchor_x = None
        self.anchor_y = None
        self.screen = libtcod.console_new(self.width, self.height)
        libtcod.console_set_foreground_color(self.screen, libtcod.black)

    def update(self):
        stage = player.thing.stage.handlers['Stage']

        libtcod.console_clear(self.screen)

        self.anchor_x = min(max(0, player.thing.x - self.width//2), stage.width - self.width)
        self.anchor_y = min(max(0, player.thing.y - self.height//2), stage.height - self.height)

        viewport = []
        for j in range(self.height):
            line = []
            for i in range(self.width):
                x, y = self.viewport_ij_to_world_xy(i, j)
                cell = {
                        'light'   : 0,
                        'char'    : ' ',
                        'fov'     : [],
                        'cell_type'     : stage.cell_type_get(x, y),
                        'discovered'    : 0,
                        'scalar'        : 1}

                if 'discovered' in stage.state[y][x]:
                    cell['discovered'] = 1

                line.append(cell)
            viewport.append(line)

        maps = []
        for thing in player.thing.stage.things:
            if 'Fov' in thing.handlers:
                maps.append((thing, thing.handlers['Fov'].fov_map, thing.handlers['Fov'].fov_map_to_world_coordinates))

        for tuple in maps:
            thing, fov_map, fov_map_to_world_coordinates = tuple
            for cell in fov_map_to_world_coordinates:
                x, y = cell[1][0], cell[1][1]

                if self.xy_in_viewport(x, y):
                    fov_map_x, fov_map_y = cell[0][0], cell[0][1]
                    i, j = self.world_xy_to_viewport_ij(x, y)

                    distance_squared = max(1, (x - thing.x) * (x - thing.x) + (y - thing.y) * (y - thing.y))
                    fov_radius_squared = thing.handlers['Fov'].fov_radius * thing.handlers['Fov'].fov_radius
                    scalar = (fov_radius_squared - distance_squared * 1.0)/fov_radius_squared

                    if libtcod.map_is_in_fov(fov_map, fov_map_x, fov_map_y):
                        viewport[j][i]['fov'].append(thing.name)

                        if thing.name == 'lamp':
                            viewport[j][i]['light'] = max(.5, scalar)

                        if thing.name == 'player':
                            viewport[j][i]['scalar'] = max(.5, scalar)

        for j in range(self.height):
            for i in range(self.width):
                cell = viewport[j][i]
                affect = 'dark'
                cell_type = cell['cell_type']
                if 'player' in cell['fov']:
                    if cell['light'] == 0:
                        affect = 'visible'
                    else:
                        affect = 'lit'

                        if cell_type == 'wall':
                            n = max(0, j-1)
                            e = min(self.width-1, i+1)
                            s = min(self.height-1, j+1)
                            w = max(0, i-1)
                            cells = [
                                        viewport[n][w],
                                        viewport[n][i],
                                        viewport[n][e],
                                        viewport[j][w],
                                        viewport[j][e],
                                        viewport[s][w],
                                        viewport[s][i],
                                        viewport[s][e]]
                            for adjacent_cell in cells:
                                if not 'player' in adjacent_cell['fov'] and adjacent_cell['cell_type'] == 'ground' and adjacent_cell['light'] &gt; 0:
                                    affect = 'visible'
                                    break
                        else:
                            cell['scalar'] = cell['light']

                elif cell['discovered'] &gt; 0:
                    affect = 'discovered'

                if 'player' in cell['fov']:
                    affect_color = player.ui.cell_colors[affect] * cell['scalar']
                else:
                    affect_color = player.ui.cell_colors[affect]
                cell_type_color = player.ui.cell_colors[cell_type]
                color = affect_color * cell_type_color
                char = cell['char']
                libtcod.console_set_back(self.screen, i, j, color, libtcod.BKGND_SET)
                libtcod.console_put_char(self.screen, i, j, char, libtcod.BKGND_NONE)                        

        for thing in player.thing.stage.things:
            i, j = self.world_xy_to_viewport_ij(thing.x, thing.y)
            if self.xy_in_viewport(thing.x, thing.y) and 'player' in viewport[j][i]['fov']:
                libtcod.console_put_char(self.screen, i, j, player.ui.chars[thing.name], libtcod.BKGND_NONE)

    def world_xy_to_viewport_ij(self, x, y):
        i = x - self.anchor_x
        j = y - self.anchor_y
        return (i, j)

    def viewport_ij_to_world_xy(self, i, j):
        x = i + self.anchor_x
        y = j + self.anchor_y
        return (x, y)

    def xy_in_viewport(self, x, y):
        if (self.anchor_x &lt;= x &lt; self.anchor_x+self.width and
            self.anchor_y &lt;= y &lt; self.anchor_y+self.height):
                return True

class Input(object):
    def __init__(self):
        self.state = self.splash

        file = open('keys.cfg', 'r')
        self.keycfg = yaml.load(file)

        self._keys = {
                        'k' : 'k',
                        'j' : 'j',
                        'h' : 'h',
                        'l' : 'l',
                        'p' : 'p',
                        libtcod.KEY_UP : 'up arrow',
                        libtcod.KEY_RIGHT : 'right arrow',
                        libtcod.KEY_LEFT : 'left arrow',
                        libtcod.KEY_DOWN : 'down arrow',
                        libtcod.KEY_KP8 : 'keypad 8',
                        libtcod.KEY_KP6 : 'keypad 6',
                        libtcod.KEY_KP4 : 'keypad 4',
                        libtcod.KEY_KP2 : 'keypad 2',
                        'x' : 'x',
                        libtcod.KEY_SPACE : 'space bar'}

        self.ctrl = ''

        self.states = {
                        'splash'    : self.splash,
                        'main_menu' : self.main_menu,
                        'new_game'  : self.new_game,
                        'load_game' : self.load_game,
                        'gameplay'  : self.gameplay}

    def get_key(self, key):
        if key.lctrl:
            self.ctrl = 'ctrl '
        else:
            self.ctrl = ''

        if not key.vk == 65:
            return key.vk
        else:
            return chr(key.c)

    def change_state(self, state):
        self.state = self.states[state]

    def update(self):
        self.state()

    def splash(self):
        libtcod.console_wait_for_keypress(True)

    def main_menu(self):
        self.key = libtcod.console_wait_for_keypress(True)

        if self.key.vk == libtcod.KEY_ESCAPE or libtcod.console_is_window_closed():
            game.exit = True
        elif self.key.vk == libtcod.KEY_ENTER:
            pass
        elif self.key.vk == libtcod.KEY_DOWN:
            player.ui.main_menu_cursor = min(len(player.ui.main_menu_options)-1, player.ui.main_menu_cursor+1)
        elif self.key.vk == libtcod.KEY_UP:
            player.ui.main_menu_cursor = max(0, player.ui.main_menu_cursor-1)

    def new_game(self):
        self.key = libtcod.console_wait_for_keypress(True)
        if self.key.vk == libtcod.KEY_ENTER:
            pass
        elif self.key.vk == libtcod.KEY_BACKSPACE:
            name = player.name
            player.name = name[:-1]
        elif self.key.vk in (65, libtcod.KEY_SPACE):
            player.name = player.name + chr(self.key.c)

    def load_game(self):
        self.key = libtcod.console_wait_for_keypress(True)
        if self.key.vk == libtcod.KEY_ENTER or self.key.vk == libtcod.KEY_ESCAPE:
            pass
        elif self.key.vk == libtcod.KEY_DOWN:
            player.ui.load_game_cursor = min(len(player.ui.save_games)-1, player.ui.load_game_cursor+1)
        elif self.key.vk == libtcod.KEY_UP:
            player.ui.load_game_cursor = max(0, player.ui.load_game_cursor-1)

    def gameplay(self):
        self.key = libtcod.console_wait_for_keypress(True)
        key = self.get_key(self.key)
        if key in self._keys:
            key = self._keys[key]

        while not key in self.keycfg:
            if self.key.vk == libtcod.KEY_ESCAPE or libtcod.console_is_window_closed():
                if SAVING: game.save()
                game.exit = True
                return
            game.message.text = &quot;Try again!&quot;
            player.ui.draw()
            self.key = libtcod.console_wait_for_keypress(True)
            key = self.get_key(self.key)
            if key in self._keys:
                key = self._keys[key]

        command_name = self.ctrl + self.keycfg[key]
        game.message.text = &quot;Go!&quot;

        if game.command.do(command_name, player.thing) == 'free action':
            player.view.update()
            player.ui.draw()
            self.gameplay()

#############################################
# game
#############################################
class Game(object):
    def __init__(self):
        self.message = Message()
        self.time = Time()
        self.command = Command()

        self.state = self.splash
        self.exit = False

        self.stages = []

        self.states = {
                        'splash'    : self.splash,
                        'main_menu' : self.main_menu,
                        'new_game'  : self.new_game,
                        'load_game' : self.load_game,
                        'gameplay'  : self.gameplay}

    def change_state(self, state):
        self.state = self.states[state]
        player.input.change_state(state)
        player.ui.change_state(state)

    def update(self):
        self.state()

    def splash(self):
        player.ui.draw()
        player.input.update()

        self.change_state('main_menu')

    def main_menu(self):
        if not player.ui.save_games:
            dir = os.listdir('.')
            for file in dir:
                if 'sav' in file:
                    player.ui.save_games.append(file)

        player.ui.draw()
        player.input.update()

        if player.input.key.vk == libtcod.KEY_ENTER:
            if player.ui.main_menu_options[player.ui.main_menu_cursor] == 'new game':
                self.change_state('new_game')

            elif player.ui.main_menu_options[player.ui.main_menu_cursor] == 'load saved game' and player.ui.save_games:
                self.change_state('load_game')

    def new_game(self):
        player.ui.draw()
        player.input.update()

        if player.input.key.vk == libtcod.KEY_ENTER:
            if player.ui.main_menu_options[player.ui.main_menu_cursor] == 'new game':
                things_files = []
                dir = os.listdir('.')
                for file in dir:
                    if 'things' in file:
                        things_files.append(file)

                for file in things_files:
                    new_things = []
                    file = open(file, 'r')
                    things = yaml.load_all(file)
                    for data in things:
                        thing = Thing(*data)
                        new_things.append(thing)
                    file.close()

                    _stage = None
                    for thing in new_things:
                        if 'Stage' in thing.handlers:
                            _stage = thing
                            self.stages.append(_stage)

                    for thing in new_things:
                        if not 'Stage' in thing.handlers:
                            thing.stage = _stage
                            _stage.things.append(thing)

                current_stage = None
                for stage in self.stages:
                    if stage.name == 'Cyanothus':
                        current_stage = stage

                player.create(current_stage)

                for handler in player.thing.handlers:
                    player.thing.handlers[handler].update()
                player.view.update()

                self.change_state('gameplay')

        elif player.input.key.vk == libtcod.KEY_ESCAPE:
            self.change_state('main_menu')

    def load_game(self):
        player.ui.draw()
        player.input.update()

        if player.input.key.vk == libtcod.KEY_ENTER:
            file = player.ui.save_games[player.ui.load_game_cursor]
            self.load(file)

            player.name = file.split('.')[0].replace('_', ' ')

            self.change_state('gameplay')

        elif player.input.key.vk == libtcod.KEY_ESCAPE:
            self.change_state('main_menu')

    def gameplay(self):
        if self.time.phase in self.time.phases_for[player.thing.speed]:
            player.input.update()

        if game.exit == True:
            return

        for thing in player.thing.stage.things:
            if self.time.phase in self.time.phases_for[thing.speed]:
                for handler in thing.handlers:
                    thing.handlers[handler].update()      

        self.time.tick()

        if PROFILE:
            PROFILER.runcall(player.view.update)
            PROFILER.dump_stats('profile_view_draw')
        else:
            player.view.update()

    def save(self):
        for stage in self.stages:
            for thing in stage.things:
                if 'Fov' in thing.handlers:
                    thing.handlers['Fov'].fov_map_to_world_coordinates = []
                if hasattr(thing, 'stage'):
                    thing.stage = None

        name = player.name.replace(' ', '_') + '.sav'
        file = open(name, 'w')
        yaml.dump_all(self.stages, file)
        file.close()

    def load(self, name):
        file = open(name, 'r')
        self.stages = list(yaml.load_all(file))
        file.close()

        for stage in self.stages:
            for thing in stage.things:
                if thing.name == 'player':
                    player.thing = thing

        for stage in self.stages:
            for thing in stage.things:
                thing.stage = stage

        for handler in player.thing.handlers:
            player.thing.handlers[handler].update()
        player.view.update()

class Message(object):
    def __init__(self):
        self.text = &quot;Go!&quot;

class Time(object):
    def __init__(self):
        self.phases = ['fast', 'normal', 'slow', 'quick', 'normal']
        self.phases_for = {
                            'fast' : ('fast', 'normal', 'slow'),
                            'normal' : ('normal', 'slow'),
                            'slow' : ('normal'),
                            'quick' : ('normal', 'slow', 'quick'),
                            'fast+quick' : ('fast', 'normal', 'slow', 'quick'),
                            'fast+slow' : ('fast', 'normal'),
                            'quick+slow' : ('quick', 'normal'),
                            'fast+quick+slow' : ('fast', 'normal', 'quick')}

        self.phase = self.phases[1]
        self.phase_count = 0
        self.turns = 0

    def tick(self):
        self.phase_count += 1
        self.phase = self.phases[self.phase_count % 5]
        if self.phase in self.phases_for['normal']: self.turns += 1

class Command(object):
    def __init__(self):
        self.playbook = {
                        'north' : ('takes turn', self.move, 0, -1),
                        'east'  : ('takes turn', self.move, 1, 0),
                        'south' : ('takes turn', self.move, 0, 1),
                        'west'  : ('takes turn', self.move, -1, 0),
                        'ctrl north'    : ('takes turn', self.ctrl, 0, -1),
                        'ctrl east'     : ('takes turn', self.ctrl, 1, 0),
                        'ctrl south'    : ('takes turn', self.ctrl, 0, 1),
                        'ctrl west'     : ('takes turn', self.ctrl, -1, 0),
                        'direct'   : ('takes turn', self.direct, None),
                        'indirect'  : ('free action', self.indirect, None),
                        'print history' : ('free action', self.print_history, None)}

        self.rulebook = {
                        'move' : ('cell has monster', 'cell is unwalkable', 'cell has closed door', 'open door implicitly'),
                        'close_door' : ('cell has closed door',),
                        'get'   : ('thing not gettable',),
                        'drop'  : ()}

        self.rules = {
                        # condition checks

                        'cell has monster' : &quot;enactor.stage.handlers['Stage'].cell_has_monster(enactor.x+dx, enactor.y+dy)&quot;,
                        'cell is unwalkable' : &quot;enactor.stage.handlers['Stage'].cell_is_unwalkable(enactor.x+dx, enactor.y+dy)&quot;,
                        'cell has closed door' : &quot;enactor.stage.handlers['Stage'].cell_has_closed_door(enactor.x+dx, enactor.y+dy)&quot;,
                        'thing not gettable' : &quot;not 'gettable' in target.properties&quot;,

                        # automatic procedures

                        'open door implicitly' : &quot;self.open_door_implicitly(enactor.x+dx, enactor.y+dy)&quot;}

        self.history = []

    def do(self, string, enactor):
        command = self.playbook[string]
        command_name, args = command[1], command[2:]
        command_name(enactor, *args)
        self.history.append((string, enactor.name))
        return command[0]

    def move(self, enactor, *args):
        dx, dy = args
        if True in [eval(self.rules[rule]) for rule in self.rulebook['move']]:
            pass
        else:
            enactor.set_position(dx, dy)

        target_stage_name = None
        for thing in enactor.stage.things:
            if thing.name == 'portal' and (enactor.x, enactor.y) == (thing.x, thing.y):
                target_stage_name = thing.properties.split(':')[1]

        target_stage = None
        for stage in game.stages:
            if stage.name == target_stage_name:
                target_stage = stage

        if target_stage:
            for stage in game.stages:
                if stage == target_stage:
                    stage.things.append(enactor)
                elif stage == enactor.stage:
                    stage.things.remove(enactor)
            enactor.stage = target_stage

    def ctrl(self, enactor, *args):
        dx, dy = args
        self.close_door(enactor, dx, dy)

    def direct(self, enactor, *args):
        self.get(enactor)

    def indirect(self, enactor, *args):
        self.drop(enactor)

    def get(self, enactor):
        target = False
        for thing in enactor.stage.things:
            if not enactor == thing and (enactor.x, enactor.y) == (thing.x, thing.y):
                target = thing

        if target:
            if True in [eval(self.rules[rule]) for rule in self.rulebook['get']]:
                pass
            else:
                enactor.things.append(target)
                enactor.stage.things.remove(target)

    def drop(self, enactor):
        to_remove = False
        if True in [eval(self.rules[rule]) for rule in self.rulebook['drop']]:
            pass
        else:
            for thing in player.thing.things:
                to_remove = thing
                thing.x, thing.y = player.thing.x, player.thing.y

        if to_remove:
            enactor.things.remove(to_remove)
            enactor.stage.things.insert(0, to_remove)

    def close_door(self, enactor, dx, dy):
        if True in [eval(self.rules[rule]) for rule in self.rulebook['close_door']]:
            pass
        else:
            for thing in player.thing.stage.things:
                if (enactor.x+dx, enactor.y+dy) == (thing.x, thing.y) and thing.name == 'open door':
                    thing.set_name('closed door')

    def open_door_implicitly(self, x, y):
        if player.thing.stage.handlers['Stage'].cell_has_closed_door(x, y):
            for thing in player.thing.stage.things:
                if (thing.x, thing.y) == (x, y) and thing.name == 'closed door':
                    thing.set_name('open door')

    def print_history(self, enactor, *args):
        print self.history
        print player.thing.things

#############################################
# get it started
#############################################

if __name__ == '__main__':
#     try:
#         import psyco
#         psyco.full()
#     except ImportError:
#         pass

    game = Game()
    player = Awesome()

    while not game.exit:
        game.update()
        if not game.exit:
            player.ui.draw()
</pre>
<p>Here are the yaml files for things. Note that &#8216;Cyanothus&#8217; currently is hardcoded as the starting stage. Much of the stage functionality is roughly coded at this point really. </p>
<pre class="brush: python;">
---
- 'Cyanothus'
- 0
- 0
- normal
- ''
- 'Stage'

---
- 'window'
- 35
- 12
- normal
- ''
- 

---
- 'closed door'
- 30
- 15
- normal
- ''
- 

---
- 'monster'
- 20
- 9
- normal
- ''
- 'AI'

---
- 'lamp'
- 29
- 6
- normal
- ''
- 'Fov'

---
- 'lamp'
- 41
- 6
- normal
- ''
- 'Fov'

---
- 'lamp'
- 29
- 11
- normal
- ''
- 'Fov'

---
- 'lamp'
- 41
- 11
- normal
- ''
- 'Fov'

---
- 'knife'
- 35
- 15
- normal
- 'gettable'
- 

---
- 'portal'
- 38
- 15
- normal
- 'to:Sexangulare'
-
</pre>
<pre class="brush: python;">
---
- 'Sexangulare'
- 0
- 0
- normal
- ''
- 'Stage'

---
- 'portal'
- 38
- 15
- normal
- 'to:Cyanothus'
-
</pre>
<p>The maps are 80&#215;50, and can be any combination of &#8216;#&#8217; and &#8216; &#8216; in plain text. The location of things will have to work with the spaces on the map of course. </p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/kooneiform.wordpress.com/367/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/kooneiform.wordpress.com/367/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/kooneiform.wordpress.com/367/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/kooneiform.wordpress.com/367/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/kooneiform.wordpress.com/367/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/kooneiform.wordpress.com/367/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/kooneiform.wordpress.com/367/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/kooneiform.wordpress.com/367/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/kooneiform.wordpress.com/367/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/kooneiform.wordpress.com/367/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=kooneiform.wordpress.com&blog=108553&post=367&subd=kooneiform&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://kooneiform.wordpress.com/2009/07/26/stages-a-roguelike-in-python-14/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/edacead2fb1ad30f1bf7cf21d1bbea55?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">kooneiform</media:title>
		</media:content>
	</item>
	</channel>
</rss>