<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">
  <id>http://www.flyingmachinestudios.com/</id>
  <title>Flying Machine Studios</title>
  <updated>2012-02-23T11:56:17Z</updated>
  <link rel="alternate" href="http://www.flyingmachinestudios.com/" />
  
  <author>
    <name>Daniel Higginbotham</name>
    <uri>http://www.flyingmachinestudios.com</uri>
  </author>
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/FlyingMachineStudios" /><feedburner:info uri="flyingmachinestudios" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:browserFriendly></feedburner:browserFriendly><entry>
    <id>tag:www.flyingmachinestudios.com,2012-02-23:/penguins/abstract-math/</id>
    <title type="html">Abstract Mathematics and Programming</title>
    <published>2012-02-23T11:56:17Z</published>
    <updated>2012-02-23T11:56:17Z</updated>
    <link rel="alternate" href="http://www.flyingmachinestudios.com/penguins/abstract-math/" />
    <content type="html">&lt;h1&gt;Abstract Mathematics and Programming&lt;/h1&gt;
&lt;p&gt;If you&amp;#8217;ve been alive long enough to develop language comprehension, you&amp;#8217;ve probably heard that most people don&amp;#8217;t like math. The usual complaint is that it&amp;#8217;s just a bunch of formulas disconnected from everything and that you have to memorize in order to finish school.&lt;/p&gt;
&lt;p&gt;My opinion is that the poor souls who hate math have never been exposed to the abstract method. This is explained by Timothy Gowers in &lt;a href="http://books.google.com/books?id=DBxSM7TIq48C&amp;amp;lpg=PP1&amp;amp;pg=PA17#v=onepage&amp;amp;q&amp;amp;f=false"&gt;Mathematics: a Very Short Introduction&lt;/a&gt; :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;What is the black king in chess? This is a strange question, and the most satisfactory way to deal with it seems to be to sidestep it slightly. What more can one do than point to a chessboard and explain the rules of the game, perhaps paying paprticular attention to the black king as one does so? What matters about the black king is not its existence, or its intrinsic nature, but the role that it plays in the game.&lt;/p&gt;
&lt;p&gt;The abstract method in mathematics, as it is sometimes called, is what results when one takes a similar attitude to mathematical objects.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This description does not paint a clear, concrete picture of the abstract method, but I hope it serves to at least rouse your curiosity, and that your curiosity rouses you to read more at the link above. By exploring mathematics from the point of view of the abstract method, you&amp;#8217;ll come to see math in a different way.&lt;/p&gt;
&lt;p&gt;You&amp;#8217;ll begin to learn how it&amp;#8217;s possible for some people to take pleasure in reading proofs. Hopefully, you yourself will experience the delight and surprise that comes from treating math as a process of defining mathematical objects in terms of their interactions, and seeing what results from the logical application of mathematical rules. It&amp;#8217;s like solving a crossword or sudoku puzzle, only, like, a million times cooler.&lt;/p&gt;
&lt;p&gt;Besides its intrinsic value, I think that learning abstract math will make it easier to learn how to program. By learning this approach to math, it makes it easier to disassociate programming symbols from their intuitive, english-y or math-y meetings. For example, &amp;#8220;function&amp;#8221; is a keyword in many programming languages, but it differs dramatically from the English meaning of &amp;#8220;function&amp;#8221; and subtly from the functions we&amp;#8217;re used to in algebra. Learning to see programming symbols as merely symbols subject to the rules of the programming language is useful.&lt;/p&gt;
&lt;p&gt;I also believe that learning abstract math makes your thinking more flexible, but it&amp;#8217;s hard for me to describe how. You just see the world differently.&lt;/p&gt;
&lt;p&gt;The above book by Timothy Gowers seems like a good introduction. Personally I was introduced to the ideas through &lt;a href="http://www.amazon.com/gp/product/0465026567/ref=as_li_ss_tl?ie=UTF8&amp;amp;tag=aflyingmachin-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=0465026567"&gt;Godel, Escher, Bach: an Eternal Golden Braid&lt;/a&gt; and &lt;a href="http://www.amazon.com/gp/product/0814758371/ref=as_li_ss_tl?ie=UTF8&amp;amp;tag=aflyingmachin-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=0814758371"&gt;Godel&amp;#8217;s Proof&lt;/a&gt; . Both books are a true joy. The first can take awhile to get through, but the second is a considerably quicker read. They both demonstrate the beauty and delight within mathematics.&lt;/p&gt;
&lt;p&gt;I regret that I don&amp;#8217;t have the time to provide some concrete examples of how learning this stuff is fun and could possibly help you learn  programming. However, I hope that writing about my own experiences might motivate folks to go out there and learn themselves some &lt;strong&gt;real&lt;/strong&gt; math.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>tag:www.flyingmachinestudios.com,2012-02-22:/penguins/machine-aided-introspection/</id>
    <title type="html">Machine-Aided Introspection</title>
    <published>2012-02-22T09:23:17Z</published>
    <updated>2012-02-22T09:23:17Z</updated>
    <link rel="alternate" href="http://www.flyingmachinestudios.com/penguins/machine-aided-introspection/" />
    <content type="html">&lt;h1&gt;Machine-Aided Introspection&lt;/h1&gt;
&lt;p&gt;What if you had a machine that provided statistics on every part of your life? You could see how many times you&amp;#8217;ve heard a song (not just listened to it on X device), how often you drink coffee, the increase in frequency to trips to your favorite restaurant.&lt;/p&gt;
&lt;p&gt;More interestingly &amp;#8212; what if this machine monitored your internal state and correlated it with external events? I mean, what would it be like to have a machine that confirmed that yes, you actually do think that your boss (or neighbor, or friend, or whoever) is actually an asshole? Such a machine could reveal that every time your visual (or auditory or olfactory) system recognizes him, your cortisol levels start rising. Or, what if the device automatically revealed that your feelings of discomfort with a colleague are triggered by some long-buried memory triggered by her glasses rather than anything she&amp;#8217;s actually said or done?&lt;/p&gt;
&lt;p&gt;I find these questions intriguing because I believe that such a device is possible, and possibly inevitable. Biofeedback devices already exist to help people control their anger or prevent migraines. In general, it takes hard work to become aware of your emotional state and to manage it. It&amp;#8217;d be interesting to see the effects of machine-aided introspection. What would happen if you made use of a device that could instantly let you know all the pieces about yourself that you wish you knew? Or that you don&amp;#8217;t want yourself to know?&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>tag:www.flyingmachinestudios.com,2012-01-10:/programming/minimax/</id>
    <title type="html">An Exhaustive Explanation of Minimax, a Staple AI Algorithm</title>
    <published>2012-01-11T02:42:00Z</published>
    <updated>2012-01-11T02:42:00Z</updated>
    <link rel="alternate" href="http://www.flyingmachinestudios.com/programming/minimax/" />
    <content type="html">&lt;h1&gt;An Exhaustive Explanation of Minimax, a Staple AI Algorithm&lt;/h1&gt;
&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;The minimax algorithm is used to determine which moves a computer player makes in games like tic-tac-toe, checkers, othello, and chess. These kinds of games are called games of perfect information because it is possible to see all possible moves. A game like scrabble is not a game of perfect information because there&amp;#8217;s no way to predict your opponent&amp;#8217;s moves because you can&amp;#8217;t see his hand.&lt;/p&gt;
&lt;p&gt;You can think of the algorithm as similar to the human thought process of saying, &amp;#8220;OK, if I make this move, then my opponent can only make two moves, and each of those would let me win. So this is the right move to make.&amp;#8221;&lt;/p&gt;
&lt;p&gt;The rest of the article explains how to represent possible moves and evaluate them. An example command-line tic-tac-toe game using Ruby is given.&lt;/p&gt;
&lt;h2&gt;Representing Moves with the Game Tree Data Structure&lt;/h2&gt;
&lt;p&gt;Here&amp;#8217;s an example of a Game Tree for tic-tac-toe:&lt;/p&gt;
&lt;p&gt;&lt;img src="/assets/images/minimax/game-tree.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Note that this isn&amp;#8217;t a full game tree. A full game tree has hundreds of thousands of game states, so that&amp;#8217;s uh&amp;#8230; not really possible to include in an image. Some of the discrepancies between the example above and a fully-drawn game tree include:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;The first Game State would show nine moves descending from it, one for each of the empty spaces on its board&lt;/li&gt;
	&lt;li&gt;Similarly, the next level of Game States would show eight moves descending from them, and so on for each Game State&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Representing the game as a game tree allows the computer to evaluate each of its current possible moves by determining whether it will ultimately result in a win or a loss. We&amp;#8217;ll get into how the computer determines this in the next section, Ranking. Before that, though, we need to clearly define the central concepts defining a Game Tree:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;The board state. In this case, where the X&amp;#8217;s and O&amp;#8217;s are.&lt;/li&gt;
	&lt;li&gt;The current player &amp;#8211; the player who will be making the next move.&lt;/li&gt;
	&lt;li&gt;The next available moves. For humans, a move involves placing a game token. For the computer, it&amp;#8217;s a matter of selecting the next game state. As humans, we never say, &amp;#8220;I&amp;#8217;ve selected the next game state&amp;#8221;, but it&amp;#8217;s useful to think of it that way in order to understand the minimax algorithm.&lt;/li&gt;
	&lt;li&gt;The game state &amp;#8211; the grouping of the three previous concepts.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So, a Game Tree is a structure for organizing all possible (legal) game states by the moves which allow you to transition from one game state to the next. This structure is ideal for allowing the computer to evaluate which moves to make because, by traversing the game tree, a computer can easily &amp;#8220;foresee&amp;#8221; the outcome of a move and thus &amp;#8220;decide&amp;#8221; whether to take it.&lt;/p&gt;
&lt;p&gt;Next we&amp;#8217;ll go into detail about how to determine whether a move is good or bad.&lt;/p&gt;
&lt;h2&gt;Ranking Game States&lt;/h2&gt;
&lt;p&gt;The basic approach is to assign a numerical value to a move based on whether it will result in a win, draw, or loss. We&amp;#8217;ll begin illustrating this concept by showing how it applies to final game states, then show how to apply it to intermediate game states.&lt;/p&gt;
&lt;h3&gt;Final Game States&lt;/h3&gt;
&lt;p&gt;Have a look at this Game Tree:&lt;/p&gt;
&lt;p&gt;&lt;img src="/assets/images/minimax/x-win.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s X&amp;#8217;s turn, and X has three possible moves, one of which (the middle one) will lead immediately to victory. It&amp;#8217;s obvious that an AI should select the winning move. The way we ensure this is to give each move a numerical value based on its board state. Let&amp;#8217;s use the following rankings:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Win: 1&lt;/li&gt;
	&lt;li&gt;Draw: 0&lt;/li&gt;
	&lt;li&gt;Lose: -1&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These rankings are arbitrary. What&amp;#8217;s important is that winning corresponds to the highest ranking, losing to the lowest, and a draw&amp;#8217;s between the two.&lt;/p&gt;
