<?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/"
	>

<channel>
	<title>The Accidental Developer &#187; games</title>
	<atom:link href="http://osric.com/chris/accidental-developer/tag/games/feed/" rel="self" type="application/rss+xml" />
	<link>http://osric.com/chris/accidental-developer</link>
	<description>What if Gregor Samsa awoke a computer programmer?</description>
	<lastBuildDate>Sat, 28 Jan 2012 23:13:31 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Generating puzzles for a Four-by-Four Word Game</title>
		<link>http://osric.com/chris/accidental-developer/2010/11/generating-puzzles-for-a-four-by-four-word-game/</link>
		<comments>http://osric.com/chris/accidental-developer/2010/11/generating-puzzles-for-a-four-by-four-word-game/#comments</comments>
		<pubDate>Sat, 06 Nov 2010 22:10:07 +0000</pubDate>
		<dc:creator>Chris Herdt</dc:creator>
				<category><![CDATA[Games]]></category>
		<category><![CDATA[algorithms]]></category>
		<category><![CDATA[crossword]]></category>
		<category><![CDATA[dictionary]]></category>
		<category><![CDATA[games]]></category>
		<category><![CDATA[graphs]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[puzzle]]></category>
		<category><![CDATA[trees]]></category>
		<category><![CDATA[words]]></category>

		<guid isPermaLink="false">http://osric.com/chris/accidental-developer/?p=286</guid>
		<description><![CDATA[While attempting to populate a word game (<a href="http://osric.com/chris/wordgame/">http://osric.com/chris/wordgame/</a>) with puzzles, I found a way to generate the puzzles with a computer program. The program ran slowly, until I found a way to reduce the running time by a factor of 10. ]]></description>
			<content:encoded><![CDATA[<p>A few years ago, I made a crossword-like game wherein users fill out a 4&#215;4 grid of letters to spell 8 words (4 across and 4 down): <a href="http://osric.com/chris/wordgame/">http://osric.com/chris/wordgame/</a></p>
<p><a href="http://osric.com/chris/wordgame/"><img src="http://osric.com/games/images/4x4puzzle200x150.png" alt="Four by Four word puzzle game" /></a></p>
<p>However, over the course of several days, I was able to develop only 20 puzzles by hand. Trying all the various combinations is clearly a task better suited to computers than humans. Such a grid has 16 slots, each of which can contain one of 26 letters&#8211;so there are 26<sup>16</sup> total permutations to check. That&#8217;s about 43,000,000,000,000,000,000,000&#8211;which could take a very long time, even for a computer. One key to speeding things up is to ignore permutations that don&#8217;t contain words.<br />
<span id="more-286"></span><br />
First I tried using the default dictionary file on my computer (/usr/share/dict/words on Mac OSX), which contains around 4000 4-letter words. I could test all of the permutations of words, placing them a word in each row of the 4&#215;4 grid and then testing the letters in the grid columns to see if they are dictionary words. This reduces the problem to 4000<sup>4</sup> (~26 trillion), which could still take a very, very long time.</p>
<p>Such a program isn&#8217;t very smart, though. Let&#8217;s say it checked this grid:</p>
<table>
<tr>
<td>B</td>
<td>A</td>
<td>B</td>
<td>Y</td>
</tr>
<tr>
<td>B</td>
<td>A</td>
<td>T</td>
<td>S</td>
</tr>
<tr>
<td>B</td>
<td>A</td>
<td>L</td>
<td>K</td>
</tr>
<tr>
<td>B</td>
<td>A</td>
<td>N</td>
<td>K</td>
</tr>
</table>
<p>After discovering that BBBB isn&#8217;t in the dictionary, in would proceed by replacing BANK with BANS and failing on the same non-word, BBBB. In fact, as soon as it inserts BATS after BABY, it should check and discover than no dictionary word begins with BB, and skip to CABS, then DABS, then EACH&#8211;where it finally finds a valid word prefix, BE. We &#8220;pruned&#8221; B, C, and D. The dictionary file has about 700 words that begin with B, C, or D&#8211;so the pruning just eliminated 700 x 4000 x 4000, or 11 billion permutations.</p>
<p>Following this strategy, I created a program in Java to test various permutations but bypass permutations that lead to invalid word prefixes. It looked like it was running properly, but would probably take several days to complete. Additionally, many of the words in the dictionary were uncommon and were creating grids unfriendly for a casual puzzle game (like ACYL).</p>
<p>I was using the Eclipse IDE for this project, and I noticed that most of the unusual words in my list were underlined in red. Eclipse didn&#8217;t recognize them as words! Eclipse must have its own dictionary. It took me a while to find it, but eventually I:</p>
<ol>
<li>Grabbed the Eclipse dictionary from <a href="http://dev.eclipse.org/viewsvn/index.cgi/org.eclipse.jdt.ui/dictionaries/en_US.dictionary?view=co">http://dev.eclipse.org/viewsvn/index.cgi/org.eclipse.jdt.ui/dictionaries/en_US.dictionary?view=co</a></li>
<li>Reduced it to the 4-letter entries<br />
<code>cat en_US.dictionary | grep '^[a-zA-Z]\{4\}$' &gt; 4letters.dictionary</code></li>
<li>Sorted it alphabetically (ignoring case)<br />
<code>sort -f -u 4letters.dictionary -o sorted4.dictionary</code></li>
</ol>
<p>The new file contained 1788 words&#8211;a smaller list with more recognizable words. This time, my program ran to completion in 5295 seconds (about an hour and a half) and found 498,672 4&#215;4 grids where all the words, across and down, were in the dictionary file! Nearly half a million grids, when I was stuck after coming up with 20 by hand!</p>
<p>Many of the grids contained the same word more than once, though, e.g.:</p>
<table>
<tr>
<td>Z</td>
<td>O</td>
<td>N</td>
<td>E</td>
</tr>
<tr>
<td>O</td>
<td>X</td>
<td>E</td>
<td>N</td>
</tr>
<tr>
<td>N</td>
<td>E</td>
<td>E</td>
<td>D</td>
</tr>
<tr>
<td>E</td>
<td>N</td>
<td>D</td>
<td>S</td>
</tr>
</table>
<p>That&#8217;s not a very interesting puzzle, so I added a check to exclude grids that contained the same word more than once. The updated program ran in 4734 seconds (~1 hour and 19 minutes) and found 192,476 grids.</p>
<p>I had an idea to speed things up further. What if, after checking the BA combinations (as in the example above), it skipped straight to EA? That&#8217;s when I had an idea to build the dictionary as a tree&#8211;my version is technically a graph, because it has an imaginary root. Each node contained a value (a word or word prefix) and pointers to a sibling or a child. For example, this is a visual representation of the graph containing ABLE, ACHE, ACHY, BAKE, BAND, and BANE:<br />
<a href="http://osric.com/chris/accidental-developer/wp-content/uploads/2010/11/word-tree.png"><img src="http://osric.com/chris/accidental-developer/wp-content/uploads/2010/11/word-tree.png" alt="Visual representation of a word graph (or tree)" title="Visual representation of a word graph (or tree)" width="444" height="262" class="alignnone size-full wp-image-297" /></a></p>
<p>While traversing this tree, if the grid fails at a certain letter, it moves on to the next sibling. If it passes&#8211;that is, all rows and columns are either words or valid word prefixes, it moves on to the child. (This is basically Depth-First Search.) This version of the program found the same number of grids&#8211;192,476&#8211;but in only 497 seconds (8 minutes and change)!</p>
<p>The running time is still problematic, though. If I think of a good 4-letter addition, such as a name (&#8220;FRED&#8221;) or a phrase (<em>as-is</em> becomes &#8220;ASIS&#8221;), I don&#8217;t want to sit around for 8 minutes waiting to generate all the puzzles again. I could address this by testing only grids that contain the new additions, which should run in a blink.</p>
<p>Also, the successful grids include isomorphic grids. For example, </p>
<table>
<tr>
<td>
<table>
<tr>
<td>Z</td>
<td>E</td>
<td>R</td>
<td>O</td>
</tr>
<tr>
<td>A</td>
<td>V</td>
<td>O</td>
<td>W</td>
</tr>
<tr>
<td>P</td>
<td>I</td>
<td>P</td>
<td>E</td>
</tr>
<tr>
<td>S</td>
<td>L</td>
<td>E</td>
<td>D</td>
</tr>
</table>
</td>
<td>
and
</td>
<td>
<table>
<tr>
<td>Z</td>
<td>A</td>
<td>P</td>
<td>S</td>
</tr>
<tr>
<td>E</td>
<td>V</td>
<td>I</td>
<td>L</td>
</tr>
<tr>
<td>R</td>
<td>O</td>
<td>P</td>
<td>E</td>
</tr>
<tr>
<td>O</td>
<td>W</td>
<td>E</td>
<td>D</td>
</tr>
</table>
</td>
</tr>
</table>
<p>This isn&#8217;t really a tremendous problem, though&#8211;a player is unlikely to run into 2 isomorphic puzzles during casual game play.</p>
<p>Now the trick is to come up with clues for all the puzzles, and find a way to let users play on Facebook (where apparently all the casual gaming takes place anymore). For now, though, I&#8217;m content to have found a clever way to reduce the running time from 80 minutes to 8 minutes.</p>
<p>I shouldn&#8217;t pat myself on the back too much, though&#8211;I&#8217;m sure someone else has already found a way to do the same in mere seconds.</p>
]]></content:encoded>
			<wfw:commentRss>http://osric.com/chris/accidental-developer/2010/11/generating-puzzles-for-a-four-by-four-word-game/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Creating a Javascript Game (LetterLock)</title>
		<link>http://osric.com/chris/accidental-developer/2010/05/creating-a-javascript-game-wordlock/</link>
		<comments>http://osric.com/chris/accidental-developer/2010/05/creating-a-javascript-game-wordlock/#comments</comments>
		<pubDate>Tue, 25 May 2010 20:17:32 +0000</pubDate>
		<dc:creator>Chris Herdt</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[games]]></category>

		<guid isPermaLink="false">http://osric.com/chris/accidental-developer/?p=273</guid>
		<description><![CDATA[I recently created a simple word game (<a href="http://osric.com/letterlock/">LetterLock</a>) using Javascript, which presented certain challenges. The game displays 3 random letters to the player, who must then attempt to create a dictionary word in as few moves as possible by shifting the letters up or down in the alphabet.

There were several programming decisions or challenges that came up during the game's creation, which I discuss in the full post.]]></description>
			<content:encoded><![CDATA[<p><img src="http://osric.com/games/images/letterlock200x150.png" alt="LetterLock - A Word Game" style="border:solid 1px #999" /><br />
<a href="http://osric.com/letterlock/">osric.com/letterlock</a></p>
<p>I recently created a simple word game using Javascript, which presented certain challenges. The game displays 3 random letters to the player, who must then attempt to create a dictionary word in as few moves as possible by shifting the letters up or down in the alphabet.</p>
<p>There were several programming decisions or challenges that came up during the game&#8217;s creation, for which I was able to apply some of the things I learned in my recent computer science classes.</p>
<p><span id="more-273"></span></p>
<p>The first challenge was how to include the dictionary. The source list I used for 3-letter words (from a Scrabble dictionary) includes 1012 entries. Although I could have developed a server-side solution to check words via AJAX, I wanted the game to be as quick and responsive as possible, and 1012 3-letter words is not all that prohibitive. First, I created an array of all the words; however, that took a lot of extra bytes for all the quotes and commas. In fact, it doubled the space required. I looked at using a prefix scheme (&#8220;A&#8221; followed by all the two-letter sequences that begin with &#8220;A&#8221;) to save a few bytes, but the savings was not as great as I had initially anticipated. In the end, I just included the dictionary as a long, unbroken string: since we know that each word is 3 characters, it is easy to access any given word. </p>
<p>The next challenge was how to look up the user&#8217;s 3-letter sequence to see if the sequence is in our dictionary. The brute-force approach is to compare it to every word in the dictionary, which would take 1012 comparisons for a sequence that isn&#8217;t present. 1012 comparisons isn&#8217;t all that bad, but there are certainly more efficient ways, and I was thinking about the implications of expanding to a 4-letter or 5-letter game. Here are some of the look-up options I considered:</p>
<ul>
<li><strong>Binary search.</strong> Because we are dealing with an alphabetized dictionary, we can start in the middle of the dictionary and immediately eliminate half as possible matches, and then perform the same binary search recursively. Now we need only 10 comparisons for a sequence that isn&#8217;t present.</li>
<li><strong>Hash table.</strong> Although we would have to create the hash table at the beginning of the game, this only took 3 comparisons for a sequence that wasn&#8217;t present (based on empirical observation).</li>
<li><strong>Bucket array.</strong> I&#8217;m not sure what else to call it, but I created a large array (17,576) that could accommodate every conceivable combination of letters. A sequence not in the dictionary remains null, and a sequence in the dictionary gets assigned a 1. This method has larger memory requirements&#8211;not extraordinary for 3-letter sequences, but would grow quickly for longer sequences. Now we only need one comparison to determine is a sequence is a dictionary word.</li>
</ul>
<p>I picked the binary search for its simplicity.</p>
<p>The last major challenge was creating the &#8220;fewest moves&#8221; algorithm. The game currently tells the user the fewest number of moves it takes to convert the random sequence to a dictionary word. I struggled with this at first, until I realized that the problem is basically just a <a href="http://en.wikipedia.org/wiki/Breadth-first_search">Breadth-First Search</a> or shortest-path algorithm. I enqueue the initial sequence. For each possible one-move combination, I check it against the dictionary, and enqueue that sequence. (I enqueue an impossible dummy sequence&#8211;&#8221;###&#8221;&#8211;to indicate that we need to increment the fewest moves.)</p>
<p>One problem with this is that if it enqueues every one-move combination, it will enqueue many duplicates. Before I checked for duplicates, I found that the fewest moves algorithm often checked more than the 17,576 unique 3-letter sequences. For letter combinations where the nearest dictionary word was 8 or more moves away, Javascript would become unresponsive (or the browser would crash). Since the already-checked sequences were in no particular order, I used the hash table (instead of the binary search) to perform look-ups (although a brute force approach would probably have been sufficient).</p>
<p>Another problem with the fewest-moves algorithm is that my first approach was to use a recursive function. However, Javascript apparently does not always perform well with recursion; Firefox would throw &#8220;too much recursion&#8221; errors. I changed the function to use a while loop (continue processing while the queue is not empty), which solved that issue.</p>
<p>Although many of these optimizations were not strictly necessary and the brute-force approach would have worked suitably in many cases, I think the optimizations will help the game scale to handle 4-and-5-letter words (although the dictionaries may become too heavy for 5-letter words).</p>
]]></content:encoded>
			<wfw:commentRss>http://osric.com/chris/accidental-developer/2010/05/creating-a-javascript-game-wordlock/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hunt the Wumpus</title>
		<link>http://osric.com/chris/accidental-developer/2010/01/javascript-hunt-the-wumpus/</link>
		<comments>http://osric.com/chris/accidental-developer/2010/01/javascript-hunt-the-wumpus/#comments</comments>
		<pubDate>Sun, 31 Jan 2010 00:09:10 +0000</pubDate>
		<dc:creator>Chris Herdt</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[games]]></category>
		<category><![CDATA[wumpus]]></category>

		<guid isPermaLink="false">http://osric.com/chris/accidental-developer/?p=263</guid>
		<description><![CDATA[I am taking a course in discrete mathematics this semester, and the professor suggested we take a look at a game called Hunt the Wumpus. Hunt the Wumpus was originally created in the 1970s, and unfortunately, most of the versions you can find on the web today are easier and less interesting that the original. [...]]]></description>
			<content:encoded><![CDATA[<p>I am taking a course in discrete mathematics this semester, and the professor suggested we take a look at a game called Hunt the Wumpus.</p>
<p>Hunt the Wumpus was originally created in the 1970s, and unfortunately, most of the versions you can find on the web today are easier and less interesting that the original. The original eschewed a square grid for the game board and instead used a &#8220;squashed&#8221; dodecahedron, where each game space was one of the vertices.</p>
<p>It is also noteworthy for introducing the <em>superbat</em>, a feature of other games (including Zork) that followed Hunt the Wumpus, and for the humorous feedback (e.g. &#8220;ZAP&#8211;Superbat Snatch! Elsewhereville for you!&#8221;) that many of my favorite games adopted.</p>
<p>At any rate, I decided to recreate a version of the easier and less interesting grid-based game in Javascript:<br />
<a href="http://osric.com/wumpus/">Hunt the Wumpus</a></p>
]]></content:encoded>
			<wfw:commentRss>http://osric.com/chris/accidental-developer/2010/01/javascript-hunt-the-wumpus/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

