<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-2452497389474481952</id><updated>2012-01-12T08:14:09.476Z</updated><title type='text'>Software, Abstract Strategy Games &amp; Other Stories</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://mpatric.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2452497389474481952/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://mpatric.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>mpatric</name><uri>http://www.blogger.com/profile/10270216082836687119</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xWpZXVYmOxY/TAGB3OXHIfI/AAAAAAAAAEM/MKjL7hNyWag/S220/mpatric-manga.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>14</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-2452497389474481952.post-6235292317537234994</id><published>2010-12-18T12:28:00.000Z</published><updated>2010-12-18T12:28:45.692Z</updated><title type='text'>Moving Blog</title><content type='html'>&lt;p&gt;This will be my last post here, I am moving my blog to &lt;a href='http://mpatric.com'&gt;http://mpatric.com&lt;/a&gt;.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;My new blog is a custom-built &lt;a href='http://rubyonrails.org/'&gt;Rails&lt;/a&gt; app, hosted on &lt;a href='http://heroku.com/'&gt;Heroku&lt;/a&gt;, using &lt;a href='http://gravatar.com/'&gt;Gravatar&lt;/a&gt; for avatars, &lt;a href='http://akismet.com/'&gt;Akismet&lt;/a&gt; for anti-spam and &lt;a href='http://aws.amazon.com/s3/'&gt;Amazon S3&lt;/a&gt; for storing assets.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2452497389474481952-6235292317537234994?l=mpatric.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mpatric.blogspot.com/feeds/6235292317537234994/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2452497389474481952&amp;postID=6235292317537234994' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2452497389474481952/posts/default/6235292317537234994'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2452497389474481952/posts/default/6235292317537234994'/><link rel='alternate' type='text/html' href='http://mpatric.blogspot.com/2010/12/moving-blog.html' title='Moving Blog'/><author><name>mpatric</name><uri>http://www.blogger.com/profile/10270216082836687119</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xWpZXVYmOxY/TAGB3OXHIfI/AAAAAAAAAEM/MKjL7hNyWag/S220/mpatric-manga.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2452497389474481952.post-1325030739667906039</id><published>2010-03-20T23:53:00.017Z</published><updated>2010-05-29T22:24:33.212+01:00</updated><title type='text'>Is reversi too difficult?</title><content type='html'>&lt;p&gt;Much time went into making the AI of &lt;a href="http://kissthemachine.com/reversi"&gt;reversi&lt;/a&gt; strong enough on its higher levels to challenge human players. The highest three levels (of the seven available) are challenging for most human players. On the lower levels, the intention was for it to play as a novice human would play. On the lowest level (&lt;i&gt;beginner&lt;/i&gt;) in particular it plays for short-term gains, without considering longer term strategy at all. On each turn, the beginner level plays the move that flips as many of the opponent's pieces, taking a corner if one is available and avoiding squares that would give the opponent a corner on the &lt;b&gt;very next&lt;/b&gt; move. This reflects the basic manner in which most novices would tend to play reversi.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Playing each of the other levels 100 times against beginner results in beginner level being whipped 100-0 by every other level. So, it's significantly weaker than all the levels above it, including the one directly above it (&lt;i&gt;intermediate&lt;/i&gt;).&lt;br /&gt;&lt;/p&gt;&lt;p&gt;All of this makes some of the comments in reviews for Reversi on the App Store all the more surprising:&lt;br /&gt;&lt;blockquote&gt;&lt;i&gt;"Othello is an awesome game I really enjoy playing it but this game is way to difficult even on the easiest setting I cannot beat this  game even once I think you should change that"&lt;/i&gt; - BjMiller20, Jan 2010&lt;/blockquote&gt;&lt;blockquote&gt;&lt;i&gt;"..it's too difficult to win even on the easy setting. After playing it just a few times, I've given up on it. It's no fun if you don't  feel like you even have the slightest hope of beating the computer and on the easy setting, you should have at least a 50/50 chance."&lt;/i&gt; - Mitchipoo, Jan 2010&lt;/blockquote&gt;&lt;blockquote&gt;&lt;i&gt;"..frak me, the AI is ridiculous! I've played this game for years but I can't beat the game on Beginner! I'm not Einstein, but I should  be able to win at that level.."&lt;/i&gt; - Nuclear Moose, Oct 2009&lt;/blockquote&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_xWpZXVYmOxY/TAGFZtieLzI/AAAAAAAAAEs/9hCrqyKsU-I/s1600/reversi-in-iphone.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_xWpZXVYmOxY/TAGFZtieLzI/AAAAAAAAAEs/9hCrqyKsU-I/s320/reversi-in-iphone.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;Is beginner level really too difficult? I have played against it dozens of times and beaten it without really thinking about where to play, but I'm probably not the best yardstick as I've played thousands of games of reversi.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;I thought a good, objective test of the difficulty of the beginner level would be to see how it does against a player that makes completely random moves on every turn. Surely if the player making random moves manages to win a few games, then the AI of the opponent player is weak. With this in mind, I pitted beginner level against a bot playing random (valid) moves on every turn; 100 games with beginner playing black and the random bot playing white, followed by 100 games with colours switched. The results of the 200 games were as follows:&lt;br /&gt;&lt;/p&gt;&lt;blockquote&gt;164 games won by beginner (80 as black, 84 as white)&lt;br /&gt;29 games won by random (11 as black, 18 as white)&lt;br /&gt;7 games drawn&lt;/blockquote&gt;&lt;p&gt;Beginner level managed to win 82% of the games against the random bot, suggesting that it is fairly weak.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Most people that have played reversi know that corner squares are important and often determine who wins the game. Adding two very simple rules to the random bot, which are to play a corner if one is available and to avoid playing squares that give away a corner to the opponent on the very next move (otherwise, just to play randomly as before) changes the results to:&lt;br /&gt;&lt;/p&gt;&lt;blockquote&gt;85 games won by beginner (40 as black, 45 as white)&lt;br /&gt;111 games won by random (53 as black, 58 as white)&lt;br /&gt;4 games drawn&lt;/blockquote&gt;&lt;p&gt;From this we may conclude that beginner level is pretty weak. It is beaten often by this simple bot. It would only be weaker if it intentionally played moves that were advantageous to the opponent - in other words, if it played to lose. It would appear that amazingly enough some human players play in this way, perhaps thinking they're playing good moves. To those complaining that the beginner level on reversi is too difficult, it really isn't. Learn some basic strategy and you'll find you will be able to beat beginner level quite easily.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;UPDATE: The difficulty levels have been spread out a bit, so beginner is now even easier.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2452497389474481952-1325030739667906039?l=mpatric.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mpatric.blogspot.com/feeds/1325030739667906039/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2452497389474481952&amp;postID=1325030739667906039' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2452497389474481952/posts/default/1325030739667906039'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2452497389474481952/posts/default/1325030739667906039'/><link rel='alternate' type='text/html' href='http://mpatric.blogspot.com/2010/03/is-reversi-too-difficult.html' title='Is reversi too difficult?'/><author><name>mpatric</name><uri>http://www.blogger.com/profile/10270216082836687119</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xWpZXVYmOxY/TAGB3OXHIfI/AAAAAAAAAEM/MKjL7hNyWag/S220/mpatric-manga.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_xWpZXVYmOxY/TAGFZtieLzI/AAAAAAAAAEs/9hCrqyKsU-I/s72-c/reversi-in-iphone.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2452497389474481952.post-2462915958552638524</id><published>2009-06-20T20:34:00.006+01:00</published><updated>2010-05-29T22:44:22.011+01:00</updated><title type='text'>Unethical practises on the App Store</title><content type='html'>&lt;p&gt;Every iPhone app developer goes through great pains to get their apps noticed and hopefully to break into the charts, which will result in increased sales. Rather than building great apps to entice buyers, the approach some &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;devs&lt;/span&gt; take is to release &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;crapware&lt;/span&gt; and then to dishonestly fill the App Store with five star reviews that rave about the brilliance of their apps, enticing many gullible users into buying them in the process. Whilst I understand the difficulty that all &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;devs&lt;/span&gt; have in promoting their applications, Apple should draw the line at this sort of unethical behaviour.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;"Hold on!" I hear you cry. "How is this even possible? You need an &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;iTunes&lt;/span&gt; account to place a review and creation of an &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;iTunes&lt;/span&gt; account requires the entering of personal details and credit card information!"&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Yes, you do need an &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;iTunes&lt;/span&gt; account to place a review; however an &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;iTunes&lt;/span&gt; account can be created quite easily using a &lt;span style="font-weight: bold;"&gt;promo code&lt;/span&gt; which EVERY developer on the App Store that has published applications can generate for their own applications. Personal details are not verified, so anything can really be entered. New email addresses are easy to generate. It wouldn't take more than a few minutes to generate each new &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;iTunes&lt;/span&gt; account. This technique can currently only be applied to the &lt;span style="font-weight: bold;"&gt;US App Store&lt;/span&gt;.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Obviously, it's hard to prove which developers are doing this, however when it's done blatantly it's obvious. Take &lt;a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewArtist?id=304659461"&gt;this developer&lt;/a&gt; for example, who has several applications on the App Store that all have suspiciously good reviews and ratings on the US App Store. Clicking through on each of the 'reviewers' reveals that each one has reviewed all of the developer's applications, giving five stars in each case and glowing reviews. The offending applications include &lt;a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=314520004&amp;amp;mt=8"&gt;My Othello&lt;/a&gt; and &lt;a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=314527433&amp;amp;mt=8"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;Reversi&lt;/span&gt; Extended&lt;/a&gt; (which look to be identical games).&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Or course, I'm not saying these reviews were submitted using this trick; however the evidence is quite strong. Furthermore, these implementations of &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;reversi&lt;/span&gt; are easily (IMHO of course) the worst on the App Store, yet have the best ratings (4 stars and 5 stars respectively on the US App Store, with 29 suspicious reviews each). The reviews are not true reflection of these implementations.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Hopefully Apple addresses this loophole, or the reviews in the App Store will become worthless. Thankfully, at this point it's &lt;span style="font-weight: bold;"&gt;only the US App Store that is affected&lt;/span&gt;; however, for most developers the US App Store is the most lucrative, so it might become difficult to compete with apps whose rating has been boosted using this technique. Apple, please close this loophole.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2452497389474481952-2462915958552638524?l=mpatric.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mpatric.blogspot.com/feeds/2462915958552638524/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2452497389474481952&amp;postID=2462915958552638524' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2452497389474481952/posts/default/2462915958552638524'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2452497389474481952/posts/default/2462915958552638524'/><link rel='alternate' type='text/html' href='http://mpatric.blogspot.com/2009/06/developer-dishonesty-on-app-store.html' title='Unethical practises on the App Store'/><author><name>mpatric</name><uri>http://www.blogger.com/profile/10270216082836687119</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xWpZXVYmOxY/TAGB3OXHIfI/AAAAAAAAAEM/MKjL7hNyWag/S220/mpatric-manga.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2452497389474481952.post-6888923722321804698</id><published>2009-05-15T17:50:00.010+01:00</published><updated>2010-05-29T22:45:51.811+01:00</updated><title type='text'>The trouble with timers</title><content type='html'>&lt;p&gt;On the iPhone it seems to have become commonplace to use a NSTimer to trigger redraws on OpenGL ES applications when displaying a changing or animated scene. To run smoothly, a frame rate of 30fps or higher is generally aimed for (60fps being the maximum, limited by the iPhone hardware refresh).&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Relying on a timer to fire the code that renders the frame has its pros and its cons. The pros are simplicity and having everything in the same thread of execution (or runloop) means not having to worry about concurrency issues. The cons are what I'm more interested in..&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The NSTimer class reference states: &lt;span style="font-style: italic;"&gt;A timer is not a real-time mechanism; it fires only when one of the run loop modes to which the timer has been added is running and able to check if the timer’s firing time has passed. Because of the various input sources a typical run loop manages, the effective resolution of the time interval for a timer is limited to on the order of 50-100 milliseconds. If a timer’s firing time occurs while the run loop is in a mode that is not monitoring the timer or during a long callout, the timer does not fire until the next time the run loop checks the timer." Therefore, the actual time at which the timer fires potentially can be a significant period of time after the scheduled firing time.&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The low resolution and the fact that a timer can misfire (skip frames) are the most worrying for me.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;A frame rate of 60fps means a timer period of 1/60 = 0.016667 seconds (or 16.667ms). What this means is that the frame needs to be rendered well within 16.667ms or the timer will misfire. Flipping buffers when rendering an OpenGL frame can block, depending on the hardware refresh sync, making the likelihood of an overrun (and subsequent misfire) even higher.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;What typically happens is the timer fires every 16.667 ms or so (depending on what else the run loop is up to), but for frames whose drawing code has not completed by the next time the timer is meant to fire, the subsequent frame is effectively skipped.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_xWpZXVYmOxY/ShFt4sEhSxI/AAAAAAAAACo/trAkplGwEm4/s1600-h/timing.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 100px;" src="http://3.bp.blogspot.com/_xWpZXVYmOxY/ShFt4sEhSxI/AAAAAAAAACo/trAkplGwEm4/s320/timing.png" alt="" id="BLOGGER_PHOTO_ID_5337167854080969490" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;A misfire results in the time between two ticks suddenly being twice the expected period (or possibly a higher multiple of the period if the overrun in the rendering is even higher). Depending on the way in which the animation is implemented in the application, this will usually cause a visible blip or stutter. Regular misfires would make the animation appear jittery and unpleasant.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;As most developers simply add the timer to the main runloop, it means that the events need to fire in between whatever other code the main runloop is executing (in particular, user events). This can add inconsistency to the timer period.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Things that can be done to improve this situation (many of which can be done together) are:&lt;br /&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Optimise the drawing code so that it comfortably completes within the timer period (16.667ms for 60fps). If it's far under this threshold, then the other things happening in the runloop shouldn't regularly push it over the threshold.&lt;/li&gt;&lt;li&gt;Change the animation code so that it does not expect a regular period and animates the scene based on how much time has passed since the last animation. This is not always feasible - see this &lt;a href="http://www.sacredsoftware.net/tutorials/Animation/TimeBasedAnimation.xhtml"&gt;time-based animation tutorial&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Set the timer on a seperate thread (not the main thread).&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Use a thread with its own custom loop rather than a timer. This in itself is not a solution if the rendering regularly exceeds the desired frame rate period, however can improve the smoothness of the animation when combined with some of the other things in this list; it also gives you greater control over when to draw the next frame when the previous frame has overrun, instead of being forced into multiples of the timer.&lt;/li&gt;&lt;li&gt;Increase the timer period and only render the scene when an appropriate amount of time has passed (oversampling).&lt;/li&gt;&lt;li&gt;Decrease the frame rate; however it can only be decreased so far before it starts to look bad.&lt;/li&gt;&lt;li&gt;Decouple the drawing from code that is not directly related to rendering (such as physics simulation or animation logic) - see this blog on &lt;a href="http://gafferongames.com/game-physics/fix-your-timestep/"&gt;fixing the animation timestep&lt;/a&gt; for a good overview of this approach.&lt;/li&gt;&lt;li&gt;Synch to the hardware refresh. This is typically what console games do and would be the best approach in many situations. Unfortunately this not currently possible on the iPhone as no hook or callback is provided by the underlying APIs.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;My preferred approach is a combination of 1, 2 and 4. If option 8 was available I would go for a combination of 1, 2 and 8.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2452497389474481952-6888923722321804698?l=mpatric.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mpatric.blogspot.com/feeds/6888923722321804698/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2452497389474481952&amp;postID=6888923722321804698' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2452497389474481952/posts/default/6888923722321804698'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2452497389474481952/posts/default/6888923722321804698'/><link rel='alternate' type='text/html' href='http://mpatric.blogspot.com/2009/05/trouble-with-timers.html' title='The trouble with timers'/><author><name>mpatric</name><uri>http://www.blogger.com/profile/10270216082836687119</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xWpZXVYmOxY/TAGB3OXHIfI/AAAAAAAAAEM/MKjL7hNyWag/S220/mpatric-manga.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_xWpZXVYmOxY/ShFt4sEhSxI/AAAAAAAAACo/trAkplGwEm4/s72-c/timing.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2452497389474481952.post-6302929843723759145</id><published>2009-05-12T10:43:00.013+01:00</published><updated>2010-05-29T22:48:13.032+01:00</updated><title type='text'>Rise of the crapplication</title><content type='html'>&lt;p&gt;There has been chatter of late in the iPhone developer forums that I frequent regarding the prolifation of crap applications (&lt;span style="font-style: italic;"&gt;crapplications&lt;/span&gt;, or simply &lt;span style="font-style: italic;"&gt;crapps&lt;/span&gt;) in the App Store and that the App Store model encourages this. Could this really be true?&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Like many others, I have a full-time job and just develop iPhone applications in my spare time. But that does not mean it costs nothing to develop my applications. On the contrary - my spare time is very valuable to me - but how do I quantify it? If you assume that I did some other work, say contract work, over that time then the opportunity cost of this lost income can be determined.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;With this in mind, I decided to examine one of my applications, &lt;a href="http://kissthemachine.com/magnetic/"&gt;Magnetic Block Puzzle&lt;/a&gt; to see what the cost of developing it was and what sort of sales I would need to achieve to break even in a reasonable period of time.&lt;br /&gt;&lt;/p&gt;&lt;h2&gt;Magnetic Block Puzzle deconstructed&lt;/h2&gt;&lt;p&gt;I estimate that it took around 200 - 300 hours to develop, from start to release-ready code. In order to calculate an opportunity cost for this time, I need to determine an hourly rate. Conservatively I am using a rate of £30 per hour. That equates to an opportunity cost of £6,000 to £9,000. For the rest of this exercise, I will use the average of £7,500 (about $11,500). Expenses incurred in developing the application have been ignored.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;So, how many sales are required to break even?&lt;br /&gt;&lt;/p&gt;&lt;table style="border: 1px solid rgb(111, 111, 111); padding: 1em; margin: 0 auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;b&gt;Tier&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt;Price ($)&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt;Price (£)&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt;Pre-tax profit (£)&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt;Req sales&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Tier 1&lt;/td&gt;&lt;td&gt;0.99&lt;/td&gt;&lt;td&gt;0.59&lt;/td&gt;&lt;td&gt;0.36&lt;/td&gt;&lt;td&gt;20,833&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Tier 2&lt;/td&gt;&lt;td&gt;1.99&lt;/td&gt;&lt;td&gt;1.19&lt;/td&gt;&lt;td&gt;0.72&lt;/td&gt;&lt;td&gt;10,417&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Tier 3&lt;/td&gt;&lt;td&gt;2.99&lt;/td&gt;&lt;td&gt;1.79&lt;/td&gt;&lt;td&gt;1.09&lt;/td&gt;&lt;td&gt;6,881&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Tier 4&lt;/td&gt;&lt;td&gt;3.99&lt;/td&gt;&lt;td&gt;2.39&lt;/td&gt;&lt;td&gt;1.45&lt;/td&gt;&lt;td&gt;5,172&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Tier 5&lt;/td&gt;&lt;td&gt;4.99&lt;/td&gt;&lt;td&gt;2.99&lt;/td&gt;&lt;td&gt;1.82&lt;/td&gt;&lt;td&gt;4,121&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Tier 6&lt;/td&gt;&lt;td&gt;5.99&lt;/td&gt;&lt;td&gt;3.49&lt;/td&gt;&lt;td&gt;2.12&lt;/td&gt;&lt;td&gt;3,538&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Tier 7&lt;/td&gt;&lt;td&gt;6.99&lt;/td&gt;&lt;td&gt;3.99&lt;/td&gt;&lt;td&gt;2.43&lt;/td&gt;&lt;td&gt;3,086&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Tier 8&lt;/td&gt;&lt;td&gt;7.99&lt;/td&gt;&lt;td&gt;4.99&lt;/td&gt;&lt;td&gt;3.04&lt;/td&gt;&lt;td&gt;2,467&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Tier 9&lt;/td&gt;&lt;td&gt;8.99&lt;/td&gt;&lt;td&gt;5.49&lt;/td&gt;&lt;td&gt;3.34&lt;/td&gt;&lt;td&gt;2,246&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Tier 10&lt;/td&gt;&lt;td&gt;9.99&lt;/td&gt;&lt;td&gt;5.99&lt;/td&gt;&lt;td&gt;3.65&lt;/td&gt;&lt;td&gt;2,055&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;div&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_xWpZXVYmOxY/SglMXD_4puI/AAAAAAAAACY/KPyqPJBgLIk/s1600-h/sales1.png" style="text-align: left"&gt;&lt;img style="margin: 12px auto; display: block; text-align: left; cursor: pointer; width: 320px; height: 224px;" src="http://4.bp.blogspot.com/_xWpZXVYmOxY/SglMXD_4puI/AAAAAAAAACY/KPyqPJBgLIk/s320/sales1.png" alt="" id="BLOGGER_PHOTO_ID_5334879192691025634" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;I need to sell 10,417 copies at its current price of £1.19 ($1.99) just to break even! How many sales are required then, per day to break even in six months?&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;table style="border: 1px solid rgb(111, 111, 111); padding: 1em; margin: 0 auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;b&gt;Tier&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt;Price ($)&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt;Price (£)&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt;Pre-tax profit (£)&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt;Req sales per day&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Tier 1&lt;/td&gt;&lt;td&gt;0.99&lt;/td&gt;&lt;td&gt;0.59&lt;/td&gt;&lt;td&gt;0.36&lt;/td&gt;&lt;td&gt;114&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Tier 2&lt;/td&gt;&lt;td&gt;1.99&lt;/td&gt;&lt;td&gt;1.19&lt;/td&gt;&lt;td&gt;0.72&lt;/td&gt;&lt;td&gt;57&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Tier 3&lt;/td&gt;&lt;td&gt;2.99&lt;/td&gt;&lt;td&gt;1.79&lt;/td&gt;&lt;td&gt;1.09&lt;/td&gt;&lt;td&gt;38&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Tier 4&lt;/td&gt;&lt;td&gt;3.99&lt;/td&gt;&lt;td&gt;2.39&lt;/td&gt;&lt;td&gt;1.45&lt;/td&gt;&lt;td&gt;28&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Tier 5&lt;/td&gt;&lt;td&gt;4.99&lt;/td&gt;&lt;td&gt;2.99&lt;/td&gt;&lt;td&gt;1.82&lt;/td&gt;&lt;td&gt;23&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Tier 6&lt;/td&gt;&lt;td&gt;5.99&lt;/td&gt;&lt;td&gt;3.49&lt;/td&gt;&lt;td&gt;2.12&lt;/td&gt;&lt;td&gt;19&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Tier 7&lt;/td&gt;&lt;td&gt;6.99&lt;/td&gt;&lt;td&gt;3.99&lt;/td&gt;&lt;td&gt;2.43&lt;/td&gt;&lt;td&gt;17&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Tier 8&lt;/td&gt;&lt;td&gt;7.99&lt;/td&gt;&lt;td&gt;4.99&lt;/td&gt;&lt;td&gt;3.04&lt;/td&gt;&lt;td&gt;13&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Tier 9&lt;/td&gt;&lt;td&gt;8.99&lt;/td&gt;&lt;td&gt;5.49&lt;/td&gt;&lt;td&gt;3.34&lt;/td&gt;&lt;td&gt;12&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Tier 10&lt;/td&gt;&lt;td&gt;9.99&lt;/td&gt;&lt;td&gt;5.99&lt;/td&gt;&lt;td&gt;3.65&lt;/td&gt;&lt;td&gt;11&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;p&gt;57 copies a day at the current price doesn't sound too bad until you consider that it needs to maintain this level for six months and that on its best sales day it hasn't come close to this amount. It's looking unlikely that I will break even on this any time soon, if ever.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;What are the options then? Raising the price requires fewer sales to break even, but raising the price will result in a decrease in sales too, so this is unlikely to help.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Perhaps lowering the price to 59p ($0.99) will help boost sales? It probably will, but at that price the required number of sales to break even shoots up to 20,833 or 114 a day for six months.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The only other option is to lower the development cost. In other words, spend less time developing it in the first place. Too late for this application, but valuable information to take to the next one. Knocking off 10% or 20% is not going to change the situation much. The decrease needs to be significant (say, an order of magnitude). Putting 20 - 30 hours of effort into building an application means an opportunity cost of around £750, which can more realistically be recouped through App Store sales in an acceptable period of time. But what can be built in 20 - 30 hours? Ah, a crapplication.&lt;br /&gt;&lt;/p&gt;&lt;h3&gt;Pricing&lt;/h3&gt;&lt;p&gt;The above logic of course assumes that a crapplication will sell as well as something that took ten times longer to develop. Unfortunately, the history of the App Store leads me to believe that you are no more certain to sell something good than you are to sell something crap. If it appeals to the masses, it will probably sell, irrespective of how bad or how good it might be (&lt;a href="http://ifartmobile.com/"&gt;this&lt;/a&gt; is the best example of the former).&lt;br /&gt;&lt;/p&gt;&lt;p&gt;A &lt;a href="http://www.highglosssoftware.com/Blog/Entries/2009/1/22_i_Wrote_a_top_10_app....and_its_shit.html"&gt;popular story&lt;/a&gt; that is quoted is the developer that decided to see what could be built in an hour; came up with Sound Grenade in 20 minutes and landed up cracking the App Store top 10 with it.&lt;br /&gt;&lt;/p&gt;&lt;h3&gt;The blessed / dreaded charts&lt;/h3&gt;&lt;p&gt;To break even many sales are required at a low price, or fewer sales at a higher price. In pre-App Store days people would happily pay £5 to £10 ($7 to $15), or even more for a mobile application. Ringtones and images were confined to the price brackets below this. The App Store has changed everything. Customers now expect to be able to buy just about anything for 59p ($0.99). It wasn't always like this - I remember the first few apps on the App Store being more costly. Didn't I purchase Super Monkey Ball and Enigmo for £5.99 ($9.99) each? Yes, I did. What happened?&lt;br /&gt;&lt;/p&gt;&lt;p&gt;This slide can arguably be attributed to the App Store charts. The charts are just based on downloads, irrespective of cost. So, a £5.99 ($10.00) application would need 10 times the turnover in order to compete with a 59p ($0.99) application in the charts. Of course, this is a losing battle. Surely charts should take the price into consideration? As it stands, it has clearly become a volume game.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Getting a spot in the App Store charts is essential for every developer. The charts tend to be self-perpetuating. Once an application is in there, it is noticed by more people and therefore downloaded more, boosting its position in the charts, leading to even more people noticing it and so on.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;It seems then that developers have little choice but to charge 59p ($0.99) or £1.19 ($1.99), or at a push £1.79 ($2.99) and hope they crack the charts. If they don't, the application is quickly confined to the &lt;span style="font-style: italic;"&gt;abyss of unnoticed applications&lt;/span&gt; (AUA), picking up the odd few sales here and there, but ultimately not very many.&lt;br /&gt;&lt;/p&gt;&lt;h3&gt;Summary&lt;/h3&gt;&lt;p&gt;It would seem that the best return on investment is to spend as little time as possible building an app, try to give it mass appeal and price it at tier 1 (59p or $0.99). Perhaps then building iPhone software with the aim of making money is viable.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;If like me you have spent a significant amount of time building applications, for very little reward, console yourself with the fact that many of us are in the same boat. Let the enjoyment of building the application be your reward and the sales (if there are any) be a nice bonus.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2452497389474481952-6302929843723759145?l=mpatric.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mpatric.blogspot.com/feeds/6302929843723759145/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2452497389474481952&amp;postID=6302929843723759145' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2452497389474481952/posts/default/6302929843723759145'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2452497389474481952/posts/default/6302929843723759145'/><link rel='alternate' type='text/html' href='http://mpatric.blogspot.com/2009/05/rise-of-crapplication.html' title='Rise of the crapplication'/><author><name>mpatric</name><uri>http://www.blogger.com/profile/10270216082836687119</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xWpZXVYmOxY/TAGB3OXHIfI/AAAAAAAAAEM/MKjL7hNyWag/S220/mpatric-manga.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_xWpZXVYmOxY/SglMXD_4puI/AAAAAAAAACY/KPyqPJBgLIk/s72-c/sales1.png' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2452497389474481952.post-7578043134857422580</id><published>2009-04-22T10:26:00.011+01:00</published><updated>2010-05-29T22:51:15.489+01:00</updated><title type='text'>New iPhone puzzle game</title><content type='html'>&lt;p&gt;&lt;a href="http://kissthemachine.com/magnetic/"&gt;Magnetic Block Puzzle&lt;/a&gt; is now available on the &lt;a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=312610414&amp;amp;mt=8"&gt;App Store&lt;/a&gt; for a small amount.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;It's a departure from my two previous games, &lt;a href="http://kissthemachine.com/reversi/"&gt;Reversi&lt;/a&gt; and &lt;a href="http://kissthemachine.com/merelles/"&gt;Merelles&lt;/a&gt;, which were both abstract strategy games. Magnetic Block Puzzle is, as the name implies, a puzzle game. The aim of each of the 110 puzzles is to join the coloured blocks, which are special magnets that stick to other blocks of the same colour, by tilting the puzzle to make the blocks move.&lt;br /&gt;&lt;/p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_xWpZXVYmOxY/Se7qsGdPHuI/AAAAAAAAACQ/C6w2uCq26vI/s1600-h/magnetic01.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 238px;" src="http://4.bp.blogspot.com/_xWpZXVYmOxY/Se7qsGdPHuI/AAAAAAAAACQ/C6w2uCq26vI/s320/magnetic01.png" alt="" id="BLOGGER_PHOTO_ID_5327453452594257634" border="0" /&gt;&lt;/a&gt;The process of building this game, from inception to completion, went something like this:&lt;br /&gt;&lt;p&gt;I started out this project by building the underlying model of the blocks and the board, including the logic to shift the blocks around. This was done in a test-driven manner, which helped to drive out the model and behaviour correctly and to identify edge and corner cases early. Towards the end of this process, I discovered a similar puzzle game on &lt;a href="http://www.clickmazes.com/magb/ixmagb.htm"&gt;clickmazes.com&lt;/a&gt; and contacted them to ensure I wouldn't be violating a copyright. They were happy for me to proceed and gave me permission to use two of their puzzles too.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The next step was to build a solver and a puzzle builder application on top of the model, to allow me to design and test puzzle layouts. This was done as an iPhone application and many puzzles were designed on my iPhone whilst I was riding on the tube :)&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Once enough puzzles had been designed, I tailored the solver to determine various things about each puzzle such as the number of solutions, the number of moves in the best solution, the number of useful positions in the solution tree (positions from which the puzzle can be solved), the number of dead-end positions (positions from which the puzzle cannot be solved), and so on. This proved to be quite CPU-intensive on the more complex puzzles, so it was compiled and run on my Mac rather than on the iPhone. These values were then used to assess the relative difficulty of each puzzle.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;So, every puzzle included in the game was designed by hand, but assessed and verified by code.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Finally I wrote the actual application, including in it the 110 puzzles that had been selected for the final application, in a local SQLite database. Like the solver and the puzzle builder, the actual game was built on top of the model built initially.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;I started this application in early December 2008 and finished it in late April 2009 - nearly five months of much of my free time went into building it. I am happy with the end product and hope that those who purchase it enjoy playing it as much as I enjoyed creating it. It's available on the &lt;a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=312610414&amp;amp;mt=8"&gt;App Store&lt;/a&gt; now.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2452497389474481952-7578043134857422580?l=mpatric.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mpatric.blogspot.com/feeds/7578043134857422580/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2452497389474481952&amp;postID=7578043134857422580' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2452497389474481952/posts/default/7578043134857422580'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2452497389474481952/posts/default/7578043134857422580'/><link rel='alternate' type='text/html' href='http://mpatric.blogspot.com/2009/04/new-iphone-puzzle-game.html' title='New iPhone puzzle game'/><author><name>mpatric</name><uri>http://www.blogger.com/profile/10270216082836687119</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xWpZXVYmOxY/TAGB3OXHIfI/AAAAAAAAAEM/MKjL7hNyWag/S220/mpatric-manga.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_xWpZXVYmOxY/Se7qsGdPHuI/AAAAAAAAACQ/C6w2uCq26vI/s72-c/magnetic01.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2452497389474481952.post-1782541361362201677</id><published>2009-04-15T15:56:00.003+01:00</published><updated>2010-05-29T22:56:25.490+01:00</updated><title type='text'>More responsive sliders on the iPhone</title><content type='html'>&lt;p&gt;One of the best things about the iPhone is you can have thin fingers or fat fingers, and pressing buttons and using controls on the touch screen is still quite easy. On old-school touch screen devices (WinMob phones in particular spring to mind), one had to be very precise as the first location touched on the screen immediately triggered a touch event, which is why a stylus was almost always necessary. The iPhone takes a slightly different approach, where a touch that consists of many points on the screen (as would occur with a finger) is converted into a co-ordinate through some sort of averaging of all the points. In general this works really well. However, using this approach still requires the controls on the screen be sufficiently large that a user will be able to put a finger over it, with the average falling comfortably on the control. From my experiments, I believe a control needs to have a touch area of at least 32x32 pixels.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Unfortunately, some of the standard controls suffer from having a touch area that is too small and subsequently difficult to press. In particular, when creating an info type &lt;span style="font-style: italic;"&gt;UIButton&lt;/span&gt; with the Interface Builder the dimensions and bounding rect are set to 18x19, which is too small. This can be fixed by changing the bounding rect through code, but not in the interface builder.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;I recently ran into a similar issue with a slider control.&lt;br /&gt;&lt;/p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_xWpZXVYmOxY/SeX2C4MpcwI/AAAAAAAAABQ/RmG5WdsBHx4/s1600-h/slider.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 200px; height: 44px;" src="http://4.bp.blogspot.com/_xWpZXVYmOxY/SeX2C4MpcwI/AAAAAAAAABQ/RmG5WdsBHx4/s320/slider.png" alt="" id="BLOGGER_PHOTO_ID_5324932663741084418" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;p&gt;When creating a &lt;span style="font-style: italic;"&gt;UISlider &lt;/span&gt;with the Interface Builder, it is given a fixed height of 23 pixels, which is too low. More troubling is the thumb control in the slider, whose size is not exposed, but is around 20x20 and is too small for the slider to be comfortably moved. I found with a horizontal slider slid all the way to the left or all the way to the right, it would be difficult to move the thumb control off the edge with my finger - and I have fingers that are relatively slender. The bounding rect of the slider and the touchable area of the thumb control are as follows:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_xWpZXVYmOxY/SeX2StVLuuI/AAAAAAAAABY/VMste1VL5cw/s1600-h/slider2.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 200px; height: 44px;" src="http://1.bp.blogspot.com/_xWpZXVYmOxY/SeX2StVLuuI/AAAAAAAAABY/VMste1VL5cw/s320/slider2.png" alt="" id="BLOGGER_PHOTO_ID_5324932935702002402" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Unfortunately, simply changing the bounding rect on the control was not a solution in this case as it simply makes the slider bigger and does not change the touchable area of the thumb control. I tried all sorts of workarounds to make the slider more responsive and eventually settled on extending the &lt;span style="font-style: italic;"&gt;UISlider &lt;/span&gt;control and overriding some behaviour with the following two-pronged approach (the code follows at the bottom of the post):&lt;br /&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;br /&gt;Override the &lt;span style="font-style: italic;"&gt;pointInside &lt;/span&gt;method to make points slightly outside of the control still appear to be inside the control (without changing the size of the actual slider). I decided to extend the touchable area by 10 pixels on either side of the control and 8 pixels above and below it.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;br /&gt;Override the &lt;span style="font-style: italic;"&gt;beginTrackingWithTouch &lt;/span&gt;method, which determines whether the user has clicked on the thumb control, to start tracking. This requires determining where the thumb control is based on the current value, then determining if the user's touch was close enough to it for tracking to begin. I effectively increased the thumb control size to 40x40.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;The new effective bounding rect of the slider and the touchable area of the thumb control are now as follows:&lt;br /&gt;&lt;/p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_xWpZXVYmOxY/SeX6tbF2UgI/AAAAAAAAABg/r6CLNx65xLE/s1600-h/slider3.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 200px; height: 44px;" src="http://3.bp.blogspot.com/_xWpZXVYmOxY/SeX6tbF2UgI/AAAAAAAAABg/r6CLNx65xLE/s320/slider3.png" alt="" id="BLOGGER_PHOTO_ID_5324937792708825602" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;p&gt;To use the code below, use the Interface Builder to drop a slider on the screen and then change its class from &lt;span style="font-style: italic;"&gt;UISlider &lt;/span&gt;to &lt;span style="font-style: italic;"&gt;MySlider&lt;/span&gt;. It only supports horizontal sliders, the &lt;span style="font-style: italic;"&gt;beginTrackingWithTouch &lt;/span&gt;method would need to be changed or extended to use it with vertical sliders.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Granted this is a hack, but until Apple sorts out this issue, I'll continue to resort to this sort of thing. I'm surprised it hasn't been sorted out already. I've seen forum posts from people having this problem with the info button, but none as yet with sliders. Am I the only one that sees this as an issue?&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;MySlider.h:&lt;/b&gt;&lt;br /&gt;&lt;/p&gt;&lt;div style="border: 1px solid rgb(191, 191, 191); overflow: auto;"&gt;&lt;pre&gt;#import &amp;lt;UIKit/UIKit.h&amp;gt;&lt;br /&gt;&lt;br /&gt;@interface MySlider : UISlider {&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;b&gt;MySlider.m:&lt;/b&gt;&lt;br /&gt;&lt;/p&gt;&lt;div style="border: 1px solid rgb(191, 191, 191); overflow: auto;"&gt;&lt;pre&gt;#import "MySlider.h"&lt;br /&gt;&lt;br /&gt;#define THUMB_SIZE 10&lt;br /&gt;#define EFFECTIVE_THUMB_SIZE 20&lt;br /&gt;&lt;br /&gt;@implementation MySlider&lt;br /&gt;&lt;br /&gt;- (BOOL) pointInside:(CGPoint)point withEvent:(UIEvent*)event {&lt;br /&gt;CGRect bounds = self.bounds;&lt;br /&gt;bounds = CGRectInset(bounds, -10, -8);&lt;br /&gt;return CGRectContainsPoint(bounds, point);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;- (BOOL) beginTrackingWithTouch:(UITouch*)touch withEvent:(UIEvent*)event {&lt;br /&gt;CGRect bounds = self.bounds;&lt;br /&gt;float thumbPercent = (self.value - self.minimumValue) / (self.maximumValue - self.minimumValue);&lt;br /&gt;float thumbPos = THUMB_SIZE + (thumbPercent * (bounds.size.width - (2 * THUMB_SIZE)));&lt;br /&gt;CGPoint touchPoint = [touch locationInView:self];&lt;br /&gt;return (touchPoint.x &amp;gt;= (thumbPos - EFFECTIVE_THUMB_SIZE) &amp;amp;&amp;amp; touchPoint.x &amp;lt;= (thumbPos + EFFECTIVE_THUMB_SIZE));&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;@end&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2452497389474481952-1782541361362201677?l=mpatric.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mpatric.blogspot.com/feeds/1782541361362201677/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2452497389474481952&amp;postID=1782541361362201677' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2452497389474481952/posts/default/1782541361362201677'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2452497389474481952/posts/default/1782541361362201677'/><link rel='alternate' type='text/html' href='http://mpatric.blogspot.com/2009/04/more-responsive-sliders-on-iphone.html' title='More responsive sliders on the iPhone'/><author><name>mpatric</name><uri>http://www.blogger.com/profile/10270216082836687119</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xWpZXVYmOxY/TAGB3OXHIfI/AAAAAAAAAEM/MKjL7hNyWag/S220/mpatric-manga.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_xWpZXVYmOxY/SeX2C4MpcwI/AAAAAAAAABQ/RmG5WdsBHx4/s72-c/slider.png' height='72' width='72'/><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2452497389474481952.post-5722327643937186686</id><published>2008-11-16T20:35:00.001Z</published><updated>2010-05-29T22:59:58.501+01:00</updated><title type='text'>Merelles iPhone game released (finally)</title><content type='html'>&lt;p&gt;I've been working on &lt;a href="http://kissthemachine.com/merelles/"&gt;Merelles&lt;/a&gt; for the last 4 months and I'm pleased to say, I've finally finished it. It's available on the Apple App Store for a small amount.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Merelles is an &lt;a href="http://en.wikipedia.org/wiki/Abstract_strategy_game"&gt;abstract strategy game&lt;/a&gt;. It is also know as &lt;span style="font-style: italic;"&gt;Mills&lt;/span&gt;, &lt;span style="font-style: italic;"&gt;x&lt;/span&gt;&lt;span style="font-style: italic;"&gt; Men's Morris&lt;/span&gt; (4, 6, 9 and 12 men variations) and by many other names.&lt;br /&gt;&lt;/p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_xWpZXVYmOxY/SSCIkSv3T2I/AAAAAAAAABI/CwBx1OgtFWY/s1600-h/merelles.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 214px; height: 320px;" src="http://3.bp.blogspot.com/_xWpZXVYmOxY/SSCIkSv3T2I/AAAAAAAAABI/CwBx1OgtFWY/s320/merelles.png" alt="" id="BLOGGER_PHOTO_ID_5269361721112743778" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;p&gt;Seeing as this is my technical blog (and the Apple NDA has been lifted), I feel compelled to provide some technical details. The app itself is written in &lt;span style="font-style: italic;"&gt;Objective-C&lt;/span&gt; (of course) using &lt;a href="http://en.wikipedia.org/wiki/Test-driven_development"&gt;TDD&lt;/a&gt; (of course!) driven by &lt;span style="font-style: italic;"&gt;OCUnit&lt;/span&gt;.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The computer AI uses a &lt;a href="http://en.wikipedia.org/wiki/Negascout"&gt;negascout&lt;/a&gt; tree search to examine the game tree. The use of the negascout algorithm means that some pruning will occur on the game tree so that not every node needs to be examined, as long as the moves are ordered so that better moves are examined first!&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Iterative_deepening_depth-first_search"&gt;Iterative deepening&lt;/a&gt; is applied on top of this, starting by searching one move ahead, then two, and so on. The moves that look to be good after a search are considered first when searching deeper. In addition, as the same board position can occur several times during a single tree search, moves that result in a really promising board position are classified as &lt;a href="http://en.wikipedia.org/wiki/Killer_heuristic"&gt;killer moves&lt;/a&gt; and examined before other moves if they occur again during the search. All this helps in obtaining an amazing prune rate of more than 90%&lt;br /&gt;&lt;/p&gt;&lt;p&gt;A question that is often asked is how do you determine if a board position is better than another board position? Unfortunately, it's a fuzzy answer. A set of heuristics is applied, which take into account things like how many pieces each player has in play, how mobile each player is (how many valid moves they have), how easily they can form a row of three pieces, and so on. The strength of the AI is determined largely by these heuristics.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;There are 3 difficulty levels. For each level, the heuristics are &lt;span style="font-weight: bold;"&gt;mostly&lt;/span&gt; the same, with varying depths for the tree search and the maximum number of board positions that are considered. For the most complex game (the 12 men game):&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;On easy, the AI only looks 2 moves ahead.&lt;/li&gt;&lt;li&gt;On medium, the AI looks 2 to 4 moves ahead examining up to 3000 board positions.&lt;/li&gt;&lt;li&gt;On difficult, the AI looks as many moves ahead as it can in examining up to 15000 board positions - in practice this is between 4 and 8 moves ahead, depending on the state of the game.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The resulting game play feels quite natural to me, with the AI coming up with some clever strategies, which in themselves have not been programmed into it, but rather are the result of the tree search and the heuristics. I've been astounded a few times at the way it has trapped me!&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The primary challenge in writing this game was to balance the heuristics to set up board positions that would yield good results later in the game rather than just constantly pursue the capture of opponent pieces, which would result in rather one dimensional game play. On top of this, it was necessary to keep the calculations light and to optimise the code as much as possible so that the tree search would not take too long, remembering that it's running on a device with limited computational power. On difficult, the deepest tree searches take up to just over 4 seconds on the iPhone.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2452497389474481952-5722327643937186686?l=mpatric.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mpatric.blogspot.com/feeds/5722327643937186686/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2452497389474481952&amp;postID=5722327643937186686' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2452497389474481952/posts/default/5722327643937186686'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2452497389474481952/posts/default/5722327643937186686'/><link rel='alternate' type='text/html' href='http://mpatric.blogspot.com/2008/11/merelles-iphone-game-released-finally.html' title='Merelles iPhone game released (finally)'/><author><name>mpatric</name><uri>http://www.blogger.com/profile/10270216082836687119</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xWpZXVYmOxY/TAGB3OXHIfI/AAAAAAAAAEM/MKjL7hNyWag/S220/mpatric-manga.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_xWpZXVYmOxY/SSCIkSv3T2I/AAAAAAAAABI/CwBx1OgtFWY/s72-c/merelles.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2452497389474481952.post-7252440497201386977</id><published>2008-08-27T17:23:00.001+01:00</published><updated>2010-05-29T23:04:25.036+01:00</updated><title type='text'>Unit testing iPhone applications</title><content type='html'>&lt;p&gt;The &lt;span style="font-style: italic;"&gt;OCUnit&lt;/span&gt; framework is bundled with a standard xcode installation, which is handy for getting up and running with unit tests and test-driven development (TDD). Somewhat annoyingly though it does not play nicely with the &lt;span style="font-style: italic;"&gt;Cocoa Touch&lt;/span&gt; framework. So, how does one go about building iPhone applications using TDD? I'm sure there are several ways of achieving this, but I wanted to stick with OCUnit. After a bit of messing about this is how I do it.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_xWpZXVYmOxY/SLWBBPJjJrI/AAAAAAAAAAs/eIod0f-aNAo/s1600-h/gears.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://3.bp.blogspot.com/_xWpZXVYmOxY/SLWBBPJjJrI/AAAAAAAAAAs/eIod0f-aNAo/s320/gears.jpg" alt="" id="BLOGGER_PHOTO_ID_5239235599761876658" border="0" /&gt;&lt;/a&gt;&lt;div style="font-size:78%; text-align: center;"&gt;Image from &lt;a href="http://flickr.com/photos/pixel_eight/493554891/"&gt;Bhavna Bahri's photostream&lt;/a&gt;.&lt;br /&gt;&lt;/div&gt;&lt;p&gt;The Cocoa Touch framework encourages the use of the model-view-controller (MVC) pattern. It's only the 'V' and 'C' bits however that need to extend Cocoa Touch objects (&lt;span style="font-style: italic;"&gt;UIView&lt;/span&gt; and &lt;span style="font-style: italic;"&gt;UIViewController&lt;/span&gt;); you're completely free to implement the 'M' bit as you see fit. So, the basic approach I take is to write the model classes against OCUnit tests compiled against the (Cocoa) &lt;span style="font-style: italic;"&gt;Foundation&lt;/span&gt; library only, and to then use these same classes in my iPhone application, which is compiled against the Cocoa Touch framework. The Foundation library exists in both the Cocoa and Cocoa Touch frameworks and is (almost) identical, although the unit tests only run against the Cocoa version.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;This setup involves creating two projects: a &lt;span style="font-style: italic;"&gt;Foundation Tool&lt;/span&gt; project and a &lt;span style="font-style: italic;"&gt;Cocoa Touch&lt;/span&gt; project, and to reference the model code (which lives in the Foundation Tool project) directly from the Cocoa Touch project. Rather than duplicating the files that comprise the model, they are just referenced from the Cocoa Touch project (which is achieved by dragging them from the finder into the Cocoa Touch project, making sure the '&lt;span style="font-style: italic;"&gt;Copy items into destination group's folder&lt;/span&gt;' option is &lt;span style="font-weight: bold;"&gt;not&lt;/span&gt; checked).&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The files that comprise the model objects should import &lt;span style="font-style: italic;"&gt;Foundation/Foundation.h&lt;/span&gt;&lt;span style="font-style: italic;"&gt;&lt;foundation h=""&gt;&lt;/foundation&gt;&lt;/span&gt; whereas the files in the Cocoa Touch project should generally import &lt;span style="font-style: italic;"&gt;&lt;uikit h=""&gt;&lt;/uikit&gt;&lt;/span&gt; &lt;span style="font-style: italic;"&gt;UIKit/UIKit.h&lt;/span&gt; (which is a higher-level header file that ultimately includes &lt;span style="font-style: italic;"&gt;&lt;foundation h=""&gt;&lt;/foundation&gt;&lt;/span&gt;&lt;span style="font-style: italic;"&gt;Foundation/Foundation.h&lt;/span&gt;).&lt;br /&gt;&lt;/p&gt;&lt;p&gt;What this means is that unit tests only cover the model, not the controllers or the views - so domain logic should be in the model, with the controllers simply acting as conduits for responses from this logic. In other words, there should be as little domain logic as possible in the controllers (and obviously the views, but there should not be any logic in the views anyway!)&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2452497389474481952-7252440497201386977?l=mpatric.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mpatric.blogspot.com/feeds/7252440497201386977/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2452497389474481952&amp;postID=7252440497201386977' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2452497389474481952/posts/default/7252440497201386977'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2452497389474481952/posts/default/7252440497201386977'/><link rel='alternate' type='text/html' href='http://mpatric.blogspot.com/2008/08/unit-testing-iphone-applications.html' title='Unit testing iPhone applications'/><author><name>mpatric</name><uri>http://www.blogger.com/profile/10270216082836687119</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xWpZXVYmOxY/TAGB3OXHIfI/AAAAAAAAAEM/MKjL7hNyWag/S220/mpatric-manga.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_xWpZXVYmOxY/SLWBBPJjJrI/AAAAAAAAAAs/eIod0f-aNAo/s72-c/gears.jpg' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2452497389474481952.post-78174895567705342</id><published>2008-07-15T12:54:00.002+01:00</published><updated>2010-05-29T23:05:13.169+01:00</updated><title type='text'>App Store Trials and Tribulations</title><content type='html'>&lt;p&gt;I got my first iPhone application submitted and accepted onto the App Store for its launch. Here are my impressions of the process so far.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;As a developer, once you've built an application and tested it on the device, and digitally signed it with an Apple-issued distribution certificate, the application is submitted to the App Store via iTunes Connect, which is a simple web application. All the meta-data for the App Store is entered at this point. I have a few small gripes about it and was hampered by a bug that didn't let me change details on a subsequent upload, but otherwise it's simple and does the job.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The application only appears on the App Store once it has been reviewed and approved by Apple. The first time around this took two days, but the rate at which they are approving releases seems to have slowed to a crawl now. I submitted an update more than a week ago, which has yet to be approved. In fact, I now have another update ready (which should be my last). My concern around the slowness of the approval process is that if there is a pressing update you need to roll out, it will take as long as Apple decide it will take and as a developer you have no control over this.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Once the application is on the App Store, you are at the mercy of the iTunes community. I am not convinced that the reviewing mechanism used for music is appropriate to applications. I've had several low ratings (zero or one star) simply because there is a free version of something similar and mine costs £1.19. Being as objective as I can, I can honestly say that the free version is free for a reason - it's not very good. Allowing people that haven't even downloaded the application to give it a rating is opening the door to this sort of abuse. It can be really gutting to see your rating drop, especially when the reviewers haven't been fair, or even downloaded the application in the first place. This of course has the knock-on effect that fewer people download it because of the low ratings. Given the months of hard work that went into producing my application, I can't understand why someone that hasn't downloaded it is able to review it and thus directly impact how many people are likely to download it. Apple, you need to change this!&lt;br /&gt;&lt;/p&gt;&lt;p&gt;My last gripe is that Apple don't provide any download statistics to the developer. A monthly report is produced, but in the fast moving world of online sales surely daily stats wouldn't be too much to expect?&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-weight: bold;"&gt;Update:&lt;/span&gt; old news now, but Apple are providing daily and weekly stats.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2452497389474481952-78174895567705342?l=mpatric.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mpatric.blogspot.com/feeds/78174895567705342/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2452497389474481952&amp;postID=78174895567705342' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2452497389474481952/posts/default/78174895567705342'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2452497389474481952/posts/default/78174895567705342'/><link rel='alternate' type='text/html' href='http://mpatric.blogspot.com/2008/07/app-store-trials-and-tribulations.html' title='App Store Trials and Tribulations'/><author><name>mpatric</name><uri>http://www.blogger.com/profile/10270216082836687119</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xWpZXVYmOxY/TAGB3OXHIfI/AAAAAAAAAEM/MKjL7hNyWag/S220/mpatric-manga.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2452497389474481952.post-4827647904736332819</id><published>2008-06-27T15:06:00.001+01:00</published><updated>2010-05-29T23:05:52.247+01:00</updated><title type='text'>New domain name shortage</title><content type='html'>&lt;p&gt;I was recently looking to register a new domain for a project I've been working on. I underestimated the amount of time it would take to find an available domain. What's incredibly annoying is that many domains have been registered purely in an attempt to make money by selling them on (especially .com domains). Let's face it, everyone wants a .com domain.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Here's an experiment to try. Think of an obscure word or combination of words that surely nobody would have thought to register, and do a whois check on it. You'd be suprised at the domains people have registered (I was).&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Let's try some... How about eatbananas.com or flybot.com. Nope, both taken.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Ok, how about purpletree.com, happycow.com and satisfiedmonkey.com? Taken, taken and taken. Yes, satisfiedmonkey is taken.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Maybe the trick is to find something that's not really a word. Something cool like digg or boingboing. How about kerplunk.com, sproing.com, flugle.com or cartoo.com? Ah, no, all taken.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Maybe the trick is to leave out letters like flickr? How about shattr.com or shtterbug.com? No.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Should it really take a day of hitting whois with odd words until amazingly you manage to find one that is available and not completely ridiculous? Shouldn't domains have a use-it-or-lose-it rule? Should there be a limit to the number of domains one can register? Until then I guess we're doomed to having lots of startups with absurd names because that was the best .com domain name they could find.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2452497389474481952-4827647904736332819?l=mpatric.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mpatric.blogspot.com/feeds/4827647904736332819/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2452497389474481952&amp;postID=4827647904736332819' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2452497389474481952/posts/default/4827647904736332819'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2452497389474481952/posts/default/4827647904736332819'/><link rel='alternate' type='text/html' href='http://mpatric.blogspot.com/2008/06/new-domain-name-shortage.html' title='New domain name shortage'/><author><name>mpatric</name><uri>http://www.blogger.com/profile/10270216082836687119</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xWpZXVYmOxY/TAGB3OXHIfI/AAAAAAAAAEM/MKjL7hNyWag/S220/mpatric-manga.jpg'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2452497389474481952.post-2049934014716955830</id><published>2008-05-22T22:21:00.001+01:00</published><updated>2010-05-29T23:06:20.585+01:00</updated><title type='text'>South Africa and Open Source</title><content type='html'>&lt;p&gt;Last year, the South African government announced their intention to &lt;a href="http://www.oss.gov.za/modules.php?op=modload&amp;amp;name=News&amp;amp;file=article&amp;amp;sid=151&amp;amp;mode=thread&amp;amp;order=0&amp;amp;thold=0"&gt;roll out open source&lt;/a&gt;  implementations across all government departments. A move that surprised, but delighted me and many others.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;So, when statements are made like the &lt;a href="http://www.tectonic.co.za/?p=2432"&gt;one made recently&lt;/a&gt; by Microsoft's director of corporate standards that South Africans were unlikely to benefit from OSS, or do any 'deep' development work on Linux (hello, heard of Ubuntu?), I have to ask myself, where is this coming from? What is a statement like that aimed at achieving? Furthermore, saying that students in South Africa are 'still grappling with coding skills' smacks of complete ignorance.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;While I don't agree with all the government's policies, they should be applauded for the move to OSS and for setting a precedent that other developing countries in Africa may follow. Well done!&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2452497389474481952-2049934014716955830?l=mpatric.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mpatric.blogspot.com/feeds/2049934014716955830/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2452497389474481952&amp;postID=2049934014716955830' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2452497389474481952/posts/default/2049934014716955830'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2452497389474481952/posts/default/2049934014716955830'/><link rel='alternate' type='text/html' href='http://mpatric.blogspot.com/2008/05/south-africa-and-open-source.html' title='South Africa and Open Source'/><author><name>mpatric</name><uri>http://www.blogger.com/profile/10270216082836687119</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xWpZXVYmOxY/TAGB3OXHIfI/AAAAAAAAAEM/MKjL7hNyWag/S220/mpatric-manga.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2452497389474481952.post-2879994495745599996</id><published>2008-05-21T16:39:00.001+01:00</published><updated>2010-05-29T23:07:27.022+01:00</updated><title type='text'>Raising the bar on bug priorities</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_xWpZXVYmOxY/SDRECyJ-mdI/AAAAAAAAAAc/W-6TbbWlPRg/s1600-h/bugs.png"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer;" src="http://4.bp.blogspot.com/_xWpZXVYmOxY/SDRECyJ-mdI/AAAAAAAAAAc/W-6TbbWlPRg/s320/bugs.png" alt="" id="BLOGGER_PHOTO_ID_5202858284133816786" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;p&gt;Inevitably during the course of writing an application, bugs creep in. And like all good software teams we diligently capture them, along with some priority level. Let's say for the purposes of discussion the priority levels are: &lt;span style="font-style: italic;"&gt;trivial&lt;/span&gt;, &lt;span style="font-style: italic;"&gt;minor&lt;/span&gt;, &lt;span style="font-style: italic;"&gt;major&lt;/span&gt; and &lt;span style="font-style: italic;"&gt;critical&lt;/span&gt;. Fine. So far, so good. But, as time goes by and bugs get raised and some get fixed, the way in which priorities are determined seems to change. If the entire bug queue does not get cleared out regularly, what was &lt;span style="font-style: italic;"&gt;minor&lt;/span&gt; before starts to become &lt;span style="font-style: italic;"&gt;major&lt;/span&gt; because the people raising the bugs know that it will be fixed sooner. The result is that most of the bugs tend to land up in the next-from-top priority level (&lt;span style="font-style: italic;"&gt;major&lt;/span&gt;) and before long the lower ones (&lt;span style="font-style: italic;"&gt;trivial&lt;/span&gt; and &lt;span style="font-style: italic;"&gt;minor&lt;/span&gt;) become little more than an afterthought. The highest priority level (&lt;span style="font-style: italic;"&gt;critical&lt;/span&gt;) is usually spared as it is those bugs that really are showstoppers that still fill this priority level. It's not uncommon for a new priority level to suddenly be introduced to start separating the &lt;span style="font-style: italic;"&gt;major&lt;/span&gt; bugs out into the &lt;span style="font-style: italic;"&gt;more major&lt;/span&gt; and the &lt;span style="font-style: italic;"&gt;less major&lt;/span&gt; bugs. This sets a dangerous precedent - what's next: &lt;span style="font-style: italic;"&gt;Even more major?&lt;/span&gt; &lt;span style="font-style: italic;"&gt;Almost critical?&lt;/span&gt; Aargh..&lt;br /&gt;&lt;/p&gt;&lt;p&gt;This seems to be a fairly common problem, seen in many organisations, on teams of varying sizes. As I see it, some of the root causes are:&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Letting the bug queue grow too big&lt;/li&gt;&lt;li&gt;Not defining exactly what is meant by each priority level&lt;/li&gt;&lt;li&gt;Having too many stakeholders. Whose priority is more important?&lt;/li&gt;&lt;li&gt;Complexity or difficulty in fixing a bug are not interchangeable with priority - just because a bug has a priority level of 'trivial' it doesn't mean it will be quick to fix; and vice-versa.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2452497389474481952-2879994495745599996?l=mpatric.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mpatric.blogspot.com/feeds/2879994495745599996/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2452497389474481952&amp;postID=2879994495745599996' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2452497389474481952/posts/default/2879994495745599996'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2452497389474481952/posts/default/2879994495745599996'/><link rel='alternate' type='text/html' href='http://mpatric.blogspot.com/2008/05/raising-bar-on-bug-priorities.html' title='Raising the bar on bug priorities'/><author><name>mpatric</name><uri>http://www.blogger.com/profile/10270216082836687119</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xWpZXVYmOxY/TAGB3OXHIfI/AAAAAAAAAEM/MKjL7hNyWag/S220/mpatric-manga.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_xWpZXVYmOxY/SDRECyJ-mdI/AAAAAAAAAAc/W-6TbbWlPRg/s72-c/bugs.png' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2452497389474481952.post-6229886278254584650</id><published>2008-05-19T23:36:00.002+01:00</published><updated>2010-05-29T23:08:22.250+01:00</updated><title type='text'>Getting into iPhone development</title><content type='html'>&lt;p&gt;So, I have an iPhone, I have a Mac and I have some ideas. It seemed only right that I combine them and build an iPhone application. Only problem... I hadn't done C or C++ in years and Objective-C looked a bit daunting. But, what the hell, I took the plunge.&lt;br /&gt;&lt;/p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_xWpZXVYmOxY/SDIIWCJ-mcI/AAAAAAAAAAU/HgC3SxBogvc/s1600-h/iphoneb.jpg"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer;" src="http://3.bp.blogspot.com/_xWpZXVYmOxY/SDIIWCJ-mcI/AAAAAAAAAAU/HgC3SxBogvc/s320/iphoneb.jpg" alt="" id="BLOGGER_PHOTO_ID_5202229694195210690" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;I am happy to report that it's not too bad. Working in xcode however is nowhere near as rewarding as IntelliJ or Eclipse. Just setting up my project to use &lt;span style="font-weight: bold;"&gt;ocunit&lt;/span&gt; &lt;span style="font-style: italic;"&gt;(see update for more on this) &lt;/span&gt;so that I could start with some tests and step through my tests with the debugger required a few hours of searching the interwebs and some messing about (thanks &lt;a href="http://chanson.livejournal.com/119578.html"&gt;Chris Hanson for this good short guide&lt;/a&gt;) . You'd think they would make creating a new project would add unit testing to it by default. It still comes as a surprise to me that people don't automatically write unit tests. Can software really be built effectively any other way??&lt;br /&gt;&lt;/p&gt;&lt;p&gt;All in all, the experience has been good. I'm just getting to the point now that I'm starting to put the GUI together. More to come on this.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-weight: bold;"&gt;Update:&lt;/span&gt; now that I'm building the GUI, I've switched to the Cocoa Touch sdk and it seems that ocunit does not work with it yet, which makes TDD (with ocunit) difficult. For now, I'm testing my classes with ocunit compiled against cocoa, then moving them to my cocoa touch application, but that's not a very good, or sustainable approach. The other options at this point are: write a simple testing framework; wait for apple to make ocunit compatible with Cocoa touch.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2452497389474481952-6229886278254584650?l=mpatric.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mpatric.blogspot.com/feeds/6229886278254584650/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2452497389474481952&amp;postID=6229886278254584650' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2452497389474481952/posts/default/6229886278254584650'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2452497389474481952/posts/default/6229886278254584650'/><link rel='alternate' type='text/html' href='http://mpatric.blogspot.com/2008/05/getting-into-iphone-development.html' title='Getting into iPhone development'/><author><name>mpatric</name><uri>http://www.blogger.com/profile/10270216082836687119</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_xWpZXVYmOxY/TAGB3OXHIfI/AAAAAAAAAEM/MKjL7hNyWag/S220/mpatric-manga.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_xWpZXVYmOxY/SDIIWCJ-mcI/AAAAAAAAAAU/HgC3SxBogvc/s72-c/iphoneb.jpg' height='72' width='72'/><thr:total>2</thr:total></entry></feed>