&lt;p&gt;Since the lowest-ranked moves correspond with the worst outcomes and highest-ranked moves correspond with the best outcomes, we should choose the move with the highest value. This is the &amp;#8220;max&amp;#8221; part of &amp;#8220;minimax&amp;#8221;. Below are some more examples of final game states and their numerical values:&lt;/p&gt;
&lt;p&gt;&lt;img src="/assets/images/minimax/final-states.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;You might be wondering whether or not we should apply different rankings based on the player whose turn it is. For now, let&amp;#8217;s ignore the question entirely and only view things from X&amp;#8217;s perspective.&lt;/p&gt;
&lt;p&gt;Of course, only the most boring game in the world would start out by presenting you with the options of &amp;#8220;win immediately&amp;#8221; and &amp;#8220;don&amp;#8217;t win immediately.&amp;#8221; And an algorithm would be useless if it only worked in such a situation. But guess what! Minimax isn&amp;#8217;t a useless algorithm. Below I&amp;#8217;ll describe how to determine the ranks of intermediate Game States.&lt;/p&gt;
&lt;h3&gt;Intermediate Game States&lt;/h3&gt;
&lt;p&gt;Have another look at this game tree:&lt;/p&gt;
&lt;p&gt;&lt;img src="/assets/images/minimax/x-win-with-rank.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;As you can see, it&amp;#8217;s X&amp;#8217;s turn in the top Game State. There are 3 possible moves, including a winning move. Since this Game State allows X to win, X should try to get it if possible. This Game State is as good as winning, so its rank should be 1. In general, we can say that the rank of an intermediate Game State where X is the current player should be set to the maximum rank of the available moves.&lt;/p&gt;
&lt;p&gt;Now have a look at this game tree:&lt;/p&gt;
&lt;p&gt;&lt;img src="/assets/images/minimax/o-win.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s O&amp;#8217;s turn, and there are 5 possible moves, three of which are shown. One of the moves results in an immediate win for O. From X&amp;#8217;s perspective this Game State is equivalent to a loss, since it allows O to select a move that will cause X to lose. Therefore, its rank should be -1. In general, we can say that the rank of an intermediate Game State where O is the current player should be set to the &lt;strong&gt;minimum&lt;/strong&gt; rank of the available moves. That&amp;#8217;s what the &amp;#8220;mini&amp;#8221; in &amp;#8220;minimax&amp;#8221; refers to.&lt;/p&gt;
&lt;p&gt;By the way &amp;#8211; the above game tree probably looks ridiculous to you. You might say, &amp;#8220;Well of course you shouldn&amp;#8217;t make such a dumb move. Why would anyone give up a win and allow O to win?&amp;#8221; Minimax is our way of giving the computer the ability to &amp;#8220;know&amp;#8221; that it&amp;#8217;s a dumb move, too.&lt;/p&gt;
&lt;p&gt;To sum up:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Final Game States are ranked according to whether they&amp;#8217;re a win, draw, or loss.&lt;/li&gt;
	&lt;li&gt;Intermediate Game States are ranked according to whose turn it is and the available moves.
	&lt;ul&gt;
		&lt;li&gt;If it&amp;#8217;s X&amp;#8217;s turn, set the rank to that of the &lt;strong&gt;maximum&lt;/strong&gt; move available. In other words, if a move will result in a win, X should take it.&lt;/li&gt;
		&lt;li&gt;If it&amp;#8217;s O&amp;#8217;s turn, set the rank to that of the &lt;strong&gt;minimum&lt;/strong&gt; move available. In other words, If a move will result in a loss, X should avoid it.&lt;/li&gt;
	&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And that&amp;#8217;s the minimax algorithm!&lt;/p&gt;
&lt;h2&gt;Ruby Example&lt;/h2&gt;
&lt;p&gt;Below is a Ruby implementation of Tic-Tac-Toe. It has a few limitations &amp;#8211; for example, the computer always plays X. This is beacuse it&amp;#8217;s meant to illustrate the concepts described here.&lt;/p&gt;
&lt;p&gt;To run it, copy it to something like &amp;#8220;tictactoe.rb&amp;#8221; and run &lt;code&gt;ruby tictactoe.rb&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You can &lt;a href="https://github.com/flyingmachine/minimax-tictactoe"&gt;view the repo on github&lt;/a&gt;. In the future, I might add Common Lisp and C versions of Tic-Tac-Toe, and I&amp;#8217;d welcome versions in other languages as well.&lt;/p&gt;
&lt;div class='attachment-path source'&gt;&lt;a href='/assets/source/minimax/tictactoe.rb'&gt;minimax/tictactoe.rb&lt;/a&gt;&lt;/div&gt;&lt;div class='code pygments'&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# This is a pretty naive implementation of Tic-Tac-Toe meant to&lt;/span&gt;
&lt;span class="c1"&gt;# demonstrate the minimax algorithm. Note that it takes awhile to&lt;/span&gt;
&lt;span class="c1"&gt;# start up - 30 seconds on a 2010 mac book air. Also note that the&lt;/span&gt;
&lt;span class="c1"&gt;# Ruby isn&amp;#39;t all that great as Ruby, but I don&amp;#39;t care as long as it&lt;/span&gt;
&lt;span class="c1"&gt;# illustrates the algorithm well.&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# You can see that there&amp;#39;s a hard-coded assumption that the AI is the&lt;/span&gt;
&lt;span class="c1"&gt;# X player, means that no human will ever be able to win. I&amp;#39;m positive&lt;/span&gt;
&lt;span class="c1"&gt;# that is only a small taste of what is to come, once robots take&lt;/span&gt;
&lt;span class="c1"&gt;# over the world.&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GameState&lt;/span&gt;
  &lt;span class="kp"&gt;attr_accessor&lt;/span&gt; &lt;span class="ss"&gt;:current_player&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:board&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:moves&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:rank&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_player&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;board&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_player&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;current_player&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;board&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;board&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;moves&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;rank&lt;/span&gt;
    &lt;span class="vi"&gt;@rank&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="n"&gt;final_state_rank&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;intermediate_state_rank&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# this is only ever called when it&amp;#39;s the AI&amp;#39;s (the X player) turn&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;next_move&lt;/span&gt;
    &lt;span class="n"&gt;moves&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rank&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rank&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;final_state_rank&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;final_state?&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;draw?&lt;/span&gt;
      &lt;span class="n"&gt;winner&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;X&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;final_state?&lt;/span&gt;
    &lt;span class="n"&gt;winner&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;draw?&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;draw?&lt;/span&gt;
    &lt;span class="n"&gt;board&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compact&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;winner&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nil?&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;intermediate_state_rank&lt;/span&gt;
    &lt;span class="c1"&gt;# recursion, baby&lt;/span&gt;
    &lt;span class="n"&gt;ranks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;moves&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;collect&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;game_state&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;game_state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rank&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;current_player&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;X&amp;#39;&lt;/span&gt;
      &lt;span class="n"&gt;ranks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="n"&gt;ranks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;min&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;  

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;winner&lt;/span&gt;
    &lt;span class="vi"&gt;@winner&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;
     &lt;span class="c1"&gt;# horizontal wins&lt;/span&gt;
     &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

     &lt;span class="c1"&gt;# vertical wins&lt;/span&gt;
     &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

     &lt;span class="c1"&gt;# diagonal wins&lt;/span&gt;
     &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;collect&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;positions&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;board&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;positions&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;board&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;positions&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class="n"&gt;board&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;positions&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;board&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;positions&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class="n"&gt;board&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;positions&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compact&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GameTree&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate&lt;/span&gt;
    &lt;span class="n"&gt;initial_game_state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;GameState&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;X&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;generate_moves&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;initial_game_state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;initial_game_state&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_moves&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;game_state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;next_player&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;game_state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_player&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;X&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;O&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;X&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;game_state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;board&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each_with_index&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;player_at_position&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;player_at_position&lt;/span&gt;
        &lt;span class="n"&gt;next_board&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;game_state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;board&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dup&lt;/span&gt;
        &lt;span class="n"&gt;next_board&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;game_state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_player&lt;/span&gt;

        &lt;span class="n"&gt;next_game_state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;GameState&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;next_player&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;next_board&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;game_state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;moves&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;next_game_state&lt;/span&gt;
        &lt;span class="n"&gt;generate_moves&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;next_game_state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Game&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;
    &lt;span class="vi"&gt;@game_state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@initial_game_state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;GameTree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;generate&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;turn&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@game_state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;final_state?&lt;/span&gt;
      &lt;span class="n"&gt;describe_final_game_state&lt;/span&gt;
      &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Play again? y/n&amp;quot;&lt;/span&gt;
      &lt;span class="n"&gt;answer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;gets&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;answer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;downcase&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;y&amp;#39;&lt;/span&gt;
        &lt;span class="vi"&gt;@game_state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@initial_game_state&lt;/span&gt;
        &lt;span class="n"&gt;turn&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="nb"&gt;exit&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@game_state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_player&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;X&amp;#39;&lt;/span&gt;
      &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;===============&amp;quot;&lt;/span&gt;
      &lt;span class="vi"&gt;@game_state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@game_state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;next_move&lt;/span&gt;
      &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;X&amp;#39;s move:&amp;quot;&lt;/span&gt;
      &lt;span class="n"&gt;render_board&lt;/span&gt;
      &lt;span class="n"&gt;turn&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="n"&gt;get_human_move&lt;/span&gt;
      &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;The result of your move:&amp;quot;&lt;/span&gt;
      &lt;span class="n"&gt;render_board&lt;/span&gt;
      &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;
      &lt;span class="n"&gt;turn&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;render_board&lt;/span&gt;
    &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;upto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot; &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="vi"&gt;@game_state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;board&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &amp;quot;&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;position&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
      &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;|&amp;quot;&lt;/span&gt;
      &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;-----------&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;position&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_human_move&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Enter square # to place your &amp;#39;O&amp;#39; in:&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;position&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;gets&lt;/span&gt;

    &lt;span class="n"&gt;move&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@game_state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;moves&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;game_state&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;game_state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;board&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_i&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;O&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;move&lt;/span&gt;
      &lt;span class="vi"&gt;@game_state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;move&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;That&amp;#39;s not a valid move&amp;quot;&lt;/span&gt;
      &lt;span class="n"&gt;get_human_move&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;describe_final_game_state&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@game_state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;draw?&lt;/span&gt;
      &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;It was a draw!&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;elsif&lt;/span&gt; &lt;span class="vi"&gt;@game_state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;winner&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;X&amp;#39;&lt;/span&gt;
      &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;X won!&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;O won!&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;Game&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;turn&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;h2&gt;The End&amp;#8230; or Is It???&lt;/h2&gt;
&lt;p&gt;I hope that explains the algorithm! If anything&amp;#8217;s unclear, please let me know in the comments below. I&amp;#8217;d like for this post to explain the algorithm completely, and I&amp;#8217;ll use any feedback to revise it.&lt;/p&gt;
&lt;p&gt;Also, you may have noticed that the algorithm, as written, requires a lot of memory. Tic-Tac-Toe, one of the simplest, most boring games in existence, requires hundreds of thousands of game states in the above, naive Ruby implementation. In the future, I may cover some optimization techniques, like alpha-beta programming. Look for it!&lt;/p&gt;
&lt;h2&gt;P.S.&lt;/h2&gt;
&lt;p&gt;My motivation for writing all this came from reading &lt;a href="http://www.amazon.com/gp/product/1593272812/ref=as_li_ss_tl?ie=UTF8&amp;amp;tag=aflyingmachin-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=1593272812"&gt;Land of Lisp: Learn to Program in Lisp, One Game at a Time!&lt;/a&gt; , which introduced me to minimax. It&amp;#8217;s one of the best programming books I&amp;#8217;ve read: it was fun to read, and I learned a lot :) It&amp;#8217;s also the only programming book I know of to have &lt;a href="http://landoflisp.com/"&gt;its own music video&lt;/a&gt;.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>tag:www.flyingmachinestudios.com,2012-01-05:/essays/a-philosophy-of-programming/</id>
    <title type="html">A Philosophy of Programming, Rough Sketch</title>
    <published>2012-01-05T19:02:00Z</published>
    <updated>2012-01-05T19:02:00Z</updated>
    <link rel="alternate" href="http://www.flyingmachinestudios.com/essays/a-philosophy-of-programming/" />
    <content type="html">&lt;h1 id="a-philosophy-of-programming-rough-sketch"&gt;A Philosophy of Programming, Rough Sketch&lt;/h1&gt;

&lt;p&gt;Below is a first attempt at describing an integrated approach to
programming. My hope is that it&amp;rsquo;ll give programmers some tools to
reason about their current practices and generate ideas on new
practices to implement.&lt;/p&gt;

&lt;p&gt;The unifying idea is that our work is governed by cognitive processes
and that we can better understand our work by understanding those
processes. There is a wealth of information available on such topics
as memory, attention, focus, and emotion, and I believe that it will
be fruitful to relate such information directly to the processes
involved in programming.&lt;/p&gt;

&lt;p&gt;Put another way, understanding our hardware will help us understand
the behavior of our software.&lt;/p&gt;

&lt;p&gt;There are a lot of gaps. My hope is that I&amp;rsquo;ll get a lot of feedback
that will help me fill in those gaps.&lt;/p&gt;

&lt;h2 id="the-processes"&gt;The Processes&lt;/h2&gt;

&lt;p&gt;There are three main processes involved in programming:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Learning&lt;/li&gt;
  &lt;li&gt;Problem Solving&lt;/li&gt;
  &lt;li&gt;Social interaction&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This article only addresses learning. Future articles will address
the other two topics.&lt;/p&gt;

&lt;h2 id="learning"&gt;Learning&lt;/h2&gt;

&lt;p&gt;We constantly need to learn: existing codebases, new libraries, the problem
domain, the application environment.&lt;/p&gt;

&lt;p&gt;Learning consists of relating new information to existing knowledge.&lt;/p&gt;

&lt;h2 id="memory"&gt;Memory&lt;/h2&gt;

&lt;p&gt;Ease of learning is in part determined by short term memory. To learn,
it is necessary to hold multiple mental objects in short term memory in
order to compare them to each other and discover the relationships
between them.&lt;/p&gt;

&lt;p&gt;Not all mental objects are created equal. Some take up more &amp;ldquo;space&amp;rdquo;
than others. Familiar objects take up less space than unfamiliar
objects. For example, the following list is relatively easy to hold in
memory:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;bed&lt;/li&gt;
  &lt;li&gt;cup&lt;/li&gt;
  &lt;li&gt;light&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The following list is harder to hold in memory:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;clorp&lt;/li&gt;
  &lt;li&gt;farg&lt;/li&gt;
  &lt;li&gt;dwesh&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Short term memory also has a temporal limitation (obviously). We
should avoid creating the need to hold objects in memory for longer
than our brains are designed for. We&amp;rsquo;ve all experienced the strain
produced by having to navigate back and forth among multiple files in
order to figure something out. More on this later.&lt;/p&gt;

&lt;h3 id="naming"&gt;Naming&lt;/h3&gt;

&lt;p&gt;The nature of memory explains why it is necessary to name things well
in code. The explanation is two-fold (using method names as an
example):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Without proper naming, it is more likely to be necessary to derive
the behavior of a method from its constituent parts. This requires
loading more items into your short-term memory, possibly resulting
in your forgetting why you were looking at the method in the first
place. The result is that learning time is increased.&lt;/li&gt;
  &lt;li&gt;Indescript names also take up more &amp;ldquo;space&amp;rdquo; in short term memory,
making it more difficult to understand how a method relates to the
larger system.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Examples needed.&lt;/p&gt;

&lt;h3 id="metaphor"&gt;Metaphor&lt;/h3&gt;

&lt;p&gt;Metaphor is at the heart of programming: stacks, queues, pipes,
memory, objects, domain models. These are all metaphors. 
Metaphor is at the heart of our craft.&lt;/p&gt;

&lt;p&gt;We also use the term &amp;ldquo;abstraction&amp;rdquo;, but I think &amp;ldquo;metaphor&amp;rdquo; is better
when it comes to naming, as it more directly denotes that we are
relating new concepts to existing concepts. But the distinction really
doesn&amp;rsquo;t matter.&lt;/p&gt;

&lt;p&gt;Good metaphors allow us to hold more information-dense items in
memory. They provide more &amp;ldquo;hooks&amp;rdquo; which allow for easier retrieval
from long-term memory.&lt;/p&gt;

&lt;p&gt;Other &amp;ldquo;metaphors&amp;rdquo;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Visual form of code. Indentiation stands for hierarchy.&lt;/li&gt;
  &lt;li&gt;Code colorization. Color stands for syntax.&lt;/li&gt;
  &lt;li&gt;Programming style. Shared programming style allows people to derive
meaning from the structure of the code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of these examples of metaphor reduce the number of mental objects
we need to retain in short-term memory, thus making learning easier.
You can easily confirm that it&amp;rsquo;s much easier to hold &amp;ldquo;stack&amp;rdquo; in memory
than it is to hold &amp;ldquo;a last in, first out abstract data type and linear
data structure.&amp;rdquo;&lt;/p&gt;

&lt;h3 id="visual-aids"&gt;Visual Aids&lt;/h3&gt;

&lt;p&gt;Visual aids are information-dense. Our visual brains are pretty
awesome at processing visual aids. My little treatise on visual
design: &lt;a href="http://www.visualmess.com"&gt;Clean Up Your Mess&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id="documentation"&gt;Documentation&lt;/h3&gt;

&lt;p&gt;API documentation is not enough. People who use your code have the
following questions, among others:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;What is the purpose of the system?&lt;/li&gt;
  &lt;li&gt;What are the subsystems, and what are their purposes?&lt;/li&gt;
  &lt;li&gt;How do the parts interact?&lt;/li&gt;
  &lt;li&gt;How do I extend it?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It&amp;rsquo;s not reasonable to expect someone to answer these questions by
reading code and API documentation. Because there are so many pieces
involved, it is very difficult for someone to a) determine which
pieces are relevant and b) hold the relevant pieces in mind long
enough to deduce the answer to his question. Such a process often
involves navigating multiple files, constantly having to refresh our
memories by looking at the same pieces of code over and over.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s possible to answer questions like the ones listed above using the
process I listed above, but it&amp;rsquo;s not optimal. Good documentation
condenses the information, making it understandable without producing
so much cognitive load.&lt;/p&gt;

&lt;p&gt;Examples of good documentation:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://nanoc.stoneship.org/docs/"&gt;nanoc&lt;/a&gt;. It was very easy to learn
how to use nanoc because the documentation is excellent. If I had to
learn how to use it by reading the code, I wouldn&amp;rsquo;t have bothered.
If I had to learn solely by going through examples, it would still
have been very difficult. Instead, the documentation provides a
mixture of prose and examples which made learning the system very
easy.&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://www.whoopsapp.com/"&gt;Whoops&lt;/a&gt;. Well, maybe I&amp;rsquo;m being a little
vain and/or delusional here, but I think my documentation for Whoops
is above-average. There&amp;rsquo;s still a good amount that I could cover,
though.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also see &lt;a href="/programming/writing-better-documentation/"&gt;my article on
documentation&lt;/a&gt;&lt;/p&gt;

&lt;h2 id="learning-skills"&gt;Learning Skills&lt;/h2&gt;

&lt;h3 id="describe-what-you-dont-know"&gt;Describe What You Don&amp;rsquo;t Know&lt;/h3&gt;

&lt;p&gt;Being able to concretely determine what it is you need to know is of
great value. Learn to quickly transform the emotion of confusion into
a concrete statement of what you need to learn.&lt;/p&gt;

&lt;h3 id="ask-about-it-directly"&gt;Ask About it Directly&lt;/h3&gt;

&lt;p&gt;Often, when seeking help, we ask the wrong question. Need examples.&lt;/p&gt;

&lt;h3 id="confirm-your-knowledge"&gt;Confirm Your Knowledge&lt;/h3&gt;

&lt;p&gt;State and restate what you think you know to someone else who can tell
you whether you&amp;rsquo;re wrong. Often, we make a lot of unconscious
assumptions when trying to learn, and this process will help you
uncover those assumptions.&lt;/p&gt;

&lt;h2 id="to-explore"&gt;To explore&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;How does emotional state affect learning?&lt;/li&gt;
  &lt;li&gt;How is emotion related to certrainty?&lt;/li&gt;
  &lt;li&gt;What is the relationship between testing, memory, and learning?&lt;/li&gt;
  &lt;li&gt;How can teams support learning?&lt;/li&gt;
  &lt;li&gt;Find concrete examples of codebases which support learning&lt;/li&gt;
  &lt;li&gt;How information navigation is related to learning, e.g. including a 
table of contents in documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="further-reading"&gt;Further Reading&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://www.amazon.com/gp/product/1934356050/ref=as_li_ss_tl?ie=UTF8&amp;amp;tag=aflyingmachin-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=1934356050"&gt;Pragmatic Thinking and
Learning&lt;/a&gt;
. Learn how to learn.&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://www.amazon.com/gp/product/0061771295/ref=as_li_ss_tl?ie=UTF8&amp;amp;tag=aflyingmachin-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=0061771295"&gt;Your Brain at Work: Strategies for Overcoming Distraction,
Regaining Focus, and Working Smarter All Day
Long&lt;/a&gt;
. This is one of the most useful books I&amp;rsquo;ve ever read. It gave me a
useful understanding of how my brain works, and how to make use of
that knowledge to improve my work life.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <id>tag:www.flyingmachinestudios.com,2011-08-03:/essays/not-a-founder/</id>
    <title type="html">Why I Don't Want to Start a Startup</title>
    <published>2011-08-04T02:30:00Z</published>
    <updated>2011-08-04T02:30:00Z</updated>
    <link rel="alternate" href="http://www.flyingmachinestudios.com/essays/not-a-founder/" />
    <content type="html">&lt;h1&gt;Why I Don&amp;#8217;t Want to Start a Startup&lt;/h1&gt;
&lt;p&gt;Over the course of my programming career I&amp;#8217;ve spent a little more than two years working at startups. At the time, I thought that the experience would help me when I eventually started my startup. Instead I became convinced that the startup life is not for me.&lt;/p&gt;
&lt;h2&gt;Reason #1: I Don&amp;#8217;t Want to be Like the Founders I&amp;#8217;ve Known&lt;/h2&gt;
&lt;p&gt;The reason why I stopped working at one of the startups was because the founder had me work for a month and a half without paying me and without telling me he was having cash flow problems.&lt;/p&gt;
&lt;p&gt;The founder &amp;#8211; let&amp;#8217;s call him &amp;#8220;Reginald&amp;#8221; &amp;#8211; had been late in paying me before, so when I didn&amp;#8217;t receive a check on time I didn&amp;#8217;t think much of it. However, when I hadn&amp;#8217;t been paid after 45 days I asked him what was going on and he told me he didn&amp;#8217;t have the money to pay me and wouldn&amp;#8217;t for four months. During those 45 days, he had known that he wouldn&amp;#8217;t be able to pay me, yet he didn&amp;#8217;t say anything to me about it.&lt;/p&gt;
&lt;p&gt;Instead, he had me to continue to work under the assumption that I would get paid in a timely manner. I ended up confronting him about this, telling him that he had been dishonest with me. His rationale for his behavior was that he wanted me to embrace a more entrepreneurial spirit. The idea is ludicrous, but even if it were not, it was not his right to make that decision for me.&lt;/p&gt;
&lt;p&gt;What made this worse was that I had considered us to be friends. How could someone whom I had worked with for nearly a year treat me that way? How could someone who I thought considered me a friend disrupt my life so tremendously?&lt;/p&gt;
&lt;p&gt;And it did disrupt my life. I was supporting someone who was very ill and required expensive treatment. &amp;#8220;Reginald&amp;#8221; knew that, yet he decided to set me back financially anyway. All of a sudden I was without income, and forty-five of the days I could have spent looking for a new job were taken from me. It was one of the most stressful periods of my life.&lt;/p&gt;
&lt;p&gt;The point of this is not to excoriate  &amp;#8220;Reginald&amp;#8221;. The point is that I don&amp;#8217;t want to become like him. My interpretation of his behavior is that his startup was so important to him that he was willing to disregard honesty and integrity and inflict suffering on a friend in order to buy a little more time for it.&lt;/p&gt;
&lt;p&gt;I could see myself behaving like that. If I had come to identify myself as a failure and saw my social status &amp;#8211; my identity, even &amp;#8211; as tied to the success of my business, it&amp;#8217;s possible that I&amp;#8217;d behave just as he did. Or at least, I might be tempted to. I&amp;#8217;d like to think that I wouldn&amp;#8217;t, but the point of all this is that I don&amp;#8217;t want to put myself in a position where I&amp;#8217;d have to find out.&lt;/p&gt;
&lt;h2&gt;Reason #2: I Don&amp;#8217;t Think Financial Freedom is Required for Happiness&lt;/h2&gt;
&lt;p&gt;One of the reasons I wanted to start a startup was that I liked the idea of having the financial freedom to do whatever I want. I thought that would allow me to be happier.&lt;/p&gt;
&lt;p&gt;In the past few years, though, I&amp;#8217;ve come to learn that happiness is something you learn to cultivate, and that it&amp;#8217;s not something that just happens as a result of changes to your external environment.&lt;/p&gt;
&lt;p&gt;This is something that&amp;#8217;s hard for me to put into words, so I&amp;#8217;ll just steal the words of Thich Nhat Hanh (even though I feel a little pretentious quoting him here):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Freedom is above all else freedom from our own notions and concepts. If we get caught in our notions and concepts, we can make ourselves suffer and we can also make those we love suffer.&lt;/p&gt;
&lt;p&gt;&amp;#8212; &lt;em&gt;Hanh, Thich (2003). No Death, No Fear (p. 11). Riverhead. Kindle Edition.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;What good would it do me to be constantly reinforcing the concept that financial freedom is required for happiness? It didn&amp;#8217;t do &amp;#8220;Reginald&amp;#8221; any good. Instead of working myself to death day in and day out, why not concentrate on being happy now?&lt;/p&gt;
&lt;h2&gt;Reason #3: I Already Have Big Challenges&lt;/h2&gt;
&lt;p&gt;Another reason the idea of starting a startup appealed to me is that it seemed like a fun challenge. To be honest, it still seems like it could be a fun challenge. It&amp;#8217;s just not one that I want to take up right now.&lt;/p&gt;
&lt;p&gt;For a little more than a year now, the challenge I&amp;#8217;ve set for myself is to express love regardless fear. That expression can take many forms, whether it&amp;#8217;s just telling a co-worker that I think they&amp;#8217;re great or telling a friend that I&amp;#8217;m glad she&amp;#8217;s in my life or telling my girlfriend that she&amp;#8217;s wonderful.&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s also influenced how I see my side projects. At the beginning of the year I decided that, for 2011, I&amp;#8217;d only work on side projects that will be freely available and that come from my desire to help other people.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.visualmess.com"&gt;Clean Up Your Mess&lt;/a&gt; was the first such project, and it was born of my desire to help other people experience the joy that I feel when I&amp;#8217;m attempting graphic design &amp;#8211; to give them some tools that will allow them to communicate more clearly and creatively. I&amp;#8217;ve received numerous tweets, emails, and comments on how the site has been useful, and those notes have been very gratifying to me.&lt;/p&gt;
&lt;p&gt;There were many times, though, when I thought it was pointless to work on the project. I imagined people criticizing it, calling it confusing or boring or worthless (which hasn&amp;#8217;t happened). The idea of expressing love regardless of fear kept me going, though.&lt;/p&gt;
&lt;p&gt;There are many more &amp;#8220;projects&amp;#8221; I&amp;#8217;d like to tackle, all of which seem more interesting than starting a startup. I&amp;#8217;d like to be a better friend and a better brother. I&amp;#8217;d like to get better at lifting other people up. I&amp;#8217;d like to communicate better. All of these challenges are meaningful to me.&lt;/p&gt;
&lt;p&gt;And they don&amp;#8217;t require me to live on ramen for the next three years.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>tag:www.flyingmachinestudios.com,2011-05-02:/design/cuym-thank-you/</id>
    <title type="html">Thank You</title>
    <published>2011-05-02T04:00:00Z</published>
    <updated>2011-05-02T04:00:00Z</updated>
    <link rel="alternate" href="http://www.flyingmachinestudios.com/design/cuym-thank-you/" />
    <content type="html">&lt;h1&gt;Thank You&lt;/h1&gt;
&lt;p&gt;Thank you, everyone who has viewed &lt;a href="http://www.visualmess.com"&gt;Clean Up Your Mess&lt;/a&gt;. Thanks as well to everyone who has passed it on.&lt;/p&gt;
&lt;p&gt;I made it because I want to help as many people as possible learn about and enjoy design, so it makes me happy to see that people are reading it and finding it worth telling other people about it.&lt;/p&gt;
&lt;p&gt;Clean Up Your Mess has been the most difficult and time-consuming of all the side projects I&amp;#8217;ve worked on. I was constantly questioning whether I was spending my time well and whether other people would find the guide useful. The past couple days have been very gratifying for me, and it feels like all the work was worth it.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>tag:www.flyingmachinestudios.com,2011-01-21:/programming/higml/</id>
    <title type="html">Higml: Hierarchical, Cascading, Dynamic Configuration</title>
    <published>2011-01-22T04:23:00Z</published>
    <updated>2011-01-22T04:23:00Z</updated>
    <link rel="alternate" href="http://www.flyingmachinestudios.com/programming/higml/" />
    <content type="html">&lt;h1&gt;Higml: Hierarchical, Cascading, Dynamic Configuration&lt;/h1&gt;
&lt;h2&gt;Purpose&lt;/h2&gt;
&lt;p&gt;Higml allows you to write hierarchical, cascading, dynamic configuration files with Ruby. It visually reflects the conditions governing how rules are applied, allowing otherwise-complicated rules to be expressed concisely and understood easily.&lt;/p&gt;
&lt;h2&gt;Examples&lt;/h2&gt;
&lt;h3&gt;Applying Hierarchical, Cascading Rules&lt;/h3&gt;
&lt;pre class="emphasize"&gt;&lt;code class="emphasize"&gt;# Higml rules; let's pretend they're in rules.higml
action:create
  :channel Create Saved Search&lt;/code&gt;
  
&lt;code class="emphasize"&gt;action:show
  :channel Search&lt;/code&gt;
  
&lt;code class="emphasize"&gt;  search_type:job
    :channel Job Search&lt;/code&gt;
  
&lt;code class="emphasize"&gt;# Let's pretend the following is run by ruby
rules = "rules.higml"&lt;/code&gt;

&lt;code class="emphasize"&gt;input1 = {:action =&amp;gt; "show"}
input2 = {:action =&amp;gt; "show", :search_type =&amp;gt; "job"}
input3 = {:action =&amp;gt; "create", :search_type =&amp;gt; "job"}&lt;/code&gt;

&lt;code class="emphasize"&gt;Higml.values_for(input1, rules)
~&amp;gt; {:channel =&amp;gt; "Search"}&lt;/code&gt;

&lt;code class="emphasize"&gt;Higml.values_for(input2, rules)
~&amp;gt; {:channel =&amp;gt; "Job Search"}&lt;/code&gt;

&lt;code class="emphasize"&gt;Higml.values_for(input3, rules)
~&amp;gt; {:channel =&amp;gt; "Create Saved Search"}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Higml checks an input hash for key/value pairs and builds an output hash. Higml rules are cascading in that if a matching rule is defined later in the Higml file, it takes precedence over a previously defined rule.&lt;/p&gt;
&lt;p&gt;You can see this with inputs 1 &amp;amp; 2. &lt;code&gt;input2&lt;/code&gt; matches the &lt;code&gt;action:show&lt;/code&gt; rule, but it also matches the &lt;code&gt;search_type:job&lt;/code&gt; rule which is defined later. The &lt;code&gt;search_type:job&lt;/code&gt; rule therefore takes precedence.&lt;/p&gt;
&lt;p&gt;Higml is hierarchical in that it does not apply child (indented) rules if the parents don&amp;#8217;t match. You can see this by comparing inputs 2 &amp;amp; 3;&lt;/p&gt;
&lt;h3&gt;Dynamic Output&lt;/h3&gt;
&lt;pre class="emphasize"&gt;&lt;code class="emphasize"&gt; # Higml rules; let's pretend they're in rules.higml
action:show
  :keywords= @keywords&lt;/code&gt;

&lt;code class="emphasize"&gt;# Let's pretend everything that follows is run by ruby
# Context object
context = Object.new
context.instance_variable_set(:@keywords, "cat mouse bird")&lt;/code&gt;

&lt;code class="emphasize"&gt;# Higml invocation, including context object
Higml.values_for({:action =&amp;gt; "show"}, 'rules.higml', context)
~&amp;gt; {:keywords =&amp;gt; "cat mouse bird"}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Whenever Higml encounters &lt;code&gt;=&lt;/code&gt; in the output definition, it uses &lt;code&gt;instance_eval&lt;/code&gt; on the context object on the text that follows; in this case, &lt;code&gt;@keywords&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Rule Application Summarized&lt;/h2&gt;
&lt;ul class="spaced"&gt;
	&lt;li&gt;Rules take the form &lt;code&gt;input_key:value&lt;/code&gt; or &lt;code&gt;input_key&lt;/code&gt;. If value is not present, any value (including nil) will cause the rule to be applied.&lt;/li&gt;
	&lt;li&gt;Multiple rules can be present on the same line, separated by commas. Example: &lt;code&gt;action:show, action:new&lt;/code&gt;. This is equivalent to an &lt;code&gt;OR&lt;/code&gt; &amp;#8211; if any rule matches, the rule is applied.&lt;/li&gt;
	&lt;li&gt;Indented (child) rules are only checked if their parent matches.&lt;/li&gt;
	&lt;li&gt;Output definitions take the form &lt;code&gt;:output_key Value&lt;/code&gt; or &lt;code&gt;:output_key= code_instance_evald_in_context&lt;/code&gt;.&lt;/li&gt;
	&lt;li&gt;Output definitions written later on the page take precedence over those written earlier,&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Pronunciation&lt;/h2&gt;
&lt;p&gt;It&amp;#8217;s pronounced like &amp;#8220;hig-uh-mole&amp;#8221;.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>tag:www.flyingmachinestudios.com,2011-01-19:/programming/writing-better-documentation/</id>
    <title type="html">Writing Better Documentation</title>
    <published>2011-01-20T04:23:00Z</published>
    <updated>2011-01-20T04:23:00Z</updated>
    <link rel="alternate" href="http://www.flyingmachinestudios.com/programming/writing-better-documentation/" />
    <content type="html">&lt;h1&gt;Writing Better Documentation&lt;/h1&gt;
&lt;p&gt;The learning curve for code libraries is often unnecessarily steep. I frequently feel that if the author had written better documentation, I&amp;#8217;d be able to use his work much more quickly, or at least figure out that it&amp;#8217;s wrong for me and move on.&lt;/p&gt;
&lt;p&gt;My own work could use better documentation, and that&amp;#8217;s part of why I&amp;#8217;ve started using &lt;a href="http://effectif.com/nesta"&gt;nesta&lt;/a&gt; as my blogging engine. Nesta looks like it provides just enough of a framework for me to efficiently write articles which are mainly text. More importantly, there&amp;#8217;s room for me to easily extend it in order to explore different ideas for creating code documentation efficiently. As a first step, I&amp;#8217;ve written a few lines that will allow me to easily include source code in a &lt;a href="http://textile.thresholdstate.com/"&gt;textile&lt;/a&gt; document:&lt;/p&gt;
&lt;div class='attachment-path source'&gt;&lt;a href='/assets/source/custom_tags.rb'&gt;custom_tags.rb&lt;/a&gt;&lt;/div&gt;&lt;div class='code pygments'&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt; 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;source&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;local_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;highlighted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;range&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/([^ :]*)(?::(\d+))?(?: (\d+-\d+))?/&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:text&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
  &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;readlines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expand_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;__FILE__&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="n"&gt;local_path&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;range&lt;/span&gt;
    &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;finish&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;range&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;-&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;collect&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_i&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;finish&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  
  &lt;span class="n"&gt;indentation_level&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/^ */&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;
  &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;collect!&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^ {&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;indentation_level&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sr"&gt;}/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt; &lt;span class="c1"&gt;#remove indendation&lt;/span&gt;
  &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;
  
  &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;lt;div class=&amp;#39;attachment-path source&amp;#39;&amp;gt;&amp;quot;&lt;/span&gt;
  &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;lt;a href=&amp;#39;/assets/source/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;local_path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#39;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;local_path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/a&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class=&amp;#39;code pygments&amp;#39;&amp;gt;&amp;quot;&lt;/span&gt;

  &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;popen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;pygmentize -O linenos=table,linenostart=&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; -f html -l ruby&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;a+&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;pygmentize&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;pygmentize&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;
    &lt;span class="n"&gt;pygmentize&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close_write&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pygmentize&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gets&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;lt;/div&amp;gt;&amp;quot;&lt;/span&gt;
  
  &lt;span class="n"&gt;html&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;p&gt;Hopefully that will come in handy when I want to include other, less self-referential snippets.&lt;/p&gt;
&lt;p&gt;In the mean time I&amp;#8217;ve also been thinking about what makes good documentation. &lt;a href="http://tom.preston-werner.com"&gt;Tom Preston-Werner&lt;/a&gt; recently wrote &lt;a href="http://tom.preston-werner.com/2010/08/23/readme-driven-development.html"&gt;an article&lt;/a&gt; urging developers to write a &lt;span class="caps"&gt;README&lt;/span&gt; before coding, and I think that&amp;#8217;s advice worth trying, though I haven&amp;#8217;t tried it myself. Unfortunately, he&amp;#8217;s not very specific on what should be included in the &lt;span class="caps"&gt;README&lt;/span&gt;. Personally, it&amp;#8217;d be a lot easier for me to write a &lt;span class="caps"&gt;README&lt;/span&gt; if there were some formula I could follow. I also believe that other programmers would write better documentation if they had the tools that facilitated the joy and creativity that they experience with programming.&lt;/p&gt;
&lt;p&gt;My initial thought on good documentation is that it should include the following:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;The purpose of the code&lt;/li&gt;
	&lt;li&gt;When it should be used and when it shouldn&amp;#8217;t (i.e. &amp;#8220;This authentication library is great if you don&amp;#8217;t require much customization.&amp;#8221;)&lt;/li&gt;
	&lt;li&gt;Installation&lt;/li&gt;
	&lt;li&gt;Basic usage&lt;/li&gt;
	&lt;li&gt;How to extend it&lt;/li&gt;
	&lt;li&gt;Its &amp;#8220;home&amp;#8221;&lt;/li&gt;
	&lt;li&gt;Links to further documentation&lt;/li&gt;
	&lt;li&gt;Other quality libraries which address the same problem&lt;/li&gt;
	&lt;li&gt;A brief tutorial&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&amp;#8230; looks like a lot of work. (Googling &amp;#8220;what goes in a readme&amp;#8221; also reveals that it looks a bit like &lt;a href="http://books.google.com/books?id=WOyuE3YYjiIC&amp;amp;lpg=PA211&amp;amp;ots=csqyUBZoOq&amp;amp;dq=what%20goes%20in%20a%20readme&amp;amp;pg=PA211#v=onepage&amp;amp;q&amp;amp;f=false"&gt;this excerpt from Ruby Best Practices&lt;/a&gt;). It also looks like it shouldn&amp;#8217;t all be put in the &lt;span class="caps"&gt;README&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;In any case, my next little project is to write some documentation for a little library I created. After that I&amp;#8217;m sure I&amp;#8217;ll have a better idea of what makes good documentation.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>tag:www.flyingmachinestudios.com,2011-01-14:/blog-reboot/</id>
    <title type="html">Blog Reboot</title>
    <published>2011-01-14T18:11:26Z</published>
    <updated>2011-01-14T18:11:26Z</updated>
    <link rel="alternate" href="http://www.flyingmachinestudios.com/blog-reboot/" />
    <content type="html">&lt;h1&gt;Blog Reboot&lt;/h1&gt;
&lt;p&gt;It&amp;#8217;s been nearly a year since I&amp;#8217;ve added anything to this site. There are a few reasons for that, though for now I&amp;#8217;ll only mention that I didn&amp;#8217;t like that the site existed in part to sell an iphone app and possibly future apps. Well, it turns out that I don&amp;#8217;t really care about selling stuff. What I really want is a place to write about I care about most.&lt;/p&gt;
&lt;p&gt;And that might make this site kinda weird. I plan on writing about design, programming, aikido, buddhism, communication, and a host of other topics which aren&amp;#8217;t usually seen rubbing elbows. The thread which wends its way through all these topics is love.&lt;/p&gt;
&lt;p&gt;With design, I&amp;#8217;ll share my attempts at creating layouts and interfaces which are a joy to use. With programming, I&amp;#8217;ll share the code I&amp;#8217;ve written, and hopefully it will help other folks. With aikido and buddhism, I&amp;#8217;ll probably just share my thoughts on what I&amp;#8217;ve read and practiced. My obsession with communication will probably be evident in most things I write, and it is, after all, why I want to write anything in the first place.&lt;/p&gt;
&lt;p&gt;So that&amp;#8217;s what this site is for. Not to sell or persuade, but just to share the things I love.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>tag:www.flyingmachinestudios.com,2010-02-15:/essays/models-for-dealing-with-fear/</id>
    <title type="html">Models for Dealing with Fear</title>
    <published>2010-02-15T18:53:00Z</published>
    <updated>2010-02-15T18:53:00Z</updated>
    <link rel="alternate" href="http://www.flyingmachinestudios.com/essays/models-for-dealing-with-fear/" />
    <content type="html">&lt;h1&gt;Models for Dealing with Fear&lt;/h1&gt;
&lt;p&gt;There is a popular kind of article on &lt;a href="http://news.ycombinator.com"&gt;Hacker News&lt;/a&gt; that is always 1/3 self-deception. The content of the article can be boiled down to three parts:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;A description of some cool accomplishment by the author or someone he knows&lt;/li&gt;
	&lt;li&gt;The behaviors which lead to that accomplishment&lt;/li&gt;
	&lt;li&gt;The world-view which allowed the accomplisher to feel comfortable with the behaviors&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example, recently &lt;a href="http://www.zacharyburt.com/2010/02/how-i-landed-a-50hr-side-gig-with-very-little-effort-how-it-relates-to-picking-up-chicks/"&gt;How I Landed A $50/hr Side Gig With Very Little Effort &amp;amp; How It Relates To Picking Up Chicks&lt;/a&gt; made it to the front page of HN. It can be broken down to:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;I landed a $50/hr side gig with very little effort&lt;/li&gt;
	&lt;li&gt;To do this I was concise, friendly, abundant, value-offering, indifferent&lt;/li&gt;
	&lt;li&gt;I felt comfortable acting this way because I believe:
	&lt;ul&gt;
		&lt;li&gt;You have complete control over the universe because it only exists in your head&lt;/li&gt;
		&lt;li&gt;Other people are only projections of your own consciousness. If you are not a friend to everyone then you are not a friend to yourself.&lt;/li&gt;
	&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Which part do you think comprises the self-deception?&lt;/p&gt;
&lt;h2&gt;Models for Overcoming Fear&lt;/h2&gt;
&lt;p&gt;These kinds of articles are perennially interesting because, at their heart, they&amp;#8217;re moral stories about overcoming fear. The author describes a situation where most people would feel fear &amp;#8211; fear of humiliation, fear of loss, fear or failure &amp;#8211; and shows how his world-view allowed him to cope with the fear well enough for him to exhibit the behaviors which lead to his success. These stories keep alive our hope that we, too, can overcome our fears and live how we want.&lt;/p&gt;
&lt;p&gt;However, these stories present their world-view as fact, and I think that&amp;#8217;s where the self-deception lies. The world-view is considered to be absolute truth, when really it&amp;#8217;s just a model that&amp;#8217;s proven useful.&lt;/p&gt;
&lt;p&gt;I think this is easy to see in the example above. You probably would not agree that &amp;#8220;you have complete control over the universe because it only exists in your head.&amp;#8221; You could try this model out for yourself by compelling the universe-in-your-head to add millions to your bank account, only to find that all you&amp;#8217;ve done is whittled away another fraction of your life. Yet, it&amp;#8217;s undeniable that this model has helped the above author and others to overcome their fears and do cool shit.&lt;/p&gt;
&lt;p&gt;The world abounds with wacky models that help actual people actually overcome actual fear. Some people believe their obstacles are put there by God as tests for them to pass. Others believe that mortal life is a game played by immortal energy beings, just for the fun of it. And some folks believe that there is nothing more to life than what we see; when we die, that&amp;#8217;s the end, so we better make the most of it. Wacky!&lt;/p&gt;
&lt;h2&gt;Models for Justifying Fear&lt;/h2&gt;
&lt;p&gt;Just as models help us overcome fear, they also help us justify fear. When we were teenagers, one of my best friends made all her decisions based on the statistical likelihood that she would be successful. She adopted a model of the world where her fear of failing had to be heeded: &amp;#8220;Since so many other people have failed at being an artist, it&amp;#8217;s likely I will fail too. I will therefore become a teacher, avoiding the pain and humiliation of constant rejection.&amp;#8221; Obviously she never said that, but that&amp;#8217;s how it seemed to me.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m not saying she was wrong to think this way. What I &lt;em&gt;am&lt;/em&gt; saying is that we adopt different models to help us cope with fear, and that we often deceive ourselves into thinking these models are absolute truth. When our models have outlived their usefulness &amp;#8212; when they no longer allow us to be happy &amp;#8212; we find it hard to change them because we believe that our models are reality itself rather than &lt;em&gt;interpretations&lt;/em&gt; of it.&lt;/p&gt;
&lt;p&gt;Which models are more useful &amp;#8212; those that help us overcome our fears or those that justify them? Well, this is honestly a bit of ridiculous question. These models are more complex than the question allows, and besides that, I think that there&amp;#8217;s no One True Model. Rather, it varies by person and context.&lt;/p&gt;
&lt;p&gt;Regardless, it&amp;#8217;s worthwhile to breakdown our world-views, our models of reality, so we can better understand them and, possibly, change them.&lt;/p&gt;
&lt;h2&gt;World-Views Dissected&lt;/h2&gt;
&lt;p&gt;Our world-views are made up of three parts: the universe, you, and your relationship to the universe. I&amp;#8217;m stealing from Ayn Rand a bit here, but those parts can be broken down further (I apologize for compressing all of philosophy into three ridiculous lists):&lt;/p&gt;
&lt;h3&gt;You&lt;/h3&gt;
&lt;p&gt;Yeah, this has gotten deep. Are your abilities fixed, or are you capable of improving them? How about your emotions, your personality? Are you good, bad, amoral? Does it depend? What does it depend on? Does it depend on who you have been up to this point? Does it depend on who&amp;#8217;s asking?&lt;/p&gt;
&lt;h3&gt;The Universe&lt;/h3&gt;
&lt;p&gt;Is the universe benevolent? Malevolent? Indifferent? Is it chaotic or orderly? Is it fair? Is it just? Is it meaningful or meaningless? Are you capable of comprehending it? Is it all in your head? Do you control all of it? Part of it? None of it?&lt;/p&gt;
&lt;h3&gt;Society&lt;/h3&gt;
&lt;p&gt;What is your place in society? Are you able to influence other people? Are you controlled by other people? How much control do you have, and in what situations? Do you fit in? Will you never fit in?&lt;/p&gt;
&lt;p&gt;Obviously, it&amp;#8217;s possible to ponder these questions for millennia. Hopefully what&amp;#8217;s listed here will help you to analyze your own world-view and to analyze other possible world-views.&lt;/p&gt;
&lt;h2&gt;The Model to End All Models: Life as an Improv Game&lt;/h2&gt;
&lt;p&gt;This article wouldn&amp;#8217;t be complete without my own unimpeachable advice on what works. Lately I&amp;#8217;ve been experimenting with approaching life as an improv game, and I&amp;#8217;ve really enjoyed it.&lt;/p&gt;
&lt;p&gt;Improv games have the following guidelines:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;There&amp;#8217;s a set of rules, but within those rules anything can happen.&lt;/li&gt;
	&lt;li&gt;You don&amp;#8217;t control what will happen next, but you control your reaction.&lt;/li&gt;
	&lt;li&gt;Whatever happens, run with it. Say &amp;#8220;yes&amp;#8221; to it.&lt;/li&gt;
	&lt;li&gt;It&amp;#8217;s only a mistake if you say it&amp;#8217;s a mistake.&lt;/li&gt;
	&lt;li&gt;You&amp;#8217;re there to make your team look good.&lt;/li&gt;
	&lt;li&gt;Your team will support you.&lt;/li&gt;
	&lt;li&gt;Have fun, or else.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This model has greatly helped me overcome social fears. It&amp;#8217;s helped me approach life with a much more adventurous spirit.&lt;/p&gt;
&lt;p&gt;Perhaps in another article I&amp;#8217;ll give a real-life example about how this approach has served me. I could call it &amp;#8220;How I Went from Folding Laundry for The Man at $8.75/hr to Living in Hawaii and Making $90/hr Working for Myself at 21 Years of Age&amp;#8221;. It&amp;#8217;d be about accomplishing cool shit and overcoming fears along the way. It would be ninety percent true.&lt;/p&gt;
&lt;p&gt;In the mean time, I hope this article has helped to clarify your own thinking about the way you cope with fear in your life. My belief is that once you accept that your world-view is only a model and not absolute Truth, it&amp;#8217;s easier to discard it in favor of a more useful one. One that will make you happier.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>tag:www.flyingmachinestudios.com,2010-01-10:/essays/look-into-my-eyes/</id>
    <title type="html">Look Into My Eyes</title>
    <published>2010-01-10T16:46:00Z</published>
    <updated>2010-01-10T16:46:00Z</updated>
    <link rel="alternate" href="http://www.flyingmachinestudios.com/essays/look-into-my-eyes/" />
    <content type="html">&lt;h1&gt;Look Into My Eyes&lt;/h1&gt;
&lt;p&gt;My first attempt to give myself super powers merely gave me sore palms. Riding in the back of my mother&amp;#8217;s beater as a five-year-old, I focused sunlight on the center of each hand using a magnifying glass likely found in a cereal box. After I was &amp;#8220;charged up&amp;#8221; I would point at trees, cars, fire hydrants, and other hapless objects and think to myself, &amp;#8220;In five years, that thing&amp;#8217;s going to burst into flames.&amp;#8221;&lt;/p&gt;
&lt;p&gt;A couple years later I set out to hypnotize people. Wagging a watch in front of my friends&amp;#8217; faces and intoning &amp;#8220;You are getting very sleepy&amp;#8221; had little effect. By that time I could read well enough to consume hypnosis books at the local library. I learned to put myself in a trance, making myself unable to lift my own arm. Making yourself immobile didn’t seem suitably spectacular for a super power, so I moved on to practical endeavors like building electric motors and crystal radios.&lt;/p&gt;
&lt;p&gt;Still, the promise of hypnosis is compelling in a deep, almost primordial way. Since the time of our earliest ancestors, we humans have believed in the power to manipulate the world &amp;#8212; our environments, our fellow humans, and ourselves &amp;#8212; with mere words. The ability to wreak devastation or relieve suffering with spells and incantations still captures our imaginations. What I would give to be able to say &amp;#8220;abodicus immaculatus&amp;#8221; and have my house cleaned!&lt;/p&gt;
&lt;p&gt;Many even believe in this power literally, especially when it comes to religion. Here in America, the majority still believe that prayer offers us a direct link to God, and many believe that saying prayers can relieve illness or financial hardship. One sect of Buddhism holds that you merely need to recite a prayer, even without meaning it sincerely, and after death you&amp;#8217;ll exist in nirvana as a buddha on a golden lotus for all eternity, while in ancient Jewish tradition pronouncing &lt;span class="caps"&gt;YHWH&lt;/span&gt;, one of the names of God, was punishable by death.&lt;/p&gt;
&lt;p&gt;Our species is at once terrified of what words can do and faithful in their power to heal and save, and hypnosis is still viewed in both these lights. A quick google search for &amp;#8220;evil hypnosis&amp;#8221; &lt;a href="http://www.rapidnet.com/~jbeard/bdm/Psychology/hypno.htm"&gt;yields this quote&lt;/a&gt;: &amp;#8220;It is obvious that hypnosis is lethal if used for evil purposes.&amp;#8221; If you&amp;#8217;re willing to take this risk, you&amp;#8217;ll find that hypnosis can help with &amp;#8220;weight loss, smoking cessation, pain management, public speaking, creativity, astral travel, self confidence&amp;#8221; &lt;a href="http://www.suite101.com/article.cfm/hypnosis/105301"&gt;and on and on and on&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;I began seriously trying to learn hypnosis again in high school, mostly out of curiosity. My interest was piqued after reading an essay by Aldous Huxley where he described the beneficent uses and effectiveness of hypnosis. I remember thinking to myself, &amp;#8220;If he thinks it&amp;#8217;s so great then maybe there&amp;#8217;s something to it.&amp;#8221; So once again I immersed myself in hypnosis books, this time with a realistic idea of what hypnosis can accomplish. None of my family would submit themselves to my budding powers, so it wasn&amp;#8217;t until college that I actually got a chance to try and hypnotize someone.&lt;/p&gt;
&lt;p&gt;After a lot of badgering, my new friend Lea agreed to be hypnotized. One night we went to her dorm room and she lied on her bed while I sat nearby and tried going through a script. We both tried not to laugh when the script had me saying &amp;#8220;Remember: you are in control. You are in the driver&amp;#8217;s seat&amp;#8221; over and over in my best monotone. Lea never did get hypnotized all the way, but she said afterward that she became deeply relaxed and that it felt good. Even if I wasn&amp;#8217;t 100% successful, the experience was thrilling.&lt;/p&gt;
&lt;p&gt;However, the real power of words was revealed years later when I deeply hurt Lea without realizing it. She had come to visit me in the house we had originally rented together after our first year of college. During our year of college and co-habitating we went through some crazy, crazy stuff together &amp;#8212; family problems, relationship problems, and one surreal night at the hotel where I worked involving college applications, Aerosmith, gun shots, and flooding &amp;#8212; and we&amp;#8217;d become great friends. So it made me really happy that she was staying with me and we&amp;#8217;d get to spend time together. Yet, one morning a few days after she arrived, she was gone.&lt;/p&gt;
&lt;p&gt;The previous night we&amp;#8217;d had a discussion about politics &amp;#8212; healthcare, actually &amp;#8212; and I acted like a complete ass. I didn&amp;#8217;t just disagree, I was strident and contemptuous in my disagreement. I cut her off, raised my voice, acting in a way no friend should act. Looking back now, my behavior seems even more ridiculous because my views on healthcare have completely changed, matching hers.&lt;/p&gt;
&lt;p&gt;Eventually we smoothed things out and we remain great friends, but I&amp;#8217;ve tried not to forget the lesson of that experience. Lea had left a note that said I must think her stupid to say some of the things I did. I&amp;#8217;ve never thought Lea stupid, but I was so concerned with making my points that I succeeded only in pushing her away, rather than connecting with her and understanding her, as I would try to do now.&lt;/p&gt;
&lt;p&gt;Over time I&amp;#8217;ve come to appreciate the inescapability of the fact that we&amp;#8217;re islands of consciousness, that we are forever bound to see the world from within our skulls. Some people claim that they&amp;#8217;ve achieved a feeling of oneness with all of humanity, but I certainly never have. It&amp;#8217;s often a struggle to bridge the vast gap between my island and the islands of those I love most, to say nothing of acquaintances or strangers. Words are a material &amp;#8212; perhaps the most abundant &amp;#8212; for building those bridges, or destroying them.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Last year I saw a different friend for the first time in five years. We had been through a lot together and it made me more than happy to see him, but it quickly became obvious he had changed. The morning after arriving he asked, &amp;#8220;Hey is there a place around here I can get some Bud Light?&amp;#8221; For the remainder of his stay he almost always had a drink with him. Over six days he drank at least thirty-six cans of beer, plus some bottles here and there. Despite the amount he drank he seemed pretty normal, and I probably wouldn&amp;#8217;t have even known if I hadn&amp;#8217;t seen the cases he bought.&lt;/p&gt;
&lt;p&gt;Except one night when we were driving home from the beach. My friend is a very kind, very gentle person. But that night his voice got louder and his speech slurred as he inexplicably argued with me over something that had happened nine years ago. I was scared that night but more scared the next day when he didn&amp;#8217;t remember what happened.&lt;/p&gt;
&lt;p&gt;Eventually I tried to talk to him about his drinking. I told him it worried me, that even if he considered himself a functioning alcoholic that it was unhealthy for him and dangerous. Looking back, it&amp;#8217;s almost like I can see my words soaring toward him, shining and proud and certain. And I can see them falling, can see them limping forward to die at his feet.&lt;/p&gt;
&lt;p&gt;I wasn&amp;#8217;t able to persuade my friend at all, and I&amp;#8217;m afraid that I may have alienated him. What could I have said differently? &amp;#8220;Look into my eyes&amp;#8230;&amp;#8221;&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ll always love him, I&amp;#8217;ll always care about him, and I&amp;#8217;ll always be his friend. Hopefully I&amp;#8217;ll get a chance to regain his trust. In the mean time, I&amp;#8217;m not as concerned with &amp;#8220;wielding&amp;#8221; my words. I&amp;#8217;m cultivating the ability to really listen &amp;#8211; not just to what&amp;#8217;s said, but to what lies beneath. And in this endeavor, the words of James Merrill have left their mark on me:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;Salt lick big as a fist, heart, hoard&lt;br /&gt;
Of self one grew up prizing above rubies &amp;#8212;&lt;br /&gt;
To feel it even by a grain dissolved&amp;#8230;&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Rather than inflicting my &amp;#8220;hoard of self&amp;#8221; upon people by insisting on my cleverness, my wisdom, or my rightness; rather than hailing others from my superior position, I&amp;#8217;m learning to open the fist of my heart and reach out.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>tag:www.flyingmachinestudios.com,2010-01-06:/im-going-to-take-all-the-help-i-can-get/</id>
    <title type="html">I'm Going to Take All the Help I Can Get</title>
    <published>2010-01-06T12:06:00Z</published>
    <updated>2010-01-06T12:06:00Z</updated>
    <link rel="alternate" href="http://www.flyingmachinestudios.com/im-going-to-take-all-the-help-i-can-get/" />
    <content type="html">&lt;h1&gt;I&amp;#8217;m Going to Take All the Help I Can Get&lt;/h1&gt;
&lt;p&gt;A few months ago, I was really psyched about some project (don&amp;#8217;t recall which), and said to myself, &amp;#8220;I&amp;#8217;m going to finish this thing, and nothing&amp;#8217;s going to get in my way.&amp;#8221; Immediately it occurred to me that a better attitude would be, &amp;#8220;I&amp;#8217;m going to finish this thing &amp;#8212; and I&amp;#8217;ll take all the help I can get.&amp;#8221;&lt;/p&gt;
&lt;p&gt;Expecting that I&amp;#8217;ll get help instead of expecting that I&amp;#8217;ll encounter conflict and resistance has made me more open about my work. My tendency is to be quite shy about my own work, but I&amp;#8217;ve since tried to go out of my way to share it with people.&lt;/p&gt;
&lt;p&gt;For example, recently I created &lt;a title="Hacker News" href="http://news.ycombinator.com/item?id=1005674"&gt;a post on Hacker News&lt;/a&gt; (and emailed the Boston Ruby Group) asking the folks there if they wanted to start a small group to give and receive writing feedback. The group has 15 members now, and though most appear to be lurkers I&amp;#8217;ve met a few great people and got some really excellent feedback on the copy for &lt;a title="Control Time" href="http://www.learngrowdo.com/control-time"&gt;Control Time&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;One fellow I met, Aaron Dragushan, has a site similar to this one: &lt;a href="http://www.upgrademe.org/"&gt;Upgrade Me&lt;/a&gt;. It has some great productivity tips, but aims to be about more than just productivity. Exciting stuff! You should check it out &amp;#8211; the content&amp;#8217;s well written and each post is a pretty quick read.&lt;/p&gt;
&lt;p&gt;And by the way, if you&amp;#8217;re interested in joining the &lt;a href="http://groups.google.com/group/writing-feedback"&gt;writing feedback group&lt;/a&gt; please do and introduce yourself. We could use some more active members :-)&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>tag:www.flyingmachinestudios.com,2010-01-01:/control-time-submitted-to-app-store/</id>
    <title type="html">Control Time Submitted to App Store</title>
    <published>2010-01-02T03:56:00Z</published>
    <updated>2010-01-02T03:56:00Z</updated>
    <link rel="alternate" href="http://www.flyingmachinestudios.com/control-time-submitted-to-app-store/" />
    <content type="html">&lt;h1&gt;Control Time Submitted to App Store&lt;/h1&gt;
&lt;p&gt;Today I finally wrapped up &lt;a title="Control Time" href="/control-time"&gt;Control Time&lt;/a&gt; and submitted it to the app store :-). Hopefully they&amp;#8217;ll publish it soon.&lt;/p&gt;
&lt;p&gt;Thanks to my brother Matt for creating the icon and to everyone who tried out the app along the way. Thanks also to the writing feedback group for helping me write ad copy.&lt;/p&gt;
&lt;p&gt;This is the first app I&amp;#8217;ve submitted, but it won&amp;#8217;t be the last!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update (Jan 4):&lt;/strong&gt; Wow, the app has already been approved! &lt;a href="itms://itunes.apple.com/us/app/control-time/id348796242?mt=8"&gt;You can see it on iTunes.&lt;/a&gt;&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>tag:www.flyingmachinestudios.com,2009-12-12:/essays/how-to-get-and-stay-motivated/</id>
    <title type="html">How to Get and Stay Motivated</title>
    <published>2009-12-13T03:03:00Z</published>
    <updated>2009-12-13T03:03:00Z</updated>
    <link rel="alternate" href="http://www.flyingmachinestudios.com/essays/how-to-get-and-stay-motivated/" />
    <content type="html">&lt;h1&gt;How to Get and Stay Motivated&lt;/h1&gt;
&lt;p&gt;A lot of people view their motivation as something out of their control. It comes and goes, catlike in its fickleness. By breaking down motivation to its components, however, you&amp;#8217;ll be able to troubleshoot your lack of motivation and figure out ways to increase it.&lt;/p&gt;
&lt;p&gt;But first: what is motivation?&lt;/p&gt;
&lt;h2&gt;Motivation is Your Emotional Energy for Making The Right Choices&lt;/h2&gt;
&lt;p&gt;Every few months I get excited about doing barefoot running and tell myself I&amp;#8217;m going to do it consistently. Running appeals to me as a way to have more energy, to feel healthy, and to clear my head. I have all the gear: running pants, running shirt, a nifty pair of shoes with virtually no sole. And every few months my excitement peters out and my gear collects dust in the closet again &amp;#8211; a scenario I&amp;#8217;m sure you&amp;#8217;re familiar with, in one way or another.&lt;/p&gt;
&lt;p&gt;That initial burst of motivation is not enough because changing your lifestyle is not an all-or-nothing proposition. It takes time (some say weeks, some say months) to develop new habits or shed old ones. During that time you&amp;#8217;re constantly encouraged to not follow through, whether by yourself or others. If you&amp;#8217;re trying to lose weight, for example, you have to pass by McDonald&amp;#8217;s and Burger Kings on your drive to work. You have to navigate past countless pastries, candy bars, and other crappy foods when you go grocery shopping. Change is a matter of consistently making the right choices, day in and day out, until making the right choice becomes as easy and habitual as it once was to make the wrong choice.&lt;/p&gt;
&lt;p&gt;Resisting the wrong choices and making the right choices takes energy, and motivation is that energy. The reason why I haven&amp;#8217;t been able to stick with running is that I&amp;#8217;m constantly faced with the wrong choices in a very compelling manner (&amp;#8220;Running hurts, but watching movies is fun!&amp;#8221; or &amp;#8220;It&amp;#8217;s cold outside man! Also did I mention that running hurts?&amp;#8221;), draining my motivation. My initial burst of motivation isn&amp;#8217;t replenished, and my intention to run dies a quiet death.&lt;/p&gt;
&lt;p&gt;Instead of just accepting that your motivation will eventually wither, you can deliberately make more. Just like baking a delicious cake, making more motivation requires you know the ingredients. That&amp;#8217;s right, making yourself more motivated is just like baking a cake.&lt;/p&gt;
&lt;h2&gt;The Anatomy of Motivation&lt;/h2&gt;
&lt;p&gt;Motivation has two main components, Incentives and Confidence. Each has a variety of sub-components.&lt;/p&gt;
&lt;h3&gt;Incentives&lt;/h3&gt;
&lt;p&gt;An incentive is, circularly enough, any factor which motivates a particular course of of action or counts as a reason for preferring one choice to the alternatives (says &lt;a href="http://en.wikipedia.org/wiki/Incentive"&gt;wikipedia&lt;/a&gt;). The same incentive will vary in effectiveness depending on how important it is for the individual person. If a gang leader offered to pay you less than minimum wage to risk your life standing on a street corner to sell crack, you would probably decline. &lt;a href="http://www.ted.com/talks/steven_levitt_analyzes_crack_economics.html"&gt;Yet there are people who have accepted that offer&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Incentives also differ in their polarity. Positive incentives are incentives that you &lt;em&gt;desire,&lt;/em&gt; whereas you &lt;em&gt;avoid&lt;/em&gt; negative incentives. You might read to avoid failing a class or to experience the pleasure of expanding your mind. Most people tend to be motivated more by one than the other, and it helps to know which type of incentive works better for you.&lt;/p&gt;
&lt;p&gt;There are a few major incentive categories, and it helps to know how you respond to each. In the future I&amp;#8217;ll write more on each category individually:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;Social:&lt;/strong&gt; Social incentives involve gaining or losing social esteem. An example would be telling your friends that you&amp;#8217;re going to stop smoking. The need to keep their respect by keeping your word is a strong motivating force.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Moral:&lt;/strong&gt; I think this one is pretty self-explanatory&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Financial:&lt;/strong&gt; This one is too&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Personal:&lt;/strong&gt; Life goals and personal passions would fall under this category. One thing I want to point out here, which I&amp;#8217;ll explore more in another post, is that a feeling of worthlessness can be a debilitating form of incentive that completely drains motivation, preventing people from making lifestyle choices.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Confidence&lt;/h3&gt;
&lt;p&gt;Confidence here refers to your belief that you&amp;#8217;re &lt;em&gt;capable&lt;/em&gt; of making the right choices. People suffering from addiction can often strongly recognize the need to quit &amp;#8211; the addiction is destroying his life and the lives of those he love &amp;#8211; but feel helpless to fight it.&lt;/p&gt;
&lt;p&gt;Confidence depends on many sub-components:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;Knowledge:&lt;/strong&gt; It&amp;#8217;s easy to give up when you feel confused. Since you don&amp;#8217;t really know what&amp;#8217;s right, you settle for what&amp;#8217;s familiar.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;Feedback:&lt;/strong&gt; Taking &amp;#8220;knowledge&amp;#8221; one step further, it&amp;#8217;s essential to get feedback. Chart your progress, get feedback from friends or whoever &amp;#8211; whatever works for you.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;Expectations:&lt;/strong&gt; If you underestimate how much time or effort it will take you to do something, it&amp;#8217;s possible you&amp;#8217;ll get frustrated and feel like you&amp;#8217;re not up to the task. On the other hand, if something is easier to do than you expected, it can be a real confidence booster.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;Other people:&lt;/strong&gt; Think of what it&amp;#8217;s like to have a boss who shoots down your ideas versus one who supports and encourages you. This component&amp;#8217;s especially important when &amp;#8220;other people&amp;#8221; have power over you, whether actual or merely perceived.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;Time:&lt;/strong&gt; In my opinion this is a very important part of confidence that&amp;#8217;s often overlooked. Feeling like you don&amp;#8217;t have enough time to change your lifestyle is enough to prevent you from trying. The perception that you don&amp;#8217;t have enough time and don&amp;#8217;t know how to make it is so detrimental that I&amp;#8217;ve made &lt;a href="http://www.learngrowdo.com/control-time"&gt;an iphone app to address those issues&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;Self-confidence:&lt;/strong&gt; Your overall feeling of self-confidence obviously affects how confident you&amp;#8217;ll feel about accomplishing a particular goal.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;Skills &amp;amp; Equipment:&lt;/strong&gt; These need the least explaining and are the most straight-forward to acquire.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Troubleshoot Your Lack of Motivation&lt;/h2&gt;
&lt;p&gt;Now that you understand what comprises motivation, you can begin to ask questions that allow you to uncover why you&amp;#8217;re not motivated. There are innumerable resources on specific facets of motivation (some of which we&amp;#8217;ll cover on this site in the future), but the following troubleshooting outline should allow you to figure out what needs fixing and give you a good start in fixing it.&lt;/p&gt;
&lt;h3&gt;Do you struggle with conflicting incentives?&lt;/h3&gt;
&lt;p&gt;An example of this would be trying to lose weight but being afraid that you&amp;#8217;ll lose friends who are uncomfortable with a healthy lifestyle. (It sounds weird, but it happens. People are weird.) You might be able to talk to some friends and work things out, even have them join you; or you might have to decide what&amp;#8217;s more important, keeping your current friends or being healthy. Or it might be that you have a pantry full of cookies that are always tempting you, in which case you can just throw them out. Either way, it helps to be aware of of the incentives pulling you in the wrong direction.&lt;/p&gt;
&lt;h3&gt;Are your current incentives important to you?&lt;/h3&gt;
&lt;p&gt;You might &amp;#8220;know&amp;#8221; you need to stop smoking because it&amp;#8217;s destroying your lungs, but that&amp;#8217;s not an important enough reason to stop. Then you might fall in love with someone who can&amp;#8217;t stand smoking, and allova sudden you find the motivation to quit. Hooray! You now have an incentive that&amp;#8217;s important to you.&lt;/p&gt;
&lt;p&gt;If a goal is truly important to you, it&amp;#8217;s even possible to &amp;#8220;manufacture&amp;#8221; an important incentive. Two that work great are writing your goal down and telling other people your goal. In the first case, your incentive is to not let yourself down, while in the second your incentive is to not let down others. What&amp;#8217;s most important, however, is knowing what kinds of incentives work for you and structuring your life to include them. How to do so is a topic worthy of a blog post, and in the future I&amp;#8217;ll provide one.&lt;/p&gt;
&lt;h3&gt;Where are you lacking confidence?&lt;/h3&gt;
&lt;p&gt;Go through the list above and ask yourself if you&amp;#8217;re lacking confidence in that area. There are myriad resources that address each area of confidence, and in time I hope to list some on my site and add some of my own. In the mean time, you can always try the best way to gain confidence:&lt;/p&gt;
&lt;h3&gt;The Best Way to Gain Confidence is to Join a Group with The Same Goals&lt;/h3&gt;
&lt;p&gt;Joining like-minded people is bar none the best way to gain confidence. You&amp;#8217;ll be able to learn from their experience and thus gain knowledge. They&amp;#8217;ll be able to teach you the skills you need and loan or give you required equipment. They&amp;#8217;ll help you set realistic expectations because they&amp;#8217;ve already been through what you&amp;#8217;re trying to go through. They&amp;#8217;ll provide you with encouragement and feedback. You&amp;#8217;ll be glad you&amp;#8217;re not going it alone.&lt;/p&gt;
&lt;p&gt;The next time you&amp;#8217;re lacking motivation, you can pinpoint what&amp;#8217;s wrong and take the steps necessary to get more motivated.&lt;/p&gt;
&lt;p&gt;Now go out there and be somebody!&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>tag:www.flyingmachinestudios.com,2009-12-01:/essays/the-why-of-this-site/</id>
    <title type="html">The Why of this Site</title>
    <published>2009-12-02T03:35:00Z</published>
    <updated>2009-12-02T03:35:00Z</updated>
    <link rel="alternate" href="http://www.flyingmachinestudios.com/essays/the-why-of-this-site/" />
    <content type="html">&lt;h1&gt;The Why of this Site&lt;/h1&gt;
&lt;p&gt;I&amp;#8217;m a young software developer and caregiver. This web site is about my experimentations in creating and following a system for constant personal growth. This article gives some background on the circumstances that motivated me to start those experimentations and this site.&lt;/p&gt;
&lt;p&gt;It was around summer of 2008 that I realized I had become mean &amp;#8212; a small person, constantly irritable and ready to cut down others. I went through nearly every day in a sour mood, showing annoyance and contempt toward those I interacted with regularly and interpreting their behavior as putting me down. It was like I was an angry drunk without the benefit of actually being drunk. At the same time, I clung to trivial diversions like video games and TV, all the while feeling like I no longer had time for anything I liked. In the mean time, my fledgling consultancy had crumbled and I felt like a professional failure.&lt;/p&gt;
&lt;p&gt;I was ashamed of myself. I knew I had to change something, but what? And how? For the previous year and a half I had been making chaotic attempts to change the way I felt and behaved. I would start to read a book and stop after the first couple chapters. I would start to create a new habit &amp;#8211; for example, of exercising regularly &amp;#8211; and quit after a week. Nothing stuck &amp;#8211; or, more accurately, I couldn&amp;#8217;t stick with anything.&lt;/p&gt;
&lt;p&gt;Life hadn&amp;#8217;t always been like this. I&amp;#8217;ve always been a tinkerer, and as a teenager I fell in love with programming. Beyond its inherent joy, I saw programming as my ticket to freedom, allowing me to go where I wanted and do what I loved. I dreamed of being able to sit on a beach, working on a laptop with a tasty drink by my side. In November of 2005 that dream was realized when I arrived at the Honolulu airport with my laptop, my suitcase, and a little extra money to spend time settling in.&lt;/p&gt;
&lt;p&gt;The next year was incredible. I made new friends and grew my business. It was awesome to finish projects quickly and successfully and have my clients tell me how happy they were with my work. At the same time, I was able to work on my own projects for fun and learn new programming languages and technologies (like javascript, ruby, and ruby on rails). And the food! Just minutes a way were handful of great restaurants that had delicious food for cheap prices. For five or six dollars I could buy enough to last me two days. Nearly every morning I woke up to sea breezes blowing my curtains, and I could see a bit of the ocean from my gigantic bedroom window.&lt;/p&gt;
&lt;p&gt;Then in December of 2006 my long &amp;#8220;vacation&amp;#8221; came to an end. The last memory I have of Hawaii is of driving up a hillside in the early afternoon with the sun shining down. Below me the island stretched out to the ocean, and it was beautiful.&lt;/p&gt;
&lt;p&gt;I left Hawaii for Massachusetts. When I got on my plane in Hawaii, it was seventy degrees (fahrenheit) and gorgeous outside. When I touched down in Boston, the temperature was below freezing. Better (and perhaps more honest) writers than I would resist symbolizing the weather like this; alas, I find the transition indicative of the upheavals I would deal with in the coming months.&lt;/p&gt;
&lt;p&gt;What brought me to Massachusetts, anyway? After years of searching and suffering, my girlfriend had finally received a treatable diagnosis for the disease that had disabled her: Lyme Disease. In order for her to receive better medical care, we moved to Massachusetts, where we would be close to &amp;#8220;Lyme-literate&amp;#8221; doctors and friends as well.&lt;/p&gt;
&lt;p&gt;Lyme Disease, if it goes untreated, can cause severe physical and neurological damage. Its victims are left without energy and in constant pain. Lyme sufferers also experience memory loss, rages, aphasia, and a host of other symptoms that leave them doubting whether they are, or ever will be, the person they were before getting Lyme.&lt;/p&gt;
&lt;p&gt;My attempts to develop a system for constant personal growth and fulfillment are primarily the result of my taking on the role of caregiver for my girlfriend. At the time, I thought of it like I did my work projects. It would take a little extra effort for awhile, and then it&amp;#8217;d be over and I moved on to something else. But work has never been so stressful, nor so heartbreaking.&lt;/p&gt;
&lt;p&gt;Some issues which caregiving brought which I&amp;#8217;d never dealt with include:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Being interrupted urgently, often, and without warning. Programming requires long stretches of concentration and can be like building a house of cards in your mind; interruptions, even slight ones, can knock the house right over. Being interrupted over and over makes it difficult to even start concentrating in the first place.&lt;/li&gt;
	&lt;li&gt;Living in a constant state of emergency. Will this new medication cause a negative reaction? How bad will it be? Ambulance bad, or &amp;#8220;just&amp;#8221; throwing up all night bad?&lt;/li&gt;
	&lt;li&gt;Watching the one you care for suffer, and knowing there&amp;#8217;s nothing more you can do about it.&lt;/li&gt;
	&lt;li&gt;Feeling guilty about everything. Guilty about being healthy. Guilty about being sick, when sick. Guilty about not doing enough. Guilty about doing too much and being exhausted. Guilty about trying to relax. Guilty about feeling guilty.&lt;/li&gt;
	&lt;li&gt;Feeling angry about feeling guilty.&lt;/li&gt;
	&lt;li&gt;Feeling angry and discouraged over the perceived lack of caring in others, including friends and family.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Over a period of years, these experiences wore me down completely. Trying to balance my full-time job, caregiving, and my personal life continues to be a challenge, but I think I&amp;#8217;m improving. This site is part of my effort to accomplish meaningful change &amp;#8211; to continuously learn about myself and others, to grow as a human being, and to do the things I love. I&amp;#8217;ll be focusing on the principles of change more than the techniques. I hope you find it useful, and I look forward to continuing this conversation with other like-minded people. Onward and upward!&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>tag:www.flyingmachinestudios.com,2009-05-21:/programming/follow-your-followers-using-ruby/</id>
    <title type="html">Follow Your Followers Using Ruby</title>
    <published>2009-05-21T04:23:00Z</published>
    <updated>2009-05-21T04:23:00Z</updated>
    <link rel="alternate" href="http://www.flyingmachinestudios.com/programming/follow-your-followers-using-ruby/" />
    <content type="html">&lt;h1&gt;Follow Your Followers Using Ruby&lt;/h1&gt;
&lt;p&gt;I have the following in a rake task run every 30 minutes. You&amp;#8217;ll need jnunemaker&amp;#8217;s twitter gem.&lt;/p&gt;
&lt;div class='attachment-path source'&gt;&lt;a href='/assets/source/follow-your-followers.rb'&gt;follow-your-followers.rb&lt;/a&gt;&lt;/div&gt;&lt;div class='code pygments'&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt; 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;twitter&amp;#39;&lt;/span&gt;
&lt;span class="c1"&gt;# Check out the twitter gem docs for using oauth&lt;/span&gt;
&lt;span class="n"&gt;httpauth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Twitter&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTTPAuth&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;username&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;password&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;base&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Twitter&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;httpauth&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;to_follow_ids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;follower_ids&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;friend_ids&lt;/span&gt;
&lt;span class="n"&gt;unavailable_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;to_follow_ids&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;tfid&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="k"&gt;begin&lt;/span&gt;
    &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;friendship_create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tfid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;Twitter&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;General&lt;/span&gt;
    &lt;span class="c1"&gt;# Twitter::General is raised for 403 errors&lt;/span&gt;
    &lt;span class="c1"&gt;# Which occur when you&amp;#39;re trying to follow someone who&amp;#39;s been banned by twitter&lt;/span&gt;
    &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tfid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;Twitter&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Unavailable&lt;/span&gt; 
    &lt;span class="c1"&gt;# Wait and try again if twitter&amp;#39;s telling you to wait&lt;/span&gt;
    &lt;span class="nb"&gt;sleep&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;unavailable_count&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
      &lt;span class="k"&gt;retry&lt;/span&gt;
      &lt;span class="n"&gt;unavailable_count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;</content>
  </entry>
  <entry>
    <id>tag:www.flyingmachinestudios.com,2009-05-11:/programming/aikidoka-prevents-namespace-collisions/</id>
    <title type="html">Aikidoka Prevents Namespace Collisions</title>
    <published>2009-05-11T04:23:00Z</published>
    <updated>2009-05-11T04:23:00Z</updated>
    <link rel="alternate" href="http://www.flyingmachinestudios.com/programming/aikidoka-prevents-namespace-collisions/" />
    <content type="html">&lt;h1&gt;Aikidoka Prevents Namespace Collisions&lt;/h1&gt;
&lt;p&gt;Recently I fell victim to the Twitter-Mash / Extlib-DataMapper-Mash &lt;a href="http://blog.zerosum.org/2009/4/17/why-namespaces-are-important"&gt;namespace collision&lt;/a&gt;. To get around this problem, I&amp;#8217;ve created a new gem, &lt;a href="http://github.com/flyingmachine/aikidoka/tree/master"&gt;Aikidoka&lt;/a&gt;&amp;quot;.&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s what happened when I tried to use Twitter when Extlib had already been loaded:&lt;/p&gt;
&lt;pre class="emphasize"&gt;&lt;code class="emphasize"&gt;irb(main):001:0&amp;gt; require 'Twitter'
=&amp;gt; ["Twitter"]
irb(main):002:0&amp;gt; Twitter::Search.new("bokken").fetch
SystemStackError: stack level too deep&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here&amp;#8217;s what happens when you use Aikidoka:&lt;/p&gt;
&lt;pre class="emphasize"&gt;&lt;code class="emphasize"&gt;irb(main):001:0&amp;gt; require 'aikidoka'
=&amp;gt; ["Aikidoka"]
irb(main):002:0&amp;gt; Aikidoka.rename("Mash" =&amp;gt; "Twitter::Mash"){require 'twitter'}
=&amp;gt; ["Mash"]
irb(main):003:0&amp;gt; Twitter::Search.new("aikidoka").fetch
=&amp;gt; &amp;lt;Mash completed_in=0.052875 max_id=1754360060 next_page="?page=2&amp;amp;max_id=1754360060&amp;amp;q=aikidoka"&amp;gt;
etc...&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It works! What this does is namespace the Mash defined when I require the Twitter gem, so that Mash is now Twitter::Mash. Also, Extlib&amp;#8217;s Mash is still there, untouched, so you don&amp;#8217;t need to worry about that. Here&amp;#8217;s how Aikidoka does its magic:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;It temporarily renames existing constants so that they don&amp;#8217;t get clobbered. In this case, &amp;#8220;Mash&amp;#8221; is renamed to &amp;#8220;AikidokaMash&amp;#8221;. Right now this only works with top-level constants.&lt;/li&gt;
	&lt;li&gt;It yields to the given block. This block should define the constants you want permanently renamed/namespaced. In this case, we&amp;#8217;re requiring &amp;#8220;twitter&amp;#8221;, which in turn requires &amp;#8220;mash&amp;#8221;. &amp;#8220;mash&amp;#8221; defines the constant we want to rename, Mash.&lt;/li&gt;
	&lt;li&gt;It creates modules as necessary to create the namespace. In this case, the module Twitter is already defined so that&amp;#8217;s used. However, if we wanted to rename &amp;#8220;Mash&amp;#8221; to &amp;#8220;Potatoes::Mash&amp;#8221;, then a module named &amp;#8220;Potatoes&amp;#8221; would have been created.&lt;/li&gt;
	&lt;li&gt;It assigns the object referred to by the old constant to its new constant. &amp;#8220;Twitter::Mash&amp;#8221; now refers to the same object that &amp;#8220;Mash&amp;#8221; refers to.&lt;/li&gt;
	&lt;li&gt;Old constants are removed to clean up the namespace. The constant &amp;#8220;Mash&amp;#8221; no longer exists, the object it used to refer to lives on.&lt;/li&gt;
	&lt;li&gt;The constants temporarily renamed in step 1 are now given their original names back. Extlib&amp;#8217;s &amp;#8220;Mash&amp;#8221; is no longer &amp;#8220;AikidokaMash&amp;#8221;; it&amp;#8217;s &amp;#8220;Mash&amp;#8221; again.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The code is very simple &amp;#8211; a total of 67 lines in one file with decent specs &amp;#8211; so hopefully it&amp;#8217;s easy to dig into.&lt;/p&gt;
&lt;p&gt;Right now Aikidoka is best at nesting an existing top-level constant within another constant of a different name. I haven&amp;#8217;t tried doing something like &lt;code&gt;Aikidoka.rename("Mash" =&amp;gt; "Mash::Twitter")&lt;/code&gt; or &lt;code&gt;Aikidoka.rename("ActiveRecord::Base" =&amp;gt; "ARBase")&lt;/code&gt;, and those examples probably wouldn&amp;#8217;t work.&lt;/p&gt;
&lt;p&gt;All in all, it does what I want it to and seems to work OK :) You can install it with &lt;code&gt;gem install flyingmachine-aikidoka&lt;/code&gt;. If you&amp;#8217;re wondering about the name, aikido is a martial art designed to resolve conflict harmoniously, and an aikidoka is a student of aikido.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>tag:www.flyingmachinestudios.com,2008-08-24:/design/usability-embodied/</id>
    <title type="html">Usability Embodied</title>
    <published>2008-08-24T22:13:36Z</published>
    <updated>2008-08-24T22:13:36Z</updated>
    <link rel="alternate" href="http://www.flyingmachinestudios.com/design/usability-embodied/" />
    <content type="html">&lt;h1&gt;Usability Embodied&lt;/h1&gt;
&lt;p&gt;A few years ago I ordered &lt;span class="caps"&gt;DSL&lt;/span&gt; service. The &lt;span class="caps"&gt;DSL&lt;/span&gt; modem came with an ethernet cable, and one end was labeled &amp;#8220;this end goes in your computer&amp;#8221;, and the other was labeled &amp;#8220;this end goes in the modem.&amp;#8221; Obviously, it doesn&amp;#8217;t matter which end goes where, but the labels undoubtedly eliminated any possible confusion.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>tag:www.flyingmachinestudios.com,2008-07-14:/robots/</id>
    <title type="html">Robots!</title>
    <published>2008-07-14T16:45:17Z</published>
    <updated>2008-07-14T16:45:17Z</updated>
    <link rel="alternate" href="http://www.flyingmachinestudios.com/robots/" />
    <content type="html">&lt;h1&gt;Robots!&lt;/h1&gt;
&lt;p&gt;I&amp;#8217;ve been learning more about electronics, in part to get a ground-up understanding of computers. In the process I&amp;#8217;ve become interested in learning to build robots.&lt;/p&gt;
&lt;p&gt;My first attempt at building a robot, about 8 years ago, wasn&amp;#8217;t really successful. I was in high school and I wanted to build a robot that would turn off my light switch across the room because at night I would read in bed, and when I was done I didn&amp;#8217;t want to have to get up to turn off the light. So I got my mom to buy me Lego Mindstorms one Christmas and put together a robot, and it would just run into the wall and fall apart. I tried a little more and kept getting the same result, so I just said &amp;#8220;fuck it&amp;#8221; and I bought a lamp to put beside my bed. Incidentally, that&amp;#8217;s still how I approach problems most of the time.&lt;/p&gt;
&lt;p&gt;Anyway, one thing I&amp;#8217;d like to make is a little wristband with an &lt;span class="caps"&gt;LCD&lt;/span&gt; (like a digital watch) displays random words throughout the day. After that, a robot parrot which repeats words it hears often. It&amp;#8217;ll have Barry White&amp;#8217;s voice.&lt;/p&gt;</content>
  </entry>
</feed>

