Initial check-in into Mercurial. Branched from 1.0 release of Apple's sample code. No longer requires garbage collection. Fixed some memory leaks of CG objects. Fixed a bug when advancing to the 8th row in the Checkers game.
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/.hgignore Fri Mar 07 11:43:02 2008 -0800
1.3 @@ -0,0 +1,9 @@
1.4 +syntax: glob
1.5 +.DS_Store
1.6 +build
1.7 +.svn
1.8 +*.pbxuser
1.9 +*.perspectivev3
1.10 +*.mpkg
1.11 +*.framework
1.12 +(*)
1.13 \ No newline at end of file
2.1 Binary file English.lproj/InfoPlist.strings has changed
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/English.lproj/MainMenu.nib/designable.nib Fri Mar 07 11:43:02 2008 -0800
3.3 @@ -0,0 +1,2126 @@
3.4 +<?xml version="1.0" encoding="UTF-8"?>
3.5 +<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.01">
3.6 + <data>
3.7 + <int key="IBDocument.SystemTarget">0</int>
3.8 + <string key="IBDocument.SystemVersion">9B18</string>
3.9 + <string key="IBDocument.InterfaceBuilderVersion">629</string>
3.10 + <string key="IBDocument.AppKitVersion">949</string>
3.11 + <string key="IBDocument.HIToolboxVersion">343.00</string>
3.12 + <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
3.13 + <bool key="EncodedWithXMLCoder">YES</bool>
3.14 + <integer value="380"/>
3.15 + <integer value="371"/>
3.16 + </object>
3.17 + <object class="NSArray" key="IBDocument.PluginDependencies">
3.18 + <bool key="EncodedWithXMLCoder">YES</bool>
3.19 + <string id="617114957">com.apple.InterfaceBuilderKit</string>
3.20 + <string id="248469711">com.apple.InterfaceBuilder.CocoaPlugin</string>
3.21 + </object>
3.22 + <object class="NSMutableArray" key="IBDocument.RootObjects" id="1048">
3.23 + <bool key="EncodedWithXMLCoder">YES</bool>
3.24 + <object class="NSCustomObject" id="1021">
3.25 + <string key="NSClassName" id="1039455869">NSApplication</string>
3.26 + </object>
3.27 + <object class="NSCustomObject" id="1014">
3.28 + <string key="NSClassName">FirstResponder</string>
3.29 + </object>
3.30 + <object class="NSCustomObject" id="1050">
3.31 + <reference key="NSClassName" ref="1039455869"/>
3.32 + </object>
3.33 + <object class="NSMenu" id="649796088">
3.34 + <string key="NSTitle">AMainMenu</string>
3.35 + <object class="NSMutableArray" key="NSMenuItems">
3.36 + <bool key="EncodedWithXMLCoder">YES</bool>
3.37 + <object class="NSMenuItem" id="694149608">
3.38 + <reference key="NSMenu" ref="649796088"/>
3.39 + <string key="NSTitle" id="101265034">GeekGameBoard</string>
3.40 + <string key="NSKeyEquiv" id="1003"/>
3.41 + <int key="NSKeyEquivModMask">1048576</int>
3.42 + <int key="NSMnemonicLoc">2147483647</int>
3.43 + <object class="NSCustomResource" key="NSOnImage" id="484312224">
3.44 + <string key="NSClassName" id="140112029">NSImage</string>
3.45 + <string key="NSResourceName">NSMenuCheckmark</string>
3.46 + </object>
3.47 + <object class="NSCustomResource" key="NSMixedImage" id="309443010">
3.48 + <reference key="NSClassName" ref="140112029"/>
3.49 + <string key="NSResourceName">NSMenuMixedState</string>
3.50 + </object>
3.51 + <string key="NSAction">submenuAction:</string>
3.52 + <object class="NSMenu" key="NSSubmenu" id="110575045">
3.53 + <reference key="NSTitle" ref="101265034"/>
3.54 + <object class="NSMutableArray" key="NSMenuItems">
3.55 + <bool key="EncodedWithXMLCoder">YES</bool>
3.56 + <object class="NSMenuItem" id="238522557">
3.57 + <reference key="NSMenu" ref="110575045"/>
3.58 + <string key="NSTitle">About GeekGameBoard</string>
3.59 + <reference key="NSKeyEquiv" ref="1003"/>
3.60 + <int key="NSMnemonicLoc">2147483647</int>
3.61 + <reference key="NSOnImage" ref="484312224"/>
3.62 + <reference key="NSMixedImage" ref="309443010"/>
3.63 + </object>
3.64 + <object class="NSMenuItem" id="304266470">
3.65 + <reference key="NSMenu" ref="110575045"/>
3.66 + <bool key="NSIsDisabled">YES</bool>
3.67 + <bool key="NSIsSeparator">YES</bool>
3.68 + <reference key="NSTitle" ref="1003"/>
3.69 + <reference key="NSKeyEquiv" ref="1003"/>
3.70 + <int key="NSKeyEquivModMask">1048576</int>
3.71 + <int key="NSMnemonicLoc">2147483647</int>
3.72 + <reference key="NSOnImage" ref="484312224"/>
3.73 + <reference key="NSMixedImage" ref="309443010"/>
3.74 + </object>
3.75 + <object class="NSMenuItem" id="609285721">
3.76 + <reference key="NSMenu" ref="110575045"/>
3.77 + <string type="base64-UTF8" key="NSTitle">UHJlZmVyZW5jZXPigKY</string>
3.78 + <string key="NSKeyEquiv">,</string>
3.79 + <int key="NSKeyEquivModMask">1048576</int>
3.80 + <int key="NSMnemonicLoc">2147483647</int>
3.81 + <reference key="NSOnImage" ref="484312224"/>
3.82 + <reference key="NSMixedImage" ref="309443010"/>
3.83 + </object>
3.84 + <object class="NSMenuItem" id="481834944">
3.85 + <reference key="NSMenu" ref="110575045"/>
3.86 + <bool key="NSIsDisabled">YES</bool>
3.87 + <bool key="NSIsSeparator">YES</bool>
3.88 + <reference key="NSTitle" ref="1003"/>
3.89 + <reference key="NSKeyEquiv" ref="1003"/>
3.90 + <int key="NSKeyEquivModMask">1048576</int>
3.91 + <int key="NSMnemonicLoc">2147483647</int>
3.92 + <reference key="NSOnImage" ref="484312224"/>
3.93 + <reference key="NSMixedImage" ref="309443010"/>
3.94 + </object>
3.95 + <object class="NSMenuItem" id="1046388886">
3.96 + <reference key="NSMenu" ref="110575045"/>
3.97 + <string key="NSTitle" id="487627014">Services</string>
3.98 + <reference key="NSKeyEquiv" ref="1003"/>
3.99 + <int key="NSKeyEquivModMask">1048576</int>
3.100 + <int key="NSMnemonicLoc">2147483647</int>
3.101 + <reference key="NSOnImage" ref="484312224"/>
3.102 + <reference key="NSMixedImage" ref="309443010"/>
3.103 + <string key="NSAction">submenuAction:</string>
3.104 + <object class="NSMenu" key="NSSubmenu" id="752062318">
3.105 + <reference key="NSTitle" ref="487627014"/>
3.106 + <object class="NSMutableArray" key="NSMenuItems">
3.107 + <bool key="EncodedWithXMLCoder">YES</bool>
3.108 + </object>
3.109 + <string key="NSName">_NSServicesMenu</string>
3.110 + </object>
3.111 + </object>
3.112 + <object class="NSMenuItem" id="646227648">
3.113 + <reference key="NSMenu" ref="110575045"/>
3.114 + <bool key="NSIsDisabled">YES</bool>
3.115 + <bool key="NSIsSeparator">YES</bool>
3.116 + <reference key="NSTitle" ref="1003"/>
3.117 + <reference key="NSKeyEquiv" ref="1003"/>
3.118 + <int key="NSKeyEquivModMask">1048576</int>
3.119 + <int key="NSMnemonicLoc">2147483647</int>
3.120 + <reference key="NSOnImage" ref="484312224"/>
3.121 + <reference key="NSMixedImage" ref="309443010"/>
3.122 + </object>
3.123 + <object class="NSMenuItem" id="755159360">
3.124 + <reference key="NSMenu" ref="110575045"/>
3.125 + <string key="NSTitle">Hide GeekGameBoard</string>
3.126 + <string key="NSKeyEquiv" id="712247123">h</string>
3.127 + <int key="NSKeyEquivModMask">1048576</int>
3.128 + <int key="NSMnemonicLoc">2147483647</int>
3.129 + <reference key="NSOnImage" ref="484312224"/>
3.130 + <reference key="NSMixedImage" ref="309443010"/>
3.131 + </object>
3.132 + <object class="NSMenuItem" id="342932134">
3.133 + <reference key="NSMenu" ref="110575045"/>
3.134 + <string key="NSTitle">Hide Others</string>
3.135 + <reference key="NSKeyEquiv" ref="712247123"/>
3.136 + <int key="NSKeyEquivModMask">1572864</int>
3.137 + <int key="NSMnemonicLoc">2147483647</int>
3.138 + <reference key="NSOnImage" ref="484312224"/>
3.139 + <reference key="NSMixedImage" ref="309443010"/>
3.140 + </object>
3.141 + <object class="NSMenuItem" id="908899353">
3.142 + <reference key="NSMenu" ref="110575045"/>
3.143 + <string key="NSTitle">Show All</string>
3.144 + <reference key="NSKeyEquiv" ref="1003"/>
3.145 + <int key="NSKeyEquivModMask">1048576</int>
3.146 + <int key="NSMnemonicLoc">2147483647</int>
3.147 + <reference key="NSOnImage" ref="484312224"/>
3.148 + <reference key="NSMixedImage" ref="309443010"/>
3.149 + </object>
3.150 + <object class="NSMenuItem" id="1056857174">
3.151 + <reference key="NSMenu" ref="110575045"/>
3.152 + <bool key="NSIsDisabled">YES</bool>
3.153 + <bool key="NSIsSeparator">YES</bool>
3.154 + <reference key="NSTitle" ref="1003"/>
3.155 + <reference key="NSKeyEquiv" ref="1003"/>
3.156 + <int key="NSKeyEquivModMask">1048576</int>
3.157 + <int key="NSMnemonicLoc">2147483647</int>
3.158 + <reference key="NSOnImage" ref="484312224"/>
3.159 + <reference key="NSMixedImage" ref="309443010"/>
3.160 + </object>
3.161 + <object class="NSMenuItem" id="632727374">
3.162 + <reference key="NSMenu" ref="110575045"/>
3.163 + <string key="NSTitle">Quit GeekGameBoard</string>
3.164 + <string key="NSKeyEquiv">q</string>
3.165 + <int key="NSKeyEquivModMask">1048576</int>
3.166 + <int key="NSMnemonicLoc">2147483647</int>
3.167 + <reference key="NSOnImage" ref="484312224"/>
3.168 + <reference key="NSMixedImage" ref="309443010"/>
3.169 + </object>
3.170 + </object>
3.171 + <string key="NSName">_NSAppleMenu</string>
3.172 + </object>
3.173 + </object>
3.174 + <object class="NSMenuItem" id="379814623">
3.175 + <reference key="NSMenu" ref="649796088"/>
3.176 + <string key="NSTitle" id="589729360">File</string>
3.177 + <reference key="NSKeyEquiv" ref="1003"/>
3.178 + <int key="NSKeyEquivModMask">1048576</int>
3.179 + <int key="NSMnemonicLoc">2147483647</int>
3.180 + <reference key="NSOnImage" ref="484312224"/>
3.181 + <reference key="NSMixedImage" ref="309443010"/>
3.182 + <string key="NSAction">submenuAction:</string>
3.183 + <object class="NSMenu" key="NSSubmenu" id="720053764">
3.184 + <reference key="NSTitle" ref="589729360"/>
3.185 + <object class="NSMutableArray" key="NSMenuItems">
3.186 + <bool key="EncodedWithXMLCoder">YES</bool>
3.187 + <object class="NSMenuItem" id="705341025">
3.188 + <reference key="NSMenu" ref="720053764"/>
3.189 + <string key="NSTitle">New</string>
3.190 + <string key="NSKeyEquiv">n</string>
3.191 + <int key="NSKeyEquivModMask">1048576</int>
3.192 + <int key="NSMnemonicLoc">2147483647</int>
3.193 + <reference key="NSOnImage" ref="484312224"/>
3.194 + <reference key="NSMixedImage" ref="309443010"/>
3.195 + </object>
3.196 + <object class="NSMenuItem" id="722745758">
3.197 + <reference key="NSMenu" ref="720053764"/>
3.198 + <string type="base64-UTF8" key="NSTitle">T3BlbuKApg</string>
3.199 + <string key="NSKeyEquiv">o</string>
3.200 + <int key="NSKeyEquivModMask">1048576</int>
3.201 + <int key="NSMnemonicLoc">2147483647</int>
3.202 + <reference key="NSOnImage" ref="484312224"/>
3.203 + <reference key="NSMixedImage" ref="309443010"/>
3.204 + </object>
3.205 + <object class="NSMenuItem" id="1025936716">
3.206 + <reference key="NSMenu" ref="720053764"/>
3.207 + <string key="NSTitle" id="1022827674">Open Recent</string>
3.208 + <reference key="NSKeyEquiv" ref="1003"/>
3.209 + <int key="NSKeyEquivModMask">1048576</int>
3.210 + <int key="NSMnemonicLoc">2147483647</int>
3.211 + <reference key="NSOnImage" ref="484312224"/>
3.212 + <reference key="NSMixedImage" ref="309443010"/>
3.213 + <string key="NSAction">submenuAction:</string>
3.214 + <object class="NSMenu" key="NSSubmenu" id="1065607017">
3.215 + <reference key="NSTitle" ref="1022827674"/>
3.216 + <object class="NSMutableArray" key="NSMenuItems">
3.217 + <bool key="EncodedWithXMLCoder">YES</bool>
3.218 + <object class="NSMenuItem" id="759406840">
3.219 + <reference key="NSMenu" ref="1065607017"/>
3.220 + <string key="NSTitle">Clear Menu</string>
3.221 + <reference key="NSKeyEquiv" ref="1003"/>
3.222 + <int key="NSKeyEquivModMask">1048576</int>
3.223 + <int key="NSMnemonicLoc">2147483647</int>
3.224 + <reference key="NSOnImage" ref="484312224"/>
3.225 + <reference key="NSMixedImage" ref="309443010"/>
3.226 + </object>
3.227 + </object>
3.228 + <string key="NSName">_NSRecentDocumentsMenu</string>
3.229 + </object>
3.230 + </object>
3.231 + <object class="NSMenuItem" id="425164168">
3.232 + <reference key="NSMenu" ref="720053764"/>
3.233 + <bool key="NSIsDisabled">YES</bool>
3.234 + <bool key="NSIsSeparator">YES</bool>
3.235 + <reference key="NSTitle" ref="1003"/>
3.236 + <reference key="NSKeyEquiv" ref="1003"/>
3.237 + <int key="NSKeyEquivModMask">1048576</int>
3.238 + <int key="NSMnemonicLoc">2147483647</int>
3.239 + <reference key="NSOnImage" ref="484312224"/>
3.240 + <reference key="NSMixedImage" ref="309443010"/>
3.241 + </object>
3.242 + <object class="NSMenuItem" id="776162233">
3.243 + <reference key="NSMenu" ref="720053764"/>
3.244 + <string key="NSTitle">Close</string>
3.245 + <string key="NSKeyEquiv">w</string>
3.246 + <int key="NSKeyEquivModMask">1048576</int>
3.247 + <int key="NSMnemonicLoc">2147483647</int>
3.248 + <reference key="NSOnImage" ref="484312224"/>
3.249 + <reference key="NSMixedImage" ref="309443010"/>
3.250 + </object>
3.251 + <object class="NSMenuItem" id="1023925487">
3.252 + <reference key="NSMenu" ref="720053764"/>
3.253 + <string key="NSTitle">Save</string>
3.254 + <string key="NSKeyEquiv">s</string>
3.255 + <int key="NSKeyEquivModMask">1048576</int>
3.256 + <int key="NSMnemonicLoc">2147483647</int>
3.257 + <reference key="NSOnImage" ref="484312224"/>
3.258 + <reference key="NSMixedImage" ref="309443010"/>
3.259 + </object>
3.260 + <object class="NSMenuItem" id="117038363">
3.261 + <reference key="NSMenu" ref="720053764"/>
3.262 + <string type="base64-UTF8" key="NSTitle">U2F2ZSBBc+KApg</string>
3.263 + <string key="NSKeyEquiv">S</string>
3.264 + <int key="NSKeyEquivModMask">1179648</int>
3.265 + <int key="NSMnemonicLoc">2147483647</int>
3.266 + <reference key="NSOnImage" ref="484312224"/>
3.267 + <reference key="NSMixedImage" ref="309443010"/>
3.268 + </object>
3.269 + <object class="NSMenuItem" id="579971712">
3.270 + <reference key="NSMenu" ref="720053764"/>
3.271 + <string key="NSTitle">Revert to Saved</string>
3.272 + <reference key="NSKeyEquiv" ref="1003"/>
3.273 + <int key="NSMnemonicLoc">2147483647</int>
3.274 + <reference key="NSOnImage" ref="484312224"/>
3.275 + <reference key="NSMixedImage" ref="309443010"/>
3.276 + </object>
3.277 + <object class="NSMenuItem" id="1010469920">
3.278 + <reference key="NSMenu" ref="720053764"/>
3.279 + <bool key="NSIsDisabled">YES</bool>
3.280 + <bool key="NSIsSeparator">YES</bool>
3.281 + <reference key="NSTitle" ref="1003"/>
3.282 + <reference key="NSKeyEquiv" ref="1003"/>
3.283 + <int key="NSKeyEquivModMask">1048576</int>
3.284 + <int key="NSMnemonicLoc">2147483647</int>
3.285 + <reference key="NSOnImage" ref="484312224"/>
3.286 + <reference key="NSMixedImage" ref="309443010"/>
3.287 + </object>
3.288 + <object class="NSMenuItem" id="294629803">
3.289 + <reference key="NSMenu" ref="720053764"/>
3.290 + <string key="NSTitle">Page Setup...</string>
3.291 + <string key="NSKeyEquiv">P</string>
3.292 + <int key="NSKeyEquivModMask">1179648</int>
3.293 + <int key="NSMnemonicLoc">2147483647</int>
3.294 + <reference key="NSOnImage" ref="484312224"/>
3.295 + <reference key="NSMixedImage" ref="309443010"/>
3.296 + <reference key="NSToolTip" ref="1003"/>
3.297 + </object>
3.298 + <object class="NSMenuItem" id="49223823">
3.299 + <reference key="NSMenu" ref="720053764"/>
3.300 + <string type="base64-UTF8" key="NSTitle">UHJpbnTigKY</string>
3.301 + <string key="NSKeyEquiv">p</string>
3.302 + <int key="NSKeyEquivModMask">1048576</int>
3.303 + <int key="NSMnemonicLoc">2147483647</int>
3.304 + <reference key="NSOnImage" ref="484312224"/>
3.305 + <reference key="NSMixedImage" ref="309443010"/>
3.306 + </object>
3.307 + </object>
3.308 + </object>
3.309 + </object>
3.310 + <object class="NSMenuItem" id="952259628">
3.311 + <reference key="NSMenu" ref="649796088"/>
3.312 + <string key="NSTitle" id="459142759">Edit</string>
3.313 + <reference key="NSKeyEquiv" ref="1003"/>
3.314 + <int key="NSKeyEquivModMask">1048576</int>
3.315 + <int key="NSMnemonicLoc">2147483647</int>
3.316 + <reference key="NSOnImage" ref="484312224"/>
3.317 + <reference key="NSMixedImage" ref="309443010"/>
3.318 + <string key="NSAction">submenuAction:</string>
3.319 + <object class="NSMenu" key="NSSubmenu" id="789758025">
3.320 + <reference key="NSTitle" ref="459142759"/>
3.321 + <object class="NSMutableArray" key="NSMenuItems">
3.322 + <bool key="EncodedWithXMLCoder">YES</bool>
3.323 + <object class="NSMenuItem" id="1058277027">
3.324 + <reference key="NSMenu" ref="789758025"/>
3.325 + <string key="NSTitle">Undo</string>
3.326 + <string key="NSKeyEquiv">z</string>
3.327 + <int key="NSKeyEquivModMask">1048576</int>
3.328 + <int key="NSMnemonicLoc">2147483647</int>
3.329 + <reference key="NSOnImage" ref="484312224"/>
3.330 + <reference key="NSMixedImage" ref="309443010"/>
3.331 + </object>
3.332 + <object class="NSMenuItem" id="790794224">
3.333 + <reference key="NSMenu" ref="789758025"/>
3.334 + <string key="NSTitle">Redo</string>
3.335 + <string key="NSKeyEquiv">Z</string>
3.336 + <int key="NSKeyEquivModMask">1179648</int>
3.337 + <int key="NSMnemonicLoc">2147483647</int>
3.338 + <reference key="NSOnImage" ref="484312224"/>
3.339 + <reference key="NSMixedImage" ref="309443010"/>
3.340 + </object>
3.341 + <object class="NSMenuItem" id="1040322652">
3.342 + <reference key="NSMenu" ref="789758025"/>
3.343 + <bool key="NSIsDisabled">YES</bool>
3.344 + <bool key="NSIsSeparator">YES</bool>
3.345 + <reference key="NSTitle" ref="1003"/>
3.346 + <reference key="NSKeyEquiv" ref="1003"/>
3.347 + <int key="NSKeyEquivModMask">1048576</int>
3.348 + <int key="NSMnemonicLoc">2147483647</int>
3.349 + <reference key="NSOnImage" ref="484312224"/>
3.350 + <reference key="NSMixedImage" ref="309443010"/>
3.351 + </object>
3.352 + <object class="NSMenuItem" id="296257095">
3.353 + <reference key="NSMenu" ref="789758025"/>
3.354 + <string key="NSTitle">Cut</string>
3.355 + <string key="NSKeyEquiv">x</string>
3.356 + <int key="NSKeyEquivModMask">1048576</int>
3.357 + <int key="NSMnemonicLoc">2147483647</int>
3.358 + <reference key="NSOnImage" ref="484312224"/>
3.359 + <reference key="NSMixedImage" ref="309443010"/>
3.360 + </object>
3.361 + <object class="NSMenuItem" id="860595796">
3.362 + <reference key="NSMenu" ref="789758025"/>
3.363 + <string key="NSTitle">Copy</string>
3.364 + <string key="NSKeyEquiv">c</string>
3.365 + <int key="NSKeyEquivModMask">1048576</int>
3.366 + <int key="NSMnemonicLoc">2147483647</int>
3.367 + <reference key="NSOnImage" ref="484312224"/>
3.368 + <reference key="NSMixedImage" ref="309443010"/>
3.369 + </object>
3.370 + <object class="NSMenuItem" id="29853731">
3.371 + <reference key="NSMenu" ref="789758025"/>
3.372 + <string key="NSTitle">Paste</string>
3.373 + <string key="NSKeyEquiv">v</string>
3.374 + <int key="NSKeyEquivModMask">1048576</int>
3.375 + <int key="NSMnemonicLoc">2147483647</int>
3.376 + <reference key="NSOnImage" ref="484312224"/>
3.377 + <reference key="NSMixedImage" ref="309443010"/>
3.378 + </object>
3.379 + <object class="NSMenuItem" id="437104165">
3.380 + <reference key="NSMenu" ref="789758025"/>
3.381 + <string key="NSTitle">Delete</string>
3.382 + <reference key="NSKeyEquiv" ref="1003"/>
3.383 + <int key="NSKeyEquivModMask">1048576</int>
3.384 + <int key="NSMnemonicLoc">2147483647</int>
3.385 + <reference key="NSOnImage" ref="484312224"/>
3.386 + <reference key="NSMixedImage" ref="309443010"/>
3.387 + </object>
3.388 + <object class="NSMenuItem" id="583158037">
3.389 + <reference key="NSMenu" ref="789758025"/>
3.390 + <string key="NSTitle">Select All</string>
3.391 + <string key="NSKeyEquiv">a</string>
3.392 + <int key="NSKeyEquivModMask">1048576</int>
3.393 + <int key="NSMnemonicLoc">2147483647</int>
3.394 + <reference key="NSOnImage" ref="484312224"/>
3.395 + <reference key="NSMixedImage" ref="309443010"/>
3.396 + </object>
3.397 + <object class="NSMenuItem" id="212016141">
3.398 + <reference key="NSMenu" ref="789758025"/>
3.399 + <bool key="NSIsDisabled">YES</bool>
3.400 + <bool key="NSIsSeparator">YES</bool>
3.401 + <reference key="NSTitle" ref="1003"/>
3.402 + <reference key="NSKeyEquiv" ref="1003"/>
3.403 + <int key="NSKeyEquivModMask">1048576</int>
3.404 + <int key="NSMnemonicLoc">2147483647</int>
3.405 + <reference key="NSOnImage" ref="484312224"/>
3.406 + <reference key="NSMixedImage" ref="309443010"/>
3.407 + </object>
3.408 + <object class="NSMenuItem" id="676164635">
3.409 + <reference key="NSMenu" ref="789758025"/>
3.410 + <string key="NSTitle" id="1050731385">Speech</string>
3.411 + <reference key="NSKeyEquiv" ref="1003"/>
3.412 + <int key="NSKeyEquivModMask">1048576</int>
3.413 + <int key="NSMnemonicLoc">2147483647</int>
3.414 + <reference key="NSOnImage" ref="484312224"/>
3.415 + <reference key="NSMixedImage" ref="309443010"/>
3.416 + <string key="NSAction">submenuAction:</string>
3.417 + <object class="NSMenu" key="NSSubmenu" id="785027613">
3.418 + <reference key="NSTitle" ref="1050731385"/>
3.419 + <object class="NSMutableArray" key="NSMenuItems">
3.420 + <bool key="EncodedWithXMLCoder">YES</bool>
3.421 + <object class="NSMenuItem" id="731782645">
3.422 + <reference key="NSMenu" ref="785027613"/>
3.423 + <string key="NSTitle">Start Speaking</string>
3.424 + <reference key="NSKeyEquiv" ref="1003"/>
3.425 + <int key="NSKeyEquivModMask">1048576</int>
3.426 + <int key="NSMnemonicLoc">2147483647</int>
3.427 + <reference key="NSOnImage" ref="484312224"/>
3.428 + <reference key="NSMixedImage" ref="309443010"/>
3.429 + </object>
3.430 + <object class="NSMenuItem" id="680220178">
3.431 + <reference key="NSMenu" ref="785027613"/>
3.432 + <string key="NSTitle">Stop Speaking</string>
3.433 + <reference key="NSKeyEquiv" ref="1003"/>
3.434 + <int key="NSKeyEquivModMask">1048576</int>
3.435 + <int key="NSMnemonicLoc">2147483647</int>
3.436 + <reference key="NSOnImage" ref="484312224"/>
3.437 + <reference key="NSMixedImage" ref="309443010"/>
3.438 + </object>
3.439 + </object>
3.440 + </object>
3.441 + </object>
3.442 + </object>
3.443 + </object>
3.444 + </object>
3.445 + <object class="NSMenuItem" id="517895433">
3.446 + <reference key="NSMenu" ref="649796088"/>
3.447 + <string key="NSTitle" id="898761740">Game</string>
3.448 + <reference key="NSKeyEquiv" ref="1003"/>
3.449 + <int key="NSKeyEquivModMask">1048576</int>
3.450 + <int key="NSMnemonicLoc">2147483647</int>
3.451 + <reference key="NSOnImage" ref="484312224"/>
3.452 + <reference key="NSMixedImage" ref="309443010"/>
3.453 + <string key="NSAction">submenuAction:</string>
3.454 + <object class="NSMenu" key="NSSubmenu" id="330268596">
3.455 + <reference key="NSTitle" ref="898761740"/>
3.456 + <object class="NSMutableArray" key="NSMenuItems">
3.457 + <bool key="EncodedWithXMLCoder">YES</bool>
3.458 + <object class="NSMenuItem" id="394352720">
3.459 + <reference key="NSMenu" ref="330268596"/>
3.460 + <string key="NSTitle">Klondike (Solitaire)</string>
3.461 + <string key="NSKeyEquiv" id="344781584">1</string>
3.462 + <int key="NSKeyEquivModMask">1048840</int>
3.463 + <int key="NSMnemonicLoc">2147483647</int>
3.464 + <reference key="NSOnImage" ref="484312224"/>
3.465 + <reference key="NSMixedImage" ref="309443010"/>
3.466 + </object>
3.467 + <object class="NSMenuItem" id="154289436">
3.468 + <reference key="NSMenu" ref="330268596"/>
3.469 + <bool key="NSIsDisabled">YES</bool>
3.470 + <bool key="NSIsSeparator">YES</bool>
3.471 + <reference key="NSTitle" ref="1003"/>
3.472 + <reference key="NSKeyEquiv" ref="1003"/>
3.473 + <int key="NSKeyEquivModMask">1048576</int>
3.474 + <int key="NSMnemonicLoc">2147483647</int>
3.475 + <reference key="NSOnImage" ref="484312224"/>
3.476 + <reference key="NSMixedImage" ref="309443010"/>
3.477 + </object>
3.478 + <object class="NSMenuItem" id="630661937">
3.479 + <reference key="NSMenu" ref="330268596"/>
3.480 + <string key="NSTitle">Checkers</string>
3.481 + <string key="NSKeyEquiv" id="5220549">2</string>
3.482 + <int key="NSKeyEquivModMask">1048840</int>
3.483 + <int key="NSMnemonicLoc">2147483647</int>
3.484 + <reference key="NSOnImage" ref="484312224"/>
3.485 + <reference key="NSMixedImage" ref="309443010"/>
3.486 + <int key="NSTag">1</int>
3.487 + </object>
3.488 + <object class="NSMenuItem" id="778498721">
3.489 + <reference key="NSMenu" ref="330268596"/>
3.490 + <string key="NSTitle">Go</string>
3.491 + <string key="NSKeyEquiv" id="8808733">3</string>
3.492 + <int key="NSKeyEquivModMask">1048840</int>
3.493 + <int key="NSMnemonicLoc">2147483647</int>
3.494 + <reference key="NSOnImage" ref="484312224"/>
3.495 + <reference key="NSMixedImage" ref="309443010"/>
3.496 + <int key="NSTag">4</int>
3.497 + </object>
3.498 + <object class="NSMenuItem" id="538211827">
3.499 + <reference key="NSMenu" ref="330268596"/>
3.500 + <string key="NSTitle">Hexchequer</string>
3.501 + <string key="NSKeyEquiv">4</string>
3.502 + <int key="NSKeyEquivModMask">1048840</int>
3.503 + <int key="NSMnemonicLoc">2147483647</int>
3.504 + <reference key="NSOnImage" ref="484312224"/>
3.505 + <reference key="NSMixedImage" ref="309443010"/>
3.506 + <int key="NSTag">2</int>
3.507 + </object>
3.508 + <object class="NSMenuItem" id="739065818">
3.509 + <reference key="NSMenu" ref="330268596"/>
3.510 + <string key="NSTitle">Tic-Tac-Toe</string>
3.511 + <string key="NSKeyEquiv" id="720655175">5</string>
3.512 + <int key="NSKeyEquivModMask">1048840</int>
3.513 + <int key="NSMnemonicLoc">2147483647</int>
3.514 + <reference key="NSOnImage" ref="484312224"/>
3.515 + <reference key="NSMixedImage" ref="309443010"/>
3.516 + <int key="NSTag">3</int>
3.517 + </object>
3.518 + </object>
3.519 + </object>
3.520 + </object>
3.521 + <object class="NSMenuItem" id="586577488">
3.522 + <reference key="NSMenu" ref="649796088"/>
3.523 + <string key="NSTitle" id="180305338">View</string>
3.524 + <reference key="NSKeyEquiv" ref="1003"/>
3.525 + <int key="NSKeyEquivModMask">1048576</int>
3.526 + <int key="NSMnemonicLoc">2147483647</int>
3.527 + <reference key="NSOnImage" ref="484312224"/>
3.528 + <reference key="NSMixedImage" ref="309443010"/>
3.529 + <string key="NSAction">submenuAction:</string>
3.530 + <object class="NSMenu" key="NSSubmenu" id="466310130">
3.531 + <reference key="NSTitle" ref="180305338"/>
3.532 + <object class="NSMutableArray" key="NSMenuItems">
3.533 + <bool key="EncodedWithXMLCoder">YES</bool>
3.534 + <object class="NSMenuItem" id="713673133">
3.535 + <reference key="NSMenu" ref="466310130"/>
3.536 + <string key="NSTitle">Full Screen</string>
3.537 + <string key="NSKeyEquiv">f</string>
3.538 + <int key="NSKeyEquivModMask">1048576</int>
3.539 + <int key="NSMnemonicLoc">2147483647</int>
3.540 + <reference key="NSOnImage" ref="484312224"/>
3.541 + <reference key="NSMixedImage" ref="309443010"/>
3.542 + </object>
3.543 + <object class="NSMenuItem" id="30531644">
3.544 + <reference key="NSMenu" ref="466310130"/>
3.545 + <bool key="NSIsDisabled">YES</bool>
3.546 + <bool key="NSIsSeparator">YES</bool>
3.547 + <reference key="NSTitle" ref="1003"/>
3.548 + <reference key="NSKeyEquiv" ref="1003"/>
3.549 + <int key="NSKeyEquivModMask">1048576</int>
3.550 + <int key="NSMnemonicLoc">2147483647</int>
3.551 + <reference key="NSOnImage" ref="484312224"/>
3.552 + <reference key="NSMixedImage" ref="309443010"/>
3.553 + </object>
3.554 + <object class="NSMenuItem" id="102151532">
3.555 + <reference key="NSMenu" ref="466310130"/>
3.556 + <string key="NSTitle">Show Toolbar</string>
3.557 + <string key="NSKeyEquiv">t</string>
3.558 + <int key="NSKeyEquivModMask">1572864</int>
3.559 + <int key="NSMnemonicLoc">2147483647</int>
3.560 + <reference key="NSOnImage" ref="484312224"/>
3.561 + <reference key="NSMixedImage" ref="309443010"/>
3.562 + </object>
3.563 + <object class="NSMenuItem" id="237841660">
3.564 + <reference key="NSMenu" ref="466310130"/>
3.565 + <string type="base64-UTF8" key="NSTitle">Q3VzdG9taXplIFRvb2xiYXLigKY</string>
3.566 + <reference key="NSKeyEquiv" ref="1003"/>
3.567 + <int key="NSKeyEquivModMask">1048576</int>
3.568 + <int key="NSMnemonicLoc">2147483647</int>
3.569 + <reference key="NSOnImage" ref="484312224"/>
3.570 + <reference key="NSMixedImage" ref="309443010"/>
3.571 + </object>
3.572 + </object>
3.573 + </object>
3.574 + </object>
3.575 + <object class="NSMenuItem" id="713487014">
3.576 + <reference key="NSMenu" ref="649796088"/>
3.577 + <string key="NSTitle" id="15506412">Window</string>
3.578 + <reference key="NSKeyEquiv" ref="1003"/>
3.579 + <int key="NSKeyEquivModMask">1048576</int>
3.580 + <int key="NSMnemonicLoc">2147483647</int>
3.581 + <reference key="NSOnImage" ref="484312224"/>
3.582 + <reference key="NSMixedImage" ref="309443010"/>
3.583 + <string key="NSAction">submenuAction:</string>
3.584 + <object class="NSMenu" key="NSSubmenu" id="835318025">
3.585 + <reference key="NSTitle" ref="15506412"/>
3.586 + <object class="NSMutableArray" key="NSMenuItems">
3.587 + <bool key="EncodedWithXMLCoder">YES</bool>
3.588 + <object class="NSMenuItem" id="1011231497">
3.589 + <reference key="NSMenu" ref="835318025"/>
3.590 + <string key="NSTitle">Minimize</string>
3.591 + <string key="NSKeyEquiv">m</string>
3.592 + <int key="NSKeyEquivModMask">1048576</int>
3.593 + <int key="NSMnemonicLoc">2147483647</int>
3.594 + <reference key="NSOnImage" ref="484312224"/>
3.595 + <reference key="NSMixedImage" ref="309443010"/>
3.596 + </object>
3.597 + <object class="NSMenuItem" id="575023229">
3.598 + <reference key="NSMenu" ref="835318025"/>
3.599 + <string key="NSTitle">Zoom</string>
3.600 + <reference key="NSKeyEquiv" ref="1003"/>
3.601 + <int key="NSKeyEquivModMask">1048576</int>
3.602 + <int key="NSMnemonicLoc">2147483647</int>
3.603 + <reference key="NSOnImage" ref="484312224"/>
3.604 + <reference key="NSMixedImage" ref="309443010"/>
3.605 + </object>
3.606 + <object class="NSMenuItem" id="299356726">
3.607 + <reference key="NSMenu" ref="835318025"/>
3.608 + <bool key="NSIsDisabled">YES</bool>
3.609 + <bool key="NSIsSeparator">YES</bool>
3.610 + <reference key="NSTitle" ref="1003"/>
3.611 + <reference key="NSKeyEquiv" ref="1003"/>
3.612 + <int key="NSKeyEquivModMask">1048576</int>
3.613 + <int key="NSMnemonicLoc">2147483647</int>
3.614 + <reference key="NSOnImage" ref="484312224"/>
3.615 + <reference key="NSMixedImage" ref="309443010"/>
3.616 + </object>
3.617 + <object class="NSMenuItem" id="625202149">
3.618 + <reference key="NSMenu" ref="835318025"/>
3.619 + <string key="NSTitle">Bring All to Front</string>
3.620 + <reference key="NSKeyEquiv" ref="1003"/>
3.621 + <int key="NSKeyEquivModMask">1048576</int>
3.622 + <int key="NSMnemonicLoc">2147483647</int>
3.623 + <reference key="NSOnImage" ref="484312224"/>
3.624 + <reference key="NSMixedImage" ref="309443010"/>
3.625 + </object>
3.626 + </object>
3.627 + <string key="NSName">_NSWindowsMenu</string>
3.628 + </object>
3.629 + </object>
3.630 + <object class="NSMenuItem" id="391199113">
3.631 + <reference key="NSMenu" ref="649796088"/>
3.632 + <string key="NSTitle" id="519223894">Help</string>
3.633 + <reference key="NSKeyEquiv" ref="1003"/>
3.634 + <int key="NSKeyEquivModMask">1048576</int>
3.635 + <int key="NSMnemonicLoc">2147483647</int>
3.636 + <reference key="NSOnImage" ref="484312224"/>
3.637 + <reference key="NSMixedImage" ref="309443010"/>
3.638 + <string key="NSAction">submenuAction:</string>
3.639 + <object class="NSMenu" key="NSSubmenu" id="374024848">
3.640 + <reference key="NSTitle" ref="519223894"/>
3.641 + <object class="NSMutableArray" key="NSMenuItems">
3.642 + <bool key="EncodedWithXMLCoder">YES</bool>
3.643 + </object>
3.644 + </object>
3.645 + </object>
3.646 + </object>
3.647 + <string key="NSName">_NSMainMenu</string>
3.648 + </object>
3.649 + <object class="NSWindowTemplate" id="972006081">
3.650 + <int key="NSWindowStyleMask">7</int>
3.651 + <int key="NSWindowBacking">2</int>
3.652 + <string key="NSWindowRect">{{57, 175}, {1084, 587}}</string>
3.653 + <int key="NSWTFlags">1946157056</int>
3.654 + <reference key="NSWindowTitle" ref="101265034"/>
3.655 + <string key="NSWindowClass">NSWindow</string>
3.656 + <nil key="NSViewClass"/>
3.657 + <object class="NSView" key="NSWindowView" id="439893737">
3.658 + <reference key="NSNextResponder"/>
3.659 + <int key="NSvFlags">256</int>
3.660 + <object class="NSMutableArray" key="NSSubviews">
3.661 + <bool key="EncodedWithXMLCoder">YES</bool>
3.662 + <object class="NSCustomView" id="1060834180">
3.663 + <reference key="NSNextResponder" ref="439893737"/>
3.664 + <int key="NSvFlags">274</int>
3.665 + <string key="NSFrameSize">{1084, 587}</string>
3.666 + <reference key="NSSuperview" ref="439893737"/>
3.667 + <reference key="NSWindow"/>
3.668 + <bool key="NSViewIsLayerTreeHost">YES</bool>
3.669 + <string key="NSClassName">DemoBoardView</string>
3.670 + </object>
3.671 + </object>
3.672 + <string key="NSFrameSize">{1084, 587}</string>
3.673 + <reference key="NSSuperview"/>
3.674 + <reference key="NSWindow"/>
3.675 + </object>
3.676 + <string key="NSScreenRect">{{0, 0}, {1440, 878}}</string>
3.677 + <reference key="NSFrameAutosaveName" ref="1003"/>
3.678 + </object>
3.679 + </object>
3.680 + <object class="IBObjectContainer" key="IBDocument.Objects">
3.681 + <object class="NSMutableArray" key="connectionRecords">
3.682 + <bool key="EncodedWithXMLCoder">YES</bool>
3.683 + <object class="IBConnectionRecord">
3.684 + <object class="IBActionConnection" key="connection">
3.685 + <string key="label">performMiniaturize:</string>
3.686 + <reference key="source" ref="1014"/>
3.687 + <reference key="destination" ref="1011231497"/>
3.688 + </object>
3.689 + <int key="connectionID">37</int>
3.690 + </object>
3.691 + <object class="IBConnectionRecord">
3.692 + <object class="IBActionConnection" key="connection">
3.693 + <string key="label">arrangeInFront:</string>
3.694 + <reference key="source" ref="1014"/>
3.695 + <reference key="destination" ref="625202149"/>
3.696 + </object>
3.697 + <int key="connectionID">39</int>
3.698 + </object>
3.699 + <object class="IBConnectionRecord">
3.700 + <object class="IBActionConnection" key="connection">
3.701 + <string key="label">print:</string>
3.702 + <reference key="source" ref="1014"/>
3.703 + <reference key="destination" ref="49223823"/>
3.704 + </object>
3.705 + <int key="connectionID">86</int>
3.706 + </object>
3.707 + <object class="IBConnectionRecord">
3.708 + <object class="IBActionConnection" key="connection">
3.709 + <string key="label">runPageLayout:</string>
3.710 + <reference key="source" ref="1014"/>
3.711 + <reference key="destination" ref="294629803"/>
3.712 + </object>
3.713 + <int key="connectionID">87</int>
3.714 + </object>
3.715 + <object class="IBConnectionRecord">
3.716 + <object class="IBActionConnection" key="connection">
3.717 + <string key="label">clearRecentDocuments:</string>
3.718 + <reference key="source" ref="1014"/>
3.719 + <reference key="destination" ref="759406840"/>
3.720 + </object>
3.721 + <int key="connectionID">127</int>
3.722 + </object>
3.723 + <object class="IBConnectionRecord">
3.724 + <object class="IBActionConnection" key="connection">
3.725 + <string key="label">orderFrontStandardAboutPanel:</string>
3.726 + <reference key="source" ref="1021"/>
3.727 + <reference key="destination" ref="238522557"/>
3.728 + </object>
3.729 + <int key="connectionID">142</int>
3.730 + </object>
3.731 + <object class="IBConnectionRecord">
3.732 + <object class="IBActionConnection" key="connection">
3.733 + <string key="label">performClose:</string>
3.734 + <reference key="source" ref="1014"/>
3.735 + <reference key="destination" ref="776162233"/>
3.736 + </object>
3.737 + <int key="connectionID">193</int>
3.738 + </object>
3.739 + <object class="IBConnectionRecord">
3.740 + <object class="IBActionConnection" key="connection">
3.741 + <string key="label">undo:</string>
3.742 + <reference key="source" ref="1014"/>
3.743 + <reference key="destination" ref="1058277027"/>
3.744 + </object>
3.745 + <int key="connectionID">223</int>
3.746 + </object>
3.747 + <object class="IBConnectionRecord">
3.748 + <object class="IBActionConnection" key="connection">
3.749 + <string key="label">copy:</string>
3.750 + <reference key="source" ref="1014"/>
3.751 + <reference key="destination" ref="860595796"/>
3.752 + </object>
3.753 + <int key="connectionID">224</int>
3.754 + </object>
3.755 + <object class="IBConnectionRecord">
3.756 + <object class="IBActionConnection" key="connection">
3.757 + <string key="label">paste:</string>
3.758 + <reference key="source" ref="1014"/>
3.759 + <reference key="destination" ref="29853731"/>
3.760 + </object>
3.761 + <int key="connectionID">226</int>
3.762 + </object>
3.763 + <object class="IBConnectionRecord">
3.764 + <object class="IBActionConnection" key="connection">
3.765 + <string key="label">stopSpeaking:</string>
3.766 + <reference key="source" ref="1014"/>
3.767 + <reference key="destination" ref="680220178"/>
3.768 + </object>
3.769 + <int key="connectionID">227</int>
3.770 + </object>
3.771 + <object class="IBConnectionRecord">
3.772 + <object class="IBActionConnection" key="connection">
3.773 + <string key="label">cut:</string>
3.774 + <reference key="source" ref="1014"/>
3.775 + <reference key="destination" ref="296257095"/>
3.776 + </object>
3.777 + <int key="connectionID">228</int>
3.778 + </object>
3.779 + <object class="IBConnectionRecord">
3.780 + <object class="IBActionConnection" key="connection">
3.781 + <string key="label">redo:</string>
3.782 + <reference key="source" ref="1014"/>
3.783 + <reference key="destination" ref="790794224"/>
3.784 + </object>
3.785 + <int key="connectionID">231</int>
3.786 + </object>
3.787 + <object class="IBConnectionRecord">
3.788 + <object class="IBActionConnection" key="connection">
3.789 + <string key="label">selectAll:</string>
3.790 + <reference key="source" ref="1014"/>
3.791 + <reference key="destination" ref="583158037"/>
3.792 + </object>
3.793 + <int key="connectionID">232</int>
3.794 + </object>
3.795 + <object class="IBConnectionRecord">
3.796 + <object class="IBActionConnection" key="connection">
3.797 + <string key="label">startSpeaking:</string>
3.798 + <reference key="source" ref="1014"/>
3.799 + <reference key="destination" ref="731782645"/>
3.800 + </object>
3.801 + <int key="connectionID">233</int>
3.802 + </object>
3.803 + <object class="IBConnectionRecord">
3.804 + <object class="IBActionConnection" key="connection">
3.805 + <string key="label">delete:</string>
3.806 + <reference key="source" ref="1014"/>
3.807 + <reference key="destination" ref="437104165"/>
3.808 + </object>
3.809 + <int key="connectionID">235</int>
3.810 + </object>
3.811 + <object class="IBConnectionRecord">
3.812 + <object class="IBActionConnection" key="connection">
3.813 + <string key="label">performZoom:</string>
3.814 + <reference key="source" ref="1014"/>
3.815 + <reference key="destination" ref="575023229"/>
3.816 + </object>
3.817 + <int key="connectionID">240</int>
3.818 + </object>
3.819 + <object class="IBConnectionRecord">
3.820 + <object class="IBActionConnection" key="connection">
3.821 + <string key="label">saveDocument:</string>
3.822 + <reference key="source" ref="1014"/>
3.823 + <reference key="destination" ref="1023925487"/>
3.824 + </object>
3.825 + <int key="connectionID">362</int>
3.826 + </object>
3.827 + <object class="IBConnectionRecord">
3.828 + <object class="IBActionConnection" key="connection">
3.829 + <string key="label">saveDocumentAs:</string>
3.830 + <reference key="source" ref="1014"/>
3.831 + <reference key="destination" ref="117038363"/>
3.832 + </object>
3.833 + <int key="connectionID">363</int>
3.834 + </object>
3.835 + <object class="IBConnectionRecord">
3.836 + <object class="IBActionConnection" key="connection">
3.837 + <string key="label">revertDocumentToSaved:</string>
3.838 + <reference key="source" ref="1014"/>
3.839 + <reference key="destination" ref="579971712"/>
3.840 + </object>
3.841 + <int key="connectionID">364</int>
3.842 + </object>
3.843 + <object class="IBConnectionRecord">
3.844 + <object class="IBActionConnection" key="connection">
3.845 + <string key="label">runToolbarCustomizationPalette:</string>
3.846 + <reference key="source" ref="1014"/>
3.847 + <reference key="destination" ref="237841660"/>
3.848 + </object>
3.849 + <int key="connectionID">365</int>
3.850 + </object>
3.851 + <object class="IBConnectionRecord">
3.852 + <object class="IBActionConnection" key="connection">
3.853 + <string key="label">toggleToolbarShown:</string>
3.854 + <reference key="source" ref="1014"/>
3.855 + <reference key="destination" ref="102151532"/>
3.856 + </object>
3.857 + <int key="connectionID">366</int>
3.858 + </object>
3.859 + <object class="IBConnectionRecord">
3.860 + <object class="IBActionConnection" key="connection">
3.861 + <string key="label">hide:</string>
3.862 + <reference key="source" ref="1014"/>
3.863 + <reference key="destination" ref="755159360"/>
3.864 + </object>
3.865 + <int key="connectionID">367</int>
3.866 + </object>
3.867 + <object class="IBConnectionRecord">
3.868 + <object class="IBActionConnection" key="connection">
3.869 + <string key="label">hideOtherApplications:</string>
3.870 + <reference key="source" ref="1014"/>
3.871 + <reference key="destination" ref="342932134"/>
3.872 + </object>
3.873 + <int key="connectionID">368</int>
3.874 + </object>
3.875 + <object class="IBConnectionRecord">
3.876 + <object class="IBActionConnection" key="connection">
3.877 + <string key="label">terminate:</string>
3.878 + <reference key="source" ref="1014"/>
3.879 + <reference key="destination" ref="632727374"/>
3.880 + </object>
3.881 + <int key="connectionID">369</int>
3.882 + </object>
3.883 + <object class="IBConnectionRecord">
3.884 + <object class="IBActionConnection" key="connection">
3.885 + <string key="label">unhideAllApplications:</string>
3.886 + <reference key="source" ref="1014"/>
3.887 + <reference key="destination" ref="908899353"/>
3.888 + </object>
3.889 + <int key="connectionID">370</int>
3.890 + </object>
3.891 + <object class="IBConnectionRecord">
3.892 + <object class="IBActionConnection" key="connection">
3.893 + <string key="label">newDocument:</string>
3.894 + <reference key="source" ref="1014"/>
3.895 + <reference key="destination" ref="705341025"/>
3.896 + </object>
3.897 + <int key="connectionID">373</int>
3.898 + </object>
3.899 + <object class="IBConnectionRecord">
3.900 + <object class="IBActionConnection" key="connection">
3.901 + <string key="label">openDocument:</string>
3.902 + <reference key="source" ref="1014"/>
3.903 + <reference key="destination" ref="722745758"/>
3.904 + </object>
3.905 + <int key="connectionID">374</int>
3.906 + </object>
3.907 + <object class="IBConnectionRecord">
3.908 + <object class="IBActionConnection" key="connection">
3.909 + <string key="label">enterFullScreen:</string>
3.910 + <reference key="source" ref="1060834180"/>
3.911 + <reference key="destination" ref="713673133"/>
3.912 + </object>
3.913 + <int key="connectionID">378</int>
3.914 + </object>
3.915 + <object class="IBConnectionRecord">
3.916 + <object class="IBActionConnection" key="connection">
3.917 + <string key="label" id="560321708">startGameFromMenu:</string>
3.918 + <reference key="source" ref="1060834180"/>
3.919 + <reference key="destination" ref="394352720"/>
3.920 + </object>
3.921 + <int key="connectionID">388</int>
3.922 + </object>
3.923 + <object class="IBConnectionRecord">
3.924 + <object class="IBActionConnection" key="connection">
3.925 + <reference key="label" ref="560321708"/>
3.926 + <reference key="source" ref="1060834180"/>
3.927 + <reference key="destination" ref="630661937"/>
3.928 + </object>
3.929 + <int key="connectionID">389</int>
3.930 + </object>
3.931 + <object class="IBConnectionRecord">
3.932 + <object class="IBActionConnection" key="connection">
3.933 + <reference key="label" ref="560321708"/>
3.934 + <reference key="source" ref="1060834180"/>
3.935 + <reference key="destination" ref="538211827"/>
3.936 + </object>
3.937 + <int key="connectionID">390</int>
3.938 + </object>
3.939 + <object class="IBConnectionRecord">
3.940 + <object class="IBActionConnection" key="connection">
3.941 + <reference key="label" ref="560321708"/>
3.942 + <reference key="source" ref="1060834180"/>
3.943 + <reference key="destination" ref="739065818"/>
3.944 + </object>
3.945 + <int key="connectionID">391</int>
3.946 + </object>
3.947 + <object class="IBConnectionRecord">
3.948 + <object class="IBActionConnection" key="connection">
3.949 + <reference key="label" ref="560321708"/>
3.950 + <reference key="source" ref="1060834180"/>
3.951 + <reference key="destination" ref="778498721"/>
3.952 + </object>
3.953 + <int key="connectionID">394</int>
3.954 + </object>
3.955 + <object class="IBConnectionRecord">
3.956 + <object class="IBOutletConnection" key="connection">
3.957 + <string key="label">initialFirstResponder</string>
3.958 + <reference key="source" ref="972006081"/>
3.959 + <reference key="destination" ref="1060834180"/>
3.960 + </object>
3.961 + <int key="connectionID">399</int>
3.962 + </object>
3.963 + <object class="IBConnectionRecord">
3.964 + <object class="IBOutletConnection" key="connection">
3.965 + <string key="label">delegate</string>
3.966 + <reference key="source" ref="1021"/>
3.967 + <reference key="destination" ref="1060834180"/>
3.968 + </object>
3.969 + <int key="connectionID">400</int>
3.970 + </object>
3.971 + </object>
3.972 + <object class="IBMutableOrderedSet" key="objectRecords">
3.973 + <object class="NSArray" key="orderedObjects">
3.974 + <bool key="EncodedWithXMLCoder">YES</bool>
3.975 + <object class="IBObjectRecord">
3.976 + <int key="objectID">0</int>
3.977 + <object class="NSArray" key="object" id="1049">
3.978 + <bool key="EncodedWithXMLCoder">YES</bool>
3.979 + </object>
3.980 + <reference key="children" ref="1048"/>
3.981 + <nil key="parent"/>
3.982 + </object>
3.983 + <object class="IBObjectRecord">
3.984 + <int key="objectID">-2</int>
3.985 + <reference key="object" ref="1021"/>
3.986 + <reference key="parent" ref="1049"/>
3.987 + <string type="base64-UTF8" key="objectName">RmlsZSdzIE93bmVyA</string>
3.988 + </object>
3.989 + <object class="IBObjectRecord">
3.990 + <int key="objectID">-1</int>
3.991 + <reference key="object" ref="1014"/>
3.992 + <reference key="parent" ref="1049"/>
3.993 + <string key="objectName">First Responder</string>
3.994 + </object>
3.995 + <object class="IBObjectRecord">
3.996 + <int key="objectID">-3</int>
3.997 + <reference key="object" ref="1050"/>
3.998 + <reference key="parent" ref="1049"/>
3.999 + <string key="objectName">Application</string>
3.1000 + </object>
3.1001 + <object class="IBObjectRecord">
3.1002 + <int key="objectID">29</int>
3.1003 + <reference key="object" ref="649796088"/>
3.1004 + <object class="NSMutableArray" key="children">
3.1005 + <bool key="EncodedWithXMLCoder">YES</bool>
3.1006 + <reference ref="713487014"/>
3.1007 + <reference ref="694149608"/>
3.1008 + <reference ref="391199113"/>
3.1009 + <reference ref="952259628"/>
3.1010 + <reference ref="379814623"/>
3.1011 + <reference ref="586577488"/>
3.1012 + <reference ref="517895433"/>
3.1013 + </object>
3.1014 + <reference key="parent" ref="1049"/>
3.1015 + <string key="objectName">MainMenu</string>
3.1016 + </object>
3.1017 + <object class="IBObjectRecord">
3.1018 + <int key="objectID">19</int>
3.1019 + <reference key="object" ref="713487014"/>
3.1020 + <object class="NSMutableArray" key="children">
3.1021 + <bool key="EncodedWithXMLCoder">YES</bool>
3.1022 + <reference ref="835318025"/>
3.1023 + </object>
3.1024 + <reference key="parent" ref="649796088"/>
3.1025 + </object>
3.1026 + <object class="IBObjectRecord">
3.1027 + <int key="objectID">56</int>
3.1028 + <reference key="object" ref="694149608"/>
3.1029 + <object class="NSMutableArray" key="children">
3.1030 + <bool key="EncodedWithXMLCoder">YES</bool>
3.1031 + <reference ref="110575045"/>
3.1032 + </object>
3.1033 + <reference key="parent" ref="649796088"/>
3.1034 + </object>
3.1035 + <object class="IBObjectRecord">
3.1036 + <int key="objectID">103</int>
3.1037 + <reference key="object" ref="391199113"/>
3.1038 + <object class="NSMutableArray" key="children">
3.1039 + <bool key="EncodedWithXMLCoder">YES</bool>
3.1040 + <reference ref="374024848"/>
3.1041 + </object>
3.1042 + <reference key="parent" ref="649796088"/>
3.1043 + <reference key="objectName" ref="344781584"/>
3.1044 + </object>
3.1045 + <object class="IBObjectRecord">
3.1046 + <int key="objectID">217</int>
3.1047 + <reference key="object" ref="952259628"/>
3.1048 + <object class="NSMutableArray" key="children">
3.1049 + <bool key="EncodedWithXMLCoder">YES</bool>
3.1050 + <reference ref="789758025"/>
3.1051 + </object>
3.1052 + <reference key="parent" ref="649796088"/>
3.1053 + </object>
3.1054 + <object class="IBObjectRecord">
3.1055 + <int key="objectID">83</int>
3.1056 + <reference key="object" ref="379814623"/>
3.1057 + <object class="NSMutableArray" key="children">
3.1058 + <bool key="EncodedWithXMLCoder">YES</bool>
3.1059 + <reference ref="720053764"/>
3.1060 + </object>
3.1061 + <reference key="parent" ref="649796088"/>
3.1062 + </object>
3.1063 + <object class="IBObjectRecord">
3.1064 + <int key="objectID">81</int>
3.1065 + <reference key="object" ref="720053764"/>
3.1066 + <object class="NSMutableArray" key="children">
3.1067 + <bool key="EncodedWithXMLCoder">YES</bool>
3.1068 + <reference ref="1023925487"/>
3.1069 + <reference ref="117038363"/>
3.1070 + <reference ref="49223823"/>
3.1071 + <reference ref="722745758"/>
3.1072 + <reference ref="705341025"/>
3.1073 + <reference ref="1025936716"/>
3.1074 + <reference ref="294629803"/>
3.1075 + <reference ref="776162233"/>
3.1076 + <reference ref="425164168"/>
3.1077 + <reference ref="579971712"/>
3.1078 + <reference ref="1010469920"/>
3.1079 + </object>
3.1080 + <reference key="parent" ref="379814623"/>
3.1081 + </object>
3.1082 + <object class="IBObjectRecord">
3.1083 + <int key="objectID">75</int>
3.1084 + <reference key="object" ref="1023925487"/>
3.1085 + <reference key="parent" ref="720053764"/>
3.1086 + <reference key="objectName" ref="8808733"/>
3.1087 + </object>
3.1088 + <object class="IBObjectRecord">
3.1089 + <int key="objectID">80</int>
3.1090 + <reference key="object" ref="117038363"/>
3.1091 + <reference key="parent" ref="720053764"/>
3.1092 + <string key="objectName">8</string>
3.1093 + </object>
3.1094 + <object class="IBObjectRecord">
3.1095 + <int key="objectID">78</int>
3.1096 + <reference key="object" ref="49223823"/>
3.1097 + <reference key="parent" ref="720053764"/>
3.1098 + <string key="objectName">6</string>
3.1099 + </object>
3.1100 + <object class="IBObjectRecord">
3.1101 + <int key="objectID">72</int>
3.1102 + <reference key="object" ref="722745758"/>
3.1103 + <reference key="parent" ref="720053764"/>
3.1104 + </object>
3.1105 + <object class="IBObjectRecord">
3.1106 + <int key="objectID">82</int>
3.1107 + <reference key="object" ref="705341025"/>
3.1108 + <reference key="parent" ref="720053764"/>
3.1109 + <string key="objectName">9</string>
3.1110 + </object>
3.1111 + <object class="IBObjectRecord">
3.1112 + <int key="objectID">124</int>
3.1113 + <reference key="object" ref="1025936716"/>
3.1114 + <object class="NSMutableArray" key="children">
3.1115 + <bool key="EncodedWithXMLCoder">YES</bool>
3.1116 + <reference ref="1065607017"/>
3.1117 + </object>
3.1118 + <reference key="parent" ref="720053764"/>
3.1119 + </object>
3.1120 + <object class="IBObjectRecord">
3.1121 + <int key="objectID">77</int>
3.1122 + <reference key="object" ref="294629803"/>
3.1123 + <reference key="parent" ref="720053764"/>
3.1124 + <reference key="objectName" ref="720655175"/>
3.1125 + </object>
3.1126 + <object class="IBObjectRecord">
3.1127 + <int key="objectID">73</int>
3.1128 + <reference key="object" ref="776162233"/>
3.1129 + <reference key="parent" ref="720053764"/>
3.1130 + <reference key="objectName" ref="344781584"/>
3.1131 + </object>
3.1132 + <object class="IBObjectRecord">
3.1133 + <int key="objectID">79</int>
3.1134 + <reference key="object" ref="425164168"/>
3.1135 + <reference key="parent" ref="720053764"/>
3.1136 + <string key="objectName">7</string>
3.1137 + </object>
3.1138 + <object class="IBObjectRecord">
3.1139 + <int key="objectID">112</int>
3.1140 + <reference key="object" ref="579971712"/>
3.1141 + <reference key="parent" ref="720053764"/>
3.1142 + <string key="objectName">10</string>
3.1143 + </object>
3.1144 + <object class="IBObjectRecord">
3.1145 + <int key="objectID">74</int>
3.1146 + <reference key="object" ref="1010469920"/>
3.1147 + <reference key="parent" ref="720053764"/>
3.1148 + <reference key="objectName" ref="5220549"/>
3.1149 + </object>
3.1150 + <object class="IBObjectRecord">
3.1151 + <int key="objectID">125</int>
3.1152 + <reference key="object" ref="1065607017"/>
3.1153 + <object class="NSMutableArray" key="children">
3.1154 + <bool key="EncodedWithXMLCoder">YES</bool>
3.1155 + <reference ref="759406840"/>
3.1156 + </object>
3.1157 + <reference key="parent" ref="1025936716"/>
3.1158 + </object>
3.1159 + <object class="IBObjectRecord">
3.1160 + <int key="objectID">126</int>
3.1161 + <reference key="object" ref="759406840"/>
3.1162 + <reference key="parent" ref="1065607017"/>
3.1163 + </object>
3.1164 + <object class="IBObjectRecord">
3.1165 + <int key="objectID">205</int>
3.1166 + <reference key="object" ref="789758025"/>
3.1167 + <object class="NSMutableArray" key="children">
3.1168 + <bool key="EncodedWithXMLCoder">YES</bool>
3.1169 + <reference ref="437104165"/>
3.1170 + <reference ref="583158037"/>
3.1171 + <reference ref="1058277027"/>
3.1172 + <reference ref="212016141"/>
3.1173 + <reference ref="296257095"/>
3.1174 + <reference ref="29853731"/>
3.1175 + <reference ref="860595796"/>
3.1176 + <reference ref="1040322652"/>
3.1177 + <reference ref="790794224"/>
3.1178 + <reference ref="676164635"/>
3.1179 + </object>
3.1180 + <reference key="parent" ref="952259628"/>
3.1181 + </object>
3.1182 + <object class="IBObjectRecord">
3.1183 + <int key="objectID">202</int>
3.1184 + <reference key="object" ref="437104165"/>
3.1185 + <reference key="parent" ref="789758025"/>
3.1186 + </object>
3.1187 + <object class="IBObjectRecord">
3.1188 + <int key="objectID">198</int>
3.1189 + <reference key="object" ref="583158037"/>
3.1190 + <reference key="parent" ref="789758025"/>
3.1191 + </object>
3.1192 + <object class="IBObjectRecord">
3.1193 + <int key="objectID">207</int>
3.1194 + <reference key="object" ref="1058277027"/>
3.1195 + <reference key="parent" ref="789758025"/>
3.1196 + </object>
3.1197 + <object class="IBObjectRecord">
3.1198 + <int key="objectID">214</int>
3.1199 + <reference key="object" ref="212016141"/>
3.1200 + <reference key="parent" ref="789758025"/>
3.1201 + </object>
3.1202 + <object class="IBObjectRecord">
3.1203 + <int key="objectID">199</int>
3.1204 + <reference key="object" ref="296257095"/>
3.1205 + <reference key="parent" ref="789758025"/>
3.1206 + </object>
3.1207 + <object class="IBObjectRecord">
3.1208 + <int key="objectID">203</int>
3.1209 + <reference key="object" ref="29853731"/>
3.1210 + <reference key="parent" ref="789758025"/>
3.1211 + </object>
3.1212 + <object class="IBObjectRecord">
3.1213 + <int key="objectID">197</int>
3.1214 + <reference key="object" ref="860595796"/>
3.1215 + <reference key="parent" ref="789758025"/>
3.1216 + </object>
3.1217 + <object class="IBObjectRecord">
3.1218 + <int key="objectID">206</int>
3.1219 + <reference key="object" ref="1040322652"/>
3.1220 + <reference key="parent" ref="789758025"/>
3.1221 + </object>
3.1222 + <object class="IBObjectRecord">
3.1223 + <int key="objectID">215</int>
3.1224 + <reference key="object" ref="790794224"/>
3.1225 + <reference key="parent" ref="789758025"/>
3.1226 + </object>
3.1227 + <object class="IBObjectRecord">
3.1228 + <int key="objectID">106</int>
3.1229 + <reference key="object" ref="374024848"/>
3.1230 + <object class="NSMutableArray" key="children">
3.1231 + <bool key="EncodedWithXMLCoder">YES</bool>
3.1232 + </object>
3.1233 + <reference key="parent" ref="391199113"/>
3.1234 + <reference key="objectName" ref="5220549"/>
3.1235 + </object>
3.1236 + <object class="IBObjectRecord">
3.1237 + <int key="objectID">57</int>
3.1238 + <reference key="object" ref="110575045"/>
3.1239 + <object class="NSMutableArray" key="children">
3.1240 + <bool key="EncodedWithXMLCoder">YES</bool>
3.1241 + <reference ref="238522557"/>
3.1242 + <reference ref="755159360"/>
3.1243 + <reference ref="908899353"/>
3.1244 + <reference ref="632727374"/>
3.1245 + <reference ref="646227648"/>
3.1246 + <reference ref="609285721"/>
3.1247 + <reference ref="481834944"/>
3.1248 + <reference ref="304266470"/>
3.1249 + <reference ref="1046388886"/>
3.1250 + <reference ref="1056857174"/>
3.1251 + <reference ref="342932134"/>
3.1252 + </object>
3.1253 + <reference key="parent" ref="694149608"/>
3.1254 + </object>
3.1255 + <object class="IBObjectRecord">
3.1256 + <int key="objectID">58</int>
3.1257 + <reference key="object" ref="238522557"/>
3.1258 + <reference key="parent" ref="110575045"/>
3.1259 + </object>
3.1260 + <object class="IBObjectRecord">
3.1261 + <int key="objectID">134</int>
3.1262 + <reference key="object" ref="755159360"/>
3.1263 + <reference key="parent" ref="110575045"/>
3.1264 + </object>
3.1265 + <object class="IBObjectRecord">
3.1266 + <int key="objectID">150</int>
3.1267 + <reference key="object" ref="908899353"/>
3.1268 + <reference key="parent" ref="110575045"/>
3.1269 + </object>
3.1270 + <object class="IBObjectRecord">
3.1271 + <int key="objectID">136</int>
3.1272 + <reference key="object" ref="632727374"/>
3.1273 + <reference key="parent" ref="110575045"/>
3.1274 + <string key="objectName">1111</string>
3.1275 + </object>
3.1276 + <object class="IBObjectRecord">
3.1277 + <int key="objectID">144</int>
3.1278 + <reference key="object" ref="646227648"/>
3.1279 + <reference key="parent" ref="110575045"/>
3.1280 + </object>
3.1281 + <object class="IBObjectRecord">
3.1282 + <int key="objectID">129</int>
3.1283 + <reference key="object" ref="609285721"/>
3.1284 + <reference key="parent" ref="110575045"/>
3.1285 + <string key="objectName">121</string>
3.1286 + </object>
3.1287 + <object class="IBObjectRecord">
3.1288 + <int key="objectID">143</int>
3.1289 + <reference key="object" ref="481834944"/>
3.1290 + <reference key="parent" ref="110575045"/>
3.1291 + </object>
3.1292 + <object class="IBObjectRecord">
3.1293 + <int key="objectID">236</int>
3.1294 + <reference key="object" ref="304266470"/>
3.1295 + <reference key="parent" ref="110575045"/>
3.1296 + </object>
3.1297 + <object class="IBObjectRecord">
3.1298 + <int key="objectID">131</int>
3.1299 + <reference key="object" ref="1046388886"/>
3.1300 + <object class="NSMutableArray" key="children">
3.1301 + <bool key="EncodedWithXMLCoder">YES</bool>
3.1302 + <reference ref="752062318"/>
3.1303 + </object>
3.1304 + <reference key="parent" ref="110575045"/>
3.1305 + </object>
3.1306 + <object class="IBObjectRecord">
3.1307 + <int key="objectID">149</int>
3.1308 + <reference key="object" ref="1056857174"/>
3.1309 + <reference key="parent" ref="110575045"/>
3.1310 + </object>
3.1311 + <object class="IBObjectRecord">
3.1312 + <int key="objectID">145</int>
3.1313 + <reference key="object" ref="342932134"/>
3.1314 + <reference key="parent" ref="110575045"/>
3.1315 + </object>
3.1316 + <object class="IBObjectRecord">
3.1317 + <int key="objectID">130</int>
3.1318 + <reference key="object" ref="752062318"/>
3.1319 + <reference key="parent" ref="1046388886"/>
3.1320 + </object>
3.1321 + <object class="IBObjectRecord">
3.1322 + <int key="objectID">24</int>
3.1323 + <reference key="object" ref="835318025"/>
3.1324 + <object class="NSMutableArray" key="children">
3.1325 + <bool key="EncodedWithXMLCoder">YES</bool>
3.1326 + <reference ref="299356726"/>
3.1327 + <reference ref="625202149"/>
3.1328 + <reference ref="575023229"/>
3.1329 + <reference ref="1011231497"/>
3.1330 + </object>
3.1331 + <reference key="parent" ref="713487014"/>
3.1332 + </object>
3.1333 + <object class="IBObjectRecord">
3.1334 + <int key="objectID">92</int>
3.1335 + <reference key="object" ref="299356726"/>
3.1336 + <reference key="parent" ref="835318025"/>
3.1337 + </object>
3.1338 + <object class="IBObjectRecord">
3.1339 + <int key="objectID">5</int>
3.1340 + <reference key="object" ref="625202149"/>
3.1341 + <reference key="parent" ref="835318025"/>
3.1342 + </object>
3.1343 + <object class="IBObjectRecord">
3.1344 + <int key="objectID">239</int>
3.1345 + <reference key="object" ref="575023229"/>
3.1346 + <reference key="parent" ref="835318025"/>
3.1347 + </object>
3.1348 + <object class="IBObjectRecord">
3.1349 + <int key="objectID">23</int>
3.1350 + <reference key="object" ref="1011231497"/>
3.1351 + <reference key="parent" ref="835318025"/>
3.1352 + </object>
3.1353 + <object class="IBObjectRecord">
3.1354 + <int key="objectID">295</int>
3.1355 + <reference key="object" ref="586577488"/>
3.1356 + <object class="NSMutableArray" key="children">
3.1357 + <bool key="EncodedWithXMLCoder">YES</bool>
3.1358 + <reference ref="466310130"/>
3.1359 + </object>
3.1360 + <reference key="parent" ref="649796088"/>
3.1361 + </object>
3.1362 + <object class="IBObjectRecord">
3.1363 + <int key="objectID">296</int>
3.1364 + <reference key="object" ref="466310130"/>
3.1365 + <object class="NSMutableArray" key="children">
3.1366 + <bool key="EncodedWithXMLCoder">YES</bool>
3.1367 + <reference ref="102151532"/>
3.1368 + <reference ref="237841660"/>
3.1369 + <reference ref="713673133"/>
3.1370 + <reference ref="30531644"/>
3.1371 + </object>
3.1372 + <reference key="parent" ref="586577488"/>
3.1373 + </object>
3.1374 + <object class="IBObjectRecord">
3.1375 + <int key="objectID">297</int>
3.1376 + <reference key="object" ref="102151532"/>
3.1377 + <reference key="parent" ref="466310130"/>
3.1378 + </object>
3.1379 + <object class="IBObjectRecord">
3.1380 + <int key="objectID">298</int>
3.1381 + <reference key="object" ref="237841660"/>
3.1382 + <reference key="parent" ref="466310130"/>
3.1383 + </object>
3.1384 + <object class="IBObjectRecord">
3.1385 + <int key="objectID">211</int>
3.1386 + <reference key="object" ref="676164635"/>
3.1387 + <object class="NSMutableArray" key="children">
3.1388 + <bool key="EncodedWithXMLCoder">YES</bool>
3.1389 + <reference ref="785027613"/>
3.1390 + </object>
3.1391 + <reference key="parent" ref="789758025"/>
3.1392 + </object>
3.1393 + <object class="IBObjectRecord">
3.1394 + <int key="objectID">212</int>
3.1395 + <reference key="object" ref="785027613"/>
3.1396 + <object class="NSMutableArray" key="children">
3.1397 + <bool key="EncodedWithXMLCoder">YES</bool>
3.1398 + <reference ref="680220178"/>
3.1399 + <reference ref="731782645"/>
3.1400 + </object>
3.1401 + <reference key="parent" ref="676164635"/>
3.1402 + </object>
3.1403 + <object class="IBObjectRecord">
3.1404 + <int key="objectID">195</int>
3.1405 + <reference key="object" ref="680220178"/>
3.1406 + <reference key="parent" ref="785027613"/>
3.1407 + </object>
3.1408 + <object class="IBObjectRecord">
3.1409 + <int key="objectID">196</int>
3.1410 + <reference key="object" ref="731782645"/>
3.1411 + <reference key="parent" ref="785027613"/>
3.1412 + </object>
3.1413 + <object class="IBObjectRecord">
3.1414 + <int key="objectID">371</int>
3.1415 + <reference key="object" ref="972006081"/>
3.1416 + <object class="NSMutableArray" key="children">
3.1417 + <bool key="EncodedWithXMLCoder">YES</bool>
3.1418 + <reference ref="439893737"/>
3.1419 + </object>
3.1420 + <reference key="parent" ref="1049"/>
3.1421 + </object>
3.1422 + <object class="IBObjectRecord">
3.1423 + <int key="objectID">372</int>
3.1424 + <reference key="object" ref="439893737"/>
3.1425 + <object class="NSMutableArray" key="children">
3.1426 + <bool key="EncodedWithXMLCoder">YES</bool>
3.1427 + <reference ref="1060834180"/>
3.1428 + </object>
3.1429 + <reference key="parent" ref="972006081"/>
3.1430 + </object>
3.1431 + <object class="IBObjectRecord">
3.1432 + <int key="objectID">375</int>
3.1433 + <reference key="object" ref="1060834180"/>
3.1434 + <reference key="parent" ref="439893737"/>
3.1435 + </object>
3.1436 + <object class="IBObjectRecord">
3.1437 + <int key="objectID">376</int>
3.1438 + <reference key="object" ref="713673133"/>
3.1439 + <reference key="parent" ref="466310130"/>
3.1440 + </object>
3.1441 + <object class="IBObjectRecord">
3.1442 + <int key="objectID">377</int>
3.1443 + <reference key="object" ref="30531644"/>
3.1444 + <reference key="parent" ref="466310130"/>
3.1445 + </object>
3.1446 + <object class="IBObjectRecord">
3.1447 + <int key="objectID">379</int>
3.1448 + <reference key="object" ref="517895433"/>
3.1449 + <object class="NSMutableArray" key="children">
3.1450 + <bool key="EncodedWithXMLCoder">YES</bool>
3.1451 + <reference ref="330268596"/>
3.1452 + </object>
3.1453 + <reference key="parent" ref="649796088"/>
3.1454 + </object>
3.1455 + <object class="IBObjectRecord">
3.1456 + <int key="objectID">380</int>
3.1457 + <reference key="object" ref="330268596"/>
3.1458 + <object class="NSMutableArray" key="children">
3.1459 + <bool key="EncodedWithXMLCoder">YES</bool>
3.1460 + <reference ref="394352720"/>
3.1461 + <reference ref="538211827"/>
3.1462 + <reference ref="739065818"/>
3.1463 + <reference ref="154289436"/>
3.1464 + <reference ref="778498721"/>
3.1465 + <reference ref="630661937"/>
3.1466 + </object>
3.1467 + <reference key="parent" ref="517895433"/>
3.1468 + </object>
3.1469 + <object class="IBObjectRecord">
3.1470 + <int key="objectID">381</int>
3.1471 + <reference key="object" ref="394352720"/>
3.1472 + <reference key="parent" ref="330268596"/>
3.1473 + </object>
3.1474 + <object class="IBObjectRecord">
3.1475 + <int key="objectID">382</int>
3.1476 + <reference key="object" ref="630661937"/>
3.1477 + <reference key="parent" ref="330268596"/>
3.1478 + </object>
3.1479 + <object class="IBObjectRecord">
3.1480 + <int key="objectID">383</int>
3.1481 + <reference key="object" ref="538211827"/>
3.1482 + <reference key="parent" ref="330268596"/>
3.1483 + </object>
3.1484 + <object class="IBObjectRecord">
3.1485 + <int key="objectID">384</int>
3.1486 + <reference key="object" ref="739065818"/>
3.1487 + <reference key="parent" ref="330268596"/>
3.1488 + </object>
3.1489 + <object class="IBObjectRecord">
3.1490 + <int key="objectID">387</int>
3.1491 + <reference key="object" ref="154289436"/>
3.1492 + <reference key="parent" ref="330268596"/>
3.1493 + </object>
3.1494 + <object class="IBObjectRecord">
3.1495 + <int key="objectID">393</int>
3.1496 + <reference key="object" ref="778498721"/>
3.1497 + <reference key="parent" ref="330268596"/>
3.1498 + </object>
3.1499 + </object>
3.1500 + </object>
3.1501 + <object class="NSMutableDictionary" key="flattenedProperties">
3.1502 + <bool key="EncodedWithXMLCoder">YES</bool>
3.1503 + <object class="NSMutableArray" key="dict.sortedKeys">
3.1504 + <bool key="EncodedWithXMLCoder">YES</bool>
3.1505 + <string>-1.IBPluginDependency</string>
3.1506 + <string>-2.IBPluginDependency</string>
3.1507 + <string>-3.IBPluginDependency</string>
3.1508 + <string>103.IBPluginDependency</string>
3.1509 + <string>103.ImportedFromIB2</string>
3.1510 + <string>106.IBPluginDependency</string>
3.1511 + <string>106.ImportedFromIB2</string>
3.1512 + <string>106.editorWindowContentRectSynchronizationRect</string>
3.1513 + <string>112.IBPluginDependency</string>
3.1514 + <string>112.ImportedFromIB2</string>
3.1515 + <string>124.IBPluginDependency</string>
3.1516 + <string>124.ImportedFromIB2</string>
3.1517 + <string>125.IBPluginDependency</string>
3.1518 + <string>125.ImportedFromIB2</string>
3.1519 + <string>125.editorWindowContentRectSynchronizationRect</string>
3.1520 + <string>126.IBPluginDependency</string>
3.1521 + <string>126.ImportedFromIB2</string>
3.1522 + <string>129.IBPluginDependency</string>
3.1523 + <string>129.ImportedFromIB2</string>
3.1524 + <string>130.IBPluginDependency</string>
3.1525 + <string>130.ImportedFromIB2</string>
3.1526 + <string>130.editorWindowContentRectSynchronizationRect</string>
3.1527 + <string>131.IBPluginDependency</string>
3.1528 + <string>131.ImportedFromIB2</string>
3.1529 + <string>134.IBPluginDependency</string>
3.1530 + <string>134.ImportedFromIB2</string>
3.1531 + <string>136.IBPluginDependency</string>
3.1532 + <string>136.ImportedFromIB2</string>
3.1533 + <string>143.IBPluginDependency</string>
3.1534 + <string>143.ImportedFromIB2</string>
3.1535 + <string>144.IBPluginDependency</string>
3.1536 + <string>144.ImportedFromIB2</string>
3.1537 + <string>145.IBPluginDependency</string>
3.1538 + <string>145.ImportedFromIB2</string>
3.1539 + <string>149.IBPluginDependency</string>
3.1540 + <string>149.ImportedFromIB2</string>
3.1541 + <string>150.IBPluginDependency</string>
3.1542 + <string>150.ImportedFromIB2</string>
3.1543 + <string>19.IBPluginDependency</string>
3.1544 + <string>19.ImportedFromIB2</string>
3.1545 + <string>195.IBPluginDependency</string>
3.1546 + <string>195.ImportedFromIB2</string>
3.1547 + <string>196.IBPluginDependency</string>
3.1548 + <string>196.ImportedFromIB2</string>
3.1549 + <string>197.IBPluginDependency</string>
3.1550 + <string>197.ImportedFromIB2</string>
3.1551 + <string>198.IBPluginDependency</string>
3.1552 + <string>198.ImportedFromIB2</string>
3.1553 + <string>199.IBPluginDependency</string>
3.1554 + <string>199.ImportedFromIB2</string>
3.1555 + <string>202.IBPluginDependency</string>
3.1556 + <string>202.ImportedFromIB2</string>
3.1557 + <string>203.IBPluginDependency</string>
3.1558 + <string>203.ImportedFromIB2</string>
3.1559 + <string>205.IBPluginDependency</string>
3.1560 + <string>205.ImportedFromIB2</string>
3.1561 + <string>205.editorWindowContentRectSynchronizationRect</string>
3.1562 + <string>206.IBPluginDependency</string>
3.1563 + <string>206.ImportedFromIB2</string>
3.1564 + <string>207.IBPluginDependency</string>
3.1565 + <string>207.ImportedFromIB2</string>
3.1566 + <string>211.IBPluginDependency</string>
3.1567 + <string>211.ImportedFromIB2</string>
3.1568 + <string>212.IBPluginDependency</string>
3.1569 + <string>212.ImportedFromIB2</string>
3.1570 + <string>212.editorWindowContentRectSynchronizationRect</string>
3.1571 + <string>214.IBPluginDependency</string>
3.1572 + <string>214.ImportedFromIB2</string>
3.1573 + <string>215.IBPluginDependency</string>
3.1574 + <string>215.ImportedFromIB2</string>
3.1575 + <string>217.IBPluginDependency</string>
3.1576 + <string>217.ImportedFromIB2</string>
3.1577 + <string>23.IBPluginDependency</string>
3.1578 + <string>23.ImportedFromIB2</string>
3.1579 + <string>236.IBPluginDependency</string>
3.1580 + <string>236.ImportedFromIB2</string>
3.1581 + <string>239.IBPluginDependency</string>
3.1582 + <string>239.ImportedFromIB2</string>
3.1583 + <string>24.IBPluginDependency</string>
3.1584 + <string>24.ImportedFromIB2</string>
3.1585 + <string>24.editorWindowContentRectSynchronizationRect</string>
3.1586 + <string>29.IBPluginDependency</string>
3.1587 + <string>29.ImportedFromIB2</string>
3.1588 + <string>29.WindowOrigin</string>
3.1589 + <string>29.editorWindowContentRectSynchronizationRect</string>
3.1590 + <string>295.IBPluginDependency</string>
3.1591 + <string>296.IBPluginDependency</string>
3.1592 + <string>296.editorWindowContentRectSynchronizationRect</string>
3.1593 + <string>297.IBPluginDependency</string>
3.1594 + <string>298.IBPluginDependency</string>
3.1595 + <string>371.IBPluginDependency</string>
3.1596 + <string>371.IBWindowTemplateEditedContentRect</string>
3.1597 + <string>371.NSWindowTemplate.visibleAtLaunch</string>
3.1598 + <string>371.editorWindowContentRectSynchronizationRect</string>
3.1599 + <string>372.IBPluginDependency</string>
3.1600 + <string>375.IBPluginDependency</string>
3.1601 + <string>376.IBPluginDependency</string>
3.1602 + <string>377.IBPluginDependency</string>
3.1603 + <string>379.IBPluginDependency</string>
3.1604 + <string>380.IBPluginDependency</string>
3.1605 + <string>380.editorWindowContentRectSynchronizationRect</string>
3.1606 + <string>381.IBPluginDependency</string>
3.1607 + <string>382.IBPluginDependency</string>
3.1608 + <string>383.IBPluginDependency</string>
3.1609 + <string>384.IBPluginDependency</string>
3.1610 + <string>387.IBPluginDependency</string>
3.1611 + <string>393.IBPluginDependency</string>
3.1612 + <string>5.IBPluginDependency</string>
3.1613 + <string>5.ImportedFromIB2</string>
3.1614 + <string>56.IBPluginDependency</string>
3.1615 + <string>56.ImportedFromIB2</string>
3.1616 + <string>57.IBPluginDependency</string>
3.1617 + <string>57.ImportedFromIB2</string>
3.1618 + <string>57.editorWindowContentRectSynchronizationRect</string>
3.1619 + <string>58.IBPluginDependency</string>
3.1620 + <string>58.ImportedFromIB2</string>
3.1621 + <string>72.IBPluginDependency</string>
3.1622 + <string>72.ImportedFromIB2</string>
3.1623 + <string>73.IBPluginDependency</string>
3.1624 + <string>73.ImportedFromIB2</string>
3.1625 + <string>74.IBPluginDependency</string>
3.1626 + <string>74.ImportedFromIB2</string>
3.1627 + <string>75.IBPluginDependency</string>
3.1628 + <string>75.ImportedFromIB2</string>
3.1629 + <string>77.IBPluginDependency</string>
3.1630 + <string>77.ImportedFromIB2</string>
3.1631 + <string>78.IBPluginDependency</string>
3.1632 + <string>78.ImportedFromIB2</string>
3.1633 + <string>79.IBPluginDependency</string>
3.1634 + <string>79.ImportedFromIB2</string>
3.1635 + <string>80.IBPluginDependency</string>
3.1636 + <string>80.ImportedFromIB2</string>
3.1637 + <string>81.IBPluginDependency</string>
3.1638 + <string>81.ImportedFromIB2</string>
3.1639 + <string>81.editorWindowContentRectSynchronizationRect</string>
3.1640 + <string>82.IBPluginDependency</string>
3.1641 + <string>82.ImportedFromIB2</string>
3.1642 + <string>83.IBPluginDependency</string>
3.1643 + <string>83.ImportedFromIB2</string>
3.1644 + <string>92.IBPluginDependency</string>
3.1645 + <string>92.ImportedFromIB2</string>
3.1646 + </object>
3.1647 + <object class="NSMutableArray" key="dict.values">
3.1648 + <bool key="EncodedWithXMLCoder">YES</bool>
3.1649 + <reference ref="248469711"/>
3.1650 + <reference ref="617114957"/>
3.1651 + <reference ref="617114957"/>
3.1652 + <reference ref="248469711"/>
3.1653 + <integer value="1" id="9"/>
3.1654 + <reference ref="248469711"/>
3.1655 + <reference ref="9"/>
3.1656 + <string>{{497, 828}, {64, 6}}</string>
3.1657 + <reference ref="248469711"/>
3.1658 + <reference ref="9"/>
3.1659 + <reference ref="248469711"/>
3.1660 + <reference ref="9"/>
3.1661 + <reference ref="248469711"/>
3.1662 + <reference ref="9"/>
3.1663 + <string>{{522, 812}, {146, 23}}</string>
3.1664 + <reference ref="248469711"/>
3.1665 + <reference ref="9"/>
3.1666 + <reference ref="248469711"/>
3.1667 + <reference ref="9"/>
3.1668 + <reference ref="248469711"/>
3.1669 + <reference ref="9"/>
3.1670 + <string>{{436, 809}, {64, 6}}</string>
3.1671 + <reference ref="248469711"/>
3.1672 + <reference ref="9"/>
3.1673 + <reference ref="248469711"/>
3.1674 + <reference ref="9"/>
3.1675 + <reference ref="248469711"/>
3.1676 + <reference ref="9"/>
3.1677 + <reference ref="248469711"/>
3.1678 + <reference ref="9"/>
3.1679 + <reference ref="248469711"/>
3.1680 + <reference ref="9"/>
3.1681 + <reference ref="248469711"/>
3.1682 + <reference ref="9"/>
3.1683 + <reference ref="248469711"/>
3.1684 + <reference ref="9"/>
3.1685 + <reference ref="248469711"/>
3.1686 + <reference ref="9"/>
3.1687 + <reference ref="248469711"/>
3.1688 + <reference ref="9"/>
3.1689 + <reference ref="248469711"/>
3.1690 + <reference ref="9"/>
3.1691 + <reference ref="248469711"/>
3.1692 + <reference ref="9"/>
3.1693 + <reference ref="248469711"/>
3.1694 + <reference ref="9"/>
3.1695 + <reference ref="248469711"/>
3.1696 + <reference ref="9"/>
3.1697 + <reference ref="248469711"/>
3.1698 + <reference ref="9"/>
3.1699 + <reference ref="248469711"/>
3.1700 + <reference ref="9"/>
3.1701 + <reference ref="248469711"/>
3.1702 + <reference ref="9"/>
3.1703 + <reference ref="248469711"/>
3.1704 + <reference ref="9"/>
3.1705 + <string>{{271, 653}, {154, 183}}</string>
3.1706 + <reference ref="248469711"/>
3.1707 + <reference ref="9"/>
3.1708 + <reference ref="248469711"/>
3.1709 + <reference ref="9"/>
3.1710 + <reference ref="248469711"/>
3.1711 + <reference ref="9"/>
3.1712 + <reference ref="248469711"/>
3.1713 + <reference ref="9"/>
3.1714 + <string>{{514, 573}, {167, 43}}</string>
3.1715 + <reference ref="248469711"/>
3.1716 + <reference ref="9"/>
3.1717 + <reference ref="248469711"/>
3.1718 + <reference ref="9"/>
3.1719 + <reference ref="248469711"/>
3.1720 + <reference ref="9"/>
3.1721 + <reference ref="248469711"/>
3.1722 + <reference ref="9"/>
3.1723 + <reference ref="248469711"/>
3.1724 + <reference ref="9"/>
3.1725 + <reference ref="248469711"/>
3.1726 + <reference ref="9"/>
3.1727 + <reference ref="248469711"/>
3.1728 + <reference ref="9"/>
3.1729 + <string>{{525, 802}, {197, 73}}</string>
3.1730 + <reference ref="248469711"/>
3.1731 + <reference ref="9"/>
3.1732 + <string>{74, 862}</string>
3.1733 + <string>{{85, 834}, {473, 20}}</string>
3.1734 + <reference ref="248469711"/>
3.1735 + <reference ref="248469711"/>
3.1736 + <string>{{319, 763}, {234, 73}}</string>
3.1737 + <reference ref="248469711"/>
3.1738 + <reference ref="248469711"/>
3.1739 + <reference ref="248469711"/>
3.1740 + <string>{{117, 199}, {1084, 587}}</string>
3.1741 + <reference ref="9"/>
3.1742 + <string>{{117, 199}, {1084, 587}}</string>
3.1743 + <reference ref="248469711"/>
3.1744 + <reference ref="248469711"/>
3.1745 + <reference ref="248469711"/>
3.1746 + <reference ref="248469711"/>
3.1747 + <reference ref="248469711"/>
3.1748 + <reference ref="248469711"/>
3.1749 + <string>{{319, 721}, {205, 113}}</string>
3.1750 + <reference ref="248469711"/>
3.1751 + <reference ref="248469711"/>
3.1752 + <reference ref="248469711"/>
3.1753 + <reference ref="248469711"/>
3.1754 + <reference ref="248469711"/>
3.1755 + <reference ref="248469711"/>
3.1756 + <reference ref="248469711"/>
3.1757 + <reference ref="9"/>
3.1758 + <reference ref="248469711"/>
3.1759 + <reference ref="9"/>
3.1760 + <reference ref="248469711"/>
3.1761 + <reference ref="9"/>
3.1762 + <string>{{97, 651}, {250, 183}}</string>
3.1763 + <reference ref="248469711"/>
3.1764 + <reference ref="9"/>
3.1765 + <reference ref="248469711"/>
3.1766 + <reference ref="9"/>
3.1767 + <reference ref="248469711"/>
3.1768 + <reference ref="9"/>
3.1769 + <reference ref="248469711"/>
3.1770 + <reference ref="9"/>
3.1771 + <reference ref="248469711"/>
3.1772 + <reference ref="9"/>
3.1773 + <reference ref="248469711"/>
3.1774 + <reference ref="9"/>
3.1775 + <reference ref="248469711"/>
3.1776 + <reference ref="9"/>
3.1777 + <reference ref="248469711"/>
3.1778 + <reference ref="9"/>
3.1779 + <reference ref="248469711"/>
3.1780 + <reference ref="9"/>
3.1781 + <reference ref="248469711"/>
3.1782 + <reference ref="9"/>
3.1783 + <string>{{233, 633}, {199, 203}}</string>
3.1784 + <reference ref="248469711"/>
3.1785 + <reference ref="9"/>
3.1786 + <reference ref="248469711"/>
3.1787 + <reference ref="9"/>
3.1788 + <reference ref="248469711"/>
3.1789 + <reference ref="9"/>
3.1790 + </object>
3.1791 + </object>
3.1792 + <object class="NSMutableDictionary" key="unlocalizedProperties">
3.1793 + <bool key="EncodedWithXMLCoder">YES</bool>
3.1794 + <object class="NSArray" key="dict.sortedKeys">
3.1795 + <bool key="EncodedWithXMLCoder">YES</bool>
3.1796 + </object>
3.1797 + <object class="NSMutableArray" key="dict.values">
3.1798 + <bool key="EncodedWithXMLCoder">YES</bool>
3.1799 + </object>
3.1800 + </object>
3.1801 + <nil key="activeLocalization"/>
3.1802 + <object class="NSMutableDictionary" key="localizations">
3.1803 + <bool key="EncodedWithXMLCoder">YES</bool>
3.1804 + <object class="NSArray" key="dict.sortedKeys">
3.1805 + <bool key="EncodedWithXMLCoder">YES</bool>
3.1806 + </object>
3.1807 + <object class="NSMutableArray" key="dict.values">
3.1808 + <bool key="EncodedWithXMLCoder">YES</bool>
3.1809 + </object>
3.1810 + </object>
3.1811 + <nil key="sourceID"/>
3.1812 + <int key="maxID">400</int>
3.1813 + </object>
3.1814 + <object class="IBClassDescriber" key="IBDocument.Classes">
3.1815 + <object class="NSMutableArray" key="referencedPartialClassDescriptions">
3.1816 + <bool key="EncodedWithXMLCoder">YES</bool>
3.1817 + <object class="IBPartialClassDescription">
3.1818 + <string key="className">BoardView</string>
3.1819 + <string key="superclassName">NSView</string>
3.1820 + <object class="NSMutableDictionary" key="actions">
3.1821 + <string key="NS.key.0">enterFullScreen:</string>
3.1822 + <string key="NS.object.0" id="765642758">id</string>
3.1823 + </object>
3.1824 + <object class="NSMutableDictionary" key="outlets">
3.1825 + <bool key="EncodedWithXMLCoder">YES</bool>
3.1826 + <object class="NSArray" key="dict.sortedKeys">
3.1827 + <bool key="EncodedWithXMLCoder">YES</bool>
3.1828 + </object>
3.1829 + <object class="NSMutableArray" key="dict.values">
3.1830 + <bool key="EncodedWithXMLCoder">YES</bool>
3.1831 + </object>
3.1832 + </object>
3.1833 + <object class="IBClassDescriptionSource" key="sourceIdentifier">
3.1834 + <string key="majorKey" id="755626269">IBProjectSource</string>
3.1835 + <string key="minorKey">Source/BoardView.h</string>
3.1836 + </object>
3.1837 + </object>
3.1838 + <object class="IBPartialClassDescription">
3.1839 + <string key="className">DemoBoardView</string>
3.1840 + <string key="superclassName">BoardView</string>
3.1841 + <object class="NSMutableDictionary" key="actions">
3.1842 + <string key="NS.key.0">startGameFromMenu:</string>
3.1843 + <reference key="NS.object.0" ref="765642758"/>
3.1844 + </object>
3.1845 + <object class="NSMutableDictionary" key="outlets">
3.1846 + <bool key="EncodedWithXMLCoder">YES</bool>
3.1847 + <object class="NSArray" key="dict.sortedKeys">
3.1848 + <bool key="EncodedWithXMLCoder">YES</bool>
3.1849 + </object>
3.1850 + <object class="NSMutableArray" key="dict.values">
3.1851 + <bool key="EncodedWithXMLCoder">YES</bool>
3.1852 + </object>
3.1853 + </object>
3.1854 + <object class="IBClassDescriptionSource" key="sourceIdentifier">
3.1855 + <reference key="majorKey" ref="755626269"/>
3.1856 + <string key="minorKey">Source/DemoBoardView.h</string>
3.1857 + </object>
3.1858 + </object>
3.1859 + </object>
3.1860 + </object>
3.1861 + <int key="IBDocument.localizationMode">0</int>
3.1862 + <string key="IBDocument.LastKnownRelativeProjectPath">../../GeekGameBoard.xcodeproj</string>
3.1863 + <int key="IBDocument.defaultPropertyAccessControl">3</int>
3.1864 + <object class="NSMutableData" key="IBDocument.RunnableNib">
3.1865 + <bytes key="NS.bytes">YnBsaXN0MDDUAAEAAgADAAQABQAGAAkAClgkdmVyc2lvblQkdG9wWSRhcmNoaXZlclgkb2JqZWN0cxIA
3.1866 +AYag0QAHAAhdSUIub2JqZWN0ZGF0YYABXxAPTlNLZXllZEFyY2hpdmVyrxEByQALAAwAMQA1ADYAPAA9
3.1867 +AEIAWABZAFoAWwALAGgAbAB2AHcAeAB9AHYACwCBAIMAhACFAIgAjACzALsAzADRANIA0wDYANkA2gDd
3.1868 +AOEA4gDlAOYA6gDuAPYA/AD9AP4BAgEJAQ0BDgEPARMBGgEeAR8BIAEkASwBMAExATIBMwE4ATkBPAFA
3.1869 +AUcBSAFJAUoBTgFVAVkBWgFbAV8BZgFnAWgBbAF0AXkBegF7AXwBgAGHAYgBiQGKAY4BlQGWAZcBmAGd
3.1870 +AaUBpgGnAawBtAG1AbYBugHBAcIBwwHIAc8B0AHRAdUB3AHhAeIB4wHnAe4B7wHwAfEB9QH8Af0B/gH/
3.1871 +AgMCCgILAgwCDQIRAhoCGwIcAh0CIQIoAikCKgIuAjUCNgI3AjgCPAJDAkQCRQJGAkoCUQJSAlMCWAJZ
3.1872 +Al0CZAJlAmYCZwJsAnMCdAJ1AnoCgQKCAoMChAKJApECkgKTApcCngKfAqACoQKlAqwCrQKuAq8CswK6
3.1873 +ArsCvAK9AsECyALJAsoCywLPAtYC1wLYAtwC4wLkAuUC5gMwAzEDOANDA0QDRgNRA1YDVwNlA24DdQN2
3.1874 +A3cDgAOJA1YDigOPA5IDkwOcA6UDpgOqA6sDrgO3A7gDxQPOA9cD4ANWA+ED5gPvA1YD+ANWBAEECgQT
3.1875 +A1YEFAQdBB4EKAQxA1YEMgRABEkDVgRKBE4ETwRYA1YEWQRgBGkDVgRyBHMEdgR4BMIFDQVYBVkFWgVb
3.1876 +BVwFXQVeBV8FYAVhBWIFYwVkBWUFZgVnBWgFaQVqBWsFbAVtBW4FbwVwBXEFcgVzBXQFdQV2BXcFeAV5
3.1877 +BXoFewV8BX0FfgV/BYAFgQWCBYMFhAWFBYYFhwWIBYkFigWLBYwFjQWOBY8FkAWRBZIFkwWUBZUFlgWX
3.1878 +BZgFmQWaBZsFnAWfBaIGEQaABoEGggaDBoQGhQaGBocGiAaJBooGiwaMBo0GjgaPBpAGkQaSBpMGlAaV
3.1879 +BpYGlwaYBpkGmgabBpwGnQaeBp8GoAahBqIGowakBqUGpganBqgGqQaqBqsGrAatBq4GrwawBrEGsgaz
3.1880 +BrQGtQa2BrcGuAa5BroGuwa8Br0Gvga/BsAGwQbCBsMGxAbFBsYGxwbIBskGygbLBswGzQbOBs8G0AbR
3.1881 +BtIG0wbUBtUG1gbXBtgG2QbaBtsG3AbdBt4G3wbgBuEG4gbjBuQG5QbmBucG6AbpBuoG6wbsBu8G8gb1
3.1882 +VSRudWxs3xASAA0ADgAPABAAEQASABMAFAAVABYAFwAYABkAGgAbABwAHQAeAB8AIAAhACIAIwAkACUA
3.1883 +JgAnACgAKQAqACsALAAtAC4ALwAwVk5TUm9vdFYkY2xhc3NdTlNPYmplY3RzS2V5c18QD05TQ2xhc3Nl
3.1884 +c1ZhbHVlc18QGU5TQWNjZXNzaWJpbGl0eU9pZHNWYWx1ZXNdTlNDb25uZWN0aW9uc1tOU05hbWVzS2V5
3.1885 +c1tOU0ZyYW1ld29ya11OU0NsYXNzZXNLZXlzWk5TT2lkc0tleXNdTlNOYW1lc1ZhbHVlc18QGU5TQWNj
3.1886 +ZXNzaWJpbGl0eUNvbm5lY3RvcnNdTlNGb250TWFuYWdlcl8QEE5TVmlzaWJsZVdpbmRvd3NfEA9OU09i
3.1887 +amVjdHNWYWx1ZXNfEBdOU0FjY2Vzc2liaWxpdHlPaWRzS2V5c1lOU05leHRPaWRcTlNPaWRzVmFsdWVz
3.1888 +gAKBAciAy4EBVoEBx4AagQEPgAWBAVWBAVeBARCBAcWAAIAGgQEOgQHGEQGSgQFY0gAOADIAMwA0W05T
3.1889 +Q2xhc3NOYW1lgASAA11OU0FwcGxpY2F0aW9u0gA3ADgAOQA6WCRjbGFzc2VzWiRjbGFzc25hbWWiADoA
3.1890 +O15OU0N1c3RvbU9iamVjdFhOU09iamVjdF8QEElCQ29jb2FGcmFtZXdvcmvSAA4APgA/AEBaTlMub2Jq
3.1891 +ZWN0c4AZoQBBgAfbAEMADgBEAEUARgBHAEgASQBKAEsATABNAE4ATwBQAFEAUgBTAFQAVQBWACtcTlNX
3.1892 +aW5kb3dWaWV3XE5TU2NyZWVuUmVjdF8QE05TRnJhbWVBdXRvc2F2ZU5hbWVdTlNXaW5kb3dUaXRsZVlO
3.1893 +U1dURmxhZ3NdTlNXaW5kb3dDbGFzc1xOU1dpbmRvd1JlY3RfEA9OU1dpbmRvd0JhY2tpbmdfEBFOU1dp
3.1894 +bmRvd1N0eWxlTWFza1tOU1ZpZXdDbGFzc4ALgBiAFoAXgAkSdAAAAIAKgAgQAhAHgABfEBh7ezU3LCAx
3.1895 +NzV9LCB7MTA4NCwgNTg3fX1dR2Vla0dhbWVCb2FyZFhOU1dpbmRvd9cAXAAOAF0AXgBfAFoAYABhAGIA
3.1896 +YwBkAGUAYQBnXxAPTlNOZXh0UmVzcG9uZGVyWk5TU3Vidmlld3NYTlN2RmxhZ3NbTlNGcmFtZVNpemVb
3.1897 +TlNTdXBlcnZpZXeADIAVgA0RAQCAE4AMgBTSAA4APgBpAGqAEqEAa4AO2ABcAA4AXgBfAFoAMgBgAG0A
3.1898 +TQBvAHAAcQBhAHMATQB1XxAVTlNWaWV3SXNMYXllclRyZWVIb3N0gAuAEREBEoAPgAyAEIALCVt7MTA4
3.1899 +NCwgNTg3fV1EZW1vQm9hcmRWaWV30gA3ADgAeQB6pAB6AHsAfAA7XE5TQ3VzdG9tVmlld1ZOU1ZpZXdb
3.1900 +TlNSZXNwb25kZXLSADcAOAB+AH+jAH8AgAA7Xk5TTXV0YWJsZUFycmF5V05TQXJyYXnSADcAOACCAHuj
3.1901 +AHsAfAA7XxAVe3swLCAwfSwgezE0NDAsIDg3OH19UNIANwA4AIYAh6IAhwA7XxAQTlNXaW5kb3dUZW1w
3.1902 +bGF0ZdIANwA4AIkAiqMAigCLADtcTlNNdXRhYmxlU2V0VU5TU2V00gAOAD4AaQCOgBKvECQAjwCQAJEA
3.1903 +kgCTAJQAlQCWAJcAmACZAJoAmwCcAJ0AngCfAKAAoQCiAKMApAClAKYApwCoAKkAqgCrAKwArQCuAK8A
3.1904 +sACxALKAG4ApgC6AM4A4gD6AQYBGgEuAT4BVgFqAX4BjgGeAa4BvgHSAeYB+gIOAiICMgJGAloCagJyA
3.1905 +oYClgKqAroCzgLiAvYDCgMbUAA4AtAC1ALYAtwBrALkAul1OU0Rlc3RpbmF0aW9uWE5TU291cmNlV05T
3.1906 +TGFiZWyAKIAOgByAJ9kADgC8AL0AvgC/AMAAwQDCAMMAxADFAMYAxwDIAMkAygDLAFVXTlNUaXRsZV8Q
3.1907 +EU5TS2V5RXF1aXZNb2RNYXNrWk5TS2V5RXF1aXZdTlNNbmVtb25pY0xvY1lOU09uSW1hZ2VcTlNNaXhl
3.1908 +ZEltYWdlVk5TTWVudVVOU1RhZ4AmgB4SABABCIAfEn////+AIIAkgB3TAA4AvADNAM4AzwDQW05TTWVu
3.1909 +dUl0ZW1zgNCA9oD4WkhleGNoZXF1ZXJRNNMADgAyANQA1QDWANdeTlNSZXNvdXJjZU5hbWWAI4AhgCJX
3.1910 +TlNJbWFnZV8QD05TTWVudUNoZWNrbWFya9IANwA4ANsA3KIA3AA7XxAQTlNDdXN0b21SZXNvdXJjZdMA
3.1911 +DgAyANQA1QDWAOCAI4AhgCVfEBBOU01lbnVNaXhlZFN0YXRl0gA3ADgA4wDkogDkADtaTlNNZW51SXRl
3.1912 +bV8QEnN0YXJ0R2FtZUZyb21NZW51OtIANwA4AOcA6KMA6ADpADtfEBVOU05pYkNvbnRyb2xDb25uZWN0
3.1913 +b3JeTlNOaWJDb25uZWN0b3LTAA4AtQC2ALcA7ADtgCiAKoAt2AAOALwAvQC+AL8AwADBAMIAxADwAPEA
3.1914 +UADIAMkAygD1gCaALBIAEAAAgBeAIIAkgCvUAA4AvAD3AM0AzgD5APoA+1ZOU05hbWWA0IDMgM+AzV8Q
3.1915 +EkJyaW5nIEFsbCB0byBGcm9udF8QD2FycmFuZ2VJbkZyb250OtMADgC1ALYAtwEAAQGAKIAvgDLYAA4A
3.1916 +vAC9AL4AvwDAAMEAwgDEAQQA8QBQAMgAyQDKAQiAJoAxgBeAIIAkgDDTAA4AvADNAM4BCwEMgNCA7IDu
3.1917 +XlN0YXJ0IFNwZWFraW5nXnN0YXJ0U3BlYWtpbmc60wAOALUAtgC3AREBEoAogDSAN9cADgC8AL4AvwDA
3.1918 +AMEAwgDEARUAUADIAMkAygEZgCaANoAXgCCAJIA10wAOALwAzQDOARwBHYDQgPyA/l8QD1JldmVydCB0
3.1919 +byBTYXZlZF8QFnJldmVydERvY3VtZW50VG9TYXZlZDrTAA4AtQC2ALcBIgEjgCiAOYA92AAOALwAvQC+
3.1920 +AL8AwADBAMIAxAEmAScBKADIAMkAygErgCaAOxIAEgAAgDyAIIAkgDrTAA4AvADNAM4BLgEvgNCA54Do
3.1921 +VFJlZG9RWlVyZWRvOtQADgC0ALUAtgE0AGsAHwE3gECADoACgD9YZGVsZWdhdGXSADcAOAE6ATujATsA
3.1922 +6QA7XxAUTlNOaWJPdXRsZXRDb25uZWN0b3LTAA4AtQC2ALcBPgE/gCiAQoBF2AAOALwAvQC+AL8AwADB
3.1923 +AMIAxAFCAPEBQwDIAMkAygEZgCaAQ4BEgCCAJIA1U05ld1FuXG5ld0RvY3VtZW50OtMADgC1ALYAtwFM
3.1924 +AU2AKIBHgErYAA4AvAC9AL4AvwDAAMEAwgDEAVAA8QBQAMgAyQDKAVSAJoBJgBeAIIAkgEjTAA4AvADN
3.1925 +AM4BVwFYgNCBAQWBAQdvEBIAQwB1AHMAdABvAG0AaQB6AGUAIABUAG8AbwBsAGIAYQByICZfEB9ydW5U
3.1926 +b29sYmFyQ3VzdG9taXphdGlvblBhbGV0dGU60wAOALUAtgC3AV0BXoAogEyATtgADgC8AL0AvgC/AMAA
3.1927 +wQDCAMQBYQDxAFAAyADJAMoBK4AmgE2AF4AggCSAOlZEZWxldGVXZGVsZXRlOtMADgC1ALYAtwFqAWuA
3.1928 +KIBQgFTYAA4AvAC9AL4AvwDAAMEAwgDEAW4BbwFwAMgAyQDKAXOAJoBSEgAYAACAU4AggCSAUdQADgC8
3.1929 +APcAzQDOAFEBdwF4gNCACYDigNRbSGlkZSBPdGhlcnNRaF8QFmhpZGVPdGhlckFwcGxpY2F0aW9uczrT
3.1930 +AA4AtQC2ALcBfgF/gCiAVoBZ2AAOALwAvQC+AL8AwADBAMIAxAGCAPEBgwDIAMkAygEZgCaAV4BYgCCA
3.1931 +JIA1ZgBQAHIAaQBuAHQgJlFwVnByaW50OtMADgC1ALYAtwGMAY2AKIBbgF7YAA4AvAC9AL4AvwDAAMEA
3.1932 +wgDEAZAA8QGRAMgAyQDKARmAJoBcgF2AIIAkgDVlAE8AcABlAG4gJlFvXW9wZW5Eb2N1bWVudDrUAA4A
3.1933 +tAC1ALYAtwBrAZsAuoAogA6AYIAn2QAOALwAvQC+AL8AwADBAMIAwwDEAZ8AxgGgAMgAyQDKAMsBpIAm
3.1934 +gGGAYoAggCSAHRAEUkdvUTPUAA4AtAC1ALYAtwBrAaoAuoAogA6AZIAn2QAOALwAvQC+AL8AwADBAMIA
3.1935 +wwDEAa4AxgGvAMgAyQDKAMsBs4AmgGWAZoAggCSAHRADW1RpYy1UYWMtVG9lUTXTAA4AtQC2ALcBuAG5
3.1936 +gCiAaIBq2AAOALwAvQC+AL8AwADBAMIAxAG8APEAUADIAMkAygD1gCaAaYAXgCCAJIArVFpvb21ccGVy
3.1937 +Zm9ybVpvb2061AAOALQAtQC2ALcAawHGALqAKIAOgGyAJ9gADgC8AL0AvgC/AMAAwQDCAMQBygDGAcsA
3.1938 +yADJAMoAy4AmgG2AboAggCSAHV8QFEtsb25kaWtlIChTb2xpdGFpcmUpUTHTAA4AtQC2ALcB0wHUgCiA
3.1939 +cIBz2AAOALwAvQC+AL8AwADBAMIAxAHXAPEAUADIAMkAygHbgCaAcoAXgCCAJIBx1AAOALwA9wDNAM4B
3.1940 +3gHfAeCA0IEBAIEBA4EBAlpDbGVhciBNZW51XxAVY2xlYXJSZWNlbnREb2N1bWVudHM60wAOALUAtgC3
3.1941 +AeUB5oAogHWAeNgADgC8AL0AvgC/AMAAwQDCAMQB6QDxAeoAyADJAMoA9YAmgHaAd4AggCSAK1hNaW5p
3.1942 +bWl6ZVFtXxATcGVyZm9ybU1pbmlhdHVyaXplOtMADgC1ALYAtwHzAfSAKIB6gH3YAA4AvAC9AL4AvwDA
3.1943 +AMEAwgDEAfcA8QH4AMgAyQDKARmAJoB7gHyAIIAkgDVUU2F2ZVFzXXNhdmVEb2N1bWVudDrTAA4AtQC2
3.1944 +ALcCAQICgCiAf4CC2AAOALwAvQC+AL8AwADBAMIAxAIFAPECBgDIAMkAygErgCaAgICBgCCAJIA6VVBh
3.1945 +c3RlUXZWcGFzdGU60wAOALUAtgC3Ag8CEIAogISAh9kADgISALwAvQC+AL8AwADBAMIAxABQAhUBJwIW
3.1946 +AMgAyQDKARlZTlNUb29sVGlwgCaAF4CFgIaAIIAkgDVdUGFnZSBTZXR1cC4uLlFQXnJ1blBhZ2VMYXlv
3.1947 +dXQ60wAOALUAtgC3Ah8CIIAogImAi9gADgC8AL0AvgC/AMAAwQDCAMQCIwDxAFAAyADJAMoBCIAmgIqA
3.1948 +F4AggCSAMF1TdG9wIFNwZWFraW5nXXN0b3BTcGVha2luZzrTAA4AtQC2ALcCLAItgCiAjYCQ2AAOALwA
3.1949 +vQC+AL8AwADBAMIAxAIwAPECMQDIAMkAygErgCaAjoCPgCCAJIA6WlNlbGVjdCBBbGxRYVpzZWxlY3RB
3.1950 +bGw60wAOALUAtgC3AjoCO4AogJKAldgADgC8AL0AvgC/AMAAwQDCAMQCPgDxAj8AyADJAMoBK4AmgJOA
3.1951 +lIAggCSAOlRDb3B5UWNVY29weTrTAA4AtQC2ALcCSAJJgCiAl4CZ2AAOALwAvQC+AL8AwADBAMIAxAJM
3.1952 +APEBcADIAMkAygFzgCaAmIBTgCCAJIBRXxASSGlkZSBHZWVrR2FtZUJvYXJkVWhpZGU61AAOALQAtQC2
3.1953 +ATQAawBBAleAQIAOgAeAm18QFWluaXRpYWxGaXJzdFJlc3BvbmRlctMADgC1ALYAtwJbAlyAKICdgKDY
3.1954 +AA4AvAC9AL4AvwDAAMEAwgDEAl8A8QJgAMgAyQDKARmAJoCegJ+AIIAkgDVVQ2xvc2VRd11wZXJmb3Jt
3.1955 +Q2xvc2U61AAOALQAtQC2ALcAHwJqAmuAKIACgKKApNcADgC8AL4AvwDAAMEAwgDEAm4AUADIAMkAygFz
3.1956 +gCaAo4AXgCCAJIBRXxATQWJvdXQgR2Vla0dhbWVCb2FyZF8QHW9yZGVyRnJvbnRTdGFuZGFyZEFib3V0
3.1957 +UGFuZWw61AAOALQAtQC2ALcAawJ4AnmAKIAOgKaAqdgADgC8AL0AvgC/AMAAwQDCAMQCfADxAn0AyADJ
3.1958 +AMoBVIAmgKeAqIAggCSASFtGdWxsIFNjcmVlblFmXxAQZW50ZXJGdWxsU2NyZWVuOtQADgC0ALUAtgC3
3.1959 +AGsChwC6gCiADoCrgCfZAA4AvAC9AL4AvwDAAMEAwgDDAMQCiwDGAowAyADJAMoAywKQgCaArICtgCCA
3.1960 +JIAdEAFYQ2hlY2tlcnNRMtMADgC1ALYAtwKVApaAKICvgLLYAA4AvAC9AL4AvwDAAMEAwgDEApkA8QKa
3.1961 +AMgAyQDKASuAJoCwgLGAIIAkgDpUVW5kb1F6VXVuZG860wAOALUAtgC3AqMCpIAogLSAt9gADgC8AL0A
3.1962 +vgC/AMAAwQDCAMQCpwDxAqgAyADJAMoBc4AmgLWAtoAggCSAUV8QElF1aXQgR2Vla0dhbWVCb2FyZFFx
3.1963 +WnRlcm1pbmF0ZTrTAA4AtQC2ALcCsQKygCiAuYC82AAOALwAvQC+AL8AwADBAMIAxAK1APECtgDIAMkA
3.1964 +ygErgCaAuoC7gCCAJIA6U0N1dFF4VGN1dDrTAA4AtQC2ALcCvwLAgCiAvoDB2AAOALwAvQC+AL8AwADB
3.1965 +AMIAxALDAW8CxADIAMkAygFUgCaAv4DAgCCAJIBIXFNob3cgVG9vbGJhclF0XxATdG9nZ2xlVG9vbGJh
3.1966 +clNob3duOtMADgC1ALYAtwLNAs6AKIDDgMXYAA4AvAC9AL4AvwDAAMEAwgDEAtEA8QBQAMgAyQDKAXOA
3.1967 +JoDEgBeAIIAkgFFYU2hvdyBBbGxfEBZ1bmhpZGVBbGxBcHBsaWNhdGlvbnM60wAOALUAtgC3AtoC24Ao
3.1968 +gMeAytgADgC8AL0AvgC/AMAAwQDCAMQC3gEnAt8AyADJAMoBGYAmgMiAyYAggCSANWgAUwBhAHYAZQAg
3.1969 +AEEAcyAmUVNfEA9zYXZlRG9jdW1lbnRBczrSAA4APgLnAuiBAQ2vEEcA9QE+AusC7AHlAu4CLAGMAvEC
3.1970 +8gKHASsBagHGAvcBcwKVAfMBIgEAAUwCowL/AdMBqgLaAg8COgK/AwYBfgMIAwkCeAMLAwwBXQMOAw8B
3.1971 +GQMRAxIDEwMUAxUAuQKxAs0ATQERAEEDHAJqAh8DHwJIAGsB2wEIAbgCAQMmAMsBmwMpAVQDKwDsAy0C
3.1972 +WwMvgCuAQoDOgNGAdYDjgI2AW4DmgNWAq4A6gFCAbIDvgFGAr4B6gDmAL4BHgLSA8IBwgGSAx4CEgJKA
3.1973 +voDrgFaA8oDdgKaA9ID1gEyA0oDZgDWA4YEBCYEBDIDWgPuAHIC5gMOAC4A0gAeA6YCigImBAQSAl4AO
3.1974 +gHGAMIBogH+A2oAdgGCA/4BIgQEIgCqA4ICdgOpWV2luZG930gAOAD4AaQMzgBKkAeUBuALrAOyAdYBo
3.1975 +gM6AKtoADgC8AL0DOQC+AzoAvwDAAMEAwgDEAFAA8QB1AFAAdQDIAMkAygD1XU5TSXNTZXBhcmF0b3Jc
3.1976 +TlNJc0Rpc2FibGVkgCaAFwmAFwmAIIAkgCteX05TV2luZG93c01lbnXSADcAOANFAMKiAMIAO9oADgNH
3.1977 +ALwAvQC+AL8AwADBAMIDSADEAXMAUQDxAFAAyADJAMoDDgNQWU5TU3VibWVudVhOU0FjdGlvboAmgFGA
3.1978 +CYAXgCCAJIDSgNPUAA4AvAD3AM0AzgNTA1QDVYDQgPmBAQuA+l5zdWJtZW51QWN0aW9uOtIADgA+AGkD
3.1979 +WYASqwJqAvIDFAMPAyYDLQJIAWoCzQMRAqOAooDVgNaA2YDagOCAl4BQgMOA4YC02gAOALwAvQM5AL4D
3.1980 +OgC/AMAAwQDCAMQAUADxAHUAUAB1AMgAyQDKAXOAJoAXCYAXCYAggCSAUdgADgC8AL0AvgC/AMAAwQDC
3.1981 +AMQDcADxA3EAyADJAMoBc4AmgNeA2IAggCSAUWwAUAByAGUAZgBlAHIAZQBuAGMAZQBzICZRLNoADgC8
3.1982 +AL0DOQC+AzoAvwDAAMEAwgDEAFAA8QB1AFAAdQDIAMkAygFzgCaAFwmAFwmAIIAkgFHaAA4DRwC8AL0A
3.1983 +vgC/AMAAwQDCA0gAxAMJA4MA8QBQAMgAyQDKAXMDiIAmgN2A24AXgCCAJIBRgNxYU2VydmljZXPUAA4A
3.1984 +vAD3AM0AzgODA40DjoDQgNuA34De0gAOAD4AaQORgBKgXxAPX05TU2VydmljZXNNZW512gAOALwAvQM5
3.1985 +AL4DOgC/AMAAwQDCAMQAUADxAHUAUAB1AMgAyQDKAXOAJoAXCYAXCYAggCSAUdoADgC8AL0DOQC+AzoA
3.1986 +vwDAAMEAwgDEAFAA8QB1AFAAdQDIAMkAygFzgCaAFwmAFwmAIIAkgFFcX05TQXBwbGVNZW510wAOALwA
3.1987 +zQDOA6gDqYDQgOSA5VRIZWxw0gAOAD4AaQOtgBKg2gAOALwAvQM5AL4DOgC/AMAAwQDCAMQAUADxAHUA
3.1988 +UAB1AMgAyQDKARmAJoAXCYAXCYAggCSANVRFZGl00gAOAD4AaQO6gBKqApUBIgMcArECOgIBAV0CLAMv
3.1989 +AwaAr4A5gOmAuYCSgH+ATICNgOqA69oADgC8AL0DOQC+AzoAvwDAAMEAwgDEAFAA8QB1AFAAdQDIAMkA
3.1990 +ygErgCaAFwmAFwmAIIAkgDraAA4AvAC9AzkAvgM6AL8AwADBAMIAxABQAPEAdQBQAHUAyADJAMoBK4Am
3.1991 +gBcJgBcJgCCAJIA62gAOA0cAvAC9AL4AvwDAAMEAwgNIAMQBCAELAPEAUADIAMkAygErA9+AJoAwgOyA
3.1992 +F4AggCSAOoDtVlNwZWVjaNIADgA+AGkD44ASogEAAh+AL4CJ2gAOALwAvQM5AL4DOgC/AMAAwQDCAMQA
3.1993 +UADxAHUAUAB1AMgAyQDKAMuAJoAXCYAXCYAggCSAHdoADgNHALwAvQC+AL8AwADBAMIDSADEAu4DqADx
3.1994 +AFAAyADJAMoDDgP3gCaA44DkgBeAIIAkgNKA8doADgNHALwAvQC+AL8AwADBAMIDSADEASsBLgDxAFAA
3.1995 +yADJAMoDDgQAgCaAOoDngBeAIIAkgNKA89oADgC8AL0DOQC+AzoAvwDAAMEAwgDEAFAA8QB1AFAAdQDI
3.1996 +AMkAygEZgCaAFwmAFwmAIIAkgDXaAA4DRwC8AL0AvgC/AMAAwQDCA0gAxADLAM8A8QBQAMgAyQDKAw4E
3.1997 +EoAmgB2A9oAXgCCAJIDSgPdUR2FtZdIADgA+AGkEFoASpgHGAvcChwGbALkBqoBsgO+Aq4BggByAZFlB
3.1998 +TWFpbk1lbnXSAA4APgBpBCCAEqcC7AMVAwgDDAMfAxIC/4DRgPuA8oD1gQEEgQEJgPDaAA4DRwC8AL0A
3.1999 +vgC/AMAAwQDCA0gAxAEZARwA8QBQAMgAyQDKAw4EMIAmgDWA/IAXgCCAJIDSgP1URmlsZdIADgA+AGkE
3.2000 +NIASqwE+AYwDKQLxAlsB8wLaAREDCwIPAX6AQoBbgP+A5oCdgHqAx4A0gPSAhIBW2gAOA0cAvAC9AL4A
3.2001 +vwDAAMEAwgNIAMQB2wHeAPEAUADIAMkAygEZBEiAJoBxgQEAgBeAIIAkgDWBAQFbT3BlbiBSZWNlbnTS
3.2002 +AA4APgBpBEyAEqEB04BwXxAWX05TUmVjZW50RG9jdW1lbnRzTWVuddoADgNHALwAvQC+AL8AwADBAMID
3.2003 +SADEAVQBVwDxAFAAyADJAMoDDgRXgCaASIEBBYAXgCCAJIDSgQEGVFZpZXfSAA4APgBpBFuAEqQCeAMr
3.2004 +Ar8BTICmgQEIgL6AR9oADgC8AL0DOQC+AzoAvwDAAMEAwgDEAFAA8QB1AFAAdQDIAMkAygFUgCaAFwmA
3.2005 +FwmAIIAkgEjaAA4DRwC8AL0AvgC/AMAAwQDCA0gAxAD1APkA8QBQAMgAyQDKAw4EcYAmgCuAzIAXgCCA
3.2006 +JIDSgQEKW19OU01haW5NZW510gAOADIAMwA0gASAA9IANwA4BHcAgKIAgAA70gAOAD4C5wR6gQENrxBH
3.2007 +AxIBGQD1Aw4A9QL/ASsBGQEZAXMAywMIAXMAywDLAuwBKwEZASsBCAFUAXMDDgHbAMsBGQEZASsBVAEr
3.2008 +ARkDDgMmAVQBGQMOASsAHwFzAxUBcwMOAB8BcwMOAMsBKwFzAEEBGQAfASsBcwEIAw4BcwBNAykDBgD1
3.2009 +ASsBcwMMAMsBGQMfAVQA9QFzARkBK4EBCYA1gCuA0oArgPCAOoA1gDWAUYAdgPKAUYAdgB2A0YA6gDWA
3.2010 +OoAwgEiAUYDSgHGAHYA1gDWAOoBIgDqANYDSgNqASIA1gNKAOoACgFGA+4BRgNKAAoBRgNKAHYA6gFGA
3.2011 +B4A1gAKAOoBRgDCA0oBRgAuA/4DrgCuAOoBRgPWAHYA1gQEEgEiAK4BRgDWAOtIADgA+AucExIEBDa8Q
3.2012 +SAD1AT4C7ALrAeUC7gIsAYwC8QLyAocBKwFqAcYC9wFzApUB8wEiAaoBTAL/AqMBAAHTAtoCDwI6Ar8D
3.2013 +BgF+AwgDCQJ4AB8DCwMMAV0DDgEZAw8DEQMSAxMDFQMUALkCsQLNAE0BEQBBAGsDHwJqAxwCSAIfAdsB
3.2014 +CAG4AMsDJgIBAZsDKQFUAysDLQDsAlsDL4ArgEKA0YDOgHWA44CNgFuA5oDVgKuAOoBQgGyA74BRgK+A
3.2015 +eoA5gGSAR4DwgLSAL4BwgMeAhICSgL6A64BWgPKA3YCmgAKA9ID1gEyA0oA1gNmA4YEBCYEBDID7gNaA
3.2016 +HIC5gMOAC4A0gAeADoEBBICigOmAl4CJgHGAMIBogB2A2oB/gGCA/4BIgQEIgOCAKoCdgOrSAA4APgLn
3.2017 +BQ+BAQ2vEEgFEAURBRIFEwUUAowFFgUXBRgFGQUaBRsFHAUdBR4FHwUgAaAFIgUjBSQBywUmBScFKAUp
3.2018 +Aa8FKwUsBS0FLgUvBTAFMQUyBTMFNAU1BTYFNwU4BTkFOgU7BTwFPQU+BT8FQAVBBUIFQwVEBUUFRgVH
3.2019 +BUgFSQVKBUsFTAVNBU4FTwVQBVEFUgVTBVQFVQVWBVeBARGBARKBAROBARSBARWArYEBFoEBF4EBGIEB
3.2020 +GYEBGoEBG4EBHIEBHYEBHoEBH4EBIIBigQEhgQEigQEjgG6BASSBASWBASaBASeAZoEBKIEBKYEBKoEB
3.2021 +K4EBLIEBLYEBLoEBL4EBMIEBMYEBMoEBM4EBNIEBNYEBNoEBN4EBOIEBOYEBOoEBO4EBPIEBPYEBPoEB
3.2022 +P4EBQIEBQYEBQoEBQ4EBRIEBRYEBRoEBR4EBSIEBSYEBSoEBS4EBTIEBTYEBToEBT4EBUIEBUYEBUoEB
3.2023 +U4EBVF1NZW51IChXaW5kb3cpUTlfEBlNZW51IEl0ZW0gKEdlZWtHYW1lQm9hcmQpW1NlcGFyYXRvci03
3.2024 +XxAUTWVudSBJdGVtIChNaW5pbWl6ZSlfEBZNZW51IEl0ZW0gKFNlbGVjdCBBbGwpbxARAE0AZQBuAHUA
3.2025 +IABJAHQAZQBtACAAKABPAHAAZQBuICYAKVE3WVNlcGFyYXRvcl8QFE1lbnUgSXRlbSAoQ2hlY2tlcnMp
3.2026 +W01lbnUgKEVkaXQpXxAXTWVudSBJdGVtIChIaWRlIE90aGVycylfECBNZW51IEl0ZW0gKEtsb25kaWtl
3.2027 +IChTb2xpdGFpcmUpKVtTZXBhcmF0b3ItNl8QFE1lbnUgKEdlZWtHYW1lQm9hcmQpXxAQTWVudSBJdGVt
3.2028 +IChVbmRvKV8QEE1lbnUgSXRlbSAoUmVkbylfEBdNZW51IEl0ZW0gKFRpYy1UYWMtVG9lKW8QHgBNAGUA
3.2029 +bgB1ACAASQB0AGUAbQAgACgAQwB1AHMAdABvAG0AaQB6AGUAIABUAG8AbwBsAGIAYQByICYAKVQxMTEx
3.2030 +XxAaTWVudSBJdGVtIChTdGFydCBTcGVha2luZylfEBZNZW51IEl0ZW0gKENsZWFyIE1lbnUpUThfEBBN
3.2031 +ZW51IEl0ZW0gKENvcHkpXxAYTWVudSBJdGVtIChTaG93IFRvb2xiYXIpXxASTWVudSBJdGVtIChTcGVl
3.2032 +Y2gpUTZfEBBNZW51IEl0ZW0gKEVkaXQpXxAPTWVudSAoU2VydmljZXMpXxAXTWVudSBJdGVtIChGdWxs
3.2033 +IFNjcmVlbilcRmlsZSdzIE93bmVyUzItMV8QEE1lbnUgSXRlbSAoR2FtZSlfEBJNZW51IEl0ZW0gKERl
3.2034 +bGV0ZSlYTWFpbk1lbnVbTWVudSAoRmlsZSlbU2VwYXJhdG9yLTFbU2VwYXJhdG9yLTJfEBJNZW51IEl0
3.2035 +ZW0gKFdpbmRvdylbQXBwbGljYXRpb25fEBBNZW51IEl0ZW0gKEZpbGUpUzEyMV8QFk1lbnUgSXRlbSAo
3.2036 +SGV4Y2hlcXVlcilfEA9NZW51IEl0ZW0gKEN1dClfEBRNZW51IEl0ZW0gKFNob3cgQWxsKVxDb250ZW50
3.2037 +IFZpZXdSMTBfEBZXaW5kb3cgKEdlZWtHYW1lQm9hcmQpXxAPRGVtbyBCb2FyZCBWaWV3XxAQTWVudSBJ
3.2038 +dGVtIChWaWV3KV8QH01lbnUgSXRlbSAoQWJvdXQgR2Vla0dhbWVCb2FyZClbU2VwYXJhdG9yLTRfEB5N
3.2039 +ZW51IEl0ZW0gKEhpZGUgR2Vla0dhbWVCb2FyZClfEBlNZW51IEl0ZW0gKFN0b3AgU3BlYWtpbmcpXxAS
3.2040 +TWVudSAoT3BlbiBSZWNlbnQpXU1lbnUgKFNwZWVjaClfEBBNZW51IEl0ZW0gKFpvb20pW01lbnUgKEdh
3.2041 +bWUpXxAUTWVudSBJdGVtIChTZXJ2aWNlcylfEBFNZW51IEl0ZW0gKFBhc3RlKV5NZW51IEl0ZW0gKEdv
3.2042 +KV8QF01lbnUgSXRlbSAoT3BlbiBSZWNlbnQpW01lbnUgKFZpZXcpW1NlcGFyYXRvci04W1NlcGFyYXRv
3.2043 +ci0zXxAeTWVudSBJdGVtIChCcmluZyBBbGwgdG8gRnJvbnQpUzEtMVtTZXBhcmF0b3ItNdIADgA+AucF
3.2044 +noEBDaDSAA4APgLnBaGBAQ2g0gAOAD4C5wWkgQENrxBsAT4AlwLuAiwBjAHGAvcAsAKVAfMBAAChAUwC
3.2045 +owL/AKUC2gI6Ar8ApACsAX4AqAMJAJUArwMLAwwAsQFdAw4BGQCcAxIApgMTAJ0DFACqAJMAngCuAs0B
3.2046 +EQBBAxwDHwCaAkgArQIBAMsBmwMrAOwDLQMvAPUC6wLsAeUC8QLyAocBKwFqAJ8BcwEiAaoAogHTAg8D
3.2047 +BgCrAKkDCACQALIAowJ4AB8ApwCPAw8DEQMVALkAkgKxAJEATQCWAGsCHwJqAJkAoAHbAQgBuAMmAJgD
3.2048 +KQFUAJQAmwJbgEKAS4DjgI2AW4BsgO+AvYCvgHqAL4B5gEeAtIDwgIyAx4CSgL6AiICqgFaAmoDdgEGA
3.2049 +uID0gPWAwoBMgNKANYBjgQEJgJGBAQyAZ4DWgKGAOIBrgLOAw4A0gAeA6YEBBIBagJeAroB/gB2AYIEB
3.2050 +CIAqgOCA6oArgM6A0YB1gOaA1YCrgDqAUIBvgFGAOYBkgH6AcICEgOuApYCcgPKAKYDGgIOApoACgJaA
3.2051 +G4DZgOGA+4AcgDOAuYAugAuARoAOgImAooBVgHSAcYAwgGiA2oBPgP+ASIA+gF+AndIADgA+AucGE4EB
3.2052 +Da8QbAYUBhUGFgYXBhgGGQYaBhsGHAYdBh4GHwYgBiEGIgYjBiQGJQYmBicGKAYpBioGKwYsBi0GLgYv
3.2053 +BjAGMQYyBjMGNAY1BjYGNwY4BjkGOgY7BjwGPQY+Bj8GQAZBBkIGQwZEBkUGRgZHBkgGSQZKBksGTAZN
3.2054 +Bk4GTwZQBlEGUgZTBlQGVQZWBlcGWAZZBloGWwZcBl0GXgZfBmAGYQZiBmMGZAZlBmYGZwZoBmkGagZr
3.2055 +BmwGbQZuBm8GcAZxBnIGcwZ0BnUGdgZ3BngGeQZ6BnsGfAZ9Bn4Gf4EBWYEBWoEBW4EBXIEBXYEBXoEB
3.2056 +X4EBYIEBYYEBYoEBY4EBZIEBZYEBZoEBZ4EBaIEBaYEBaoEBa4EBbIEBbYEBboEBb4EBcIEBcYEBcoEB
3.2057 +c4EBdIEBdYEBdoEBd4EBeIEBeYEBeoEBe4EBfIEBfYEBfoEBf4EBgIEBgYEBgoEBg4EBhIEBhYEBhoEB
3.2058 +h4EBiIEBiYEBioEBi4EBjIEBjYEBjoEBj4EBkIEBkYEBkoEBk4EBlIEBlYEBloEBl4EBmIEBmYEBmoEB
3.2059 +m4EBnIEBnYEBnoEBn4EBoIEBoYEBooEBo4EBpIEBpYEBpoEBp4EBqIEBqYEBqoEBq4EBrIEBrYEBroEB
3.2060 +r4EBsIEBsYEBsoEBs4EBtIEBtYEBtoEBt4EBuIEBuYEBuoEBu4EBvIEBvYEBvoEBv4EBwIEBwYEBwoEB
3.2061 +w4EBxBBSEOsQahDGEEgRAX0RAYMRAW4QzxBLEMQRAWoRASoQiBBnEOgQUBDFEQEpEOMRAYUQThEBjxCC
3.2062 +EQF1EOQQShEBexEBchDKEB0QUREBhxATEOAT//////////0Q8BCBEI4Q5xEBhBEBcRCWEHARAXMQzhEB
3.2063 +JxEBdhCGEN8QyxEBfBEBiREBeRAFEJAQ1hAYEFwQOBAXEE8Q7BEBfhDNEJEQfxA5ENcRAYAQ4hB+EE0Q
3.2064 +0xEBehDBENkQJxEBaxBXEQF4EQGREQFvEQGGEI8QlRBTEQF/EQFsEMcQ6REBdBEBbREBdxDDEDoQVhAl
3.2065 +EH0Q1BDvEIMRAXAQfBEBKBEBkBEBihBJ0gAOAD4AaQbugBKg0gAOAD4C5wbxgQENoNIADgA+AucG9IEB
3.2066 +DaDSADcAOAb2BveiBvcAO15OU0lCT2JqZWN0RGF0YQAIABkAIgAnADEAOgA/AEQAUgBUAGYD/AQCBE0E
3.2067 +VARbBGkEewSXBKUEsQS9BMsE1gTkBQAFDgUhBTMFTQVXBWQFZgVpBWsFbgVxBXMFdgV4BXsFfgWBBYQF
3.2068 +hgWIBYsFjgWRBZQFnQWpBasFrQW7BcQFzQXYBd0F7AX1BggGEQYcBh4GIQYjBlAGXQZqBoAGjgaYBqYG
3.2069 +swbFBtkG5QbnBukG6wbtBu8G9Ab2BvgG+gb8Bv4HGQcnBzAHTQdfB2oHcwd/B4sHjQePB5EHlAeWB5gH
3.2070 +mgejB6UHqAeqB8sH4wflB+cH6gfsB+4H8AfyB/MH/wgNCBYIHwgsCDMIPwhICE8IXghmCG8IdgiOCI8I
3.2071 +mAidCLAIuQjACM0I0wjcCN4JKQkrCS0JLwkxCTMJNQk3CTkJOwk9CT8JQQlDCUUJRwlJCUsJTQlPCVEJ
3.2072 +UwlVCVcJWQlbCV0JXwlhCWMJZQlnCWkJawltCW8JcQmCCZAJmQmhCaMJpQmnCakJzgnWCeoJ9QoDCg0K
3.2073 +GgohCicKKQorCjAKMgo3CjkKOwo9CkoKVgpYCloKXApnCmkKdgqFCocKiQqLCpMKpQquCrMKxgrTCtUK
3.2074 +1wrZCuwK9Qr6CwULGgsjCyoLQgtRC14LYAtiC2QLhQuHC4kLjguQC5ILlAuWC6cLrguwC7ILtAu2C8sL
3.2075 +3QvqC+wL7gvwDBEMEwwVDBcMGQwbDB0MKgwsDC4MMAw/DE4MWwxdDF8MYQx+DIAMggyEDIYMiAyKDJcM
3.2076 +mQybDJ0MrwzIDNUM1wzZDNsM/Az+DQANBQ0HDQkNCw0NDRoNHA0eDSANJQ0nDS0NPg1ADUINRA1GDU8N
3.2077 +WA1fDXYNgw2FDYcNiQ2qDawNrg2wDbINtA22DboNvA3JDdYN2A3aDdwN/Q3/DgEOAw4FDgcOCQ4WDhgO
3.2078 +Gw4eDkUOZw50DnYOeA56DpsOnQ6fDqEOow6lDqcOrg62DsMOxQ7HDskO6g7sDu4O8w71DvcO+Q77DwwP
3.2079 +Dg8QDxIPFA8gDyIPOw9ID0oPTA9OD28PcQ9zD3UPdw95D3sPiA+KD5EPng+gD6IPpA/FD8cPyQ/LD80P
3.2080 +zw/RD9wP3g/sD/0P/xABEAMQBRAqECwQLhAwEDIQNBA2EDgQOxA9EE4QUBBSEFQQVhB7EH0QfxCBEIMQ
3.2081 +hRCHEIkQlRCXEKQQphCoEKoQyxDNEM8Q0RDTENUQ1xDcEOkQ+hD8EP4RABECESMRJREnESkRKxEtES8R
3.2082 +RhFIEVURVxFZEVsRfBF+EYARghGEEYYRiBGZEZsRnhGhEaQRrxHHEdQR1hHYEdoR+xH9Ef8SARIDEgUS
3.2083 +BxIQEhISKBI1EjcSORI7ElwSXhJgEmISZBJmEmgSbRJvEn0SihKMEo4SkBKxErMStRK3ErkSuxK9EsMS
3.2084 +xRLMEtkS2xLdEt8TBBMOExATEhMUExYTGBMaExwTKhMsEzsTSBNKE0wTThNvE3ETcxN1E3cTeRN7E4kT
3.2085 +lxOkE6YTqBOqE8sTzRPPE9ET0xPVE9cT4hPkE+8T/BP+FAAUAhQjFCUUJxQpFCsULRQvFDQUNhQ8FEkU
3.2086 +SxRNFE8UcBRyFHQUdhR4FHoUfBSRFJcUqBSqFKwUrhSwFMgU1RTXFNkU2xT8FP4VABUCFQQVBhUIFQ4V
3.2087 +EBUeFS8VMRUzFTUVNxVUFVYVWBVaFVwVXhVgFXYVlhWnFakVqxWtFa8V0BXSFdQV1hXYFdoV3BXoFeoV
3.2088 +/RYOFhAWEhYUFhYWOxY9Fj8WQRZDFkUWRxZJFlIWVBZhFmMWZRZnFogWihaMFo4WkBaSFpQWmRabFqEW
3.2089 +rhawFrIWtBbVFtcW2RbbFt0W3xbhFvYW+BcDFxAXEhcUFxYXNxc5FzsXPRc/F0EXQxdHF0kXThdbF10X
3.2090 +XxdhF4IXhBeGF4gXiheMF44XmxedF7MXwBfCF8QXxhfnF+kX6xftF+8X8RfzF/wYFRgiGCQYJhgoGEkY
3.2091 +SxhNGE8YURhTGFUYZhhoGHoYgxiGGRcZGRkbGR0ZHxkhGSMZJRknGSkZKxktGS8ZMRkzGTUZNxk5GTsZ
3.2092 +PRk/GUEZQxlFGUcZSRlLGU0ZTxlRGVMZVRlXGVkZWxldGV8ZYRljGWUZZxlpGWwZbxlxGXMZdRl3GXkZ
3.2093 +exl9GX8ZgRmDGYUZiBmKGYwZjhmQGZIZlBmWGZgZmhmcGZ4ZoRmjGaUZpxmpGbAZuRm7GcQZxhnIGcoZ
3.2094 +zBn1GgMaEBoSGhQaFRoXGhgaGhocGh4aLRo2GjsaZBpuGncaeRp7Gn0afxqBGoMahRqHGpgamhqcGp8a
3.2095 +oRqwGrkauxrSGtQa1hrYGtoa3BreGuAa4hrkGuYa6BsRGxMbFRsWGxgbGRsbGx0bHxtAG0IbRBtGG0gb
3.2096 +ShtMG2UbZxuQG5IblBuVG5cbmBuaG5wbnhvHG8kbyxvNG88b0RvTG9Ub1xvgG/Eb8xv1G/cb+RwCHAQc
3.2097 +BRwXHEAcQhxEHEUcRxxIHEocTBxOHHcceRx7HHwcfhx/HIEcgxyFHJIcnxyhHKMcpRyqHLMctRy2HN8c
3.2098 +4RzjHOQc5hznHOkc6xztHPIc+xz9HRIdFB0WHRgdGh0cHR4dIB0iHSQdJh1PHVEdUx1UHVYdVx1ZHVsd
3.2099 +XR2GHYgdih2LHY0djh2QHZIdlB29Hb8dwR3DHcUdxx3JHcsdzR3UHd0d3x3kHeYd6B4RHhMeFR4WHhge
3.2100 +GR4bHh0eHx5IHkoeTB5OHlAeUh5UHlYeWB6BHoMehR6HHokeix6NHo8ekR66Hrwevh6/HsEewh7EHsYe
3.2101 +yB7xHvMe9R73Hvke+x79Hv8fAR8GHw8fER8eHyAfIh8kHyYfKB8qHzQfPR8/H04fUB9SH1QfVh9ZH1wf
3.2102 +Xh+HH4kfix+NH48fkR+TH5Uflx+cH6Ufpx++H8Afwh/EH8YfyB/KH8wfzh/QH9If1B/9H/8gASAEIAYg
3.2103 +CCAKIAwgDyAbICQgJiApICsgRCBtIG8gcSB0IHYgeCB6IHwgfyCEII0gjyCYIJognSCfIKEgyiDMIM4g
3.2104 +zyDRINIg1CDWINghASEDIQUhByEJIQshDSEPIRIhHiEnISkhKyE0ITkhQiFFIdYh2SHbId0h3yHhIeMh
3.2105 +5SHnIekh6yHtIe8h8SHzIfUh9yH5Ifsh/SH/IgEiAyIFIgciCSILIg0iDyIRIhMiFSIXIhkiGyIdIh8i
3.2106 +ISIjIiUiJyIpIisiLSIvIjEiMyI1IjciOSI7Ij0iPyJBIkMiRSJHIkkiSyJNIk8iUSJTIlUiVyJZIlwi
3.2107 +XiJgImIiZCJmIm8iciMFIwcjCSMLIw0jDyMRIxMjFSMXIxkjGyMdIx8jISMjIyUjJyMpIysjLSMvIzEj
3.2108 +MyM1IzcjOSM7Iz0jPyNBI0MjRSNHI0kjSyNNI08jUSNTI1UjVyNZI1wjXyNhI2MjZSNnI2kjayNtI28j
3.2109 +cSN0I3YjeCN6I3wjfiOAI4IjhCOGI4gjiiOMI44jkSOTI5UjlyOZI6IjpSQ4JDskPiRBJEQkRyRJJEwk
3.2110 +TyRSJFUkWCRbJF4kYSRkJGckaiRsJG8kciR1JHckeiR9JIAkgySFJIgkiySOJJEklCSXJJoknSSgJKMk
3.2111 +piSpJKwkrySyJLUkuCS7JL4kwSTEJMckyiTNJNAk0yTWJNkk3CTfJOIk5SToJOsk7iTxJPQk9yT6JP0l
3.2112 +ACUDJQYlCSUMJRolHCU4JUQlWyV0JZklmyWlJbwlyCXiJgUmESYoJjsmTiZoJqcmrCbJJuIm5Cb3JxIn
3.2113 +JycpJzwnTidoJ3UneSeMJ6Enqie2J8InzifjJ+8oAigGKB8oMShIKFUoWChxKIMolii4KMQo5SkBKRYp
3.2114 +JCk3KUMpWiluKX0plymjKa8puyncKeAp7Cn1Kfgp+SoCKgUqBioPKhIq7SrvKvEq8yr1Kvcq+Sr7Kv0q
3.2115 +/ysBKwMrBSsHKwkrCysNKw8rESsTKxUrFysZKxsrHSsfKyErIyslKycrKSsrKy0rLysyKzQrNys5Kzsr
3.2116 +PSs/K0ErQytFK0crSStLK04rUCtSK1QrVitYK1orXStfK2ErYytlK2craStrK20rbytxK3MrdSt3K3kr
3.2117 +eyt9K38rgSuDK4UrhyuJK4srjSuPK5ErkyuVK5crmSubK50rnyuhK6MrpSunK6krqyutK68rsSuzK7Ur
3.2118 +tyu5K7srvSu/K8ErwyvFK8crySvSK9UssCyzLLYsuSy8LL8swizFLMgsyyzOLNEs1CzXLNos3SzgLOMs
3.2119 +5izpLOws7yzyLPUs+Cz7LP4tAS0ELQctCi0NLRAtEy0WLRktHC0fLSItJS0oLSstLi0xLTQtNy06LT0t
3.2120 +QC1DLUYtSS1MLU8tUi1VLVgtWy1eLWEtZC1nLWotbS1wLXMtdi15LXwtfy2CLYUtiC2LLY4tkS2ULZct
3.2121 +mi2dLaAtoy2mLaktrC2vLbIttS24Lbstvi3BLcQtxy3KLc0t0C3TLdYt2S3cLd8t4i3lLegt6y3uLfEt
3.2122 +9C32Lfgt+i38Lf4uAS4ELgcuCS4LLg0uEC4TLhUuFy4ZLhsuHS4gLiIuJS4nLiouLC4vLjEuMy42Ljku
3.2123 +Oy49Lj8uQi5ELkYuTy5RLlMuVS5XLlouXS5fLmEuZC5mLmkubC5uLnAuci51Lnguey59Ln8ugS6DLoUu
3.2124 +hy6JLosujS6QLpIulC6WLpgumi6dLp8uoS6jLqUuqC6qLqwuri6xLrMuti65Lrwuvy7BLsMuxS7ILssu
3.2125 +zS7PLtIu1S7YLtou3C7eLuAu4i7kLuYu6C7rLu0u8C7zLvYu+C8BLwMvBC8NLxAvES8aLx0vHi8nLywA
3.2126 +AAAAAAACAgAAAAAAAAb4AAAAAAAAAAAAAAAAAAAvOw</bytes>
3.2127 + </object>
3.2128 + </data>
3.2129 +</archive>
4.1 Binary file English.lproj/MainMenu.nib/keyedobjects.nib has changed
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/GeekGameBoard.xcodeproj/project.pbxproj Fri Mar 07 11:43:02 2008 -0800
5.3 @@ -0,0 +1,460 @@
5.4 +// !$*UTF8*$!
5.5 +{
5.6 + archiveVersion = 1;
5.7 + classes = {
5.8 + };
5.9 + objectVersion = 44;
5.10 + objects = {
5.11 +
5.12 +/* Begin PBXBuildFile section */
5.13 + 27224FA00CC29B1A00814095 /* Grid.m in Sources */ = {isa = PBXBuildFile; fileRef = 27224F9F0CC29B1A00814095 /* Grid.m */; };
5.14 + 2722526F0CC2E86600814095 /* QuartzUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 2722526E0CC2E86600814095 /* QuartzUtils.m */; };
5.15 + 2727556A0CC3234F009C4C6C /* Dispenser.m in Sources */ = {isa = PBXBuildFile; fileRef = 272755690CC3234F009C4C6C /* Dispenser.m */; };
5.16 + 27275A550CC6713E009C4C6C /* HexGrid.m in Sources */ = {isa = PBXBuildFile; fileRef = 27275A540CC6713E009C4C6C /* HexGrid.m */; };
5.17 + 27275C4B0CC700F2009C4C6C /* Game.m in Sources */ = {isa = PBXBuildFile; fileRef = 27275C4A0CC700F2009C4C6C /* Game.m */; };
5.18 + 27275C920CC7C578009C4C6C /* TicTacToeGame.m in Sources */ = {isa = PBXBuildFile; fileRef = 27275C910CC7C578009C4C6C /* TicTacToeGame.m */; };
5.19 + 272C90AB0CCACBA4009EE530 /* DiscPiece.m in Sources */ = {isa = PBXBuildFile; fileRef = 272C90AA0CCACBA4009EE530 /* DiscPiece.m */; };
5.20 + 2731E0280CD430B800E6E4C8 /* Deck.m in Sources */ = {isa = PBXBuildFile; fileRef = 2731E0270CD430B800E6E4C8 /* Deck.m */; };
5.21 + 2731E2A80CD5630600E6E4C8 /* BitHolder.m in Sources */ = {isa = PBXBuildFile; fileRef = 2731E2A70CD5630600E6E4C8 /* BitHolder.m */; };
5.22 + 2734B2620CC7F25A0070C008 /* HexchequerGame.m in Sources */ = {isa = PBXBuildFile; fileRef = 2734B2610CC7F25A0070C008 /* HexchequerGame.m */; };
5.23 + 2734B4F00CCA5BDB0070C008 /* CheckersGame.m in Sources */ = {isa = PBXBuildFile; fileRef = 2734B4EF0CCA5BDB0070C008 /* CheckersGame.m */; };
5.24 + 274124060CFCCF9D00842A9B /* DemoBoardView.m in Sources */ = {isa = PBXBuildFile; fileRef = 274124050CFCCF9D00842A9B /* DemoBoardView.m */; };
5.25 + 276DFC410D00867000D329AE /* Green Ball.png in Resources */ = {isa = PBXBuildFile; fileRef = 276DFC400D00867000D329AE /* Green Ball.png */; };
5.26 + 276DFC560D00890C00D329AE /* Red Ball.png in Resources */ = {isa = PBXBuildFile; fileRef = 276DFC530D00890C00D329AE /* Red Ball.png */; };
5.27 + 276DFC570D00890C00D329AE /* Yellow Ball.png in Resources */ = {isa = PBXBuildFile; fileRef = 276DFC540D00890C00D329AE /* Yellow Ball.png */; };
5.28 + 276DFC580D00890C00D329AE /* White Ball.png in Resources */ = {isa = PBXBuildFile; fileRef = 276DFC550D00890C00D329AE /* White Ball.png */; };
5.29 + 2795C2B80CC278C800D7B2BD /* Piece.m in Sources */ = {isa = PBXBuildFile; fileRef = 2795C2B70CC278C800D7B2BD /* Piece.m */; };
5.30 + 27B7543E0D08884F000516B9 /* Wood.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 27B7543D0D08884F000516B9 /* Wood.jpg */; };
5.31 + 27C999C30D81185E005AFD4F /* GGBUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 27C999C20D81185E005AFD4F /* GGBUtils.m */; };
5.32 + 27CCA8050CB8A3F9001CFE24 /* BoardView.m in Sources */ = {isa = PBXBuildFile; fileRef = 27CCA8040CB8A3F9001CFE24 /* BoardView.m */; };
5.33 + 27CCA95F0CB8A74D001CFE24 /* Quartz.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27CCA95E0CB8A74D001CFE24 /* Quartz.framework */; };
5.34 + 27CCAABD0CB92A9F001CFE24 /* Card.m in Sources */ = {isa = PBXBuildFile; fileRef = 27CCAABC0CB92A9F001CFE24 /* Card.m */; };
5.35 + 27CCABBF0CB9496B001CFE24 /* Bit.m in Sources */ = {isa = PBXBuildFile; fileRef = 27CCABBE0CB9496B001CFE24 /* Bit.m */; };
5.36 + 27CCAC750CB95C2B001CFE24 /* PlayingCard.m in Sources */ = {isa = PBXBuildFile; fileRef = 27CCAC740CB95C2B001CFE24 /* PlayingCard.m */; };
5.37 + 27D4F1260CCF011200923605 /* Stack.m in Sources */ = {isa = PBXBuildFile; fileRef = 27D4F1250CCF011200923605 /* Stack.m */; };
5.38 + 27DFC4410CCD01B7005E34CE /* GoGame.m in Sources */ = {isa = PBXBuildFile; fileRef = 27DFC4400CCD01B7005E34CE /* GoGame.m */; };
5.39 + 27F230B90CD1A61B006939C1 /* KlondikeGame.m in Sources */ = {isa = PBXBuildFile; fileRef = 27F230B80CD1A61B006939C1 /* KlondikeGame.m */; };
5.40 + 8D11072A0486CEB800E47090 /* MainMenu.nib in Resources */ = {isa = PBXBuildFile; fileRef = 29B97318FDCFA39411CA2CEA /* MainMenu.nib */; };
5.41 + 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; };
5.42 + 8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; };
5.43 + 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
5.44 +/* End PBXBuildFile section */
5.45 +
5.46 +/* Begin PBXFileReference section */
5.47 + 089C165DFE840E0CC02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
5.48 + 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
5.49 + 27224F9E0CC29B1A00814095 /* Grid.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Grid.h; sourceTree = "<group>"; };
5.50 + 27224F9F0CC29B1A00814095 /* Grid.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Grid.m; sourceTree = "<group>"; };
5.51 + 2722526D0CC2E86600814095 /* QuartzUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QuartzUtils.h; sourceTree = "<group>"; };
5.52 + 2722526E0CC2E86600814095 /* QuartzUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QuartzUtils.m; sourceTree = "<group>"; };
5.53 + 272755680CC3234F009C4C6C /* Dispenser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Dispenser.h; sourceTree = "<group>"; };
5.54 + 272755690CC3234F009C4C6C /* Dispenser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Dispenser.m; sourceTree = "<group>"; };
5.55 + 27275A530CC6713E009C4C6C /* HexGrid.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HexGrid.h; sourceTree = "<group>"; };
5.56 + 27275A540CC6713E009C4C6C /* HexGrid.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HexGrid.m; sourceTree = "<group>"; };
5.57 + 27275C490CC700F2009C4C6C /* Game.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Game.h; sourceTree = "<group>"; };
5.58 + 27275C4A0CC700F2009C4C6C /* Game.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Game.m; sourceTree = "<group>"; };
5.59 + 27275C900CC7C578009C4C6C /* TicTacToeGame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TicTacToeGame.h; sourceTree = "<group>"; };
5.60 + 27275C910CC7C578009C4C6C /* TicTacToeGame.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TicTacToeGame.m; sourceTree = "<group>"; };
5.61 + 272C90A90CCACBA4009EE530 /* DiscPiece.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DiscPiece.h; sourceTree = "<group>"; };
5.62 + 272C90AA0CCACBA4009EE530 /* DiscPiece.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DiscPiece.m; sourceTree = "<group>"; };
5.63 + 2731E0260CD430B800E6E4C8 /* Deck.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Deck.h; sourceTree = "<group>"; };
5.64 + 2731E0270CD430B800E6E4C8 /* Deck.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Deck.m; sourceTree = "<group>"; };
5.65 + 2731E2A60CD5630600E6E4C8 /* BitHolder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BitHolder.h; sourceTree = "<group>"; };
5.66 + 2731E2A70CD5630600E6E4C8 /* BitHolder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BitHolder.m; sourceTree = "<group>"; };
5.67 + 2734B2600CC7F25A0070C008 /* HexchequerGame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HexchequerGame.h; sourceTree = "<group>"; };
5.68 + 2734B2610CC7F25A0070C008 /* HexchequerGame.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HexchequerGame.m; sourceTree = "<group>"; };
5.69 + 2734B4EE0CCA5BDB0070C008 /* CheckersGame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CheckersGame.h; sourceTree = "<group>"; };
5.70 + 2734B4EF0CCA5BDB0070C008 /* CheckersGame.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CheckersGame.m; sourceTree = "<group>"; };
5.71 + 274124040CFCCF9D00842A9B /* DemoBoardView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DemoBoardView.h; sourceTree = "<group>"; };
5.72 + 274124050CFCCF9D00842A9B /* DemoBoardView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DemoBoardView.m; sourceTree = "<group>"; };
5.73 + 276DFC400D00867000D329AE /* Green Ball.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Green Ball.png"; path = "Resources/Green Ball.png"; sourceTree = "<group>"; };
5.74 + 276DFC530D00890C00D329AE /* Red Ball.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Red Ball.png"; path = "Resources/Red Ball.png"; sourceTree = "<group>"; };
5.75 + 276DFC540D00890C00D329AE /* Yellow Ball.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Yellow Ball.png"; path = "Resources/Yellow Ball.png"; sourceTree = "<group>"; };
5.76 + 276DFC550D00890C00D329AE /* White Ball.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "White Ball.png"; path = "Resources/White Ball.png"; sourceTree = "<group>"; };
5.77 + 2795C2B60CC278C800D7B2BD /* Piece.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Piece.h; sourceTree = "<group>"; };
5.78 + 2795C2B70CC278C800D7B2BD /* Piece.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Piece.m; sourceTree = "<group>"; };
5.79 + 27B7543D0D08884F000516B9 /* Wood.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; name = Wood.jpg; path = Resources/Wood.jpg; sourceTree = "<group>"; };
5.80 + 27C999C10D81185E005AFD4F /* GGBUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GGBUtils.h; sourceTree = "<group>"; };
5.81 + 27C999C20D81185E005AFD4F /* GGBUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GGBUtils.m; sourceTree = "<group>"; };
5.82 + 27CCA8030CB8A3F9001CFE24 /* BoardView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BoardView.h; sourceTree = "<group>"; };
5.83 + 27CCA8040CB8A3F9001CFE24 /* BoardView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BoardView.m; sourceTree = "<group>"; };
5.84 + 27CCA95E0CB8A74D001CFE24 /* Quartz.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Quartz.framework; path = /System/Library/Frameworks/Quartz.framework; sourceTree = "<absolute>"; };
5.85 + 27CCAABB0CB92A9F001CFE24 /* Card.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Card.h; sourceTree = "<group>"; };
5.86 + 27CCAABC0CB92A9F001CFE24 /* Card.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Card.m; sourceTree = "<group>"; };
5.87 + 27CCABBD0CB9496B001CFE24 /* Bit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Bit.h; sourceTree = "<group>"; };
5.88 + 27CCABBE0CB9496B001CFE24 /* Bit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Bit.m; sourceTree = "<group>"; };
5.89 + 27CCAC730CB95C2B001CFE24 /* PlayingCard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlayingCard.h; sourceTree = "<group>"; };
5.90 + 27CCAC740CB95C2B001CFE24 /* PlayingCard.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PlayingCard.m; sourceTree = "<group>"; };
5.91 + 27D4F1240CCF011200923605 /* Stack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Stack.h; sourceTree = "<group>"; };
5.92 + 27D4F1250CCF011200923605 /* Stack.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Stack.m; sourceTree = "<group>"; };
5.93 + 27DFC43F0CCD01B7005E34CE /* GoGame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GoGame.h; sourceTree = "<group>"; };
5.94 + 27DFC4400CCD01B7005E34CE /* GoGame.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GoGame.m; sourceTree = "<group>"; };
5.95 + 27F230B70CD1A61B006939C1 /* KlondikeGame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KlondikeGame.h; sourceTree = "<group>"; };
5.96 + 27F230B80CD1A61B006939C1 /* KlondikeGame.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KlondikeGame.m; sourceTree = "<group>"; };
5.97 + 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
5.98 + 29B97319FDCFA39411CA2CEA /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/MainMenu.nib; sourceTree = "<group>"; };
5.99 + 29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
5.100 + 29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
5.101 + 32CA4F630368D1EE00C91783 /* GeekGameBoard_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GeekGameBoard_Prefix.pch; sourceTree = "<group>"; };
5.102 + 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Resources/Info.plist; sourceTree = "<group>"; };
5.103 + 8D1107320486CEB800E47090 /* GeekGameBoard.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = GeekGameBoard.app; sourceTree = BUILT_PRODUCTS_DIR; };
5.104 +/* End PBXFileReference section */
5.105 +
5.106 +/* Begin PBXFrameworksBuildPhase section */
5.107 + 8D11072E0486CEB800E47090 /* Frameworks */ = {
5.108 + isa = PBXFrameworksBuildPhase;
5.109 + buildActionMask = 2147483647;
5.110 + files = (
5.111 + 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */,
5.112 + 27CCA95F0CB8A74D001CFE24 /* Quartz.framework in Frameworks */,
5.113 + );
5.114 + runOnlyForDeploymentPostprocessing = 0;
5.115 + };
5.116 +/* End PBXFrameworksBuildPhase section */
5.117 +
5.118 +/* Begin PBXGroup section */
5.119 + 080E96DDFE201D6D7F000001 /* Source */ = {
5.120 + isa = PBXGroup;
5.121 + children = (
5.122 + 27CCA8030CB8A3F9001CFE24 /* BoardView.h */,
5.123 + 27CCA8040CB8A3F9001CFE24 /* BoardView.m */,
5.124 + 27CCABBD0CB9496B001CFE24 /* Bit.h */,
5.125 + 27CCABBE0CB9496B001CFE24 /* Bit.m */,
5.126 + 2731E2A60CD5630600E6E4C8 /* BitHolder.h */,
5.127 + 2731E2A70CD5630600E6E4C8 /* BitHolder.m */,
5.128 + 27D4F1240CCF011200923605 /* Stack.h */,
5.129 + 27D4F1250CCF011200923605 /* Stack.m */,
5.130 + 27275C440CC70095009C4C6C /* Cards */,
5.131 + 27275C450CC700C4009C4C6C /* Boards and Pieces */,
5.132 + 27275C480CC700D8009C4C6C /* Games */,
5.133 + 2722526D0CC2E86600814095 /* QuartzUtils.h */,
5.134 + 2722526E0CC2E86600814095 /* QuartzUtils.m */,
5.135 + 27C999C10D81185E005AFD4F /* GGBUtils.h */,
5.136 + 27C999C20D81185E005AFD4F /* GGBUtils.m */,
5.137 + );
5.138 + path = Source;
5.139 + sourceTree = "<group>";
5.140 + };
5.141 + 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = {
5.142 + isa = PBXGroup;
5.143 + children = (
5.144 + 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */,
5.145 + );
5.146 + name = "Linked Frameworks";
5.147 + sourceTree = "<group>";
5.148 + };
5.149 + 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */ = {
5.150 + isa = PBXGroup;
5.151 + children = (
5.152 + 29B97324FDCFA39411CA2CEA /* AppKit.framework */,
5.153 + 27CCA95E0CB8A74D001CFE24 /* Quartz.framework */,
5.154 + 29B97325FDCFA39411CA2CEA /* Foundation.framework */,
5.155 + );
5.156 + name = "Other Frameworks";
5.157 + sourceTree = "<group>";
5.158 + };
5.159 + 19C28FACFE9D520D11CA2CBB /* Products */ = {
5.160 + isa = PBXGroup;
5.161 + children = (
5.162 + 8D1107320486CEB800E47090 /* GeekGameBoard.app */,
5.163 + );
5.164 + name = Products;
5.165 + sourceTree = "<group>";
5.166 + };
5.167 + 27275C440CC70095009C4C6C /* Cards */ = {
5.168 + isa = PBXGroup;
5.169 + children = (
5.170 + 27CCAABB0CB92A9F001CFE24 /* Card.h */,
5.171 + 27CCAABC0CB92A9F001CFE24 /* Card.m */,
5.172 + 2731E0260CD430B800E6E4C8 /* Deck.h */,
5.173 + 2731E0270CD430B800E6E4C8 /* Deck.m */,
5.174 + 27CCAC730CB95C2B001CFE24 /* PlayingCard.h */,
5.175 + 27CCAC740CB95C2B001CFE24 /* PlayingCard.m */,
5.176 + );
5.177 + name = Cards;
5.178 + sourceTree = "<group>";
5.179 + };
5.180 + 27275C450CC700C4009C4C6C /* Boards and Pieces */ = {
5.181 + isa = PBXGroup;
5.182 + children = (
5.183 + 2795C2B60CC278C800D7B2BD /* Piece.h */,
5.184 + 2795C2B70CC278C800D7B2BD /* Piece.m */,
5.185 + 272C90A90CCACBA4009EE530 /* DiscPiece.h */,
5.186 + 272C90AA0CCACBA4009EE530 /* DiscPiece.m */,
5.187 + 27224F9E0CC29B1A00814095 /* Grid.h */,
5.188 + 27224F9F0CC29B1A00814095 /* Grid.m */,
5.189 + 27275A530CC6713E009C4C6C /* HexGrid.h */,
5.190 + 27275A540CC6713E009C4C6C /* HexGrid.m */,
5.191 + 272755680CC3234F009C4C6C /* Dispenser.h */,
5.192 + 272755690CC3234F009C4C6C /* Dispenser.m */,
5.193 + );
5.194 + name = "Boards and Pieces";
5.195 + sourceTree = "<group>";
5.196 + };
5.197 + 27275C480CC700D8009C4C6C /* Games */ = {
5.198 + isa = PBXGroup;
5.199 + children = (
5.200 + 27275C490CC700F2009C4C6C /* Game.h */,
5.201 + 27275C4A0CC700F2009C4C6C /* Game.m */,
5.202 + 27275C900CC7C578009C4C6C /* TicTacToeGame.h */,
5.203 + 27275C910CC7C578009C4C6C /* TicTacToeGame.m */,
5.204 + 2734B4EE0CCA5BDB0070C008 /* CheckersGame.h */,
5.205 + 2734B4EF0CCA5BDB0070C008 /* CheckersGame.m */,
5.206 + 2734B2600CC7F25A0070C008 /* HexchequerGame.h */,
5.207 + 2734B2610CC7F25A0070C008 /* HexchequerGame.m */,
5.208 + 27DFC43F0CCD01B7005E34CE /* GoGame.h */,
5.209 + 27DFC4400CCD01B7005E34CE /* GoGame.m */,
5.210 + 27F230B70CD1A61B006939C1 /* KlondikeGame.h */,
5.211 + 27F230B80CD1A61B006939C1 /* KlondikeGame.m */,
5.212 + );
5.213 + name = Games;
5.214 + sourceTree = "<group>";
5.215 + };
5.216 + 29B97314FDCFA39411CA2CEA /* BoardGame */ = {
5.217 + isa = PBXGroup;
5.218 + children = (
5.219 + 080E96DDFE201D6D7F000001 /* Source */,
5.220 + 29B97315FDCFA39411CA2CEA /* Demo Application */,
5.221 + 29B97317FDCFA39411CA2CEA /* Resources */,
5.222 + 29B97323FDCFA39411CA2CEA /* Frameworks */,
5.223 + 19C28FACFE9D520D11CA2CBB /* Products */,
5.224 + );
5.225 + name = BoardGame;
5.226 + sourceTree = "<group>";
5.227 + };
5.228 + 29B97315FDCFA39411CA2CEA /* Demo Application */ = {
5.229 + isa = PBXGroup;
5.230 + children = (
5.231 + 274124040CFCCF9D00842A9B /* DemoBoardView.h */,
5.232 + 274124050CFCCF9D00842A9B /* DemoBoardView.m */,
5.233 + 32CA4F630368D1EE00C91783 /* GeekGameBoard_Prefix.pch */,
5.234 + 29B97316FDCFA39411CA2CEA /* main.m */,
5.235 + );
5.236 + name = "Demo Application";
5.237 + path = Source;
5.238 + sourceTree = "<group>";
5.239 + };
5.240 + 29B97317FDCFA39411CA2CEA /* Resources */ = {
5.241 + isa = PBXGroup;
5.242 + children = (
5.243 + 29B97318FDCFA39411CA2CEA /* MainMenu.nib */,
5.244 + 8D1107310486CEB800E47090 /* Info.plist */,
5.245 + 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */,
5.246 + 276DFC400D00867000D329AE /* Green Ball.png */,
5.247 + 276DFC530D00890C00D329AE /* Red Ball.png */,
5.248 + 276DFC540D00890C00D329AE /* Yellow Ball.png */,
5.249 + 276DFC550D00890C00D329AE /* White Ball.png */,
5.250 + 27B7543D0D08884F000516B9 /* Wood.jpg */,
5.251 + );
5.252 + name = Resources;
5.253 + sourceTree = "<group>";
5.254 + };
5.255 + 29B97323FDCFA39411CA2CEA /* Frameworks */ = {
5.256 + isa = PBXGroup;
5.257 + children = (
5.258 + 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */,
5.259 + 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */,
5.260 + );
5.261 + name = Frameworks;
5.262 + sourceTree = "<group>";
5.263 + };
5.264 +/* End PBXGroup section */
5.265 +
5.266 +/* Begin PBXNativeTarget section */
5.267 + 8D1107260486CEB800E47090 /* BoardGame */ = {
5.268 + isa = PBXNativeTarget;
5.269 + buildConfigurationList = C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "BoardGame" */;
5.270 + buildPhases = (
5.271 + 8D1107290486CEB800E47090 /* Resources */,
5.272 + 8D11072C0486CEB800E47090 /* Sources */,
5.273 + 8D11072E0486CEB800E47090 /* Frameworks */,
5.274 + );
5.275 + buildRules = (
5.276 + );
5.277 + dependencies = (
5.278 + );
5.279 + name = BoardGame;
5.280 + productInstallPath = "$(HOME)/Applications";
5.281 + productName = BoardGame;
5.282 + productReference = 8D1107320486CEB800E47090 /* GeekGameBoard.app */;
5.283 + productType = "com.apple.product-type.application";
5.284 + };
5.285 +/* End PBXNativeTarget section */
5.286 +
5.287 +/* Begin PBXProject section */
5.288 + 29B97313FDCFA39411CA2CEA /* Project object */ = {
5.289 + isa = PBXProject;
5.290 + buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "GeekGameBoard" */;
5.291 + compatibilityVersion = "Xcode 3.0";
5.292 + hasScannedForEncodings = 1;
5.293 + mainGroup = 29B97314FDCFA39411CA2CEA /* BoardGame */;
5.294 + projectDirPath = "";
5.295 + projectRoot = "";
5.296 + targets = (
5.297 + 8D1107260486CEB800E47090 /* BoardGame */,
5.298 + );
5.299 + };
5.300 +/* End PBXProject section */
5.301 +
5.302 +/* Begin PBXResourcesBuildPhase section */
5.303 + 8D1107290486CEB800E47090 /* Resources */ = {
5.304 + isa = PBXResourcesBuildPhase;
5.305 + buildActionMask = 2147483647;
5.306 + files = (
5.307 + 8D11072A0486CEB800E47090 /* MainMenu.nib in Resources */,
5.308 + 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */,
5.309 + 276DFC410D00867000D329AE /* Green Ball.png in Resources */,
5.310 + 276DFC560D00890C00D329AE /* Red Ball.png in Resources */,
5.311 + 276DFC570D00890C00D329AE /* Yellow Ball.png in Resources */,
5.312 + 276DFC580D00890C00D329AE /* White Ball.png in Resources */,
5.313 + 27B7543E0D08884F000516B9 /* Wood.jpg in Resources */,
5.314 + );
5.315 + runOnlyForDeploymentPostprocessing = 0;
5.316 + };
5.317 +/* End PBXResourcesBuildPhase section */
5.318 +
5.319 +/* Begin PBXSourcesBuildPhase section */
5.320 + 8D11072C0486CEB800E47090 /* Sources */ = {
5.321 + isa = PBXSourcesBuildPhase;
5.322 + buildActionMask = 2147483647;
5.323 + files = (
5.324 + 8D11072D0486CEB800E47090 /* main.m in Sources */,
5.325 + 27CCA8050CB8A3F9001CFE24 /* BoardView.m in Sources */,
5.326 + 27CCAABD0CB92A9F001CFE24 /* Card.m in Sources */,
5.327 + 27CCABBF0CB9496B001CFE24 /* Bit.m in Sources */,
5.328 + 27CCAC750CB95C2B001CFE24 /* PlayingCard.m in Sources */,
5.329 + 2795C2B80CC278C800D7B2BD /* Piece.m in Sources */,
5.330 + 27224FA00CC29B1A00814095 /* Grid.m in Sources */,
5.331 + 2722526F0CC2E86600814095 /* QuartzUtils.m in Sources */,
5.332 + 2727556A0CC3234F009C4C6C /* Dispenser.m in Sources */,
5.333 + 27275A550CC6713E009C4C6C /* HexGrid.m in Sources */,
5.334 + 27275C4B0CC700F2009C4C6C /* Game.m in Sources */,
5.335 + 27275C920CC7C578009C4C6C /* TicTacToeGame.m in Sources */,
5.336 + 2734B2620CC7F25A0070C008 /* HexchequerGame.m in Sources */,
5.337 + 2734B4F00CCA5BDB0070C008 /* CheckersGame.m in Sources */,
5.338 + 272C90AB0CCACBA4009EE530 /* DiscPiece.m in Sources */,
5.339 + 27DFC4410CCD01B7005E34CE /* GoGame.m in Sources */,
5.340 + 27D4F1260CCF011200923605 /* Stack.m in Sources */,
5.341 + 27F230B90CD1A61B006939C1 /* KlondikeGame.m in Sources */,
5.342 + 2731E0280CD430B800E6E4C8 /* Deck.m in Sources */,
5.343 + 2731E2A80CD5630600E6E4C8 /* BitHolder.m in Sources */,
5.344 + 274124060CFCCF9D00842A9B /* DemoBoardView.m in Sources */,
5.345 + 27C999C30D81185E005AFD4F /* GGBUtils.m in Sources */,
5.346 + );
5.347 + runOnlyForDeploymentPostprocessing = 0;
5.348 + };
5.349 +/* End PBXSourcesBuildPhase section */
5.350 +
5.351 +/* Begin PBXVariantGroup section */
5.352 + 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */ = {
5.353 + isa = PBXVariantGroup;
5.354 + children = (
5.355 + 089C165DFE840E0CC02AAC07 /* English */,
5.356 + );
5.357 + name = InfoPlist.strings;
5.358 + sourceTree = "<group>";
5.359 + };
5.360 + 29B97318FDCFA39411CA2CEA /* MainMenu.nib */ = {
5.361 + isa = PBXVariantGroup;
5.362 + children = (
5.363 + 29B97319FDCFA39411CA2CEA /* English */,
5.364 + );
5.365 + name = MainMenu.nib;
5.366 + sourceTree = "<group>";
5.367 + };
5.368 +/* End PBXVariantGroup section */
5.369 +
5.370 +/* Begin XCBuildConfiguration section */
5.371 + C01FCF4B08A954540054247B /* Debug */ = {
5.372 + isa = XCBuildConfiguration;
5.373 + buildSettings = {
5.374 + COPY_PHASE_STRIP = NO;
5.375 + GCC_DYNAMIC_NO_PIC = NO;
5.376 + GCC_ENABLE_FIX_AND_CONTINUE = YES;
5.377 + GCC_MODEL_TUNING = G5;
5.378 + GCC_OPTIMIZATION_LEVEL = 0;
5.379 + GCC_PRECOMPILE_PREFIX_HEADER = YES;
5.380 + GCC_PREFIX_HEADER = Source/GeekGameBoard_Prefix.pch;
5.381 + INFOPLIST_FILE = Resources/Info.plist;
5.382 + INSTALL_PATH = "$(HOME)/Applications";
5.383 + PRODUCT_NAME = GeekGameBoard;
5.384 + WRAPPER_EXTENSION = app;
5.385 + ZERO_LINK = YES;
5.386 + };
5.387 + name = Debug;
5.388 + };
5.389 + C01FCF4C08A954540054247B /* Release */ = {
5.390 + isa = XCBuildConfiguration;
5.391 + buildSettings = {
5.392 + ARCHS = (
5.393 + i386,
5.394 + ppc,
5.395 + ppc64,
5.396 + x86_64,
5.397 + );
5.398 + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
5.399 + GCC_MODEL_TUNING = G5;
5.400 + GCC_PRECOMPILE_PREFIX_HEADER = YES;
5.401 + GCC_PREFIX_HEADER = Source/GeekGameBoard_Prefix.pch;
5.402 + INFOPLIST_FILE = Resources/Info.plist;
5.403 + INSTALL_PATH = "$(HOME)/Applications";
5.404 + PRODUCT_NAME = GeekGameBoard;
5.405 + WRAPPER_EXTENSION = app;
5.406 + };
5.407 + name = Release;
5.408 + };
5.409 + C01FCF4F08A954540054247B /* Debug */ = {
5.410 + isa = XCBuildConfiguration;
5.411 + buildSettings = {
5.412 + GCC_C_LANGUAGE_STANDARD = gnu99;
5.413 + GCC_ENABLE_OBJC_GC = unsupported;
5.414 + GCC_TREAT_WARNINGS_AS_ERRORS = YES;
5.415 + GCC_WARN_ABOUT_RETURN_TYPE = YES;
5.416 + GCC_WARN_UNUSED_VARIABLE = YES;
5.417 + PREBINDING = NO;
5.418 + WARNING_CFLAGS = "-Wall";
5.419 + };
5.420 + name = Debug;
5.421 + };
5.422 + C01FCF5008A954540054247B /* Release */ = {
5.423 + isa = XCBuildConfiguration;
5.424 + buildSettings = {
5.425 + ARCHS = (
5.426 + ppc,
5.427 + i386,
5.428 + );
5.429 + GCC_C_LANGUAGE_STANDARD = gnu99;
5.430 + GCC_ENABLE_OBJC_GC = unsupported;
5.431 + GCC_TREAT_WARNINGS_AS_ERRORS = YES;
5.432 + GCC_WARN_ABOUT_RETURN_TYPE = YES;
5.433 + GCC_WARN_UNUSED_VARIABLE = YES;
5.434 + PREBINDING = NO;
5.435 + WARNING_CFLAGS = "-Wall";
5.436 + };
5.437 + name = Release;
5.438 + };
5.439 +/* End XCBuildConfiguration section */
5.440 +
5.441 +/* Begin XCConfigurationList section */
5.442 + C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "BoardGame" */ = {
5.443 + isa = XCConfigurationList;
5.444 + buildConfigurations = (
5.445 + C01FCF4B08A954540054247B /* Debug */,
5.446 + C01FCF4C08A954540054247B /* Release */,
5.447 + );
5.448 + defaultConfigurationIsVisible = 0;
5.449 + defaultConfigurationName = Release;
5.450 + };
5.451 + C01FCF4E08A954540054247B /* Build configuration list for PBXProject "GeekGameBoard" */ = {
5.452 + isa = XCConfigurationList;
5.453 + buildConfigurations = (
5.454 + C01FCF4F08A954540054247B /* Debug */,
5.455 + C01FCF5008A954540054247B /* Release */,
5.456 + );
5.457 + defaultConfigurationIsVisible = 0;
5.458 + defaultConfigurationName = Release;
5.459 + };
5.460 +/* End XCConfigurationList section */
5.461 + };
5.462 + rootObject = 29B97313FDCFA39411CA2CEA /* Project object */;
5.463 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/Read Me.rtf Fri Mar 07 11:43:02 2008 -0800
6.3 @@ -0,0 +1,139 @@
6.4 +{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf270
6.5 +{\fonttbl\f0\fnil\fcharset0 Verdana;}
6.6 +{\colortbl;\red255\green255\blue255;}
6.7 +\margl1440\margr1440\vieww13900\viewh17120\viewkind0
6.8 +\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\ql\qnatural\pardirnatural
6.9 +
6.10 +\f0\b\fs38 \cf0 GeekGameBoard
6.11 +\b0\fs22 \
6.12 +\
6.13 +
6.14 +\b by Jens Alfke
6.15 +\b0 \
6.16 +\
6.17 +GeekGameBoard is an example of using Core Animation to present the user interface of a board or card game. It implements a small framework for implementing such games, with domain-specific classes like "Grid" and "Piece", and examples of several game definitions built on top of the framework.\
6.18 +\
6.19 +Some of the generally-useful Core Animation techniques illustrated are:\
6.20 +\'95 Hit testing\
6.21 +\'95 Dragging CALayers with the mouse\
6.22 +\'95 Loading images from files and setting them as layer contents\
6.23 +\'95 3D "card-flip" animations\
6.24 +\
6.25 +
6.26 +\b\fs28 History
6.27 +\b0 \
6.28 +
6.29 +\fs22 \
6.30 +I wrote GeekGameBoard in 2007 while at Apple, which published it as sample code. Apple's sample code license allows unrestricted use of the source code, requiring only that you keep their copyright notice in an
6.31 +\i unmodified
6.32 +\i0 distribution.\
6.33 +\
6.34 +I am no longer employed by Apple. To encourage further development of this framework, in March 2008 I created this open source project (under a BSD license) based on a slightly-evolved version of the published sample code.\
6.35 +\
6.36 +1.0: Original Apple sample code release (12/19/2007)\
6.37 +2.0: First open source release. (Major version number bumped to avoid conflict with any future Apple revisions.) No longer requires garbage collection. Fixed some memory leaks of CG objects. Fixed a bug when advancing to the 8th row in the Checkers game. (3/7/2008)\
6.38 +\
6.39 +
6.40 +\b\fs28 Project Description\
6.41 +
6.42 +\b0\fs22 \
6.43 +
6.44 +\b Important Classes
6.45 +\b0 \
6.46 +\
6.47 +A
6.48 +\b Bit
6.49 +\b0 is a moveable object in a game, either a
6.50 +\b Card
6.51 +\b0 or a
6.52 +\b Piece
6.53 +\b0 .\
6.54 +A
6.55 +\b BitHolder
6.56 +\b0 is a container for Bits; they can be dragged into and/or out of it. Typical BitHolders are
6.57 +\b GridCell
6.58 +\b0 s (the squares/hexes in a board),
6.59 +\b Deck
6.60 +\b0 s or
6.61 +\b Stack
6.62 +\b0 s of cards, and
6.63 +\b Dispensers
6.64 +\b0 (supplies of new pieces.)\
6.65 +A
6.66 +\b Grid
6.67 +\b0 is a regular arrangement of
6.68 +\b GridCell
6.69 +\b0 s; rectangular and hex grids are implemented.\
6.70 +
6.71 +\b BoardView
6.72 +\b0 is the NSView whose layer hosts all of the above. It also tracks mouse events so the user can drag Bits.\
6.73 +
6.74 +\b Game
6.75 +\b0 represents the rules of a particular game. It sets up the pieces/cards/grids that make up the game, decides which moves are legal, keeps track of whose turn it is, and decides when someone's won.\
6.76 +
6.77 +\b Player
6.78 +\b0 is a passive object that represents one of the players in a Game.\
6.79 +\
6.80 +
6.81 +\b Class Hierarchy
6.82 +\b0 \
6.83 +\
6.84 +(Underlined classes are from external frameworks; italic classes are abstract.)\
6.85 +\
6.86 +\ul CALayer\ulnone \
6.87 +
6.88 +\i Bit
6.89 +\i0 \
6.90 + Card\
6.91 + PlayingCard\
6.92 + DraggedStack\
6.93 + Piece\
6.94 + DiscPiece\
6.95 +
6.96 +\i BitHolder*
6.97 +\i0 \
6.98 +
6.99 +\i GridCell
6.100 +\i0 \
6.101 + Hex\
6.102 + Square\
6.103 + GoSquare\
6.104 + Deck\
6.105 + Dispenser\
6.106 + Stack\
6.107 +
6.108 +\i Grid
6.109 +\i0 \
6.110 + HexGrid\
6.111 + RectGrid\
6.112 +\
6.113 +\ul NSView\ulnone \
6.114 + BoardView\
6.115 +\
6.116 +
6.117 +\i \ul NSObject
6.118 +\i0 \ulnone \
6.119 +
6.120 +\i Game
6.121 +\i0 \
6.122 + TicTacToeGame (etc...)\
6.123 + Player\
6.124 +\
6.125 +
6.126 +\fs20 * BitHolder is actually both a protocol, and a class that implements the protocol. I've combined them here, for simplicity.\
6.127 +
6.128 +\fs22 \
6.129 +\
6.130 +
6.131 +\b\fs28 Related Information\
6.132 +
6.133 +\b0\fs22 \
6.134 +\'95 {\field{\*\fldinst{HYPERLINK "http://developer.apple.com/samplecode/GeekGameBoard/"}}{\fldrslt Apple's original GeekGameBoard sample code}}\
6.135 +\'95 {\field{\*\fldinst{HYPERLINK "http://developer.apple.com/documentation/Cocoa/Conceptual/CoreAnimation_guide/index.html"}}{\fldrslt
6.136 +\i Core Animation Programming Guide}}\
6.137 +
6.138 +\i \'95 {\field{\*\fldinst{HYPERLINK "http://developer.apple.com/documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_images/chapter_12_section_4.html"}}{\fldrslt Quartz 2D Programming Guide: Creating Images}}\
6.139 +\'95 {\field{\*\fldinst{HYPERLINK "http://developer.apple.com/documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_patterns/chapter_7_section_1.html"}}{\fldrslt Quartz 2D Programming Guide: Patterns}}\
6.140 +\'95 {\field{\*\fldinst{HYPERLINK "http://developer.apple.com/documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_paths/chapter_4_section_1.html"}}{\fldrslt Quartz 2D Programming Guide: Paths}}
6.141 +\i0 \
6.142 +}
6.143 \ No newline at end of file
7.1 Binary file Resources/Green Ball.png has changed
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/Resources/Info.plist Fri Mar 07 11:43:02 2008 -0800
8.3 @@ -0,0 +1,26 @@
8.4 +<?xml version="1.0" encoding="UTF-8"?>
8.5 +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
8.6 +<plist version="1.0">
8.7 +<dict>
8.8 + <key>CFBundleDevelopmentRegion</key>
8.9 + <string>English</string>
8.10 + <key>CFBundleExecutable</key>
8.11 + <string>${EXECUTABLE_NAME}</string>
8.12 + <key>CFBundleIdentifier</key>
8.13 + <string>com.apple.sample.GeekGameBoard</string>
8.14 + <key>CFBundleInfoDictionaryVersion</key>
8.15 + <string>6.0</string>
8.16 + <key>CFBundleName</key>
8.17 + <string>${PRODUCT_NAME}</string>
8.18 + <key>CFBundlePackageType</key>
8.19 + <string>APPL</string>
8.20 + <key>CFBundleSignature</key>
8.21 + <string>????</string>
8.22 + <key>CFBundleVersion</key>
8.23 + <string>1.0</string>
8.24 + <key>NSMainNibFile</key>
8.25 + <string>MainMenu</string>
8.26 + <key>NSPrincipalClass</key>
8.27 + <string>NSApplication</string>
8.28 +</dict>
8.29 +</plist>
9.1 Binary file Resources/Red Ball.png has changed
10.1 Binary file Resources/White Ball.png has changed
11.1 Binary file Resources/Wood.jpg has changed
12.1 Binary file Resources/Yellow Ball.png has changed
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/Source/Bit.h Fri Mar 07 11:43:02 2008 -0800
13.3 @@ -0,0 +1,69 @@
13.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
13.5 + http://developer.apple.com/samplecode/GeekGameBoard/
13.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
13.7 +
13.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
13.9 + provided that the following conditions are met:
13.10 +
13.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
13.12 + and the following disclaimer.
13.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
13.14 + conditions and the following disclaimer in the documentation and/or other materials provided
13.15 + with the distribution.
13.16 +
13.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
13.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
13.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
13.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
13.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
13.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
13.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
13.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13.25 +*/
13.26 +#import <Quartz/Quartz.h>
13.27 +
13.28 +
13.29 +@class Game, Player;
13.30 +@protocol BitHolder;
13.31 +
13.32 +
13.33 +/** Standard Z positions */
13.34 +enum {
13.35 + kBoardZ = 1,
13.36 + kCardZ = 2,
13.37 + kPieceZ = 3,
13.38 +
13.39 + kPickedUpZ = 100
13.40 +};
13.41 +
13.42 +
13.43 +/** A moveable item in a card/board game.
13.44 + Abstract superclass of Card and Piece. */
13.45 +@interface Bit : CALayer <NSCopying>
13.46 +{
13.47 + @private
13.48 + int _restingZ; // Original z position, saved while pickedUp
13.49 + Player *_owner; // Player that owns this Bit
13.50 +}
13.51 +
13.52 +/** Conveniences for getting/setting the layer's scale and rotation */
13.53 +@property CGFloat scale;
13.54 +@property int rotation; // in degrees! Positive = clockwise
13.55 +
13.56 +/** "Picking up" a Bit makes it larger, translucent, and in front of everything else */
13.57 +@property BOOL pickedUp;
13.58 +
13.59 +/** Current holder (or nil) */
13.60 +@property (readonly) id<BitHolder> holder;
13.61 +
13.62 +/** Ownership of this Bit */
13.63 +@property (assign) Player *owner;
13.64 +
13.65 +/** Conveniences for owner.friendly, owner.unfriendly */
13.66 +@property (readonly, getter=isFriendly) BOOL friendly;
13.67 +@property (readonly, getter=isUnfriendly) BOOL unfriendly;
13.68 +
13.69 +/** Removes this Bit while running a explosion/fade-out animation */
13.70 +- (void) destroy;
13.71 +
13.72 +@end
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
14.2 +++ b/Source/Bit.m Fri Mar 07 11:43:02 2008 -0800
14.3 @@ -0,0 +1,172 @@
14.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
14.5 + http://developer.apple.com/samplecode/GeekGameBoard/
14.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
14.7 +
14.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
14.9 + provided that the following conditions are met:
14.10 +
14.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
14.12 + and the following disclaimer.
14.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
14.14 + conditions and the following disclaimer in the documentation and/or other materials provided
14.15 + with the distribution.
14.16 +
14.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
14.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
14.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
14.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
14.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
14.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
14.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
14.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14.25 +*/
14.26 +#import "Bit.h"
14.27 +#import "Game.h"
14.28 +#import "QuartzUtils.h"
14.29 +
14.30 +
14.31 +@implementation Bit
14.32 +
14.33 +
14.34 +- (id) copyWithZone: (NSZone*)zone
14.35 +{
14.36 + // NSLayer isn't copyable, but it is archivable. So create a copy by archiving to
14.37 + // a temporary data block, then unarchiving a new layer from that block.
14.38 +
14.39 + // One complication is that, due to a bug in Core Animation, CALayer can't archive
14.40 + // a pattern-based CGColor. So as a workaround, clear the background before archiving,
14.41 + // then restore it afterwards.
14.42 +
14.43 + // Also, archiving a CALayer with an image in it leaks memory. (Filed as rdar://5786865 )
14.44 + // As a workaround, clear the contents before archiving, then restore.
14.45 +
14.46 + CGColorRef bg = CGColorRetain(self.backgroundColor);
14.47 + self.backgroundColor = NULL;
14.48 + id contents = [self.contents retain];
14.49 + self.contents = nil;
14.50 +
14.51 + NSData *data = [NSKeyedArchiver archivedDataWithRootObject: self];
14.52 +
14.53 + self.backgroundColor = bg;
14.54 + self.contents = contents;
14.55 +
14.56 + Bit *clone = [NSKeyedUnarchiver unarchiveObjectWithData: data];
14.57 + clone.backgroundColor = bg;
14.58 + clone.contents = contents;
14.59 + CGColorRelease(bg);
14.60 + [contents release];
14.61 +
14.62 + clone->_owner = _owner; // _owner is not archived
14.63 + return [clone retain];
14.64 +}
14.65 +
14.66 +
14.67 +- (NSString*) description
14.68 +{
14.69 + return [NSString stringWithFormat: @"%@[(%g,%g)]", self.class,self.position.x,self.position.y];
14.70 +}
14.71 +
14.72 +
14.73 +@synthesize owner=_owner;
14.74 +
14.75 +- (BOOL) isFriendly {return _owner.friendly;}
14.76 +- (BOOL) isUnfriendly {return _owner.unfriendly;}
14.77 +
14.78 +
14.79 +- (CGFloat) scale
14.80 +{
14.81 + NSNumber *scale = [self valueForKeyPath: @"transform.scale"];
14.82 + return scale.floatValue;
14.83 +}
14.84 +
14.85 +- (void) setScale: (CGFloat)scale
14.86 +{
14.87 + [self setValue: [NSNumber numberWithFloat: scale]
14.88 + forKeyPath: @"transform.scale"];
14.89 +}
14.90 +
14.91 +
14.92 +- (int) rotation
14.93 +{
14.94 + NSNumber *rot = [self valueForKeyPath: @"transform.rotation"];
14.95 + return round( rot.doubleValue * 180.0 / M_PI );
14.96 +}
14.97 +
14.98 +- (void) setRotation: (int)rotation
14.99 +{
14.100 + [self setValue: [NSNumber numberWithDouble: rotation*M_PI/180.0]
14.101 + forKeyPath: @"transform.rotation"];
14.102 +}
14.103 +
14.104 +
14.105 +- (BOOL) pickedUp
14.106 +{
14.107 + return self.zPosition >= kPickedUpZ;
14.108 +}
14.109 +
14.110 +- (void) setPickedUp: (BOOL)up
14.111 +{
14.112 + if( up != self.pickedUp ) {
14.113 + CGFloat shadow, offset, radius, opacity, z, scale;
14.114 + if( up ) {
14.115 + shadow = 0.8;
14.116 + offset = 2;
14.117 + radius = 8;
14.118 + opacity = 0.9;
14.119 + scale = 1.2;
14.120 + z = kPickedUpZ;
14.121 + _restingZ = self.zPosition;
14.122 + } else {
14.123 + shadow = offset = radius = 0.0;
14.124 + opacity = 1.0;
14.125 + scale = 1.0/1.2;
14.126 + z = _restingZ;
14.127 + }
14.128 +
14.129 + self.zPosition = z;
14.130 + self.shadowOpacity = shadow;
14.131 + self.shadowOffset = CGSizeMake(offset,-offset);
14.132 + self.shadowRadius = radius;
14.133 + self.opacity = opacity;
14.134 + self.scale *= scale;
14.135 + }
14.136 +}
14.137 +
14.138 +
14.139 +- (BOOL)containsPoint:(CGPoint)p
14.140 +{
14.141 + // Make picked-up pieces invisible to hit-testing.
14.142 + // Otherwise, while dragging a Bit, hit-testing the cursor position would always return
14.143 + // that Bit, since it's directly under the cursor...
14.144 + if( self.pickedUp )
14.145 + return NO;
14.146 + else
14.147 + return [super containsPoint: p];
14.148 +}
14.149 +
14.150 +
14.151 +-(id<BitHolder>) holder
14.152 +{
14.153 + // Look for my nearest ancestor that's a BitHolder:
14.154 + for( CALayer *layer=self.superlayer; layer; layer=layer.superlayer ) {
14.155 + if( [layer conformsToProtocol: @protocol(BitHolder)] )
14.156 + return (id<BitHolder>)layer;
14.157 + else if( [layer isKindOfClass: [Bit class]] )
14.158 + return nil;
14.159 + }
14.160 + return nil;
14.161 +}
14.162 +
14.163 +
14.164 +- (void) destroy
14.165 +{
14.166 + // "Pop" the Bit by expanding it 5x as it fades away:
14.167 + self.scale = 5;
14.168 + self.opacity = 0.0;
14.169 + // Removing the view from its superlayer right now would cancel the animations.
14.170 + // Instead, defer the removal until sometime shortly after the animations finish:
14.171 + [self performSelector: @selector(removeFromSuperlayer) withObject: nil afterDelay: 1.0];
14.172 +}
14.173 +
14.174 +
14.175 +@end
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
15.2 +++ b/Source/BitHolder.h Fri Mar 07 11:43:02 2008 -0800
15.3 @@ -0,0 +1,73 @@
15.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
15.5 + http://developer.apple.com/samplecode/GeekGameBoard/
15.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
15.7 +
15.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
15.9 + provided that the following conditions are met:
15.10 +
15.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
15.12 + and the following disclaimer.
15.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
15.14 + conditions and the following disclaimer in the documentation and/or other materials provided
15.15 + with the distribution.
15.16 +
15.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
15.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
15.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
15.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
15.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
15.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
15.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
15.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15.25 +*/
15.26 +#import <Quartz/Quartz.h>
15.27 +@class Bit;
15.28 +
15.29 +
15.30 +/** Protocol for a layer that acts as a container for Bits. */
15.31 +@protocol BitHolder <NSObject>
15.32 +
15.33 +/** Current Bit, or nil if empty */
15.34 +@property (retain) Bit* bit;
15.35 +
15.36 +/** Conveniences for comparing self.bit with nil */
15.37 +@property (readonly, getter=isEmpty) BOOL empty;
15.38 +
15.39 +/** BitHolders will be highlighted while the target of a drag operation */
15.40 +@property BOOL highlighted;
15.41 +
15.42 +
15.43 +/** Tests whether the bit is allowed to be dragged out of me.
15.44 + Returns the input bit, or possibly a different Bit to drag instead, or nil if not allowed.
15.45 + Either -cancelDragBit: or -draggedBit:to: must be called next. */
15.46 +- (Bit*) canDragBit: (Bit*)bit;
15.47 +
15.48 +/** Cancels a pending drag (begun by -canDragBit:). */
15.49 +- (void) cancelDragBit: (Bit*)bit;
15.50 +
15.51 +/** Called after a drag finishes. */
15.52 +- (void) draggedBit: (Bit*)bit to: (id<BitHolder>)dst;
15.53 +
15.54 +
15.55 +/** Tests whether the bit is allowed to be dropped into me.
15.56 + Either -willNotDropBit: or -dropBit:atPoint: must be called next. */
15.57 +- (BOOL) canDropBit: (Bit*)bit atPoint: (CGPoint)point;
15.58 +
15.59 +/** Cancels a pending drop (after -canDropBit:atPoint: was already called.) */
15.60 +- (void) willNotDropBit: (Bit*)bit;
15.61 +
15.62 +/** Finishes a drop. */
15.63 +- (BOOL) dropBit: (Bit*)bit atPoint: (CGPoint)point;
15.64 +
15.65 +@end
15.66 +
15.67 +
15.68 +/** A basic implementation of the BitHolder protocol. */
15.69 +@interface BitHolder : CALayer <BitHolder>
15.70 +{
15.71 + @protected
15.72 + Bit *_bit;
15.73 + BOOL _highlighted;
15.74 +}
15.75 +
15.76 +@end
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
16.2 +++ b/Source/BitHolder.m Fri Mar 07 11:43:02 2008 -0800
16.3 @@ -0,0 +1,80 @@
16.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
16.5 + http://developer.apple.com/samplecode/GeekGameBoard/
16.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
16.7 +
16.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
16.9 + provided that the following conditions are met:
16.10 +
16.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
16.12 + and the following disclaimer.
16.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
16.14 + conditions and the following disclaimer in the documentation and/or other materials provided
16.15 + with the distribution.
16.16 +
16.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
16.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
16.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
16.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
16.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
16.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
16.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16.25 +*/
16.26 +#import "BitHolder.h"
16.27 +#import "Bit.h"
16.28 +#import "QuartzUtils.h"
16.29 +#import "GGBUtils.h"
16.30 +
16.31 +
16.32 +@implementation BitHolder
16.33 +
16.34 +
16.35 +- (void) dealloc
16.36 +{
16.37 + [_bit release];
16.38 + [super dealloc];
16.39 +}
16.40 +
16.41 +
16.42 +- (Bit*) bit
16.43 +{
16.44 + if( _bit && _bit.superlayer != self && !_bit.pickedUp )
16.45 + setObj(&_bit,nil);
16.46 + return _bit;
16.47 +}
16.48 +
16.49 +- (void) setBit: (Bit*)bit
16.50 +{
16.51 + if( bit != self.bit ) {
16.52 + if( bit && _bit )
16.53 + [_bit destroy];
16.54 + setObj(&_bit,bit);
16.55 + ChangeSuperlayer(bit,self,-1);
16.56 + }
16.57 +}
16.58 +
16.59 +- (BOOL) isEmpty {return self.bit==nil;}
16.60 +
16.61 +@synthesize highlighted=_highlighted;
16.62 +
16.63 +- (Bit*) canDragBit: (Bit*)bit
16.64 +{
16.65 + if( bit.superlayer == self && ! bit.unfriendly )
16.66 + return bit;
16.67 + else
16.68 + return nil;
16.69 +}
16.70 +
16.71 +- (void) cancelDragBit: (Bit*)bit { }
16.72 +- (void) draggedBit: (Bit*)bit to: (id<BitHolder>)dst {self.bit = nil;}
16.73 +
16.74 +- (BOOL) canDropBit: (Bit*)bit atPoint: (CGPoint)point {return YES;}
16.75 +- (void) willNotDropBit: (Bit*)bit { }
16.76 +
16.77 +- (BOOL) dropBit: (Bit*)bit atPoint: (CGPoint)point
16.78 +{
16.79 + self.bit = bit;
16.80 + return YES;
16.81 +}
16.82 +
16.83 +@end
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
17.2 +++ b/Source/BoardView.h Fri Mar 07 11:43:02 2008 -0800
17.3 @@ -0,0 +1,60 @@
17.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
17.5 + http://developer.apple.com/samplecode/GeekGameBoard/
17.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
17.7 +
17.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
17.9 + provided that the following conditions are met:
17.10 +
17.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
17.12 + and the following disclaimer.
17.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
17.14 + conditions and the following disclaimer in the documentation and/or other materials provided
17.15 + with the distribution.
17.16 +
17.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
17.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
17.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
17.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
17.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
17.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
17.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
17.25 +*/
17.26 +#import <Cocoa/Cocoa.h>
17.27 +@class Bit, Card, Grid, Game;
17.28 +@protocol BitHolder;
17.29 +
17.30 +
17.31 +/** NSView that hosts a game. */
17.32 +@interface BoardView : NSView
17.33 +{
17.34 + @private
17.35 + Game *_game; // Current Game
17.36 + CALayer *_gameboard; // Game's main layer
17.37 +
17.38 + // Used during mouse-down tracking:
17.39 + NSPoint _dragStartPos; // Starting position of mouseDown
17.40 + Bit *_dragBit; // Bit being dragged
17.41 + id<BitHolder> _oldHolder; // Bit's original holder
17.42 + CALayer *_oldSuperlayer; // Bit's original superlayer
17.43 + int _oldLayerIndex; // Bit's original index in _oldSuperlayer.layers
17.44 + CGPoint _oldPos; // Bit's original x/y position
17.45 + CGPoint _dragOffset; // Offset of mouse position from _dragBit's origin
17.46 + BOOL _dragMoved; // Has the mouse moved more than 3 pixels since mouseDown?
17.47 + id<BitHolder> _dropTarget; // Current BitHolder the cursor is over
17.48 +
17.49 + // Used while handling incoming drags:
17.50 + CALayer *_viewDropTarget; // Current drop target during an incoming drag-n-drop
17.51 + NSDragOperation _viewDropOp; // Current drag operation
17.52 +}
17.53 +
17.54 +- (void) startGameNamed: (NSString*)gameClassName;
17.55 +
17.56 +- (IBAction) enterFullScreen: (id)sender;
17.57 +
17.58 +@property (readonly) Game *game;
17.59 +@property (readonly) CALayer *gameboard;
17.60 +
17.61 +- (CGRect) gameBoardFrame;
17.62 +
17.63 +@end
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
18.2 +++ b/Source/BoardView.m Fri Mar 07 11:43:02 2008 -0800
18.3 @@ -0,0 +1,329 @@
18.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
18.5 + http://developer.apple.com/samplecode/GeekGameBoard/
18.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
18.7 +
18.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
18.9 + provided that the following conditions are met:
18.10 +
18.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
18.12 + and the following disclaimer.
18.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
18.14 + conditions and the following disclaimer in the documentation and/or other materials provided
18.15 + with the distribution.
18.16 +
18.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
18.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
18.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
18.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
18.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
18.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
18.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
18.25 +*/
18.26 +#import "BoardView.h"
18.27 +#import "Bit.h"
18.28 +#import "BitHolder.h"
18.29 +#import "Game.h"
18.30 +#import "QuartzUtils.h"
18.31 +#import "GGBUtils.h"
18.32 +
18.33 +
18.34 +@implementation BoardView
18.35 +
18.36 +
18.37 +@synthesize game=_game, gameboard=_gameboard;
18.38 +
18.39 +
18.40 +- (void) dealloc
18.41 +{
18.42 + [_game release];
18.43 + [super dealloc];
18.44 +}
18.45 +
18.46 +
18.47 +- (void) startGameNamed: (NSString*)gameClassName
18.48 +{
18.49 + if( _gameboard ) {
18.50 + [_gameboard removeFromSuperlayer];
18.51 + _gameboard = nil;
18.52 + }
18.53 + _gameboard = [[CALayer alloc] init];
18.54 + _gameboard.frame = [self gameBoardFrame];
18.55 + _gameboard.autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable;
18.56 + [self.layer addSublayer: _gameboard];
18.57 + [_gameboard release];
18.58 +
18.59 + Class gameClass = NSClassFromString(gameClassName);
18.60 + setObj(&_game, [[gameClass alloc] initWithBoard: _gameboard]);
18.61 +}
18.62 +
18.63 +
18.64 +- (CGRect) gameBoardFrame
18.65 +{
18.66 + return self.layer.bounds;
18.67 +}
18.68 +
18.69 +
18.70 +- (void)resetCursorRects
18.71 +{
18.72 + [super resetCursorRects];
18.73 + [self addCursorRect: self.bounds cursor: [NSCursor openHandCursor]];
18.74 +}
18.75 +
18.76 +
18.77 +- (IBAction) enterFullScreen: (id)sender
18.78 +{
18.79 + if( self.isInFullScreenMode ) {
18.80 + [self exitFullScreenModeWithOptions: nil];
18.81 + } else {
18.82 + [self enterFullScreenMode: self.window.screen
18.83 + withOptions: nil];
18.84 + }
18.85 +}
18.86 +
18.87 +
18.88 +#pragma mark -
18.89 +#pragma mark KEY EVENTS:
18.90 +
18.91 +
18.92 +- (void) keyDown: (NSEvent*)ev
18.93 +{
18.94 + if( self.isInFullScreenMode ) {
18.95 + if( [ev.charactersIgnoringModifiers hasPrefix: @"\033"] ) // Esc key
18.96 + [self enterFullScreen: self];
18.97 + }
18.98 +}
18.99 +
18.100 +
18.101 +#pragma mark -
18.102 +#pragma mark HIT-TESTING:
18.103 +
18.104 +
18.105 +// Hit-testing callbacks (to identify which layers caller is interested in):
18.106 +typedef BOOL (*LayerMatchCallback)(CALayer*);
18.107 +
18.108 +static BOOL layerIsBit( CALayer* layer ) {return [layer isKindOfClass: [Bit class]];}
18.109 +static BOOL layerIsBitHolder( CALayer* layer ) {return [layer conformsToProtocol: @protocol(BitHolder)];}
18.110 +static BOOL layerIsDropTarget( CALayer* layer ) {return [layer respondsToSelector: @selector(draggingEntered:)];}
18.111 +
18.112 +
18.113 +/** Locates the layer at a given point in window coords.
18.114 + If the leaf layer doesn't pass the layer-match callback, the nearest ancestor that does is returned.
18.115 + If outOffset is provided, the point's position relative to the layer is stored into it. */
18.116 +- (CALayer*) hitTestPoint: (NSPoint)locationInWindow
18.117 + forLayerMatching: (LayerMatchCallback)match
18.118 + offset: (CGPoint*)outOffset
18.119 +{
18.120 + CGPoint where = NSPointToCGPoint([self convertPoint: locationInWindow fromView: nil]);
18.121 + where = [_gameboard convertPoint: where fromLayer: self.layer];
18.122 + CALayer *layer = [_gameboard hitTest: where];
18.123 + while( layer ) {
18.124 + if( match(layer) ) {
18.125 + CGPoint bitPos = [self.layer convertPoint: layer.position
18.126 + fromLayer: layer.superlayer];
18.127 + if( outOffset )
18.128 + *outOffset = CGPointMake( bitPos.x-where.x, bitPos.y-where.y);
18.129 + return layer;
18.130 + } else
18.131 + layer = layer.superlayer;
18.132 + }
18.133 + return nil;
18.134 +}
18.135 +
18.136 +
18.137 +#pragma mark -
18.138 +#pragma mark MOUSE CLICKS & DRAGS:
18.139 +
18.140 +
18.141 +- (void) mouseDown: (NSEvent*)ev
18.142 +{
18.143 + _dragStartPos = ev.locationInWindow;
18.144 + _dragBit = (Bit*) [self hitTestPoint: _dragStartPos
18.145 + forLayerMatching: layerIsBit
18.146 + offset: &_dragOffset];
18.147 + if( _dragBit ) {
18.148 + _dragMoved = NO;
18.149 + _dropTarget = nil;
18.150 + _oldHolder = _dragBit.holder;
18.151 + // Ask holder's and game's permission before dragging:
18.152 + if( _oldHolder )
18.153 + _dragBit = [_oldHolder canDragBit: _dragBit];
18.154 + if( _dragBit && ! [_game canBit: _dragBit moveFrom: _oldHolder] ) {
18.155 + [_oldHolder cancelDragBit: _dragBit];
18.156 + _dragBit = nil;
18.157 + }
18.158 + if( ! _dragBit ) {
18.159 + _oldHolder = nil;
18.160 + NSBeep();
18.161 + return;
18.162 + }
18.163 + // Start dragging:
18.164 + _oldSuperlayer = _dragBit.superlayer;
18.165 + _oldLayerIndex = [_oldSuperlayer.sublayers indexOfObjectIdenticalTo: _dragBit];
18.166 + _oldPos = _dragBit.position;
18.167 + ChangeSuperlayer(_dragBit, self.layer, self.layer.sublayers.count);
18.168 + _dragBit.pickedUp = YES;
18.169 + [[NSCursor closedHandCursor] push];
18.170 + } else
18.171 + NSBeep();
18.172 +}
18.173 +
18.174 +- (void) mouseDragged: (NSEvent*)ev
18.175 +{
18.176 + if( _dragBit ) {
18.177 + // Get the mouse position, and see if we've moved 3 pixels since the mouseDown:
18.178 + NSPoint pos = ev.locationInWindow;
18.179 + if( fabs(pos.x-_dragStartPos.x)>=3 || fabs(pos.y-_dragStartPos.y)>=3 )
18.180 + _dragMoved = YES;
18.181 +
18.182 + // Move the _dragBit (without animation -- it's unnecessary and slows down responsiveness):
18.183 + NSPoint where = [self convertPoint: pos fromView: nil];
18.184 + where.x += _dragOffset.x;
18.185 + where.y += _dragOffset.y;
18.186 +
18.187 + CGPoint newPos = [_dragBit.superlayer convertPoint: NSPointToCGPoint(where)
18.188 + fromLayer: self.layer];
18.189 +
18.190 + [CATransaction flush];
18.191 + [CATransaction begin];
18.192 + [CATransaction setValue:(id)kCFBooleanTrue
18.193 + forKey:kCATransactionDisableActions];
18.194 + _dragBit.position = newPos;
18.195 + [CATransaction commit];
18.196 +
18.197 + // Find what it's over:
18.198 + id<BitHolder> target = (id<BitHolder>) [self hitTestPoint: where
18.199 + forLayerMatching: layerIsBitHolder
18.200 + offset: NULL];
18.201 + if( target == _oldHolder )
18.202 + target = nil;
18.203 + if( target != _dropTarget ) {
18.204 + [_dropTarget willNotDropBit: _dragBit];
18.205 + _dropTarget.highlighted = NO;
18.206 + _dropTarget = nil;
18.207 + }
18.208 + if( target ) {
18.209 + CGPoint targetPos = [(CALayer*)target convertPoint: _dragBit.position
18.210 + fromLayer: _dragBit.superlayer];
18.211 + if( [target canDropBit: _dragBit atPoint: targetPos]
18.212 + && [_game canBit: _dragBit moveFrom: _oldHolder to: target] ) {
18.213 + _dropTarget = target;
18.214 + _dropTarget.highlighted = YES;
18.215 + }
18.216 + }
18.217 + }
18.218 +}
18.219 +
18.220 +- (void) mouseUp: (NSEvent*)ev
18.221 +{
18.222 + if( _dragBit ) {
18.223 + if( _dragMoved ) {
18.224 + // Update the drag tracking to the final mouse position:
18.225 + [self mouseDragged: ev];
18.226 + _dropTarget.highlighted = NO;
18.227 + _dragBit.pickedUp = NO;
18.228 +
18.229 + // Is the move legal?
18.230 + if( _dropTarget && [_dropTarget dropBit: _dragBit
18.231 + atPoint: [(CALayer*)_dropTarget convertPoint: _dragBit.position
18.232 + fromLayer: _dragBit.superlayer]] ) {
18.233 + // Yes, notify the interested parties:
18.234 + [_oldHolder draggedBit: _dragBit to: _dropTarget];
18.235 + [_game bit: _dragBit movedFrom: _oldHolder to: _dropTarget];
18.236 + } else {
18.237 + // Nope, cancel:
18.238 + [_dropTarget willNotDropBit: _dragBit];
18.239 + ChangeSuperlayer(_dragBit, _oldSuperlayer, _oldLayerIndex);
18.240 + _dragBit.position = _oldPos;
18.241 + [_oldHolder cancelDragBit: _dragBit];
18.242 + }
18.243 + } else {
18.244 + // Just a click, without a drag:
18.245 + _dropTarget.highlighted = NO;
18.246 + _dragBit.pickedUp = NO;
18.247 + ChangeSuperlayer(_dragBit, _oldSuperlayer, _oldLayerIndex);
18.248 + [_oldHolder cancelDragBit: _dragBit];
18.249 + if( ! [_game clickedBit: _dragBit] )
18.250 + NSBeep();
18.251 + }
18.252 + _dropTarget = nil;
18.253 + _dragBit = nil;
18.254 + [NSCursor pop];
18.255 + }
18.256 +}
18.257 +
18.258 +
18.259 +#pragma mark -
18.260 +#pragma mark INCOMING DRAGS:
18.261 +
18.262 +
18.263 +// subroutine to call the target
18.264 +static int tell( id target, SEL selector, id arg, int defaultValue )
18.265 +{
18.266 + if( target && [target respondsToSelector: selector] )
18.267 + return (ssize_t) [target performSelector: selector withObject: arg];
18.268 + else
18.269 + return defaultValue;
18.270 +}
18.271 +
18.272 +
18.273 +- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
18.274 +{
18.275 + _viewDropTarget = [self hitTestPoint: [sender draggingLocation]
18.276 + forLayerMatching: layerIsDropTarget
18.277 + offset: NULL];
18.278 + _viewDropOp = _viewDropTarget ?[_viewDropTarget draggingEntered: sender] :NSDragOperationNone;
18.279 + return _viewDropOp;
18.280 +}
18.281 +
18.282 +- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
18.283 +{
18.284 + CALayer *target = [self hitTestPoint: [sender draggingLocation]
18.285 + forLayerMatching: layerIsDropTarget
18.286 + offset: NULL];
18.287 + if( target == _viewDropTarget ) {
18.288 + if( _viewDropTarget )
18.289 + _viewDropOp = tell(_viewDropTarget,@selector(draggingUpdated:),sender,_viewDropOp);
18.290 + } else {
18.291 + tell(_viewDropTarget,@selector(draggingExited:),sender,0);
18.292 + _viewDropTarget = target;
18.293 + if( _viewDropTarget )
18.294 + _viewDropOp = [_viewDropTarget draggingEntered: sender];
18.295 + else
18.296 + _viewDropOp = NSDragOperationNone;
18.297 + }
18.298 + return _viewDropOp;
18.299 +}
18.300 +
18.301 +- (BOOL)wantsPeriodicDraggingUpdates
18.302 +{
18.303 + return (_viewDropTarget!=nil);
18.304 +}
18.305 +
18.306 +- (void)draggingExited:(id <NSDraggingInfo>)sender
18.307 +{
18.308 + tell(_viewDropTarget,@selector(draggingExited:),sender,0);
18.309 + _viewDropTarget = nil;
18.310 +}
18.311 +
18.312 +- (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
18.313 +{
18.314 + return tell(_viewDropTarget,@selector(prepareForDragOperation:),sender,YES);
18.315 +}
18.316 +
18.317 +- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
18.318 +{
18.319 + return [_viewDropTarget performDragOperation: sender];
18.320 +}
18.321 +
18.322 +- (void)concludeDragOperation:(id <NSDraggingInfo>)sender
18.323 +{
18.324 + tell(_viewDropTarget,@selector(concludeDragOperation:),sender,0);
18.325 +}
18.326 +
18.327 +- (void)draggingEnded:(id <NSDraggingInfo>)sender
18.328 +{
18.329 + tell(_viewDropTarget,@selector(draggingEnded:),sender,0);
18.330 +}
18.331 +
18.332 +@end
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
19.2 +++ b/Source/Card.h Fri Mar 07 11:43:02 2008 -0800
19.3 @@ -0,0 +1,66 @@
19.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
19.5 + http://developer.apple.com/samplecode/GeekGameBoard/
19.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
19.7 +
19.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
19.9 + provided that the following conditions are met:
19.10 +
19.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
19.12 + and the following disclaimer.
19.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
19.14 + conditions and the following disclaimer in the documentation and/or other materials provided
19.15 + with the distribution.
19.16 +
19.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
19.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
19.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
19.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
19.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
19.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
19.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
19.25 +*/
19.26 +#import "Bit.h"
19.27 +
19.28 +
19.29 +/** Hardcoded dimensions of a Card */
19.30 +#define kCardWidth 100
19.31 +#define kCardHeight 150
19.32 +
19.33 +
19.34 +/* A card of some type (playing card, Community Chest, money, ...)
19.35 + Has an identifying serial number (could be in the range 1..52 for playing cards).
19.36 + Can be face-up or down. */
19.37 +@interface Card : Bit
19.38 +{
19.39 + @private
19.40 + int _serialNumber;
19.41 + CALayer *_front, *_back;
19.42 + BOOL _faceUp;
19.43 +}
19.44 +
19.45 +/** The range of serialNumbers used for this type of card. Used when instantiating Decks.
19.46 + Abstract; must be overridden. */
19.47 ++ (NSRange) serialNumberRange;
19.48 +
19.49 +- (id) initWithSerialNumber: (int)serial position: (CGPoint)pos;
19.50 +
19.51 +@property (readonly) int serialNumber;
19.52 +
19.53 +/** Cards can be face-up or face-down, of course. */
19.54 +@property BOOL faceUp;
19.55 +
19.56 +
19.57 +//protected -- for subclasses only:
19.58 +
19.59 +/** Creates the sub-layer that displays the front side of the card.
19.60 + Subclasses should probably call the superclass method, configure the layer it returns
19.61 + (based on the card's serialNumber) and then return that layer. */
19.62 +- (CALayer*) createFront;
19.63 +
19.64 +/** Creates the sub-layer that displays the back side of the card.
19.65 + Subclasses should probably call the superclass method, configure the layer it returns and
19.66 + return that layer. */
19.67 +- (CALayer*) createBack;
19.68 +
19.69 +@end
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
20.2 +++ b/Source/Card.m Fri Mar 07 11:43:02 2008 -0800
20.3 @@ -0,0 +1,186 @@
20.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
20.5 + http://developer.apple.com/samplecode/GeekGameBoard/
20.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
20.7 +
20.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
20.9 + provided that the following conditions are met:
20.10 +
20.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
20.12 + and the following disclaimer.
20.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
20.14 + conditions and the following disclaimer in the documentation and/or other materials provided
20.15 + with the distribution.
20.16 +
20.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
20.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
20.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
20.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
20.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
20.25 +*/
20.26 +#import "Card.h"
20.27 +#import "QuartzUtils.h"
20.28 +
20.29 +
20.30 +@implementation Card
20.31 +
20.32 +
20.33 +static CATransform3D kFaceUpTransform, kFaceDownTransform;
20.34 +
20.35 ++ (void) initialize
20.36 +{
20.37 + if( self==[Card class] ) {
20.38 + kFaceUpTransform = kFaceDownTransform = CATransform3DIdentity;
20.39 + // Construct a 180-degree rotation matrix:
20.40 + kFaceDownTransform.m11 = kFaceDownTransform.m33 = -1;
20.41 + // The more obvious way to create kFaceDownTransform would be to call
20.42 + // CATransform3DMakeRotation(pi,0,1,0), but due to round-off errors, that transform
20.43 + // will have non-zero values in some other places, making it appear to CA as a true
20.44 + // 3D transform; this will then cause unexpected clipping behaviors when used.
20.45 + }
20.46 +}
20.47 +
20.48 +
20.49 ++ (NSRange) serialNumberRange;
20.50 +{
20.51 + NSAssert1(NO,@"%@ forgot to override +serialNumberRange",self);
20.52 + return NSMakeRange(0,0);
20.53 +}
20.54 +
20.55 +
20.56 +- (id) initWithSerialNumber: (int)serial position: (CGPoint)pos
20.57 +{
20.58 + self = [super init];
20.59 + if (self != nil) {
20.60 + _serialNumber = serial;
20.61 + self.bounds = CGRectMake(0,0,kCardWidth,kCardHeight);
20.62 + self.position = pos;
20.63 + self.edgeAntialiasingMask = 0;
20.64 + _back = [self createBack];
20.65 + [self addSublayer: _back];
20.66 + _front = [self createFront];
20.67 + _front.transform = kFaceDownTransform;
20.68 + [self addSublayer: _front];
20.69 + }
20.70 + return self;
20.71 +}
20.72 +
20.73 +
20.74 +- (void)encodeWithCoder:(NSCoder *)aCoder
20.75 +{
20.76 + [super encodeWithCoder: aCoder];
20.77 + [aCoder encodeInt: _serialNumber forKey: @"serialNumber"];
20.78 +}
20.79 +
20.80 +- (id)initWithCoder:(NSCoder *)aDecoder
20.81 +{
20.82 + self = [super initWithCoder: aDecoder];
20.83 + if( self ) {
20.84 + _serialNumber = [aDecoder decodeIntForKey: @"serialNumber"];
20.85 + }
20.86 + return self;
20.87 +}
20.88 +
20.89 +
20.90 +- (NSString*) description
20.91 +{
20.92 + return [NSString stringWithFormat: @"%@[#%i]",self.class,_serialNumber];
20.93 +}
20.94 +
20.95 +
20.96 +@synthesize serialNumber=_serialNumber;
20.97 +
20.98 +
20.99 +- (BOOL) faceUp
20.100 +{
20.101 + return _faceUp;
20.102 +}
20.103 +
20.104 +- (void) setFaceUp: (BOOL)up
20.105 +{
20.106 + if( up != _faceUp ) {
20.107 + // The Card has separate sub-layers for its front and back. At any time, one of them
20.108 + // is hidden, by having a 180 degree rotation about the Y axis.
20.109 + // To flip the card, both front and back layers are flipped over.
20.110 + CATransform3D xform;
20.111 + xform = up ?kFaceUpTransform :kFaceDownTransform;
20.112 + _front.transform = xform;
20.113 +
20.114 + xform = up ?kFaceDownTransform :kFaceUpTransform;
20.115 + _back.transform = xform;
20.116 + _faceUp = up;
20.117 + }
20.118 +}
20.119 +
20.120 +
20.121 +- (CALayer*) createFront
20.122 +{
20.123 + CALayer *front = [[CALayer alloc] init];
20.124 + front.bounds = CGRectMake(0,0,kCardWidth,kCardHeight);
20.125 + front.position = CGPointMake(kCardWidth/2,kCardHeight/2);
20.126 + front.edgeAntialiasingMask = 0;
20.127 + front.backgroundColor = kWhiteColor;
20.128 + front.cornerRadius = 8;
20.129 + front.borderWidth = 1;
20.130 + front.borderColor = CGColorCreateGenericGray(0.7, 1.0);
20.131 + front.doubleSided = NO; // this makes the layer invisible when it's flipped
20.132 + return [front autorelease];
20.133 +}
20.134 +
20.135 +
20.136 +- (CALayer*) createBack
20.137 +{
20.138 + CGSize size = self.bounds.size;
20.139 + CALayer *back = [[CALayer alloc] init];
20.140 + back.bounds = CGRectMake(0,0,size.width,size.height);
20.141 + back.position = CGPointMake(kCardWidth/2,kCardHeight/2);
20.142 + back.contents = (id) GetCGImageNamed(@"/Library/Desktop Pictures/Classic Aqua Blue.jpg");
20.143 + back.contentsGravity = kCAGravityResize;
20.144 + back.masksToBounds = YES;
20.145 + back.borderWidth = 4;
20.146 + back.borderColor = kWhiteColor;
20.147 + back.cornerRadius = 8;
20.148 + back.edgeAntialiasingMask = 0;
20.149 + back.doubleSided = NO; // this makes the layer invisible when it's flipped
20.150 +
20.151 + CATextLayer *label = AddTextLayer(back, @"\u2603", // Unicode snowman character
20.152 + [NSFont systemFontOfSize: 0.9*size.width],
20.153 + kCALayerWidthSizable|kCALayerHeightSizable);
20.154 + label.foregroundColor = CGColorCreateGenericGray(1.0,0.5);
20.155 + return [back autorelease];
20.156 +}
20.157 +
20.158 +
20.159 +#pragma mark -
20.160 +#pragma mark DRAG-AND-DROP:
20.161 +
20.162 +
20.163 +// An image from another app can be dragged onto a Card to change its background. */
20.164 +
20.165 +
20.166 +- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
20.167 +{
20.168 + NSPasteboard *pb = [sender draggingPasteboard];
20.169 + if( [NSImage canInitWithPasteboard: pb] )
20.170 + return NSDragOperationCopy;
20.171 + else
20.172 + return NSDragOperationNone;
20.173 +}
20.174 +
20.175 +- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
20.176 +{
20.177 + CGImageRef image = GetCGImageFromPasteboard([sender draggingPasteboard]);
20.178 + if( image ) {
20.179 + CALayer *face = _faceUp ?_front :_back;
20.180 + face.contents = (id) image;
20.181 + face.contentsGravity = kCAGravityResizeAspectFill;
20.182 + face.masksToBounds = YES;
20.183 + return YES;
20.184 + } else
20.185 + return NO;
20.186 +}
20.187 +
20.188 +
20.189 +@end
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
21.2 +++ b/Source/CheckersGame.h Fri Mar 07 11:43:02 2008 -0800
21.3 @@ -0,0 +1,41 @@
21.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
21.5 + http://developer.apple.com/samplecode/GeekGameBoard/
21.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
21.7 +
21.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
21.9 + provided that the following conditions are met:
21.10 +
21.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
21.12 + and the following disclaimer.
21.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
21.14 + conditions and the following disclaimer in the documentation and/or other materials provided
21.15 + with the distribution.
21.16 +
21.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
21.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
21.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
21.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
21.25 +*/
21.26 +#import "Game.h"
21.27 +@class Grid;
21.28 +
21.29 +
21.30 +/** US Checkers, known as Draughts in the UK. (Other countries use similar but not identical rules.)
21.31 + See: http://en.wikipedia.org/wiki/Draughts */
21.32 +@interface CheckersGame : Game
21.33 +{
21.34 + int _numPieces[2];
21.35 +}
21.36 +
21.37 +// For subclasses (See HexchequerGame):
21.38 +- (void) addPieces: (NSString*)imageName
21.39 + toGrid: (Grid*)grid
21.40 + forPlayer: (int)playerNum
21.41 + rows: (NSRange)rows
21.42 + alternating: (BOOL)alternating;
21.43 +
21.44 +@end
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
22.2 +++ b/Source/CheckersGame.m Fri Mar 07 11:43:02 2008 -0800
22.3 @@ -0,0 +1,156 @@
22.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
22.5 + http://developer.apple.com/samplecode/GeekGameBoard/
22.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
22.7 +
22.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
22.9 + provided that the following conditions are met:
22.10 +
22.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
22.12 + and the following disclaimer.
22.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
22.14 + conditions and the following disclaimer in the documentation and/or other materials provided
22.15 + with the distribution.
22.16 +
22.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
22.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
22.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
22.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
22.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22.25 +*/
22.26 +#import "CheckersGame.h"
22.27 +#import "Grid.h"
22.28 +#import "Piece.h"
22.29 +#import "QuartzUtils.h"
22.30 +
22.31 +
22.32 +@implementation CheckersGame
22.33 +
22.34 +
22.35 +- (void) addPieces: (NSString*)imageName
22.36 + toGrid: (Grid*)grid
22.37 + forPlayer: (int)playerNum
22.38 + rows: (NSRange)rows
22.39 + alternating: (BOOL)alternating
22.40 +{
22.41 + Piece *prototype = [[Piece alloc] initWithImageNamed: imageName scale: floor(grid.spacing.width * 0.8)];
22.42 + prototype.owner = [self.players objectAtIndex: playerNum];
22.43 + unsigned cols=grid.columns;
22.44 + for( unsigned row=rows.location; row<NSMaxRange(rows); row++ )
22.45 + for( unsigned col=0; col<cols; col++ ) {
22.46 + if( !alternating || ((row+col) & 1) == 0 ) {
22.47 + GridCell *cell = [grid cellAtRow: row column: col];
22.48 + if( cell ) {
22.49 + Piece *piece = [prototype copy];
22.50 + cell.bit = piece;
22.51 + [piece release];
22.52 + //cell.bit.rotation = random() % 360; // keeps pieces from looking too samey
22.53 + _numPieces[playerNum]++;
22.54 + }
22.55 + }
22.56 + }
22.57 + [prototype release];
22.58 +}
22.59 +
22.60 +
22.61 +- (Grid*) x_makeGrid
22.62 +{
22.63 + RectGrid *grid = [[[RectGrid alloc] initWithRows: 8 columns: 8 frame: _board.bounds] autorelease];
22.64 + CGPoint pos = grid.position;
22.65 + pos.x = floor((_board.bounds.size.width-grid.frame.size.width)/2);
22.66 + [grid addAllCells];
22.67 + grid.position = pos;
22.68 + grid.allowsMoves = YES;
22.69 + grid.allowsCaptures = NO;
22.70 + grid.cellColor = CGColorCreateGenericGray(0.0, 0.25);
22.71 + grid.altCellColor = CGColorCreateGenericGray(1.0, 0.25);
22.72 + grid.lineColor = nil;
22.73 + [self addPieces: @"Green Ball.png" toGrid: grid forPlayer: 0 rows: NSMakeRange(0,3) alternating: YES];
22.74 + [self addPieces: @"Red Ball.png" toGrid: grid forPlayer: 1 rows: NSMakeRange(5,3) alternating: YES];
22.75 + return grid;
22.76 +}
22.77 +
22.78 +
22.79 +- (id) initWithBoard: (CALayer*)board
22.80 +{
22.81 + self = [super initWithBoard: board];
22.82 + if (self != nil) {
22.83 + [self setNumberOfPlayers: 2];
22.84 + [board addSublayer: [self x_makeGrid]];
22.85 + [self nextPlayer];
22.86 + }
22.87 + return self;
22.88 +}
22.89 +
22.90 +
22.91 +- (BOOL) canBit: (Bit*)bit moveFrom: (id<BitHolder>)srcHolder to: (id<BitHolder>)dstHolder
22.92 +{
22.93 + Square *src=(Square*)srcHolder, *dst=(Square*)dstHolder;
22.94 + if( [bit valueForKey: @"King"] )
22.95 + if( dst==src.bl || dst==src.br || dst==src.l || dst==src.r
22.96 + || (src.bl.bit.unfriendly && dst==src.bl.bl) || (src.br.bit.unfriendly && dst==src.br.br) )
22.97 + return YES;
22.98 + return dst==src.fl || dst==src.fr
22.99 + || (src.fl.bit.unfriendly && dst==src.fl.fl) || (src.fr.bit.unfriendly && dst==src.fr.fr);
22.100 +}
22.101 +
22.102 +- (void) bit: (Bit*)bit movedFrom: (id<BitHolder>)srcHolder to: (id<BitHolder>)dstHolder
22.103 +{
22.104 + Square *src=(Square*)srcHolder, *dst=(Square*)dstHolder;
22.105 + int playerIndex = self.currentPlayer.index;
22.106 + BOOL isKing = ([bit valueForKey: @"King"] != nil);
22.107 +
22.108 + [[NSSound soundNamed: (isKing ?@"Funk" :@"Tink")] play];
22.109 +
22.110 + // "King" a piece that made it to the last row:
22.111 + if( dst.row == (playerIndex ?0 :7) )
22.112 + if( ! isKing ) {
22.113 + [[NSSound soundNamed: @"Blow"] play];
22.114 + bit.scale = 1.4;
22.115 + [bit setValue: @"King" forKey: @"King"];
22.116 + // don't set isKing flag - piece can't jump again after being kinged.
22.117 + }
22.118 +
22.119 + // Check for a capture:
22.120 + Square *capture = nil;
22.121 + if(dst==src.fl.fl)
22.122 + capture = src.fl;
22.123 + else if(dst==src.fr.fr)
22.124 + capture = src.fr;
22.125 + else if(dst==src.bl.bl)
22.126 + capture = src.bl;
22.127 + else if(dst==src.br.br)
22.128 + capture = src.br;
22.129 +
22.130 + if( capture ) {
22.131 + [[NSSound soundNamed: @"Pop"] play];
22.132 + Bit *bit = capture.bit;
22.133 + _numPieces[bit.owner.index]--;
22.134 + [bit destroy];
22.135 +
22.136 + // Now check if another capture is possible. If so, don't end the turn:
22.137 + if( (dst.fl.bit.unfriendly && dst.fl.fl.empty) || (dst.fr.bit.unfriendly && dst.fr.fr.empty) )
22.138 + return;
22.139 + if( isKing )
22.140 + if( (dst.bl.bit.unfriendly && dst.bl.bl.empty) || (dst.br.bit.unfriendly && dst.br.br.empty) )
22.141 + return;
22.142 + }
22.143 +
22.144 + [self endTurn];
22.145 +}
22.146 +
22.147 +- (Player*) checkForWinner
22.148 +{
22.149 + // Whoever runs out of pieces loses:
22.150 + if( _numPieces[0]==0 )
22.151 + return [self.players objectAtIndex: 1];
22.152 + else if( _numPieces[1]==0 )
22.153 + return [self.players objectAtIndex: 0];
22.154 + else
22.155 + return nil;
22.156 +}
22.157 +
22.158 +
22.159 +@end
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
23.2 +++ b/Source/Deck.h Fri Mar 07 11:43:02 2008 -0800
23.3 @@ -0,0 +1,57 @@
23.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
23.5 + http://developer.apple.com/samplecode/GeekGameBoard/
23.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
23.7 +
23.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
23.9 + provided that the following conditions are met:
23.10 +
23.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
23.12 + and the following disclaimer.
23.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
23.14 + conditions and the following disclaimer in the documentation and/or other materials provided
23.15 + with the distribution.
23.16 +
23.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
23.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
23.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
23.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
23.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23.25 +*/
23.26 +#import "BitHolder.h"
23.27 +@class Card;
23.28 +
23.29 +
23.30 +/** A pile of Cards. Unlike a Stack, only the top card is visible or accessible;
23.31 + so as an optimization, it's the only one that's added to the layer tree. */
23.32 +@interface Deck : BitHolder
23.33 +{
23.34 + NSMutableArray *_cards;
23.35 +}
23.36 +
23.37 +/** Creates an empty Deck. */
23.38 +- (id) init;
23.39 +
23.40 +/** Creates a Deck populated with a full set of cards (in order.) */
23.41 +- (id) initWithCardsOfClass: (Class)klass;
23.42 +
23.43 +@property (readonly) NSArray *cards;
23.44 +@property (readonly) Card *topCard; // same as the -bit property
23.45 +
23.46 +/** Randomly shuffles all the cards in the Deck. */
23.47 +- (void) shuffle;
23.48 +
23.49 +/** Flips over the Deck: Reverses the order of cards, and inverts their -faceUp flags. */
23.50 +- (void) flip;
23.51 +
23.52 +- (void) addCard: (Card*)card;
23.53 +- (void) addCardAtBottom: (Card*)card;
23.54 +- (void) addCardAtRandom: (Card*)card;
23.55 +- (void) addCards: (NSArray*)cards;
23.56 +
23.57 +- (Card*) removeTopCard;
23.58 +- (NSArray*) removeAllCards;
23.59 +
23.60 +@end
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
24.2 +++ b/Source/Deck.m Fri Mar 07 11:43:02 2008 -0800
24.3 @@ -0,0 +1,267 @@
24.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
24.5 + http://developer.apple.com/samplecode/GeekGameBoard/
24.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
24.7 +
24.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
24.9 + provided that the following conditions are met:
24.10 +
24.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
24.12 + and the following disclaimer.
24.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
24.14 + conditions and the following disclaimer in the documentation and/or other materials provided
24.15 + with the distribution.
24.16 +
24.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
24.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
24.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
24.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
24.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24.25 +*/
24.26 +#import "Deck.h"
24.27 +#import "Card.h"
24.28 +#import "Stack.h"
24.29 +#import "QuartzUtils.h"
24.30 +#import "GGBUtils.h"
24.31 +
24.32 +
24.33 +@interface Deck ()
24.34 +- (void) setCards: (NSMutableArray*)cards;
24.35 +- (void) x_showTopCard;
24.36 +@end
24.37 +
24.38 +
24.39 +@implementation Deck
24.40 +
24.41 +
24.42 +- (id) init
24.43 +{
24.44 + self = [super init];
24.45 + if (self != nil) {
24.46 + self.bounds = CGRectMake(0,0,kCardWidth,kCardHeight);
24.47 + self.cornerRadius = 8;
24.48 + self.backgroundColor = kAlmostInvisibleWhiteColor;
24.49 + self.borderColor = kHighlightColor;
24.50 + self.cards = [NSMutableArray array];
24.51 + }
24.52 + return self;
24.53 +}
24.54 +
24.55 +- (id) initWithCardsOfClass: (Class)klass
24.56 +{
24.57 + self = [self init];
24.58 + if (self != nil) {
24.59 + // Create a full deck of cards:
24.60 + NSRange serials = [klass serialNumberRange];
24.61 + for( int i=serials.location; i<NSMaxRange(serials); i++ ) {
24.62 + Card *card = [[klass alloc] initWithSerialNumber: i
24.63 + position: CGPointZero];
24.64 + [_cards addObject: card];
24.65 + [card release];
24.66 + }
24.67 + [self x_showTopCard];
24.68 + }
24.69 + return self;
24.70 +}
24.71 +
24.72 +
24.73 +- (void) dealloc
24.74 +{
24.75 + [_cards release];
24.76 + [super dealloc];
24.77 +}
24.78 +
24.79 +
24.80 +- (NSArray*) cards {return _cards;}
24.81 +- (void) setCards: (NSMutableArray*)cards {setObj(&_cards,cards);}
24.82 +
24.83 +- (Card*) topCard {return (Card*)_bit;}
24.84 +
24.85 +
24.86 +- (void) setBit: (Bit*)bit
24.87 +{
24.88 + NSAssert(NO,@"Don't call -setBit");
24.89 +}
24.90 +
24.91 +
24.92 +- (void) x_removeObsoleteCard: (Card*)card
24.93 +{
24.94 + if( [_cards containsObject: card] && card != _bit )
24.95 + RemoveImmediately(card);
24.96 +}
24.97 +
24.98 +
24.99 +/** Sync up my display with the _cards array. The last element of _cards should be shown,
24.100 + and no others (they shouldn't even be in the layer tree, for performance reasons.) */
24.101 +- (void) x_showTopCard
24.102 +{
24.103 + Card *curTopCard = [_cards lastObject];
24.104 + if( curTopCard != _bit ) {
24.105 + if( _bit ) {
24.106 + // Remove card that used to be the top one
24.107 + if( [_cards containsObject: _bit] ) // wait till new card animates on top of it
24.108 + [self performSelector: @selector(x_removeObsoleteCard:) withObject: _bit afterDelay: 1.0];
24.109 + else
24.110 + RemoveImmediately(_bit);
24.111 + }
24.112 + _bit = curTopCard;
24.113 + if( curTopCard ) {
24.114 + if( curTopCard.superlayer==self ) {
24.115 + [self addSublayer: curTopCard]; // move to top
24.116 + curTopCard.position = GetCGRectCenter(self.bounds);
24.117 + } else {
24.118 + if( curTopCard.superlayer )
24.119 + ChangeSuperlayer(curTopCard, self, -1);
24.120 + curTopCard.position = GetCGRectCenter(self.bounds);
24.121 + if( ! curTopCard.superlayer )
24.122 + [self addSublayer: curTopCard];
24.123 + }
24.124 + }
24.125 + }
24.126 +}
24.127 +
24.128 +
24.129 +- (void) shuffle
24.130 +{
24.131 + int n = _cards.count;
24.132 + NSMutableArray *shuffled = [NSMutableArray arrayWithCapacity: n];
24.133 + for( ; n > 0; n-- ) {
24.134 + int i = random() % n;
24.135 + Card *card = [_cards objectAtIndex: i];
24.136 + [shuffled addObject: card];
24.137 + [_cards removeObjectAtIndex: i];
24.138 + }
24.139 + self.cards = shuffled;
24.140 + [self x_showTopCard];
24.141 +}
24.142 +
24.143 +
24.144 +- (void) flip
24.145 +{
24.146 + int n = _cards.count;
24.147 + NSMutableArray *flipped = [NSMutableArray arrayWithCapacity: n];
24.148 + while( --n >= 0 ) {
24.149 + Card *card = [_cards objectAtIndex: n];
24.150 + card.faceUp = ! card.faceUp;
24.151 + [flipped addObject: card];
24.152 + }
24.153 + self.cards = flipped;
24.154 + [self x_showTopCard];
24.155 +}
24.156 +
24.157 +
24.158 +- (void) addCard: (Card*)card
24.159 +{
24.160 + [_cards addObject: card];
24.161 + [self x_showTopCard];
24.162 +}
24.163 +
24.164 +- (void) addCardAtBottom: (Card*)card
24.165 +{
24.166 + [_cards insertObject: card atIndex: 0];
24.167 + if( _cards.count==1 )
24.168 + [self x_showTopCard];
24.169 +}
24.170 +
24.171 +- (void) addCardAtRandom: (Card*)card
24.172 +{
24.173 + // Put the card at some random location, but _not_ on top (unless the deck is empty.)
24.174 + int n = _cards.count;
24.175 + if( n==0 )
24.176 + [self addCard: card];
24.177 + else
24.178 + [_cards insertObject: card atIndex: (random() % (n-1))];
24.179 +}
24.180 +
24.181 +
24.182 +- (void) addCards: (NSArray*)cards
24.183 +{
24.184 + [_cards addObjectsFromArray: cards];
24.185 + [self x_showTopCard];
24.186 +}
24.187 +
24.188 +
24.189 +- (BOOL) addBit: (Bit*)bit
24.190 +{
24.191 + if( [bit isKindOfClass: [DraggedStack class]] ) {
24.192 + // Convert a DraggedStack back to a group of Cards:
24.193 + for( Bit *subBit in [(DraggedStack*)bit bits] )
24.194 + if( ! [self addBit: subBit] )
24.195 + return NO;
24.196 + return YES;
24.197 + } else if( [bit isKindOfClass: [Card class]] ) {
24.198 + [self addCard: (Card*)bit];
24.199 + return YES;
24.200 + } else
24.201 + return NO;
24.202 +}
24.203 +
24.204 +
24.205 +- (Card*) removeTopCard
24.206 +{
24.207 + Card *card = [_cards lastObject];
24.208 + if( card ) {
24.209 + [[card retain] autorelease];
24.210 + [_cards removeLastObject];
24.211 + _bit = nil; // keep it from being removed from superlayer by _showTopCard
24.212 + [self x_showTopCard];
24.213 + }
24.214 + return card;
24.215 +}
24.216 +
24.217 +
24.218 +- (NSArray*) removeAllCards
24.219 +{
24.220 + NSArray *removedCards = [[_cards retain] autorelease];
24.221 + self.cards = [NSMutableArray array];
24.222 + [removedCards makeObjectsPerformSelector: @selector(removeFromSuperlayer)];
24.223 + [self x_showTopCard];
24.224 + return removedCards;
24.225 +}
24.226 +
24.227 +
24.228 +#pragma mark -
24.229 +#pragma mark BITHOLDER INTERFACE:
24.230 +
24.231 +
24.232 +- (Bit*) canDragBit: (Bit*)bit
24.233 +{
24.234 + if( bit == _bit ) {
24.235 + [bit retain];
24.236 + [_cards removeObjectIdenticalTo: bit];
24.237 + _bit = nil; // prevent the card from being removed from my layer
24.238 + [self x_showTopCard];
24.239 + return [bit autorelease];
24.240 + } else
24.241 + return nil;
24.242 +}
24.243 +
24.244 +- (void) cancelDragBit: (Bit*)bit
24.245 +{
24.246 + [self addCard: (Card*)bit];
24.247 +}
24.248 +
24.249 +- (void) draggedBit: (Bit*)bit to: (id<BitHolder>)dst {}
24.250 +
24.251 +
24.252 +- (void) setHighlighted: (BOOL)h
24.253 +{
24.254 + [super setHighlighted: h];
24.255 + self.borderWidth = h ?6 :0;
24.256 +}
24.257 +
24.258 +- (BOOL) canDropBit: (Bit*)bit atPoint: (CGPoint)point
24.259 +{
24.260 + return [bit isKindOfClass: [Card class]] || [bit isKindOfClass: [DraggedStack class]];
24.261 +}
24.262 +
24.263 +- (BOOL) dropBit: (Bit*)bit atPoint: (CGPoint)point
24.264 +{
24.265 + return [self addBit: bit];
24.266 +}
24.267 +
24.268 +
24.269 +
24.270 +@end
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
25.2 +++ b/Source/DemoBoardView.h Fri Mar 07 11:43:02 2008 -0800
25.3 @@ -0,0 +1,35 @@
25.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
25.5 + http://developer.apple.com/samplecode/GeekGameBoard/
25.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
25.7 +
25.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
25.9 + provided that the following conditions are met:
25.10 +
25.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
25.12 + and the following disclaimer.
25.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
25.14 + conditions and the following disclaimer in the documentation and/or other materials provided
25.15 + with the distribution.
25.16 +
25.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
25.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
25.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
25.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
25.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25.25 +*/
25.26 +#import "BoardView.h"
25.27 +
25.28 +
25.29 +/** Simple subclass of BoardView that lets you pick a game from a menu,
25.30 + and displays the game status in a headline. */
25.31 +@interface DemoBoardView : BoardView
25.32 +{
25.33 + CATextLayer *_headline;
25.34 +}
25.35 +
25.36 +- (IBAction) startGameFromMenu: (id)sender;
25.37 +
25.38 +@end
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
26.2 +++ b/Source/DemoBoardView.m Fri Mar 07 11:43:02 2008 -0800
26.3 @@ -0,0 +1,137 @@
26.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
26.5 + http://developer.apple.com/samplecode/GeekGameBoard/
26.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
26.7 +
26.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
26.9 + provided that the following conditions are met:
26.10 +
26.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
26.12 + and the following disclaimer.
26.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
26.14 + conditions and the following disclaimer in the documentation and/or other materials provided
26.15 + with the distribution.
26.16 +
26.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
26.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
26.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
26.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
26.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26.25 +*/
26.26 +#import "DemoBoardView.h"
26.27 +#import "Game.h"
26.28 +#import "QuartzUtils.h"
26.29 +
26.30 +
26.31 +/** WARNING: THIS CODE REQUIRES GARBAGE COLLECTION!
26.32 + ** This sample application uses Objective-C 2.0 garbage collection.
26.33 + ** Therefore, the source code in this file does NOT perform manual object memory management.
26.34 + ** If you reuse any of this code in a process that isn't garbage collected, you will need to
26.35 + ** add all necessary retain/release/autorelease calls, and implement -dealloc methods,
26.36 + ** otherwise unpleasant leakage will occur!
26.37 + **/
26.38 +
26.39 +
26.40 +@implementation DemoBoardView
26.41 +
26.42 +
26.43 +/** Class names of available games */
26.44 +static NSString* const kMenuGameNames[] = {@"KlondikeGame", @"CheckersGame", @"HexchequerGame",
26.45 + @"TicTacToeGame", @"GoGame"};
26.46 +
26.47 +/** Class name of the current game. */
26.48 +static NSString* sCurrentGameName = @"KlondikeGame";
26.49 +
26.50 +
26.51 +- (void) startGameNamed: (NSString*)gameClassName
26.52 +{
26.53 + [super startGameNamed: gameClassName];
26.54 +
26.55 + Game *game = self.game;
26.56 + [game addObserver: self
26.57 + forKeyPath: @"currentPlayer"
26.58 + options: NSKeyValueObservingOptionInitial
26.59 + context: NULL];
26.60 + [game addObserver: self
26.61 + forKeyPath: @"winner"
26.62 + options: 0
26.63 + context: NULL];
26.64 +
26.65 + self.window.title = [(id)[game class] displayName];
26.66 +}
26.67 +
26.68 +
26.69 +- (CGRect) gameBoardFrame
26.70 +{
26.71 + CGRect bounds = [super gameBoardFrame];
26.72 + bounds.size.height -= 32; // Leave room for headline
26.73 + return CGRectInset(bounds,4,4);
26.74 +}
26.75 +
26.76 +
26.77 +- (void) awakeFromNib
26.78 +{
26.79 + srandomdev();
26.80 +
26.81 + [self registerForDraggedTypes: [NSImage imagePasteboardTypes]];
26.82 + [self registerForDraggedTypes: [NSArray arrayWithObject: NSFilenamesPboardType]];
26.83 +
26.84 + CGRect bounds = self.layer.bounds;
26.85 + self.layer.backgroundColor = GetCGPatternNamed(@"/Library/Desktop Pictures/Small Ripples graphite.png");
26.86 +
26.87 + bounds.size.height -= 32;
26.88 + _headline = AddTextLayer(self.layer,
26.89 + nil, [NSFont boldSystemFontOfSize: 24],
26.90 + kCALayerWidthSizable | kCALayerMinYMargin);
26.91 +
26.92 + [self startGameNamed: sCurrentGameName];
26.93 +}
26.94 +
26.95 +
26.96 +- (void) startGameFromMenu: (id)sender
26.97 +{
26.98 + sCurrentGameName = kMenuGameNames[ [sender tag] ];
26.99 + [self startGameNamed: sCurrentGameName];
26.100 +}
26.101 +
26.102 +
26.103 +- (void)observeValueForKeyPath:(NSString *)keyPath
26.104 + ofObject:(id)object
26.105 + change:(NSDictionary *)change
26.106 + context:(void *)context
26.107 +{
26.108 + Game *game = self.game;
26.109 + if( object == game ) {
26.110 + Player *p = game.winner;
26.111 + NSString *msg;
26.112 + if( p ) {
26.113 + [[NSSound soundNamed: @"Sosumi"] play];
26.114 + msg = @"%@ wins! Congratulations!";
26.115 + } else {
26.116 + p = game.currentPlayer;
26.117 + msg = @"Your turn, %@";
26.118 + }
26.119 + _headline.string = [NSString stringWithFormat: msg, p.name];
26.120 + }
26.121 +}
26.122 +
26.123 +
26.124 +- (IBAction) enterFullScreen: (id)sender
26.125 +{
26.126 + [super enterFullScreen: sender];
26.127 + [self startGameNamed: sCurrentGameName]; // restart game so it'll use the new size
26.128 +}
26.129 +
26.130 +
26.131 +#pragma mark -
26.132 +#pragma mark NSAPPLICATION DELEGATE:
26.133 +
26.134 +
26.135 +- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
26.136 +{
26.137 + return YES;
26.138 +}
26.139 +
26.140 +@end
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
27.2 +++ b/Source/DiscPiece.h Fri Mar 07 11:43:02 2008 -0800
27.3 @@ -0,0 +1,33 @@
27.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
27.5 + http://developer.apple.com/samplecode/GeekGameBoard/
27.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
27.7 +
27.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
27.9 + provided that the following conditions are met:
27.10 +
27.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
27.12 + and the following disclaimer.
27.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
27.14 + conditions and the following disclaimer in the documentation and/or other materials provided
27.15 + with the distribution.
27.16 +
27.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
27.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
27.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
27.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
27.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27.25 +*/
27.26 +#import "Piece.h"
27.27 +
27.28 +
27.29 +/** A Piece whose image is superimposed on a disc.
27.30 + Set the backgroundColor property to change the color or texture of the disc. */
27.31 +@interface DiscPiece : Piece
27.32 +{
27.33 + CALayer *_imageLayer;
27.34 +}
27.35 +
27.36 +@end
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
28.2 +++ b/Source/DiscPiece.m Fri Mar 07 11:43:02 2008 -0800
28.3 @@ -0,0 +1,57 @@
28.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
28.5 + http://developer.apple.com/samplecode/GeekGameBoard/
28.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
28.7 +
28.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
28.9 + provided that the following conditions are met:
28.10 +
28.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
28.12 + and the following disclaimer.
28.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
28.14 + conditions and the following disclaimer in the documentation and/or other materials provided
28.15 + with the distribution.
28.16 +
28.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
28.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
28.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
28.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
28.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28.25 +*/
28.26 +#import "DiscPiece.h"
28.27 +#import "QuartzUtils.h"
28.28 +
28.29 +
28.30 +@implementation DiscPiece
28.31 +
28.32 +
28.33 +- (void) setImage: (CGImageRef)image scale: (CGFloat)scale
28.34 +{
28.35 + if( scale < 4.0 ) {
28.36 + int size = MAX(CGImageGetWidth(image), CGImageGetHeight(image));
28.37 + if( scale > 0 )
28.38 + scale = ceil( size * scale);
28.39 + else
28.40 + scale = size;
28.41 + scale *= 1.2;
28.42 + }
28.43 + self.bounds = CGRectMake(0,0,scale,scale);
28.44 +
28.45 + if( ! _imageLayer ) {
28.46 + _imageLayer = [[CALayer alloc] init];
28.47 + _imageLayer.contentsGravity = @"resizeAspect";
28.48 + [self addSublayer: _imageLayer];
28.49 + [_imageLayer release];
28.50 + }
28.51 + _imageLayer.frame = CGRectInset(self.bounds, scale*.1, scale*.1);
28.52 + _imageLayer.contents = (id) image;
28.53 + self.cornerRadius = scale/2;
28.54 + self.borderWidth = 3;
28.55 + self.borderColor = kTranslucentLightGrayColor;
28.56 + self.imageName = nil;
28.57 +}
28.58 +
28.59 +
28.60 +@end
29.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
29.2 +++ b/Source/Dispenser.h Fri Mar 07 11:43:02 2008 -0800
29.3 @@ -0,0 +1,43 @@
29.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
29.5 + http://developer.apple.com/samplecode/GeekGameBoard/
29.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
29.7 +
29.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
29.9 + provided that the following conditions are met:
29.10 +
29.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
29.12 + and the following disclaimer.
29.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
29.14 + conditions and the following disclaimer in the documentation and/or other materials provided
29.15 + with the distribution.
29.16 +
29.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
29.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
29.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
29.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
29.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29.25 +*/
29.26 +#import "BitHolder.h"
29.27 +
29.28 +
29.29 +/** A Dispenser provides a supply of identical copies of a particular Bit, one at a time. */
29.30 +
29.31 +@interface Dispenser : BitHolder
29.32 +{
29.33 + Bit *_prototype;
29.34 + unsigned _quantity;
29.35 +}
29.36 +
29.37 +- (id) initWithPrototype: (Bit*)prototype quantity: (unsigned)quantity frame: (CGRect)frame;
29.38 +
29.39 +/** The Bit that will be copied. */
29.40 +@property (retain) Bit *prototype;
29.41 +
29.42 +/** The number of Bits remaining; decremented whenever one is dragged out.
29.43 + When it hits zero, no more Bits will appear. */
29.44 +@property unsigned quantity;
29.45 +
29.46 +@end
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
30.2 +++ b/Source/Dispenser.m Fri Mar 07 11:43:02 2008 -0800
30.3 @@ -0,0 +1,194 @@
30.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
30.5 + http://developer.apple.com/samplecode/GeekGameBoard/
30.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
30.7 +
30.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
30.9 + provided that the following conditions are met:
30.10 +
30.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
30.12 + and the following disclaimer.
30.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
30.14 + conditions and the following disclaimer in the documentation and/or other materials provided
30.15 + with the distribution.
30.16 +
30.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
30.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
30.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
30.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30.25 +*/
30.26 +#import "Dispenser.h"
30.27 +#import "Piece.h"
30.28 +#import "QuartzUtils.h"
30.29 +#import "GGBUtils.h"
30.30 +
30.31 +
30.32 +@implementation Dispenser
30.33 +
30.34 +
30.35 +- (id) initWithPrototype: (Bit*)prototype quantity: (unsigned)quantity frame: (CGRect)frame
30.36 +{
30.37 + self = [super init];
30.38 + if (self != nil) {
30.39 + self.backgroundColor = kTranslucentLightGrayColor;
30.40 + self.borderColor = kTranslucentGrayColor;
30.41 + self.borderWidth = 3;
30.42 + self.cornerRadius = 16;
30.43 + self.zPosition = kBoardZ;
30.44 + self.masksToBounds = YES;
30.45 + self.frame = frame;
30.46 + self.prototype = prototype;
30.47 + self.quantity = quantity;
30.48 + }
30.49 + return self;
30.50 +}
30.51 +
30.52 +
30.53 +- (void) dealloc
30.54 +{
30.55 + [_prototype release];
30.56 + [super dealloc];
30.57 +}
30.58 +
30.59 +
30.60 +@synthesize bit=_bit;
30.61 +
30.62 +
30.63 +- (Bit*) createBit
30.64 +{
30.65 + if( _prototype ) {
30.66 + Bit *bit = [_prototype copy];
30.67 + CGRect bounds = self.bounds;
30.68 + bit.position = GetCGRectCenter(bounds);
30.69 + return [bit autorelease];
30.70 + } else
30.71 + return nil;
30.72 +}
30.73 +
30.74 +- (void) x_regenerateCurrentBit
30.75 +{
30.76 + NSAssert(_bit==nil,@"Already have a currentBit");
30.77 +
30.78 + [CATransaction begin];
30.79 + [CATransaction setValue: (id)kCFBooleanTrue
30.80 + forKey: kCATransactionDisableActions];
30.81 + self.bit = [self createBit];
30.82 + CGPoint pos = _bit.position;
30.83 + _bit.position = CGPointMake(pos.x, pos.y+70);
30.84 + [self addSublayer: _bit];
30.85 + [CATransaction commit];
30.86 +
30.87 + _bit.position = pos;
30.88 +}
30.89 +
30.90 +
30.91 +- (Bit*) prototype
30.92 +{
30.93 + return _prototype;
30.94 +}
30.95 +
30.96 +- (void) setPrototype: (Bit*)prototype
30.97 +{
30.98 + setObj(&_prototype, prototype);
30.99 + if( _bit ) {
30.100 + [_bit removeFromSuperlayer];
30.101 + self.bit = nil;
30.102 + if( prototype )
30.103 + [self x_regenerateCurrentBit];
30.104 + }
30.105 +}
30.106 +
30.107 +
30.108 +- (unsigned) quantity
30.109 +{
30.110 + return _quantity;
30.111 +}
30.112 +
30.113 +- (void) setQuantity: (unsigned)quantity
30.114 +{
30.115 + _quantity = quantity;
30.116 + if( quantity > 0 && !_bit )
30.117 + [self x_regenerateCurrentBit];
30.118 + else if( quantity==0 && _bit ) {
30.119 + [_bit removeFromSuperlayer];
30.120 + self.bit = nil;
30.121 + }
30.122 +}
30.123 +
30.124 +
30.125 +#pragma mark -
30.126 +#pragma mark DRAGGING BITS:
30.127 +
30.128 +
30.129 +- (Bit*) canDragBit: (Bit*)bit
30.130 +{
30.131 + bit = [super canDragBit: bit];
30.132 + if( bit==_bit ) {
30.133 + [[bit retain] autorelease];
30.134 + self.bit = nil;
30.135 + }
30.136 + return bit;
30.137 +}
30.138 +
30.139 +- (void) cancelDragBit: (Bit*)bit
30.140 +{
30.141 + if( ! _bit )
30.142 + self.bit = bit;
30.143 + else
30.144 + [bit removeFromSuperlayer];
30.145 +}
30.146 +
30.147 +- (void) draggedBit: (Bit*)bit to: (id<BitHolder>)dst
30.148 +{
30.149 + if( --_quantity > 0 )
30.150 + [self performSelector: @selector(x_regenerateCurrentBit) withObject: nil afterDelay: 0.0];
30.151 +}
30.152 +
30.153 +- (BOOL) canDropBit: (Bit*)bit atPoint: (CGPoint)point
30.154 +{
30.155 + return [bit isEqual: _bit];
30.156 +}
30.157 +
30.158 +- (BOOL) dropBit: (Bit*)bit atPoint: (CGPoint)point
30.159 +{
30.160 + [bit removeFromSuperlayer];
30.161 + return YES;
30.162 +}
30.163 +
30.164 +
30.165 +#pragma mark -
30.166 +#pragma mark DRAG-AND-DROP:
30.167 +
30.168 +
30.169 +// An image from another app can be dragged onto a Dispenser to change the Piece's appearance.
30.170 +
30.171 +
30.172 +- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
30.173 +{
30.174 + if( ! [_prototype isKindOfClass: [Piece class]] )
30.175 + return NSDragOperationNone;
30.176 + NSPasteboard *pb = [sender draggingPasteboard];
30.177 + if( [NSImage canInitWithPasteboard: pb] )
30.178 + return NSDragOperationCopy;
30.179 + else
30.180 + return NSDragOperationNone;
30.181 +}
30.182 +
30.183 +- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
30.184 +{
30.185 + if( ! [_prototype isKindOfClass: [Piece class]] )
30.186 + return NO;
30.187 + CGImageRef image = GetCGImageFromPasteboard([sender draggingPasteboard]);
30.188 + if( image ) {
30.189 + [(Piece*)_prototype setImage: image];
30.190 + self.prototype = _prototype; // recreates _bit
30.191 + return YES;
30.192 + } else
30.193 + return NO;
30.194 +}
30.195 +
30.196 +
30.197 +@end
31.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
31.2 +++ b/Source/GGBUtils.h Fri Mar 07 11:43:02 2008 -0800
31.3 @@ -0,0 +1,31 @@
31.4 +/* Copyright © 2008 Jens Alfke. All Rights Reserved.
31.5 +
31.6 + Redistribution and use in source and binary forms, with or without modification, are permitted
31.7 + provided that the following conditions are met:
31.8 +
31.9 + * Redistributions of source code must retain the above copyright notice, this list of conditions
31.10 + and the following disclaimer.
31.11 + * Redistributions in binary form must reproduce the above copyright notice, this list of
31.12 + conditions and the following disclaimer in the documentation and/or other materials provided
31.13 + with the distribution.
31.14 +
31.15 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
31.16 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31.17 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
31.18 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31.19 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31.20 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31.21 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
31.22 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31.23 +*/
31.24 +#import <Cocoa/Cocoa.h>
31.25 +
31.26 +/** Handy utility for assigning a new value to a retained instance variable. Use as:
31.27 + setObj(&_instanceVar, newValue);
31.28 + It releases the old value and retains the new one. */
31.29 +
31.30 +void setObj( id *variable, id newValue );
31.31 +
31.32 +
31.33 +/** Just like setObj except that it _copies_ the new value. */
31.34 +void setObjCopy( id<NSCopying> *variable, id<NSCopying> newValue );
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
32.2 +++ b/Source/GGBUtils.m Fri Mar 07 11:43:02 2008 -0800
32.3 @@ -0,0 +1,38 @@
32.4 +/* Copyright © 2008 Jens Alfke. All Rights Reserved.
32.5 +
32.6 + Redistribution and use in source and binary forms, with or without modification, are permitted
32.7 + provided that the following conditions are met:
32.8 +
32.9 + * Redistributions of source code must retain the above copyright notice, this list of conditions
32.10 + and the following disclaimer.
32.11 + * Redistributions in binary form must reproduce the above copyright notice, this list of
32.12 + conditions and the following disclaimer in the documentation and/or other materials provided
32.13 + with the distribution.
32.14 +
32.15 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
32.16 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
32.17 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
32.18 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
32.19 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32.20 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32.21 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
32.22 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32.23 +*/
32.24 +#import "GGBUtils.h"
32.25 +
32.26 +
32.27 +void setObj( id *variable, id newValue )
32.28 +{
32.29 + if( *variable != newValue ) {
32.30 + [*variable release];
32.31 + *variable = [newValue retain];
32.32 + }
32.33 +}
32.34 +
32.35 +void setObjCopy( id<NSCopying> *variable, id<NSCopying> newValue )
32.36 +{
32.37 + if( *variable != newValue ) {
32.38 + [*variable release];
32.39 + *variable = [(id)newValue copy];
32.40 + }
32.41 +}
33.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
33.2 +++ b/Source/Game.h Fri Mar 07 11:43:02 2008 -0800
33.3 @@ -0,0 +1,115 @@
33.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
33.5 + http://developer.apple.com/samplecode/GeekGameBoard/
33.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
33.7 +
33.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
33.9 + provided that the following conditions are met:
33.10 +
33.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
33.12 + and the following disclaimer.
33.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
33.14 + conditions and the following disclaimer in the documentation and/or other materials provided
33.15 + with the distribution.
33.16 +
33.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
33.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
33.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
33.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
33.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
33.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33.25 +*/
33.26 +#import <Cocoa/Cocoa.h>
33.27 +@class Bit, Player;
33.28 +@protocol BitHolder;
33.29 +
33.30 +
33.31 +/** Abstract superclass. Keeps track of the rules and turns of a game. */
33.32 +@interface Game : NSObject
33.33 +{
33.34 + CALayer *_board;
33.35 + NSArray *_players;
33.36 + Player *_currentPlayer, *_winner;
33.37 +}
33.38 +
33.39 +/** Returns the human-readable name of this game.
33.40 + (By default it just returns the class name with the "Game" suffix removed.) */
33.41 ++ (NSString*) displayName;
33.42 +
33.43 +@property (readonly, copy) NSArray *players;
33.44 +@property (readonly) Player *currentPlayer, *winner;
33.45 +
33.46 +
33.47 +// Methods for subclasses to implement:
33.48 +
33.49 +/** Designated initializer. After calling the superclass implementation,
33.50 + it should add the necessary Grids, Pieces, Cards, Decks etc. to the board. */
33.51 +- (id) initWithBoard: (CALayer*)board;
33.52 +
33.53 +/** Should return YES if it is legal for the given bit to be moved from its current holder.
33.54 + Default implementation always returns YES. */
33.55 +- (BOOL) canBit: (Bit*)bit moveFrom: (id<BitHolder>)src;
33.56 +
33.57 +/** Should return YES if it is legal for the given Bit to move from src to dst.
33.58 + Default implementation always returns YES. */
33.59 +- (BOOL) canBit: (Bit*)bit moveFrom: (id<BitHolder>)src to: (id<BitHolder>)dst;
33.60 +
33.61 +/** Should handle any side effects of a Bit's movement, such as captures or scoring.
33.62 + Does not need to do the actual movement! That's already happened.
33.63 + It should end by calling -endTurn, if the player's turn is over.
33.64 + Default implementation just calls -endTurn. */
33.65 +- (void) bit: (Bit*)bit movedFrom: (id<BitHolder>)src to: (id<BitHolder>)dst;
33.66 +
33.67 +/** Called instead of the above if a Bit is simply clicked, not dragged.
33.68 + Should return NO if the click is illegal (i.e. clicking an empty draw pile in a card game.)
33.69 + Default implementation always returns YES. */
33.70 +- (BOOL) clickedBit: (Bit*)bit;
33.71 +
33.72 +/** Should return the winning player, if the current position is a win, else nil.
33.73 + Default implementation returns nil. */
33.74 +- (Player*) checkForWinner;
33.75 +
33.76 +
33.77 +// Protected methods for subclasses to call:
33.78 +
33.79 +/** Sets the number of players in the game. Subclass initializers should call this. */
33.80 +- (void) setNumberOfPlayers: (unsigned)n;
33.81 +
33.82 +/** Advance to the next player, when a turn is over. */
33.83 +- (void) nextPlayer;
33.84 +
33.85 +/** Checks for a winner and advances to the next player. */
33.86 +- (void) endTurn;
33.87 +
33.88 +@end
33.89 +
33.90 +
33.91 +
33.92 +/** A mostly-passive object used to represent a player. */
33.93 +@interface Player : NSObject
33.94 +{
33.95 + Game *_game;
33.96 + NSString *_name;
33.97 +}
33.98 +
33.99 +- (id) initWithGame: (Game*)game;
33.100 +
33.101 +@property (readonly) Game *game;
33.102 +@property (copy) NSString *name;
33.103 +@property (readonly) int index;
33.104 +@property (readonly, getter=isCurrent) BOOL current;
33.105 +@property (readonly, getter=isFriendly) BOOL friendly;
33.106 +@property (readonly, getter=isUnfriendly) BOOL unfriendly;
33.107 +@property (readonly) Player *nextPlayer, *previousPlayer;
33.108 +
33.109 +@end
33.110 +
33.111 +
33.112 +
33.113 +@interface CALayer (Game)
33.114 +
33.115 +/** Called on any CALayer in the game's layer tree, will return the current Game object. */
33.116 +@property (readonly) Game *game;
33.117 +
33.118 +@end
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
34.2 +++ b/Source/Game.m Fri Mar 07 11:43:02 2008 -0800
34.3 @@ -0,0 +1,212 @@
34.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
34.5 + http://developer.apple.com/samplecode/GeekGameBoard/
34.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
34.7 +
34.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
34.9 + provided that the following conditions are met:
34.10 +
34.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
34.12 + and the following disclaimer.
34.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
34.14 + conditions and the following disclaimer in the documentation and/or other materials provided
34.15 + with the distribution.
34.16 +
34.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
34.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
34.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
34.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
34.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34.25 +*/
34.26 +#import "Game.h"
34.27 +#import "Bit.h"
34.28 +
34.29 +
34.30 +@interface Game ()
34.31 +@property (copy) NSArray *players;
34.32 +@property (assign) Player *currentPlayer, *winner;
34.33 +@end
34.34 +
34.35 +
34.36 +/** WARNING: THIS CODE REQUIRES GARBAGE COLLECTION!
34.37 + ** This sample application uses Objective-C 2.0 garbage collection.
34.38 + ** Therefore, the source code in this file does NOT perform manual object memory management.
34.39 + ** If you reuse any of this code in a process that isn't garbage collected, you will need to
34.40 + ** add all necessary retain/release/autorelease calls, and implement -dealloc methods,
34.41 + ** otherwise unpleasant leakage will occur!
34.42 + **/
34.43 +
34.44 +
34.45 +@implementation Game
34.46 +
34.47 +
34.48 ++ (NSString*) displayName
34.49 +{
34.50 + NSString* name = [self description];
34.51 + if( [name hasSuffix: @"Game"] )
34.52 + name = [name substringToIndex: name.length-4];
34.53 + return name;
34.54 +}
34.55 +
34.56 +
34.57 +- (id) initWithBoard: (CALayer*)board
34.58 +{
34.59 + self = [super init];
34.60 + if (self != nil) {
34.61 + _board = [board retain];
34.62 + // Store a pointer to myself as the value of the "Game" property
34.63 + // of my root layer. (CALayers can have arbitrary KV properties stored into them.)
34.64 + // This is used by the -[CALayer game] category method defined below, to find the Game.
34.65 + [board setValue: self forKey: @"Game"];
34.66 + }
34.67 + return self;
34.68 +}
34.69 +
34.70 +
34.71 +- (void) dealloc
34.72 +{
34.73 + [_board release];
34.74 + [_players release];
34.75 + [super dealloc];
34.76 +}
34.77 +
34.78 +
34.79 +@synthesize players=_players, currentPlayer=_currentPlayer, winner=_winner;
34.80 +
34.81 +
34.82 +- (void) setNumberOfPlayers: (unsigned)n
34.83 +{
34.84 + NSMutableArray *players = [NSMutableArray arrayWithCapacity: n];
34.85 + for( int i=1; i<=n; i++ ) {
34.86 + Player *player = [[Player alloc] initWithGame: self];
34.87 + player.name = [NSString stringWithFormat: @"Player %i",i];
34.88 + [players addObject: player];
34.89 + [player release];
34.90 + }
34.91 + self.winner = nil;
34.92 + self.currentPlayer = nil;
34.93 + self.players = players;
34.94 +}
34.95 +
34.96 +
34.97 +- (void) nextPlayer
34.98 +{
34.99 + if( ! _currentPlayer ) {
34.100 + NSLog(@"*** The %@ Begins! ***", self.class);
34.101 + self.currentPlayer = [_players objectAtIndex: 0];
34.102 + } else {
34.103 + self.currentPlayer = _currentPlayer.nextPlayer;
34.104 + }
34.105 + NSLog(@"Current player is %@",_currentPlayer);
34.106 +}
34.107 +
34.108 +
34.109 +- (void) endTurn
34.110 +{
34.111 + NSLog(@"--- End of turn");
34.112 + Player *winner = [self checkForWinner];
34.113 + if( winner ) {
34.114 + NSLog(@"*** The %@ Ends! The winner is %@ ! ***", self.class, winner);
34.115 + self.winner = winner;
34.116 + } else
34.117 + [self nextPlayer];
34.118 +}
34.119 +
34.120 +
34.121 +#pragma mark -
34.122 +#pragma mark GAMEPLAY METHODS TO BE OVERRIDDEN:
34.123 +
34.124 +
34.125 +- (BOOL) canBit: (Bit*)bit moveFrom: (id<BitHolder>)src
34.126 +{
34.127 + return YES;
34.128 +}
34.129 +
34.130 +- (BOOL) canBit: (Bit*)bit moveFrom: (id<BitHolder>)src to: (id<BitHolder>)dst
34.131 +{
34.132 + return YES;
34.133 +}
34.134 +
34.135 +- (void) bit: (Bit*)bit movedFrom: (id<BitHolder>)src to: (id<BitHolder>)dst
34.136 +{
34.137 + [self endTurn];
34.138 +}
34.139 +
34.140 +- (BOOL) clickedBit: (Bit*)bit
34.141 +{
34.142 + return YES;
34.143 +}
34.144 +
34.145 +- (Player*) checkForWinner
34.146 +{
34.147 + return nil;
34.148 +}
34.149 +
34.150 +
34.151 +@end
34.152 +
34.153 +
34.154 +
34.155 +
34.156 +@implementation Player
34.157 +
34.158 +
34.159 +- (id) initWithGame: (Game*)game
34.160 +{
34.161 + self = [super init];
34.162 + if (self != nil) {
34.163 + _game = game;
34.164 + }
34.165 + return self;
34.166 +}
34.167 +
34.168 +
34.169 +@synthesize game=_game, name=_name;
34.170 +
34.171 +- (BOOL) isCurrent {return self == _game.currentPlayer;}
34.172 +- (BOOL) isFriendly {return self == _game.currentPlayer;} // could be overridden for games with partners
34.173 +- (BOOL) isUnfriendly {return ! self.friendly;}
34.174 +
34.175 +- (int) index
34.176 +{
34.177 + return [_game.players indexOfObjectIdenticalTo: self];
34.178 +}
34.179 +
34.180 +- (Player*) nextPlayer
34.181 +{
34.182 + return [_game.players objectAtIndex: (self.index+1) % _game.players.count];
34.183 +}
34.184 +
34.185 +- (Player*) previousPlayer
34.186 +{
34.187 + return [_game.players objectAtIndex: (self.index-1) % _game.players.count];
34.188 +}
34.189 +
34.190 +- (NSString*) description
34.191 +{
34.192 + return [NSString stringWithFormat: @"%@[%@]", self.class,self.name];
34.193 +}
34.194 +
34.195 +@end
34.196 +
34.197 +
34.198 +
34.199 +
34.200 +@implementation CALayer (Game)
34.201 +
34.202 +- (Game*) game
34.203 +{
34.204 + // The Game object stores a pointer to itself as the value of the "Game" property
34.205 + // of its root layer. (CALayers can have arbitrary KV properties stored into them.)
34.206 + for( CALayer *layer = self; layer; layer=layer.superlayer ) {
34.207 + Game *game = [layer valueForKey: @"Game"];
34.208 + if( game )
34.209 + return game;
34.210 + }
34.211 + NSAssert1(NO,@"Couldn't look up Game from %@",self);
34.212 + return nil;
34.213 +}
34.214 +
34.215 +@end
35.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
35.2 +++ b/Source/GeekGameBoard_Prefix.pch Fri Mar 07 11:43:02 2008 -0800
35.3 @@ -0,0 +1,31 @@
35.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
35.5 + http://developer.apple.com/samplecode/GeekGameBoard/
35.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
35.7 +
35.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
35.9 + provided that the following conditions are met:
35.10 +
35.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
35.12 + and the following disclaimer.
35.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
35.14 + conditions and the following disclaimer in the documentation and/or other materials provided
35.15 + with the distribution.
35.16 +
35.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
35.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
35.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
35.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
35.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
35.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
35.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35.25 +*/
35.26 +
35.27 +//
35.28 +// Prefix header for all source files of the 'GeekGameBoard' target in the 'GeekGameBoard' project
35.29 +//
35.30 +
35.31 +#ifdef __OBJC__
35.32 + #import <Cocoa/Cocoa.h>
35.33 + #import <Quartz/Quartz.h>
35.34 +#endif
36.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
36.2 +++ b/Source/GoGame.h Fri Mar 07 11:43:02 2008 -0800
36.3 @@ -0,0 +1,35 @@
36.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
36.5 + http://developer.apple.com/samplecode/GeekGameBoard/
36.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
36.7 +
36.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
36.9 + provided that the following conditions are met:
36.10 +
36.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
36.12 + and the following disclaimer.
36.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
36.14 + conditions and the following disclaimer in the documentation and/or other materials provided
36.15 + with the distribution.
36.16 +
36.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
36.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
36.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
36.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
36.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
36.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
36.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36.25 +*/
36.26 +#import "Game.h"
36.27 +@class RectGrid, Stack;
36.28 +
36.29 +
36.30 +/** The Asian board game Go.
36.31 + See: http://en.wikipedia.org/wiki/Go_%28board_game%29 */
36.32 +@interface GoGame : Game
36.33 +{
36.34 + RectGrid *_grid;
36.35 + Stack *_captured[2];
36.36 +}
36.37 +
36.38 +@end
37.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
37.2 +++ b/Source/GoGame.m Fri Mar 07 11:43:02 2008 -0800
37.3 @@ -0,0 +1,166 @@
37.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
37.5 + http://developer.apple.com/samplecode/GeekGameBoard/
37.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
37.7 +
37.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
37.9 + provided that the following conditions are met:
37.10 +
37.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
37.12 + and the following disclaimer.
37.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
37.14 + conditions and the following disclaimer in the documentation and/or other materials provided
37.15 + with the distribution.
37.16 +
37.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
37.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
37.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
37.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
37.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
37.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37.25 +*/
37.26 +#import "GoGame.h"
37.27 +#import "Grid.h"
37.28 +#import "Piece.h"
37.29 +#import "Dispenser.h"
37.30 +#import "Stack.h"
37.31 +#import "QuartzUtils.h"
37.32 +
37.33 +
37.34 +@implementation GoGame
37.35 +
37.36 +
37.37 +- (void) x_createDispenser: (NSString*)imageName position: (CGPoint)position forPlayer: (unsigned)playerNo
37.38 +{
37.39 + CGFloat pieceSize = (int)(_grid.spacing.width * 0.9) & ~1; // make sure it's even
37.40 + Piece *stone = [[Piece alloc] initWithImageNamed: imageName scale: pieceSize];
37.41 + stone.owner = [self.players objectAtIndex: playerNo];
37.42 + CGRect frame = {position, {1.5*pieceSize,1.5*pieceSize}};
37.43 + Dispenser *disp = [[Dispenser alloc] initWithPrototype: stone quantity: INT_MAX frame:frame];
37.44 + [_board addSublayer: disp];
37.45 + [disp release];
37.46 + [stone release];
37.47 +}
37.48 +
37.49 +
37.50 +- (id) initWithBoard: (CALayer*)board
37.51 +{
37.52 + self = [super initWithBoard: board];
37.53 + if (self != nil) {
37.54 + [self setNumberOfPlayers: 2];
37.55 +
37.56 + CGSize size = board.bounds.size;
37.57 + RectGrid *grid = [[RectGrid alloc] initWithRows: 9 columns: 9
37.58 + frame: CGRectMake((size.width-size.height+16)/2,8,
37.59 + size.height-16,size.height-16)];
37.60 + _grid = grid;
37.61 + grid.backgroundColor = GetCGPatternNamed(@"Wood.jpg");
37.62 + grid.borderColor = kTranslucentLightGrayColor;
37.63 + grid.borderWidth = 2;
37.64 + grid.lineColor = kTranslucentGrayColor;
37.65 + grid.cellClass = [GoSquare class];
37.66 + [grid addAllCells];
37.67 + ((GoSquare*)[grid cellAtRow: 2 column: 2]).dotted = YES;
37.68 + ((GoSquare*)[grid cellAtRow: 6 column: 6]).dotted = YES;
37.69 + ((GoSquare*)[grid cellAtRow: 2 column: 6]).dotted = YES;
37.70 + ((GoSquare*)[grid cellAtRow: 6 column: 2]).dotted = YES;
37.71 + grid.usesDiagonals = grid.allowsMoves = grid.allowsCaptures = NO;
37.72 + [board addSublayer: grid];
37.73 + [grid release];
37.74 +
37.75 + CGRect gridFrame = grid.frame;
37.76 + CGFloat pieceSize = (int)grid.spacing.width & ~1; // make sure it's even
37.77 + [self x_createDispenser: @"Red Ball.png"
37.78 + position: CGPointMake(CGRectGetMinX(gridFrame)-2*pieceSize,
37.79 + CGRectGetMinY(gridFrame))
37.80 + forPlayer: 0];
37.81 + [self x_createDispenser: @"White Ball.png"
37.82 + position: CGPointMake(CGRectGetMaxX(gridFrame)+0.5*pieceSize,
37.83 + CGRectGetMaxY(gridFrame)-1.5*pieceSize)
37.84 + forPlayer: 1];
37.85 +
37.86 + CGFloat captureHeight = gridFrame.size.height-4*pieceSize;
37.87 + _captured[0] = [[Stack alloc] initWithStartPos: CGPointMake(2*pieceSize,0)
37.88 + spacing: CGSizeMake(0,pieceSize)
37.89 + wrapInterval: floor(captureHeight/pieceSize)
37.90 + wrapSpacing: CGSizeMake(-pieceSize,0)];
37.91 + _captured[0].frame = CGRectMake(CGRectGetMinX(gridFrame)-3*pieceSize,
37.92 + CGRectGetMinY(gridFrame)+3*pieceSize,
37.93 + 2*pieceSize, captureHeight);
37.94 + _captured[0].zPosition = kPieceZ+1;
37.95 + [board addSublayer: _captured[0]];
37.96 + [_captured[0] release];
37.97 +
37.98 + _captured[1] = [[Stack alloc] initWithStartPos: CGPointMake(0,captureHeight)
37.99 + spacing: CGSizeMake(0,-pieceSize)
37.100 + wrapInterval: floor(captureHeight/pieceSize)
37.101 + wrapSpacing: CGSizeMake(pieceSize,0)];
37.102 + _captured[1].frame = CGRectMake(CGRectGetMaxX(gridFrame)+pieceSize,
37.103 + CGRectGetMinY(gridFrame)+pieceSize,
37.104 + 2*pieceSize, captureHeight);
37.105 + _captured[1].zPosition = kPieceZ+1;
37.106 + [board addSublayer: _captured[1]];
37.107 + [_captured[1] release];
37.108 +
37.109 + [self nextPlayer];
37.110 +}
37.111 + return self;
37.112 +}
37.113 +
37.114 +
37.115 +- (BOOL) canBit: (Bit*)bit moveFrom: (id<BitHolder>)srcHolder to: (id<BitHolder>)dstHolder
37.116 +{
37.117 + Square *dst=(Square*)dstHolder;
37.118 +
37.119 + // There should be a check here for a "ko" (repeated position) ... exercise for the reader!
37.120 +
37.121 + // Check for suicidal move. First an easy check for an empty adjacent space:
37.122 + NSArray *neighbors = dst.neighbors;
37.123 + for( GridCell *c in neighbors )
37.124 + if( c.empty )
37.125 + return YES; // there's an empty space
37.126 + // If the piece is surrounded, check the neighboring groups' liberties:
37.127 + for( GridCell *c in neighbors ) {
37.128 + int nLiberties;
37.129 + [c getGroup: &nLiberties];
37.130 + if( c.bit.unfriendly ) {
37.131 + if( nLiberties <= 1 )
37.132 + return YES; // the move captures, so it's not suicidal
37.133 + } else {
37.134 + if( nLiberties > 1 )
37.135 + return YES; // the stone joins a group with other liberties
37.136 + }
37.137 + }
37.138 + return NO;
37.139 +}
37.140 +
37.141 +
37.142 +- (void) bit: (Bit*)bit movedFrom: (id<BitHolder>)srcHolder to: (id<BitHolder>)dstHolder
37.143 +{
37.144 + Square *dst=(Square*)dstHolder;
37.145 + int curIndex = _currentPlayer.index;
37.146 + // Check for captured enemy groups:
37.147 + BOOL captured = NO;
37.148 + for( GridCell *c in dst.neighbors )
37.149 + if( c.bit.unfriendly ) {
37.150 + int nLiberties;
37.151 + NSSet *group = [c getGroup: &nLiberties];
37.152 + if( nLiberties == 0 ) {
37.153 + captured = YES;
37.154 + for( GridCell *capture in group )
37.155 + [_captured[curIndex] addBit: capture.bit]; // Moves piece to POW camp!
37.156 + }
37.157 + }
37.158 + if( captured )
37.159 + [[NSSound soundNamed: @"Pop"] play];
37.160 +
37.161 + [self nextPlayer];
37.162 +}
37.163 +
37.164 +
37.165 +// This sample code makes no attempt to detect the end of the game, or count score,
37.166 +// both of which are rather complex to decide in Go.
37.167 +
37.168 +
37.169 +@end
38.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
38.2 +++ b/Source/Grid.h Fri Mar 07 11:43:02 2008 -0800
38.3 @@ -0,0 +1,139 @@
38.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
38.5 + http://developer.apple.com/samplecode/GeekGameBoard/
38.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
38.7 +
38.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
38.9 + provided that the following conditions are met:
38.10 +
38.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
38.12 + and the following disclaimer.
38.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
38.14 + conditions and the following disclaimer in the documentation and/or other materials provided
38.15 + with the distribution.
38.16 +
38.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
38.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
38.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
38.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
38.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
38.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
38.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
38.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38.25 +*/
38.26 +#import "BitHolder.h"
38.27 +@class GridCell;
38.28 +
38.29 +
38.30 +/** Abstract superclass of regular geometric grids of GridCells that Bits can be placed on. */
38.31 +@interface Grid : CALayer
38.32 +{
38.33 + unsigned _nRows, _nColumns;
38.34 + CGSize _spacing;
38.35 + Class _cellClass;
38.36 + CGColorRef _cellColor, _lineColor;
38.37 + BOOL _usesDiagonals, _allowsMoves, _allowsCaptures;
38.38 + NSMutableArray *_cells; // Really a 2D array, in row-major order.
38.39 +}
38.40 +
38.41 +/** Initializes a new Grid with the given dimensions and cell size, and position in superview.
38.42 + Note that a new Grid has no cells! Either call -addAllCells, or -addCellAtRow:column:. */
38.43 +- (id) initWithRows: (unsigned)nRows columns: (unsigned)nColumns
38.44 + spacing: (CGSize)spacing
38.45 + position: (CGPoint)pos;
38.46 +
38.47 +/** Initializes a new Grid with the given dimensions and frame in superview.
38.48 + The cell size will be computed by dividing frame size by dimensions.
38.49 + Note that a new Grid has no cells! Either call -addAllCells, or -addCellAtRow:column:. */
38.50 +- (id) initWithRows: (unsigned)nRows columns: (unsigned)nColumns
38.51 + frame: (CGRect)frame;
38.52 +
38.53 +@property Class cellClass; // What kind of GridCells to create
38.54 +@property (readonly) unsigned rows, columns; // Dimensions of the grid
38.55 +@property (readonly) CGSize spacing; // x,y spacing of GridCells
38.56 +@property CGColorRef cellColor, lineColor; // Cell background color, line color (or nil)
38.57 +@property BOOL usesDiagonals; // Affects GridCell.neighbors, for rect grids
38.58 +@property BOOL allowsMoves, allowsCaptures; // Can pieces be moved, and can they land on others?
38.59 +
38.60 +/** Returns the GridCell at the given coordinates, or nil if there is no cell there.
38.61 + It's OK to call this with off-the-board coordinates; it will just return nil.*/
38.62 +- (GridCell*) cellAtRow: (unsigned)row column: (unsigned)col;
38.63 +
38.64 +/** Adds cells at all coordinates, creating a complete grid. */
38.65 +- (void) addAllCells;
38.66 +
38.67 +/** Adds a GridCell at the given coordinates. */
38.68 +- (GridCell*) addCellAtRow: (unsigned)row column: (unsigned)col;
38.69 +
38.70 +/** Removes a particular cell, leaving a blank space. */
38.71 +- (void) removeCellAtRow: (unsigned)row column: (unsigned)col;
38.72 +
38.73 +
38.74 +// protected:
38.75 +- (GridCell*) createCellAtRow: (unsigned)row column: (unsigned)col
38.76 + suggestedFrame: (CGRect)frame;
38.77 +
38.78 +@end
38.79 +
38.80 +
38.81 +/** Abstract superclass of a single cell in a grid. */
38.82 +@interface GridCell : BitHolder
38.83 +{
38.84 + Grid *_grid;
38.85 + unsigned _row, _column;
38.86 +}
38.87 +
38.88 +- (id) initWithGrid: (Grid*)grid
38.89 + row: (unsigned)row column: (unsigned)col
38.90 + frame: (CGRect)frame;
38.91 +
38.92 +@property (readonly) Grid* grid;
38.93 +@property (readonly) unsigned row, column;
38.94 +@property (readonly) NSArray* neighbors; // Dependent on grid.usesDiagonals
38.95 +
38.96 +/** Returns YES if 'forward' is north (increasing row#) for the current player */
38.97 +@property (readonly) BOOL fwdIsN;
38.98 +
38.99 +/* Go-style group detection. Returns the set of contiguous GridCells that have pieces of the same
38.100 + owner as this one, and optionally a count of the number of "liberties", or adjacent empty cells. */
38.101 +- (NSSet*) getGroup: (int*)outLiberties;
38.102 +
38.103 +// protected:
38.104 +- (void) drawInParentContext: (CGContextRef)ctx fill: (BOOL)fill;
38.105 +@end
38.106 +
38.107 +
38.108 +
38.109 +/** A rectangular grid of squares. */
38.110 +@interface RectGrid : Grid
38.111 +{
38.112 + CGColorRef _altCellColor;
38.113 +}
38.114 +
38.115 +/** If non-nil, alternate cells will be drawn with this background color, in a checkerboard pattern.
38.116 + The precise rule is that cells whose row+column is odd use the altCellColor.*/
38.117 +@property CGColorRef altCellColor;
38.118 +
38.119 +@end
38.120 +
38.121 +
38.122 +
38.123 +/* A square in a RectGrid */
38.124 +@interface Square : GridCell
38.125 +
38.126 +@property (readonly) Square *nw, *n, *ne, *e, *se, *s, *sw, *w; // Absolute directions (n = increasing row#)
38.127 +@property (readonly) Square *fl, *f, *fr, *r, *br, *b, *bl, *l; // Relative to player (upside-down for player 2)
38.128 +
38.129 +@end
38.130 +
38.131 +
38.132 +/* Substitute this for Square in a RectGrid's cellClass to draw the lines through the centers
38.133 + of the squares, so the pieces sit on the intersections, as in a Go board. */
38.134 +@interface GoSquare : Square
38.135 +{
38.136 + BOOL _dotted;
38.137 +}
38.138 +
38.139 +/** Set to YES to put a dot at the intersection, as in the handicap points of a Go board. */
38.140 +@property BOOL dotted;
38.141 +
38.142 +@end
39.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
39.2 +++ b/Source/Grid.m Fri Mar 07 11:43:02 2008 -0800
39.3 @@ -0,0 +1,486 @@
39.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
39.5 + http://developer.apple.com/samplecode/GeekGameBoard/
39.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
39.7 +
39.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
39.9 + provided that the following conditions are met:
39.10 +
39.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
39.12 + and the following disclaimer.
39.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
39.14 + conditions and the following disclaimer in the documentation and/or other materials provided
39.15 + with the distribution.
39.16 +
39.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
39.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
39.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
39.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
39.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
39.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39.25 +*/
39.26 +#import "Grid.h"
39.27 +#import "Bit.h"
39.28 +#import "Game.h"
39.29 +#import "QuartzUtils.h"
39.30 +
39.31 +
39.32 +@implementation Grid
39.33 +
39.34 +
39.35 +- (id) initWithRows: (unsigned)nRows columns: (unsigned)nColumns
39.36 + spacing: (CGSize)spacing
39.37 + position: (CGPoint)pos
39.38 +{
39.39 + NSParameterAssert(nRows>0 && nColumns>0);
39.40 + self = [super init];
39.41 + if( self ) {
39.42 + _nRows = nRows;
39.43 + _nColumns = nColumns;
39.44 + _spacing = spacing;
39.45 + _cellClass = [GridCell class];
39.46 + _lineColor = kBlackColor;
39.47 + _allowsMoves = YES;
39.48 + _usesDiagonals = YES;
39.49 +
39.50 + self.bounds = CGRectMake(-1, -1, nColumns*spacing.width+2, nRows*spacing.height+2);
39.51 + self.position = pos;
39.52 + self.anchorPoint = CGPointMake(0,0);
39.53 + self.zPosition = kBoardZ;
39.54 + self.needsDisplayOnBoundsChange = YES;
39.55 +
39.56 + unsigned n = nRows*nColumns;
39.57 + _cells = [[NSMutableArray alloc] initWithCapacity: n];
39.58 + id null = [NSNull null];
39.59 + while( n-- > 0 )
39.60 + [_cells addObject: null];
39.61 +
39.62 + [self setNeedsDisplay];
39.63 + }
39.64 + return self;
39.65 +}
39.66 +
39.67 +
39.68 +- (id) initWithRows: (unsigned)nRows columns: (unsigned)nColumns
39.69 + frame: (CGRect)frame
39.70 +{
39.71 + CGFloat spacing = floor(MIN( (frame.size.width -2)/(CGFloat)nColumns,
39.72 + (frame.size.height-2)/(CGFloat)nRows) );
39.73 + return [self initWithRows: nRows columns: nColumns
39.74 + spacing: CGSizeMake(spacing,spacing)
39.75 + position: frame.origin];
39.76 +}
39.77 +
39.78 +
39.79 +- (void) dealloc
39.80 +{
39.81 + CGColorRelease(_cellColor);
39.82 + CGColorRelease(_lineColor);
39.83 + [_cells release];
39.84 + [super dealloc];
39.85 +}
39.86 +
39.87 +
39.88 +static void setcolor( CGColorRef *var, CGColorRef color )
39.89 +{
39.90 + if( color != *var ) {
39.91 + CGColorRelease(*var);
39.92 + *var = CGColorRetain(color);
39.93 + }
39.94 +}
39.95 +
39.96 +- (CGColorRef) cellColor {return _cellColor;}
39.97 +- (void) setCellColor: (CGColorRef)cellColor {setcolor(&_cellColor,cellColor);}
39.98 +
39.99 +- (CGColorRef) lineColor {return _lineColor;}
39.100 +- (void) setLineColor: (CGColorRef)lineColor {setcolor(&_lineColor,lineColor);}
39.101 +
39.102 +@synthesize cellClass=_cellClass, rows=_nRows, columns=_nColumns, spacing=_spacing,
39.103 + usesDiagonals=_usesDiagonals, allowsMoves=_allowsMoves, allowsCaptures=_allowsCaptures;
39.104 +
39.105 +
39.106 +#pragma mark -
39.107 +#pragma mark GEOMETRY:
39.108 +
39.109 +
39.110 +- (GridCell*) cellAtRow: (unsigned)row column: (unsigned)col
39.111 +{
39.112 + if( row < _nRows && col < _nColumns ) {
39.113 + id cell = [_cells objectAtIndex: row*_nColumns+col];
39.114 + if( cell != [NSNull null] )
39.115 + return cell;
39.116 + }
39.117 + return nil;
39.118 +}
39.119 +
39.120 +
39.121 +/** Subclasses can override this, to change the cell's class or frame. */
39.122 +- (GridCell*) createCellAtRow: (unsigned)row column: (unsigned)col
39.123 + suggestedFrame: (CGRect)frame
39.124 +{
39.125 + return [[[_cellClass alloc] initWithGrid: self
39.126 + row: row column: col
39.127 + frame: frame]
39.128 + autorelease];
39.129 +}
39.130 +
39.131 +
39.132 +- (GridCell*) addCellAtRow: (unsigned)row column: (unsigned)col
39.133 +{
39.134 + NSParameterAssert(row<_nRows);
39.135 + NSParameterAssert(col<_nColumns);
39.136 + unsigned index = row*_nColumns+col;
39.137 + GridCell *cell = [_cells objectAtIndex: index];
39.138 + if( (id)cell == [NSNull null] ) {
39.139 + CGRect frame = CGRectMake(col*_spacing.width, row*_spacing.height,
39.140 + _spacing.width,_spacing.height);
39.141 + cell = [self createCellAtRow: row column: col suggestedFrame: frame];
39.142 + if( cell ) {
39.143 + [_cells replaceObjectAtIndex: index withObject: cell];
39.144 + [self addSublayer: cell];
39.145 + [self setNeedsDisplay];
39.146 + }
39.147 + }
39.148 + return cell;
39.149 +}
39.150 +
39.151 +
39.152 +- (void) addAllCells
39.153 +{
39.154 + for( int row=_nRows-1; row>=0; row-- ) // makes 'upper' cells be in 'back'
39.155 + for( int col=0; col<_nColumns; col++ )
39.156 + [self addCellAtRow: row column: col];
39.157 +}
39.158 +
39.159 +
39.160 +- (void) removeCellAtRow: (unsigned)row column: (unsigned)col
39.161 +{
39.162 + NSParameterAssert(row<_nRows);
39.163 + NSParameterAssert(col<_nColumns);
39.164 + unsigned index = row*_nColumns+col;
39.165 + id cell = [_cells objectAtIndex: index];
39.166 + if( cell != [NSNull null] )
39.167 + [cell removeFromSuperlayer];
39.168 + [_cells replaceObjectAtIndex: index withObject: [NSNull null]];
39.169 + [self setNeedsDisplay];
39.170 +}
39.171 +
39.172 +
39.173 +#pragma mark -
39.174 +#pragma mark DRAWING:
39.175 +
39.176 +
39.177 +- (void) drawCellsInContext: (CGContextRef)ctx fill: (BOOL)fill
39.178 +{
39.179 + // Subroutine of -drawInContext:. Draws all the cells, with or without a fill.
39.180 + for( unsigned row=0; row<_nRows; row++ )
39.181 + for( unsigned col=0; col<_nColumns; col++ ) {
39.182 + GridCell *cell = [self cellAtRow: row column: col];
39.183 + if( cell )
39.184 + [cell drawInParentContext: ctx fill: fill];
39.185 + }
39.186 +}
39.187 +
39.188 +
39.189 +- (void)drawInContext:(CGContextRef)ctx
39.190 +{
39.191 + // Custom CALayer drawing implementation. Delegates to the cells to draw themselves
39.192 + // in me; this is more efficient than having each cell have its own drawing.
39.193 + if( _cellColor ) {
39.194 + CGContextSetFillColorWithColor(ctx, _cellColor);
39.195 + [self drawCellsInContext: ctx fill: YES];
39.196 + }
39.197 + if( _lineColor ) {
39.198 + CGContextSetStrokeColorWithColor(ctx,_lineColor);
39.199 + [self drawCellsInContext:ctx fill: NO];
39.200 + }
39.201 +}
39.202 +
39.203 +
39.204 +@end
39.205 +
39.206 +
39.207 +
39.208 +#pragma mark -
39.209 +
39.210 +@implementation GridCell
39.211 +
39.212 +
39.213 +- (id) initWithGrid: (Grid*)grid
39.214 + row: (unsigned)row column: (unsigned)col
39.215 + frame: (CGRect)frame
39.216 +{
39.217 + self = [super init];
39.218 + if (self != nil) {
39.219 + _grid = grid;
39.220 + _row = row;
39.221 + _column = col;
39.222 + self.position = frame.origin;
39.223 + CGRect bounds = frame;
39.224 + bounds.origin.x -= floor(bounds.origin.x); // make sure my coords fall on pixel boundaries
39.225 + bounds.origin.y -= floor(bounds.origin.y);
39.226 + self.bounds = bounds;
39.227 + self.anchorPoint = CGPointMake(0,0);
39.228 + self.borderColor = kHighlightColor; // Used when highlighting (see -setHighlighted:)
39.229 + }
39.230 + return self;
39.231 +}
39.232 +
39.233 +- (NSString*) description
39.234 +{
39.235 + return [NSString stringWithFormat: @"%@(%u,%u)", [self class],_column,_row];
39.236 +}
39.237 +
39.238 +@synthesize grid=_grid, row=_row, column=_column;
39.239 +
39.240 +
39.241 +- (void) drawInParentContext: (CGContextRef)ctx fill: (BOOL)fill
39.242 +{
39.243 + // Default implementation just fills or outlines the cell.
39.244 + CGRect frame = self.frame;
39.245 + if( fill )
39.246 + CGContextFillRect(ctx,frame);
39.247 + else
39.248 + CGContextStrokeRect(ctx, frame);
39.249 +}
39.250 +
39.251 +
39.252 +- (void) setBit: (Bit*)bit
39.253 +{
39.254 + if( bit != self.bit ) {
39.255 + [super setBit: bit];
39.256 + if( bit ) {
39.257 + // Center it:
39.258 + CGSize size = self.bounds.size;
39.259 + bit.position = CGPointMake(floor(size.width/2.0),
39.260 + floor(size.height/2.0));
39.261 + }
39.262 + }
39.263 +}
39.264 +
39.265 +- (Bit*) canDragBit: (Bit*)bit
39.266 +{
39.267 + if( _grid.allowsMoves && bit==self.bit )
39.268 + return [super canDragBit: bit];
39.269 + else
39.270 + return nil;
39.271 +}
39.272 +
39.273 +- (BOOL) canDropBit: (Bit*)bit atPoint: (CGPoint)point
39.274 +{
39.275 + return self.bit == nil || _grid.allowsCaptures;
39.276 +}
39.277 +
39.278 +
39.279 +- (BOOL) fwdIsN
39.280 +{
39.281 + return self.game.currentPlayer.index == 0;
39.282 +}
39.283 +
39.284 +
39.285 +- (NSArray*) neighbors
39.286 +{
39.287 + BOOL orthogonal = ! _grid.usesDiagonals;
39.288 + NSMutableArray *neighbors = [NSMutableArray arrayWithCapacity: 8];
39.289 + for( int dy=-1; dy<=1; dy++ )
39.290 + for( int dx=-1; dx<=1; dx++ )
39.291 + if( (dx || dy) && !(orthogonal && dx && dy) ) {
39.292 + GridCell *cell = [_grid cellAtRow: _row+dy column: _column+dx];
39.293 + if( cell )
39.294 + [neighbors addObject: cell];
39.295 + }
39.296 + return neighbors;
39.297 +}
39.298 +
39.299 +
39.300 +// Recursive subroutine used by getGroup:.
39.301 +- (void) x_addToGroup: (NSMutableSet*)group liberties: (NSMutableSet*)liberties owner: (Player*)owner
39.302 +{
39.303 + Bit *bit = self.bit;
39.304 + if( bit == nil ) {
39.305 + if( [liberties containsObject: self] )
39.306 + return; // already traversed
39.307 + [liberties addObject: self];
39.308 + } else if( bit.owner==owner ) {
39.309 + if( [group containsObject: self] )
39.310 + return; // already traversed
39.311 + [group addObject: self];
39.312 + for( GridCell *c in self.neighbors )
39.313 + [c x_addToGroup: group liberties: liberties owner: owner];
39.314 + }
39.315 +}
39.316 +
39.317 +
39.318 +- (NSSet*) getGroup: (int*)outLiberties
39.319 +{
39.320 + NSMutableSet *group=[NSMutableSet set], *liberties=nil;
39.321 + if( outLiberties )
39.322 + liberties = [NSMutableSet set];
39.323 + [self x_addToGroup: group liberties: liberties owner: self.bit.owner];
39.324 + if( outLiberties )
39.325 + *outLiberties = liberties.count;
39.326 + return group;
39.327 +}
39.328 +
39.329 +
39.330 +#pragma mark -
39.331 +#pragma mark DRAG-AND-DROP:
39.332 +
39.333 +
39.334 +// An image from another app can be dragged onto a Dispenser to change the Piece's appearance.
39.335 +
39.336 +
39.337 +- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
39.338 +{
39.339 + NSPasteboard *pb = [sender draggingPasteboard];
39.340 + if( [NSImage canInitWithPasteboard: pb] )
39.341 + return NSDragOperationCopy;
39.342 + else
39.343 + return NSDragOperationNone;
39.344 +}
39.345 +
39.346 +- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
39.347 +{
39.348 + CGImageRef image = GetCGImageFromPasteboard([sender draggingPasteboard]);
39.349 + if( image ) {
39.350 + CGColorRef pattern = CreatePatternColor(image);
39.351 + _grid.cellColor = pattern;
39.352 + CGColorRelease(pattern);
39.353 + [_grid setNeedsDisplay];
39.354 + return YES;
39.355 + } else
39.356 + return NO;
39.357 +}
39.358 +
39.359 +
39.360 +@end
39.361 +
39.362 +
39.363 +
39.364 +
39.365 +#pragma mark -
39.366 +
39.367 +@implementation RectGrid
39.368 +
39.369 +
39.370 +- (id) initWithRows: (unsigned)nRows columns: (unsigned)nColumns
39.371 + spacing: (CGSize)spacing
39.372 + position: (CGPoint)pos
39.373 +{
39.374 + self = [super initWithRows: nRows columns: nColumns spacing: spacing position: pos];
39.375 + if( self ) {
39.376 + _cellClass = [Square class];
39.377 + }
39.378 + return self;
39.379 +}
39.380 +
39.381 +
39.382 +- (CGColorRef) altCellColor {return _altCellColor;}
39.383 +- (void) setAltCellColor: (CGColorRef)altCellColor {setcolor(&_altCellColor,altCellColor);}
39.384 +
39.385 +
39.386 +@end
39.387 +
39.388 +
39.389 +
39.390 +#pragma mark -
39.391 +
39.392 +@implementation Square
39.393 +
39.394 +
39.395 +- (void) drawInParentContext: (CGContextRef)ctx fill: (BOOL)fill
39.396 +{
39.397 + if( fill ) {
39.398 + CGColorRef c = ((RectGrid*)_grid).altCellColor;
39.399 + if( c ) {
39.400 + if( ! ((_row+_column) & 1) )
39.401 + c = _grid.cellColor;
39.402 + CGContextSetFillColorWithColor(ctx, c);
39.403 + }
39.404 + }
39.405 + [super drawInParentContext: ctx fill: fill];
39.406 +}
39.407 +
39.408 +
39.409 +- (void) setHighlighted: (BOOL)highlighted
39.410 +{
39.411 + [super setHighlighted: highlighted];
39.412 + self.borderWidth = (highlighted ?6 :0);
39.413 +}
39.414 +
39.415 +
39.416 +- (Square*) nw {return (Square*)[_grid cellAtRow: _row+1 column: _column-1];}
39.417 +- (Square*) n {return (Square*)[_grid cellAtRow: _row+1 column: _column ];}
39.418 +- (Square*) ne {return (Square*)[_grid cellAtRow: _row+1 column: _column+1];}
39.419 +- (Square*) e {return (Square*)[_grid cellAtRow: _row column: _column+1];}
39.420 +- (Square*) se {return (Square*)[_grid cellAtRow: _row-1 column: _column+1];}
39.421 +- (Square*) s {return (Square*)[_grid cellAtRow: _row-1 column: _column ];}
39.422 +- (Square*) sw {return (Square*)[_grid cellAtRow: _row-1 column: _column-1];}
39.423 +- (Square*) w {return (Square*)[_grid cellAtRow: _row column: _column-1];}
39.424 +
39.425 +// Directions relative to the current player:
39.426 +- (Square*) fl {return self.fwdIsN ?self.nw :self.se;}
39.427 +- (Square*) f {return self.fwdIsN ?self.n :self.s;}
39.428 +- (Square*) fr {return self.fwdIsN ?self.ne :self.sw;}
39.429 +- (Square*) r {return self.fwdIsN ?self.e :self.w;}
39.430 +- (Square*) br {return self.fwdIsN ?self.se :self.nw;}
39.431 +- (Square*) b {return self.fwdIsN ?self.s :self.n;}
39.432 +- (Square*) bl {return self.fwdIsN ?self.sw :self.ne;}
39.433 +- (Square*) l {return self.fwdIsN ?self.w :self.e;}
39.434 +
39.435 +
39.436 +- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
39.437 +{
39.438 + CGImageRef image = GetCGImageFromPasteboard([sender draggingPasteboard]);
39.439 + if( image ) {
39.440 + CGColorRef color = CreatePatternColor(image);
39.441 + RectGrid *rectGrid = (RectGrid*)_grid;
39.442 + if( rectGrid.altCellColor && ((_row+_column) & 1) )
39.443 + rectGrid.altCellColor = color;
39.444 + else
39.445 + rectGrid.cellColor = color;
39.446 + CGColorRelease(color);
39.447 + [rectGrid setNeedsDisplay];
39.448 + return YES;
39.449 + } else
39.450 + return NO;
39.451 +}
39.452 +
39.453 +@end
39.454 +
39.455 +
39.456 +
39.457 +#pragma mark -
39.458 +
39.459 +@implementation GoSquare
39.460 +
39.461 +@synthesize dotted=_dotted;
39.462 +
39.463 +- (void) drawInParentContext: (CGContextRef)ctx fill: (BOOL)fill
39.464 +{
39.465 + if( fill )
39.466 + [super drawInParentContext: ctx fill: fill];
39.467 + else {
39.468 + CGRect frame = self.frame;
39.469 + const CGFloat midx=floor(CGRectGetMidX(frame))+0.5,
39.470 + midy=floor(CGRectGetMidY(frame))+0.5;
39.471 + CGPoint p[4] = {{CGRectGetMinX(frame),midy},
39.472 + {CGRectGetMaxX(frame),midy},
39.473 + {midx,CGRectGetMinY(frame)},
39.474 + {midx,CGRectGetMaxY(frame)}};
39.475 + if( ! self.s ) p[2].y = midy;
39.476 + if( ! self.n ) p[3].y = midy;
39.477 + if( ! self.w ) p[0].x = midx;
39.478 + if( ! self.e ) p[1].x = midx;
39.479 + CGContextStrokeLineSegments(ctx, p, 4);
39.480 +
39.481 + if( _dotted ) {
39.482 + CGContextSetFillColorWithColor(ctx,_grid.lineColor);
39.483 + CGRect dot = CGRectMake(midx-2.5, midy-2.5, 5, 5);
39.484 + CGContextFillEllipseInRect(ctx, dot);
39.485 + }
39.486 + }
39.487 +}
39.488 +
39.489 +@end
40.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
40.2 +++ b/Source/HexGrid.h Fri Mar 07 11:43:02 2008 -0800
40.3 @@ -0,0 +1,47 @@
40.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
40.5 + http://developer.apple.com/samplecode/GeekGameBoard/
40.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
40.7 +
40.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
40.9 + provided that the following conditions are met:
40.10 +
40.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
40.12 + and the following disclaimer.
40.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
40.14 + conditions and the following disclaimer in the documentation and/or other materials provided
40.15 + with the distribution.
40.16 +
40.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
40.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
40.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
40.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
40.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
40.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
40.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
40.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40.25 +*/
40.26 +#import "Grid.h"
40.27 +
40.28 +
40.29 +/** Hexagonal grid.
40.30 + The hexes are oriented with points facing up and down.
40.31 + The coords are still rectangular, since the hexes line up in straight horizontal rows,
40.32 + but every odd-numbered row of hexes is offset slightly to the right. */
40.33 +@interface HexGrid : Grid
40.34 +{
40.35 + CGFloat _side, _capHeight;
40.36 + CGPathRef _cellPath;
40.37 +}
40.38 +
40.39 +/** Similar to -addAllCells, but only adds enough cells to create a hexagonal board. */
40.40 +- (void) addCellsInHexagon;
40.41 +
40.42 +@end
40.43 +
40.44 +
40.45 +@interface Hex : GridCell
40.46 +
40.47 +@property (readonly) Hex *nw, *ne, *e, *se, *sw, *w; // Absolute directions (n = increasing row#)
40.48 +@property (readonly) Hex *fl, *fr, *r, *br, *bl, *l; // Relative to player (upside-down for player 2)
40.49 +
40.50 +@end
40.51 \ No newline at end of file
41.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
41.2 +++ b/Source/HexGrid.m Fri Mar 07 11:43:02 2008 -0800
41.3 @@ -0,0 +1,200 @@
41.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
41.5 + http://developer.apple.com/samplecode/GeekGameBoard/
41.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
41.7 +
41.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
41.9 + provided that the following conditions are met:
41.10 +
41.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
41.12 + and the following disclaimer.
41.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
41.14 + conditions and the following disclaimer in the documentation and/or other materials provided
41.15 + with the distribution.
41.16 +
41.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
41.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
41.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
41.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
41.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
41.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
41.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
41.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41.25 +*/
41.26 +#import "HexGrid.h"
41.27 +#import "Game.h"
41.28 +
41.29 +
41.30 +@implementation HexGrid
41.31 +
41.32 +
41.33 +- (id) initWithRows: (unsigned)nRows columns: (unsigned)nColumns
41.34 + spacing: (CGSize)spacing
41.35 + position: (CGPoint)pos
41.36 +{
41.37 + // Ignore given spacing.height; set it to make the hexagons regular.
41.38 + CGFloat capHeight = spacing.height / 2 * tan(M_PI/6);
41.39 + CGFloat side = spacing.height / 2 / cos(M_PI/6);
41.40 + spacing.height = side + capHeight;
41.41 +
41.42 + self = [super initWithRows: nRows columns: nColumns
41.43 + spacing: spacing
41.44 + position: pos];
41.45 + if( self ) {
41.46 + _capHeight = capHeight;
41.47 + _side = side;
41.48 + self.bounds = CGRectMake(-1, -1,
41.49 + (nColumns+0.5)*spacing.width + 2,
41.50 + nRows*spacing.height+capHeight + 2);
41.51 + _cellClass = [Hex class];
41.52 + }
41.53 + return self;
41.54 +}
41.55 +
41.56 +
41.57 +- (id) initWithRows: (unsigned)nRows columns: (unsigned)nColumns
41.58 + frame: (CGRect)frame;
41.59 +{
41.60 + // Compute the horizontal spacing:
41.61 + CGFloat s = floor(MIN( (frame.size.width -2.0)/nColumns,
41.62 + (frame.size.height-2.0)/(nRows+0.5*tan(M_PI/6)) / (0.5*(tan(M_PI/6)+1/cos(M_PI/6))) ));
41.63 + return [self initWithRows: nRows columns: nColumns
41.64 + spacing: CGSizeMake(s,s)
41.65 + position: frame.origin];
41.66 +}
41.67 +
41.68 +
41.69 +- (void) dealloc
41.70 +{
41.71 + CGPathRelease(_cellPath);
41.72 + [super dealloc];
41.73 +}
41.74 +
41.75 +
41.76 +- (void) addCellsInHexagon
41.77 +{
41.78 + int size = _nRows - !(_nRows & 1); // make it odd
41.79 + for( int row=0; row<_nRows; row++ ) {
41.80 + int n; // # of hexes remaining in this row
41.81 + if( row < size )
41.82 + n = size - abs(row-size/2);
41.83 + else
41.84 + n = 0;
41.85 + int c0 = floor(((int)_nRows+1-n -(row&1))/2.0); // col of 1st remaining hex
41.86 +
41.87 + for( int col=0; col<_nColumns; col++ )
41.88 + if( col>=c0 && col<c0+n )
41.89 + [self addCellAtRow: row column: col];
41.90 + }
41.91 +}
41.92 +
41.93 +
41.94 +- (GridCell*) createCellAtRow: (unsigned)row column: (unsigned)col
41.95 + suggestedFrame: (CGRect)frame
41.96 +{
41.97 + // Overridden to stagger the odd-numbered rows
41.98 + if( row & 1 )
41.99 + frame.origin.x += _spacing.width/2;
41.100 + frame.size.height += _capHeight;
41.101 + return [super createCellAtRow: row column: col suggestedFrame: frame];
41.102 +}
41.103 +
41.104 +
41.105 +// Returns a hexagonal CG path defining a cell's outline. Used by cells when drawing & hit-testing.
41.106 +- (CGPathRef) cellPath
41.107 +{
41.108 + if( ! _cellPath ) {
41.109 + CGFloat x1 = _spacing.width/2;
41.110 + CGFloat x2 = _spacing.width;
41.111 + CGFloat y1 = _capHeight;
41.112 + CGFloat y2 = y1 + _side;
41.113 + CGFloat y3 = y2 + _capHeight;
41.114 + CGPoint p[6] = { {0,y1}, {x1,0}, {x2,y1}, {x2,y2}, {x1,y3}, {0,y2} };
41.115 +
41.116 + CGMutablePathRef path = CGPathCreateMutable();
41.117 + CGPathAddLines(path, NULL, p, 6);
41.118 + CGPathCloseSubpath(path);
41.119 + _cellPath = path;
41.120 + }
41.121 + return _cellPath;
41.122 +}
41.123 +
41.124 +
41.125 +@end
41.126 +
41.127 +
41.128 +
41.129 +
41.130 +
41.131 +#pragma mark -
41.132 +
41.133 +@implementation Hex
41.134 +
41.135 +
41.136 +- (void) drawInParentContext: (CGContextRef)ctx fill: (BOOL)fill
41.137 +{
41.138 + CGContextSaveGState(ctx);
41.139 + CGPoint pos = self.position;
41.140 + CGContextTranslateCTM(ctx, pos.x, pos.y);
41.141 + CGContextBeginPath(ctx);
41.142 + CGContextAddPath(ctx, ((HexGrid*)_grid).cellPath);
41.143 + CGContextDrawPath(ctx, (fill ?kCGPathFill :kCGPathStroke));
41.144 +
41.145 + if( !fill && self.highlighted ) {
41.146 + // Highlight by drawing my outline in the highlight color:
41.147 + CGContextSetStrokeColorWithColor(ctx, self.borderColor);
41.148 + CGContextSetLineWidth(ctx,6);
41.149 + CGContextBeginPath(ctx);
41.150 + CGContextAddPath(ctx, ((HexGrid*)_grid).cellPath);
41.151 + CGContextDrawPath(ctx, kCGPathStroke);
41.152 + }
41.153 + CGContextRestoreGState(ctx);
41.154 +}
41.155 +
41.156 +
41.157 +- (BOOL)containsPoint:(CGPoint)p
41.158 +{
41.159 + return [super containsPoint: p]
41.160 + && CGPathContainsPoint( ((HexGrid*)_grid).cellPath, NULL, p, NO );
41.161 +}
41.162 +
41.163 +
41.164 +- (void) setHighlighted: (BOOL)highlighted
41.165 +{
41.166 + if( highlighted != self.highlighted ) {
41.167 + [super setHighlighted: highlighted];
41.168 + [_grid setNeedsDisplay]; // So I'll be asked to redraw myself
41.169 + }
41.170 +}
41.171 +
41.172 +
41.173 +#pragma mark -
41.174 +#pragma mark NEIGHBORS:
41.175 +
41.176 +
41.177 +- (NSArray*) neighbors
41.178 +{
41.179 + NSMutableArray *neighbors = [NSMutableArray arrayWithCapacity: 6];
41.180 + Hex* n[6] = {self.nw, self.ne, self.w, self.e, self.sw, self.se};
41.181 + for( int i=0; i<6; i++ )
41.182 + if( n[i] )
41.183 + [neighbors addObject: n[i]];
41.184 + return neighbors;
41.185 +}
41.186 +
41.187 +- (Hex*) nw {return (Hex*)[_grid cellAtRow: _row+1 column: _column - ((_row+1)&1)];}
41.188 +- (Hex*) ne {return (Hex*)[_grid cellAtRow: _row+1 column: _column + (_row&1)];}
41.189 +- (Hex*) e {return (Hex*)[_grid cellAtRow: _row column: _column + 1];}
41.190 +- (Hex*) se {return (Hex*)[_grid cellAtRow: _row-1 column: _column + (_row&1)];}
41.191 +- (Hex*) sw {return (Hex*)[_grid cellAtRow: _row-1 column: _column - ((_row-1)&1)];}
41.192 +- (Hex*) w {return (Hex*)[_grid cellAtRow: _row column: _column - 1];}
41.193 +
41.194 +// Directions relative to the current player:
41.195 +- (Hex*) fl {return self.fwdIsN ?self.nw :self.se;}
41.196 +- (Hex*) fr {return self.fwdIsN ?self.ne :self.sw;}
41.197 +- (Hex*) r {return self.fwdIsN ?self.e :self.w;}
41.198 +- (Hex*) br {return self.fwdIsN ?self.se :self.nw;}
41.199 +- (Hex*) bl {return self.fwdIsN ?self.sw :self.ne;}
41.200 +- (Hex*) l {return self.fwdIsN ?self.w :self.e;}
41.201 +
41.202 +
41.203 +@end
42.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
42.2 +++ b/Source/HexchequerGame.h Fri Mar 07 11:43:02 2008 -0800
42.3 @@ -0,0 +1,32 @@
42.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
42.5 + http://developer.apple.com/samplecode/GeekGameBoard/
42.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
42.7 +
42.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
42.9 + provided that the following conditions are met:
42.10 +
42.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
42.12 + and the following disclaimer.
42.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
42.14 + conditions and the following disclaimer in the documentation and/or other materials provided
42.15 + with the distribution.
42.16 +
42.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
42.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
42.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
42.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
42.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
42.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
42.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
42.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42.25 +*/
42.26 +#import "CheckersGame.h"
42.27 +
42.28 +/** A hex-grid variant of checkers, made up on a whim to test out hex boards.
42.29 + A much better existing hexagonal checkers is HexDame --
42.30 + see: http://www.mindsports.net/CompleteGames/Elimination/HexDame.html
42.31 + Its implementation is left as an exercise for the reader.
42.32 + Hint: rotate the HexGrid 30 degrees! */
42.33 +@interface HexchequerGame : CheckersGame
42.34 +
42.35 +@end
43.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
43.2 +++ b/Source/HexchequerGame.m Fri Mar 07 11:43:02 2008 -0800
43.3 @@ -0,0 +1,113 @@
43.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
43.5 + http://developer.apple.com/samplecode/GeekGameBoard/
43.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
43.7 +
43.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
43.9 + provided that the following conditions are met:
43.10 +
43.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
43.12 + and the following disclaimer.
43.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
43.14 + conditions and the following disclaimer in the documentation and/or other materials provided
43.15 + with the distribution.
43.16 +
43.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
43.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
43.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
43.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
43.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
43.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
43.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
43.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43.25 +*/
43.26 +#import "HexchequerGame.h"
43.27 +#import "HexGrid.h"
43.28 +#import "Piece.h"
43.29 +#import "QuartzUtils.h"
43.30 +
43.31 +
43.32 +@implementation HexchequerGame
43.33 +
43.34 +
43.35 +- (Grid*) x_makeGrid
43.36 +{
43.37 + HexGrid *grid = [[[HexGrid alloc] initWithRows: 9 columns: 9 frame: _board.bounds] autorelease];
43.38 + CGPoint pos = grid.position;
43.39 + pos.x = floor((_board.bounds.size.width-grid.frame.size.width)/2);
43.40 + grid.position = pos;
43.41 + [grid addCellsInHexagon];
43.42 + grid.allowsMoves = YES;
43.43 + grid.allowsCaptures = NO; // no land-on captures, that is
43.44 + grid.cellColor = CGColorCreateGenericGray(1.0, 0.25);
43.45 + grid.lineColor = kTranslucentLightGrayColor;
43.46 +
43.47 + [self addPieces: @"Green Ball.png" toGrid: grid forPlayer: 0 rows: NSMakeRange(0,2) alternating: NO];
43.48 + [self addPieces: @"Red Ball.png" toGrid: grid forPlayer: 1 rows: NSMakeRange(7,2) alternating: NO];
43.49 + return grid;
43.50 +}
43.51 +
43.52 +
43.53 +- (BOOL) canBit: (Bit*)bit moveFrom: (id<BitHolder>)srcHolder to: (id<BitHolder>)dstHolder
43.54 +{
43.55 + Hex *src=(Hex*)srcHolder, *dst=(Hex*)dstHolder;
43.56 + if( [bit valueForKey: @"King"] )
43.57 + if( dst==src.bl || dst==src.br || dst==src.l || dst==src.r
43.58 + || (src.bl.bit.unfriendly && dst==src.bl.bl) || (src.br.bit.unfriendly && dst==src.br.br)
43.59 + || (src.l.bit.unfriendly && dst==src.l.l) || (src.r.bit.unfriendly && dst==src.r.r) )
43.60 + return YES;
43.61 + return dst==src.fl || dst==src.fr
43.62 + || (src.fl.bit.unfriendly && dst==src.fl.fl) || (src.fr.bit.unfriendly && dst==src.fr.fr);
43.63 +}
43.64 +
43.65 +- (void) bit: (Bit*)bit movedFrom: (id<BitHolder>)srcHolder to: (id<BitHolder>)dstHolder
43.66 +{
43.67 + Hex *src=(Hex*)srcHolder, *dst=(Hex*)dstHolder;
43.68 + int playerIndex = self.currentPlayer.index;
43.69 + BOOL isKing = ([bit valueForKey: @"King"] != nil);
43.70 +
43.71 + [[NSSound soundNamed: (isKing ?@"Funk" :@"Tink")] play];
43.72 +
43.73 + // "King" a piece that made it to the last row:
43.74 + if( dst.row == (playerIndex ?0 :8) )
43.75 + if( ! isKing ) {
43.76 + [[NSSound soundNamed: @"Blow"] play];
43.77 + bit.scale = 1.4;
43.78 + [bit setValue: @"King" forKey: @"King"];
43.79 + // don't set isKing flag - piece can't capture again after being kinged.
43.80 + }
43.81 +
43.82 + // Check for a capture:
43.83 + Hex *capture = nil;
43.84 + if(dst==src.fl.fl)
43.85 + capture = src.fl;
43.86 + else if(dst==src.fr.fr)
43.87 + capture = src.fr;
43.88 + else if(dst==src.bl.bl)
43.89 + capture = src.bl;
43.90 + else if(dst==src.br.br)
43.91 + capture = src.br;
43.92 + else if(dst==src.l.l)
43.93 + capture = src.l;
43.94 + else if(dst==src.r.r)
43.95 + capture = src.r;
43.96 +
43.97 + if( capture ) {
43.98 + [[NSSound soundNamed: @"Pop"] play];
43.99 + Bit *bit = capture.bit;
43.100 + _numPieces[bit.owner.index]--;
43.101 + [bit destroy];
43.102 +
43.103 + // Now check if another capture is possible. If so, don't end the turn:
43.104 + if( (dst.fl.bit.unfriendly && dst.fl.fl.empty) || (dst.fr.bit.unfriendly && dst.fr.fr.empty) )
43.105 + return;
43.106 + if( isKing )
43.107 + if( (dst.bl.bit.unfriendly && dst.bl.bl.empty) || (dst.br.bit.unfriendly && dst.br.br.empty)
43.108 + || (dst.l.bit.unfriendly && dst.l.l.empty) || (dst.r.bit.unfriendly && dst.r.r.empty))
43.109 + return;
43.110 + }
43.111 +
43.112 + [self endTurn];
43.113 +}
43.114 +
43.115 +
43.116 +@end
44.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
44.2 +++ b/Source/KlondikeGame.h Fri Mar 07 11:43:02 2008 -0800
44.3 @@ -0,0 +1,34 @@
44.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
44.5 + http://developer.apple.com/samplecode/GeekGameBoard/
44.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
44.7 +
44.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
44.9 + provided that the following conditions are met:
44.10 +
44.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
44.12 + and the following disclaimer.
44.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
44.14 + conditions and the following disclaimer in the documentation and/or other materials provided
44.15 + with the distribution.
44.16 +
44.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
44.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
44.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
44.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
44.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
44.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
44.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
44.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44.25 +*/
44.26 +#import "Game.h"
44.27 +@class Deck, Stack;
44.28 +
44.29 +
44.30 +/** The classic card solitaire game Klondike.
44.31 + See: http://en.wikipedia.org/wiki/Klondike_(solitaire) */
44.32 +@interface KlondikeGame : Game {
44.33 + Deck *_deck, *_sink;
44.34 + Deck *_aces[4];
44.35 +}
44.36 +
44.37 +@end
45.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
45.2 +++ b/Source/KlondikeGame.m Fri Mar 07 11:43:02 2008 -0800
45.3 @@ -0,0 +1,181 @@
45.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
45.5 + http://developer.apple.com/samplecode/GeekGameBoard/
45.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
45.7 +
45.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
45.9 + provided that the following conditions are met:
45.10 +
45.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
45.12 + and the following disclaimer.
45.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
45.14 + conditions and the following disclaimer in the documentation and/or other materials provided
45.15 + with the distribution.
45.16 +
45.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
45.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
45.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
45.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
45.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
45.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
45.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
45.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45.25 +*/
45.26 +#import "KlondikeGame.h"
45.27 +#import "Deck.h"
45.28 +#import "PlayingCard.h"
45.29 +#import "Stack.h"
45.30 +
45.31 +
45.32 +#define kStackHeight 500
45.33 +
45.34 +
45.35 +/** WARNING: THIS CODE REQUIRES GARBAGE COLLECTION!
45.36 + ** This sample application uses Objective-C 2.0 garbage collection.
45.37 + ** Therefore, the source code in this file does NOT perform manual object memory management.
45.38 + ** If you reuse any of this code in a process that isn't garbage collected, you will need to
45.39 + ** add all necessary retain/release/autorelease calls, and implement -dealloc methods,
45.40 + ** otherwise unpleasant leakage will occur!
45.41 + **/
45.42 +
45.43 +
45.44 +@implementation KlondikeGame
45.45 +
45.46 +
45.47 +- (id) initWithBoard: (CALayer*)board
45.48 +{
45.49 + self = [super initWithBoard: board];
45.50 + if (self != nil) {
45.51 + [self setNumberOfPlayers: 1];
45.52 +
45.53 + _deck = [[Deck alloc] initWithCardsOfClass: [PlayingCard class]];
45.54 + [_deck shuffle];
45.55 + _deck.position = CGPointMake(kCardWidth/2+16,kCardHeight/2+16);
45.56 + [board addSublayer: _deck];
45.57 +
45.58 + _sink = [[Deck alloc] init];
45.59 + _sink.position = CGPointMake(3*kCardWidth/2+32,kCardHeight/2+16);
45.60 + [board addSublayer: _sink];
45.61 +
45.62 + for( CardSuit suit=kSuitClubs; suit<=kSuitSpades; suit++ ) {
45.63 + Deck *aces = [[Deck alloc] init];
45.64 + aces.position = CGPointMake(kCardWidth/2+16+(kCardWidth+16)*(suit%2),
45.65 + 120+kCardHeight+(kCardHeight+16)*(suit/2));
45.66 + [board addSublayer: aces];
45.67 + _aces[suit] = aces;
45.68 + }
45.69 +
45.70 + for( int s=0; s<7; s++ ) {
45.71 + Stack *stack = [[Stack alloc] initWithStartPos: CGPointMake(kCardWidth/2,
45.72 + kStackHeight-kCardHeight/2.0)
45.73 + spacing: CGSizeMake(0,-22)];
45.74 + stack.frame = CGRectMake(260+s*(kCardWidth+16),16, kCardWidth,kStackHeight);
45.75 + stack.backgroundColor = nil;
45.76 + stack.dragAsStacks = YES;
45.77 + [board addSublayer: stack];
45.78 +
45.79 + // According to the rules, one card should be added to each stack in turn, instead
45.80 + // of populating entire stacks one at a time. However, if one trusts the Deck's
45.81 + // -shuffle method (which uses the random() function, seeded with a high-entropy
45.82 + // cryptographically-strong value), it shouldn't make any difference :-)
45.83 + for( int c=0; c<=s; c++ )
45.84 + [stack addBit: [_deck removeTopCard]];
45.85 + ((Card*)stack.bits.lastObject).faceUp = YES;
45.86 + }
45.87 +
45.88 + [self nextPlayer];
45.89 + }
45.90 + return self;
45.91 +}
45.92 +
45.93 +
45.94 +- (BOOL) clickedBit: (Bit*)bit
45.95 +{
45.96 + if( [bit isKindOfClass: [Card class]] ) {
45.97 + Card *card = (Card*)bit;
45.98 + if( card.holder == _deck ) {
45.99 + // Click on deck deals 3 cards to the sink:
45.100 + for( int i=0; i<3; i++ ) {
45.101 + Card *card = [_deck removeTopCard];
45.102 + if( card ) {
45.103 + [_sink addCard: card];
45.104 + card.faceUp = YES;
45.105 + }
45.106 + }
45.107 + [self endTurn];
45.108 + return YES;
45.109 + } else if( card.holder == _sink ) {
45.110 + // Clicking the sink when the deck is empty re-deals:
45.111 + if( _deck.empty ) {
45.112 + [_deck addCards: [_sink removeAllCards]];
45.113 + [_deck flip];
45.114 + [self endTurn];
45.115 + return YES;
45.116 + }
45.117 + } else {
45.118 + // Click on a card elsewhere turns it face-up:
45.119 + if( ! card.faceUp ) {
45.120 + card.faceUp = YES;
45.121 + return YES;
45.122 + }
45.123 + }
45.124 + }
45.125 + return NO;
45.126 +}
45.127 +
45.128 +
45.129 +- (BOOL) canBit: (Bit*)bit moveFrom: (id<BitHolder>)src
45.130 +{
45.131 + if( [bit isKindOfClass: [DraggedStack class]] ) {
45.132 + Card *bottomSrc = [[(DraggedStack*)bit bits] objectAtIndex: 0];
45.133 + if( ! bottomSrc.faceUp )
45.134 + return NO;
45.135 + }
45.136 + return YES;
45.137 +}
45.138 +
45.139 +
45.140 +- (BOOL) canBit: (Bit*)bit moveFrom: (id<BitHolder>)src to: (id<BitHolder>)dst
45.141 +{
45.142 + if( src==_deck || dst==_deck || dst==_sink )
45.143 + return NO;
45.144 +
45.145 + // Find the bottom card being moved, and the top card it's moving onto:
45.146 + PlayingCard *bottomSrc;
45.147 + if( [bit isKindOfClass: [DraggedStack class]] )
45.148 + bottomSrc = [[(DraggedStack*)bit bits] objectAtIndex: 0];
45.149 + else
45.150 + bottomSrc = (PlayingCard*)bit;
45.151 +
45.152 + PlayingCard *topDst;
45.153 + if( [dst isKindOfClass: [Deck class]] ) {
45.154 + // Dragging to an ace pile:
45.155 + if( ! [bit isKindOfClass: [Card class]] )
45.156 + return NO;
45.157 + topDst = (PlayingCard*) ((Deck*)dst).topCard;
45.158 + if( topDst == nil )
45.159 + return bottomSrc.rank == kRankAce;
45.160 + else
45.161 + return bottomSrc.suit == topDst.suit && bottomSrc.rank == topDst.rank+1;
45.162 +
45.163 + } else {
45.164 + // Dragging to a card stack:
45.165 + topDst = (PlayingCard*) ((Stack*)dst).topBit;
45.166 + if( topDst == nil )
45.167 + return bottomSrc.rank == kRankKing;
45.168 + else
45.169 + return bottomSrc.color != topDst.color && bottomSrc.rank == topDst.rank-1;
45.170 + }
45.171 +}
45.172 +
45.173 +
45.174 +- (Player*) checkForWinner
45.175 +{
45.176 + for( CardSuit suit=kSuitClubs; suit<=kSuitSpades; suit++ )
45.177 + if( _aces[suit].cards.count < 13 )
45.178 + return nil;
45.179 + return _currentPlayer;
45.180 +}
45.181 +
45.182 +
45.183 +
45.184 +@end
46.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
46.2 +++ b/Source/Piece.h Fri Mar 07 11:43:02 2008 -0800
46.3 @@ -0,0 +1,47 @@
46.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
46.5 + http://developer.apple.com/samplecode/GeekGameBoard/
46.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
46.7 +
46.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
46.9 + provided that the following conditions are met:
46.10 +
46.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
46.12 + and the following disclaimer.
46.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
46.14 + conditions and the following disclaimer in the documentation and/or other materials provided
46.15 + with the distribution.
46.16 +
46.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
46.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
46.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
46.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
46.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
46.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
46.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
46.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
46.25 +*/
46.26 +#import "Bit.h"
46.27 +
46.28 +
46.29 +/** A playing piece. A concrete subclass of Bit that displays an image. */
46.30 +@interface Piece : Bit
46.31 +{
46.32 + @private
46.33 + NSString *_imageName;
46.34 +}
46.35 +
46.36 +/** Initialize a Piece from an image file.
46.37 + imageName can be a resource name from the app bundle, or an absolute path.
46.38 + If scale is 0.0, the image's natural size will be used.
46.39 + If 0.0 < scale < 4.0, the image will be scaled by that factor.
46.40 + If scale >= 4.0, it will be used as the size to scale the maximum dimension to. */
46.41 +- (id) initWithImageNamed: (NSString*)imageName
46.42 + scale: (CGFloat)scale;
46.43 +
46.44 +- (void) setImage: (CGImageRef)image scale: (CGFloat)scale;
46.45 +- (void) setImage: (CGImageRef)image;
46.46 +- (void) setImageNamed: (NSString*)name;
46.47 +
46.48 +@property (copy) NSString* imageName;
46.49 +
46.50 +@end
47.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
47.2 +++ b/Source/Piece.m Fri Mar 07 11:43:02 2008 -0800
47.3 @@ -0,0 +1,132 @@
47.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
47.5 + http://developer.apple.com/samplecode/GeekGameBoard/
47.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
47.7 +
47.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
47.9 + provided that the following conditions are met:
47.10 +
47.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
47.12 + and the following disclaimer.
47.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
47.14 + conditions and the following disclaimer in the documentation and/or other materials provided
47.15 + with the distribution.
47.16 +
47.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
47.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
47.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
47.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
47.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
47.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
47.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
47.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47.25 +*/
47.26 +#import "Piece.h"
47.27 +#import "QuartzUtils.h"
47.28 +
47.29 +
47.30 +@implementation Piece
47.31 +
47.32 +
47.33 +- (id) initWithImageNamed: (NSString*)imageName
47.34 + scale: (CGFloat)scale
47.35 +{
47.36 + self = [super init];
47.37 + if (self != nil) {
47.38 + self.imageName = imageName;
47.39 + [self setImage: GetCGImageNamed(imageName) scale: scale];
47.40 + self.zPosition = kPieceZ;
47.41 + }
47.42 + return self;
47.43 +}
47.44 +
47.45 +
47.46 +- (id) initWithCoder: (NSCoder*)decoder
47.47 +{
47.48 + self = [super initWithCoder: decoder];
47.49 + if( self ) {
47.50 + self.imageName = [decoder decodeObjectForKey: @"imageName"];
47.51 + // (actual image (self.contents) was already restord by superclass)
47.52 + }
47.53 + return self;
47.54 +}
47.55 +
47.56 +- (void) encodeWithCoder: (NSCoder*)coder
47.57 +{
47.58 + [super encodeWithCoder: coder];
47.59 + [coder encodeObject: _imageName forKey: @"imageName"];
47.60 +}
47.61 +
47.62 +
47.63 +- (void) dealloc
47.64 +{
47.65 + [_imageName release];
47.66 + [super dealloc];
47.67 +}
47.68 +
47.69 +
47.70 +- (NSString*) description
47.71 +{
47.72 + return [NSString stringWithFormat: @"%@[%@]",
47.73 + [self class],
47.74 + _imageName.lastPathComponent.stringByDeletingPathExtension];
47.75 +}
47.76 +
47.77 +
47.78 +@synthesize imageName=_imageName;
47.79 +
47.80 +
47.81 +- (void) setImage: (CGImageRef)image scale: (CGFloat)scale
47.82 +{
47.83 + self.contents = (id) image;
47.84 + self.contentsGravity = @"resize";
47.85 + self.minificationFilter = kCAFilterLinear;
47.86 + int width = CGImageGetWidth(image), height = CGImageGetHeight(image);
47.87 + if( scale > 0 ) {
47.88 + if( scale >= 4.0 )
47.89 + scale /= MAX(width,height); // interpret scale as target dimensions
47.90 + width = ceil( width * scale);
47.91 + height= ceil( height* scale);
47.92 + }
47.93 + self.bounds = CGRectMake(0,0,width,height);
47.94 + self.imageName = nil;
47.95 +}
47.96 +
47.97 +- (void) setImage: (CGImageRef)image
47.98 +{
47.99 + CGSize size = self.bounds.size;
47.100 + [self setImage: image scale: MAX(size.width,size.height)];
47.101 +}
47.102 +
47.103 +- (void) setImageNamed: (NSString*)name
47.104 +{
47.105 + [self setImage: GetCGImageNamed(name)];
47.106 + self.imageName = name;
47.107 +}
47.108 +
47.109 +
47.110 +- (BOOL)containsPoint:(CGPoint)p
47.111 +{
47.112 + // Overrides CGLayer's implementation,
47.113 + // returning YES only for pixels at which this layer's alpha is at least 0.5.
47.114 + // This takes into account the opacity, bg color, and background image's alpha channel.
47.115 + if( ! [super containsPoint: p] )
47.116 + return NO;
47.117 + float opacity = self.opacity;
47.118 + if( opacity < 0.5 )
47.119 + return NO;
47.120 + float thresholdAlpha = 0.5 / self.opacity;
47.121 +
47.122 + CGColorRef bg = self.backgroundColor;
47.123 + float alpha = bg ?CGColorGetAlpha(bg) :0.0;
47.124 + if( alpha < thresholdAlpha ) {
47.125 + CGImageRef image = (CGImageRef)self.contents;
47.126 + if( image ) {
47.127 + // Note: This makes the convenient assumption that the image entirely fills the bounds.
47.128 + alpha = MAX(alpha, GetPixelAlpha(image, self.bounds.size, p));
47.129 + }
47.130 + }
47.131 + return alpha >= thresholdAlpha;
47.132 +}
47.133 +
47.134 +
47.135 +@end
48.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
48.2 +++ b/Source/PlayingCard.h Fri Mar 07 11:43:02 2008 -0800
48.3 @@ -0,0 +1,55 @@
48.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
48.5 + http://developer.apple.com/samplecode/GeekGameBoard/
48.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
48.7 +
48.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
48.9 + provided that the following conditions are met:
48.10 +
48.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
48.12 + and the following disclaimer.
48.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
48.14 + conditions and the following disclaimer in the documentation and/or other materials provided
48.15 + with the distribution.
48.16 +
48.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
48.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
48.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
48.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
48.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
48.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
48.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
48.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48.25 +*/
48.26 +#import "Card.h"
48.27 +
48.28 +typedef enum {
48.29 + kSuitClubs,
48.30 + kSuitDiamonds,
48.31 + kSuitHearts,
48.32 + kSuitSpades
48.33 +} CardSuit;
48.34 +
48.35 +typedef enum {
48.36 + kColorRed = 0,
48.37 + kColorBlack = 1
48.38 +} CardColor;
48.39 +
48.40 +typedef enum {
48.41 + kRankAce = 1,
48.42 + kRankJack = 11,
48.43 + kRankQueen = 12,
48.44 + kRankKing = 13
48.45 +} CardRank;
48.46 +
48.47 +
48.48 +/* A standard Western playing card. Serial numbers go from 1..52. */
48.49 +@interface PlayingCard : Card
48.50 +
48.51 +@property (readonly) CardSuit suit;
48.52 +@property (readonly) CardColor color;
48.53 +@property (readonly) CardRank rank;
48.54 +
48.55 +@property (readonly) NSString *suitString, *rankString, *faceSymbol;
48.56 +@property (readonly) CGColorRef suitColor;
48.57 +
48.58 +@end
49.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
49.2 +++ b/Source/PlayingCard.m Fri Mar 07 11:43:02 2008 -0800
49.3 @@ -0,0 +1,111 @@
49.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
49.5 + http://developer.apple.com/samplecode/GeekGameBoard/
49.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
49.7 +
49.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
49.9 + provided that the following conditions are met:
49.10 +
49.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
49.12 + and the following disclaimer.
49.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
49.14 + conditions and the following disclaimer in the documentation and/or other materials provided
49.15 + with the distribution.
49.16 +
49.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
49.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
49.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
49.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
49.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
49.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
49.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
49.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
49.25 +*/
49.26 +#import "PlayingCard.h"
49.27 +#import "QuartzUtils.h"
49.28 +
49.29 +
49.30 +@implementation PlayingCard
49.31 +
49.32 +
49.33 ++ (NSRange) serialNumberRange;
49.34 +{
49.35 + return NSMakeRange(1,52);
49.36 +}
49.37 +
49.38 +
49.39 +- (CALayer*) createFront
49.40 +{
49.41 + CALayer *front = [super createFront];
49.42 + NSString *name = [NSString stringWithFormat: @"%@%@",
49.43 + self.rankString, self.suitString];
49.44 +
49.45 + CGColorRef suitColor = self.suitColor;
49.46 + CATextLayer *label;
49.47 + label = AddTextLayer(front, name, [NSFont systemFontOfSize: 18],
49.48 + kCALayerMaxXMargin | kCALayerMinYMargin);
49.49 + label.foregroundColor = suitColor;
49.50 + label = AddTextLayer(front, name, [NSFont systemFontOfSize: 18],
49.51 + kCALayerMaxXMargin | kCALayerMaxYMargin);
49.52 + label.foregroundColor = suitColor;
49.53 + label.anchorPoint = CGPointMake(1,1);
49.54 + [label setValue: [NSNumber numberWithFloat: M_PI] forKeyPath: @"transform.rotation"];
49.55 +
49.56 + label = AddTextLayer(front, self.faceSymbol, [NSFont systemFontOfSize: 80],
49.57 + kCALayerWidthSizable | kCALayerHeightSizable);
49.58 + label.foregroundColor = suitColor;
49.59 + return front;
49.60 +}
49.61 +
49.62 +
49.63 +- (CardRank) rank {return (self.serialNumber-1)%13 + 1;}
49.64 +- (CardSuit) suit {return (self.serialNumber-1)/13;}
49.65 +
49.66 +- (CardColor) color
49.67 +{
49.68 + CardSuit suit = self.suit;
49.69 + return suit==kSuitDiamonds || suit==kSuitHearts ?kColorRed :kColorBlack;
49.70 +}
49.71 +
49.72 +
49.73 +- (NSString*) suitString
49.74 +{
49.75 + return [@"\u2663\u2666\u2665\u2660" substringWithRange: NSMakeRange(self.suit,1)];
49.76 +}
49.77 +
49.78 +- (NSString*) rankString
49.79 +{
49.80 + CardRank rank = self.rank;
49.81 + if( rank == 10 )
49.82 + return @"10";
49.83 + else
49.84 + return [@"A234567890JQK" substringWithRange: NSMakeRange(rank-1,1)];
49.85 +}
49.86 +
49.87 +- (CGColorRef) suitColor
49.88 +{
49.89 + static CGColorRef kSuitColor[4];
49.90 + if( ! kSuitColor[0] ) {
49.91 + kSuitColor[0] = kSuitColor[3] = kBlackColor;
49.92 + kSuitColor[1] = kSuitColor[2] = CGColorCreateGenericRGB(1, 0, 0, 1);
49.93 + }
49.94 + return kSuitColor[self.suit];
49.95 +}
49.96 +
49.97 +
49.98 +- (NSString*) faceSymbol
49.99 +{
49.100 + int rank = self.rank;
49.101 + if( rank < kRankJack )
49.102 + return self.suitString;
49.103 + else
49.104 + return [@"\u265E\u265B\u265A" substringWithRange: NSMakeRange(rank-kRankJack,1)]; // actually chess symbols
49.105 +}
49.106 +
49.107 +
49.108 +- (NSString*) description
49.109 +{
49.110 + return [NSString stringWithFormat: @"%@[%@%@]",self.class,self.rankString,self.suitString];
49.111 +}
49.112 +
49.113 +
49.114 +@end
50.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
50.2 +++ b/Source/QuartzUtils.h Fri Mar 07 11:43:02 2008 -0800
50.3 @@ -0,0 +1,70 @@
50.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
50.5 + http://developer.apple.com/samplecode/GeekGameBoard/
50.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
50.7 +
50.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
50.9 + provided that the following conditions are met:
50.10 +
50.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
50.12 + and the following disclaimer.
50.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
50.14 + conditions and the following disclaimer in the documentation and/or other materials provided
50.15 + with the distribution.
50.16 +
50.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
50.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
50.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
50.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
50.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
50.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
50.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
50.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
50.25 +*/
50.26 +#import <Quartz/Quartz.h>
50.27 +
50.28 +
50.29 +/** Constants for various commonly used colors. */
50.30 +extern CGColorRef kBlackColor, kWhiteColor,
50.31 + kTranslucentGrayColor, kTranslucentLightGrayColor,
50.32 + kAlmostInvisibleWhiteColor,
50.33 + kHighlightColor;
50.34 +
50.35 +
50.36 +/** Moves a layer from one superlayer to another, without changing its position onscreen. */
50.37 +void ChangeSuperlayer( CALayer *layer, CALayer *newSuperlayer, int index );
50.38 +
50.39 +/** Removes a layer from its superlayer without any fade-out animation. */
50.40 +void RemoveImmediately( CALayer *layer );
50.41 +
50.42 +/** Convenience for creating a CATextLayer. */
50.43 +CATextLayer* AddTextLayer( CALayer *superlayer,
50.44 + NSString *text, NSFont* font,
50.45 + enum CAAutoresizingMask align );
50.46 +
50.47 +
50.48 +/** Loads an image or pattern file into a CGImage or CGPattern.
50.49 + If the name begins with "/", it's interpreted as an absolute filesystem path.
50.50 + Otherwise, it's the name of a resource that's looked up in the app bundle.
50.51 + The image must exist, or an assertion-failure exception will be raised!
50.52 + Loaded images/patterns are cached in memory, so subsequent calls with the same name
50.53 + are very fast.
50.54 + The caller must NOT release the result, since it's retained in the cache. */
50.55 +CGImageRef GetCGImageNamed( NSString *name );
50.56 +CGColorRef GetCGPatternNamed( NSString *name );
50.57 +
50.58 +/** Loads image data from the pasteboard into a CGImage. */
50.59 +CGImageRef GetCGImageFromPasteboard( NSPasteboard *pb );
50.60 +
50.61 +/** Creates a CGPattern from a CGImage. Caller must release it. */
50.62 +CGPatternRef CreateImagePattern( CGImageRef image );
50.63 +
50.64 +/** Creates a CGColor that draws the given CGImage as a pattern. Caller must release it. */
50.65 +CGColorRef CreatePatternColor( CGImageRef image );
50.66 +
50.67 +/** Returns the alpha value of a single pixel in a CGImage, scaled to a particular size. */
50.68 +float GetPixelAlpha( CGImageRef image, CGSize imageSize, CGPoint pt );
50.69 +
50.70 +/** Returns the center point of a CGRect. */
50.71 +static inline CGPoint GetCGRectCenter( CGRect rect ) {
50.72 + return CGPointMake(CGRectGetMidX(rect),CGRectGetMidY(rect));
50.73 +}
50.74 \ No newline at end of file
51.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
51.2 +++ b/Source/QuartzUtils.m Fri Mar 07 11:43:02 2008 -0800
51.3 @@ -0,0 +1,273 @@
51.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
51.5 + http://developer.apple.com/samplecode/GeekGameBoard/
51.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
51.7 +
51.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
51.9 + provided that the following conditions are met:
51.10 +
51.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
51.12 + and the following disclaimer.
51.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
51.14 + conditions and the following disclaimer in the documentation and/or other materials provided
51.15 + with the distribution.
51.16 +
51.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
51.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
51.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
51.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
51.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
51.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
51.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
51.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51.25 +*/
51.26 +#import "QuartzUtils.h"
51.27 +
51.28 +
51.29 +CGColorRef kBlackColor, kWhiteColor,
51.30 + kTranslucentGrayColor, kTranslucentLightGrayColor,
51.31 + kAlmostInvisibleWhiteColor,
51.32 + kHighlightColor;
51.33 +
51.34 +
51.35 +__attribute__((constructor)) // Makes this function run when the app loads
51.36 +static void InitQuartzUtils()
51.37 +{
51.38 + kBlackColor = CGColorCreateGenericGray(0.0, 1.0);
51.39 + kWhiteColor = CGColorCreateGenericGray(1.0, 1.0);
51.40 + kTranslucentGrayColor = CGColorCreateGenericGray(0.0, 0.5);
51.41 + kTranslucentLightGrayColor = CGColorCreateGenericGray(0.0, 0.25);
51.42 + kAlmostInvisibleWhiteColor = CGColorCreateGenericGray(1, 0.05);
51.43 + kHighlightColor = CGColorCreateGenericRGB(1, 1, 0, 0.5);
51.44 +}
51.45 +
51.46 +
51.47 +void ChangeSuperlayer( CALayer *layer, CALayer *newSuperlayer, int index )
51.48 +{
51.49 + // Disable actions, else the layer will move to the wrong place and then back!
51.50 + [CATransaction flush];
51.51 + [CATransaction begin];
51.52 + [CATransaction setValue:(id)kCFBooleanTrue
51.53 + forKey:kCATransactionDisableActions];
51.54 +
51.55 + CGPoint pos = [newSuperlayer convertPoint: layer.position
51.56 + fromLayer: layer.superlayer];
51.57 + [layer retain];
51.58 + [layer removeFromSuperlayer];
51.59 + if( index >= 0 )
51.60 + [newSuperlayer insertSublayer: layer atIndex: index];
51.61 + else
51.62 + [newSuperlayer addSublayer: layer];
51.63 + layer.position = pos;
51.64 + [layer release];
51.65 +
51.66 + [CATransaction commit];
51.67 +}
51.68 +
51.69 +
51.70 +void RemoveImmediately( CALayer *layer )
51.71 +{
51.72 + [CATransaction flush];
51.73 + [CATransaction begin];
51.74 + [CATransaction setValue:(id)kCFBooleanTrue
51.75 + forKey:kCATransactionDisableActions];
51.76 + [layer removeFromSuperlayer];
51.77 + [CATransaction commit];
51.78 +}
51.79 +
51.80 +
51.81 +CATextLayer* AddTextLayer( CALayer *superlayer,
51.82 + NSString *text, NSFont* font,
51.83 + enum CAAutoresizingMask align )
51.84 +{
51.85 + CATextLayer *label = [[CATextLayer alloc] init];
51.86 + label.string = text;
51.87 + label.font = font;
51.88 + label.fontSize = font.pointSize;
51.89 + label.foregroundColor = kBlackColor;
51.90 +
51.91 + NSString *mode;
51.92 + if( align & kCALayerWidthSizable )
51.93 + mode = @"center";
51.94 + else if( align & kCALayerMinXMargin )
51.95 + mode = @"right";
51.96 + else
51.97 + mode = @"left";
51.98 + align |= kCALayerWidthSizable;
51.99 + label.alignmentMode = mode;
51.100 +
51.101 + CGFloat inset = superlayer.borderWidth + 3;
51.102 + CGRect bounds = CGRectInset(superlayer.bounds, inset, inset);
51.103 + CGFloat height = font.ascender;
51.104 + CGFloat y = bounds.origin.y;
51.105 + if( align & kCALayerHeightSizable )
51.106 + y += (bounds.size.height-height)/2.0;
51.107 + else if( align & kCALayerMinYMargin )
51.108 + y += bounds.size.height - height;
51.109 + align &= ~kCALayerHeightSizable;
51.110 + label.bounds = CGRectMake(0, font.descender,
51.111 + bounds.size.width, height - font.descender);
51.112 + label.position = CGPointMake(bounds.origin.x,y+font.descender);
51.113 + label.anchorPoint = CGPointMake(0,0);
51.114 +
51.115 + label.autoresizingMask = align;
51.116 + [superlayer addSublayer: label];
51.117 + [label release];
51.118 + return label;
51.119 +}
51.120 +
51.121 +
51.122 +CGImageRef CreateCGImageFromFile( NSString *path )
51.123 +{
51.124 + CGImageRef image = NULL;
51.125 + CFURLRef url = (CFURLRef) [NSURL fileURLWithPath: path];
51.126 + CGImageSourceRef src = CGImageSourceCreateWithURL(url, NULL);
51.127 + if( src ) {
51.128 + image = CGImageSourceCreateImageAtIndex(src, 0, NULL);
51.129 + CFRelease(src);
51.130 + if(!image) NSLog(@"Warning: CGImageSourceCreateImageAtIndex failed on file %@ (ptr size=%u)",path,sizeof(void*));
51.131 + }
51.132 + return image;
51.133 +}
51.134 +
51.135 +
51.136 +CGImageRef GetCGImageNamed( NSString *name )
51.137 +{
51.138 + // For efficiency, loaded images are cached in a dictionary by name.
51.139 + static NSMutableDictionary *sMap;
51.140 + if( ! sMap )
51.141 + sMap = [[NSMutableDictionary alloc] init];
51.142 +
51.143 + CGImageRef image = (CGImageRef) [sMap objectForKey: name];
51.144 + if( ! image ) {
51.145 + // Hasn't been cached yet, so load it:
51.146 + NSString *path;
51.147 + if( [name hasPrefix: @"/"] )
51.148 + path = name;
51.149 + else {
51.150 + path = [[NSBundle mainBundle] pathForResource: name ofType: nil];
51.151 + NSCAssert1(path,@"Couldn't find bundle image resource '%@'",name);
51.152 + }
51.153 + image = CreateCGImageFromFile(path);
51.154 + NSCAssert1(image,@"Failed to load image from %@",path);
51.155 + [sMap setObject: (id)image forKey: name];
51.156 + CGImageRelease(image);
51.157 + }
51.158 + return image;
51.159 +}
51.160 +
51.161 +
51.162 +CGColorRef GetCGPatternNamed( NSString *name ) // can be resource name or abs. path
51.163 +{
51.164 + // For efficiency, loaded patterns are cached in a dictionary by name.
51.165 + static NSMutableDictionary *sMap;
51.166 + if( ! sMap )
51.167 + sMap = [[NSMutableDictionary alloc] init];
51.168 +
51.169 + CGColorRef pattern = (CGColorRef) [sMap objectForKey: name];
51.170 + if( ! pattern ) {
51.171 + pattern = CreatePatternColor( GetCGImageNamed(name) );
51.172 + [sMap setObject: (id)pattern forKey: name];
51.173 + CGColorRelease(pattern);
51.174 + }
51.175 + return pattern;
51.176 +}
51.177 +
51.178 +
51.179 +CGImageRef GetCGImageFromPasteboard( NSPasteboard *pb )
51.180 +{
51.181 + CGImageSourceRef src = NULL;
51.182 + NSArray *paths = [pb propertyListForType: NSFilenamesPboardType];
51.183 + if( paths.count==1 ) {
51.184 + // If a file is being dragged, read it:
51.185 + CFURLRef url = (CFURLRef) [NSURL fileURLWithPath: [paths objectAtIndex: 0]];
51.186 + src = CGImageSourceCreateWithURL(url, NULL);
51.187 + } else {
51.188 + // Else look for an image type:
51.189 + NSString *type = [pb availableTypeFromArray: [NSImage imageUnfilteredPasteboardTypes]];
51.190 + if( type ) {
51.191 + NSData *data = [pb dataForType: type];
51.192 + src = CGImageSourceCreateWithData((CFDataRef)data, NULL);
51.193 + }
51.194 + }
51.195 + if(src) {
51.196 + CGImageRef image = CGImageSourceCreateImageAtIndex(src, 0, NULL);
51.197 + CFRelease(src);
51.198 + return image;
51.199 + } else
51.200 + return NULL;
51.201 +}
51.202 +
51.203 +
51.204 +float GetPixelAlpha( CGImageRef image, CGSize imageSize, CGPoint pt )
51.205 +{
51.206 + // Trivial reject:
51.207 + if( pt.x<0 || pt.x>=imageSize.width || pt.y<0 || pt.y>=imageSize.height )
51.208 + return 0.0;
51.209 +
51.210 + // sTinyContext is a 1x1 CGBitmapContext whose pixmap stores only alpha.
51.211 + static UInt8 sPixel[1];
51.212 + static CGContextRef sTinyContext;
51.213 + if( ! sTinyContext ) {
51.214 + sTinyContext = CGBitmapContextCreate(sPixel, 1, 1,
51.215 + 8, 1, // bpp, rowBytes
51.216 + NULL,
51.217 + kCGImageAlphaOnly);
51.218 + CGContextSetBlendMode(sTinyContext, kCGBlendModeCopy);
51.219 + }
51.220 +
51.221 + // Draw the image into sTinyContext, positioned so the desired point is at
51.222 + // (0,0), then examine the alpha value in the pixmap:
51.223 + CGContextDrawImage(sTinyContext,
51.224 + CGRectMake(-pt.x,-pt.y, imageSize.width,imageSize.height),
51.225 + image);
51.226 + return sPixel[0] / 255.0;
51.227 +}
51.228 +
51.229 +
51.230 +#pragma mark -
51.231 +#pragma mark PATTERNS:
51.232 +
51.233 +
51.234 +// callback for CreateImagePattern.
51.235 +static void drawPatternImage (void *info, CGContextRef ctx)
51.236 +{
51.237 + CGImageRef image = (CGImageRef) info;
51.238 + CGContextDrawImage(ctx,
51.239 + CGRectMake(0,0, CGImageGetWidth(image),CGImageGetHeight(image)),
51.240 + image);
51.241 +}
51.242 +
51.243 +// callback for CreateImagePattern.
51.244 +static void releasePatternImage( void *info )
51.245 +{
51.246 + CGImageRelease( (CGImageRef)info );
51.247 +}
51.248 +
51.249 +
51.250 +CGPatternRef CreateImagePattern( CGImageRef image )
51.251 +{
51.252 + NSCParameterAssert(image);
51.253 + int width = CGImageGetWidth(image);
51.254 + int height = CGImageGetHeight(image);
51.255 + static const CGPatternCallbacks callbacks = {0, &drawPatternImage, &releasePatternImage};
51.256 + return CGPatternCreate (image,
51.257 + CGRectMake (0, 0, width, height),
51.258 + CGAffineTransformMake (1, 0, 0, 1, 0, 0),
51.259 + width,
51.260 + height,
51.261 + kCGPatternTilingConstantSpacing,
51.262 + true,
51.263 + &callbacks);
51.264 +}
51.265 +
51.266 +
51.267 +CGColorRef CreatePatternColor( CGImageRef image )
51.268 +{
51.269 + CGPatternRef pattern = CreateImagePattern(image);
51.270 + CGColorSpaceRef space = CGColorSpaceCreatePattern(NULL);
51.271 + CGFloat components[1] = {1.0};
51.272 + CGColorRef color = CGColorCreateWithPattern(space, pattern, components);
51.273 + CGColorSpaceRelease(space);
51.274 + CGPatternRelease(pattern);
51.275 + return color;
51.276 +}
52.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
52.2 +++ b/Source/Stack.h Fri Mar 07 11:43:02 2008 -0800
52.3 @@ -0,0 +1,68 @@
52.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
52.5 + http://developer.apple.com/samplecode/GeekGameBoard/
52.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
52.7 +
52.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
52.9 + provided that the following conditions are met:
52.10 +
52.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
52.12 + and the following disclaimer.
52.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
52.14 + conditions and the following disclaimer in the documentation and/or other materials provided
52.15 + with the distribution.
52.16 +
52.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
52.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
52.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
52.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
52.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
52.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
52.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
52.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52.25 +*/
52.26 +#import "Bit.h"
52.27 +#import "BitHolder.h"
52.28 +
52.29 +
52.30 +/** A holder for multiple Bits that lines them up in stacks or rows.
52.31 + For example, this is used in solitaire card games for each pile in the "tableau". */
52.32 +@interface Stack : BitHolder
52.33 +{
52.34 + CGPoint _startPos; // see properties below for descriptions
52.35 + CGSize _spacing;
52.36 + CGSize _wrapSpacing;
52.37 + int _wrapInterval;
52.38 + NSMutableArray *_bits;
52.39 + BOOL _dragAsStacks;
52.40 +}
52.41 +
52.42 +- (id) initWithStartPos: (CGPoint)startPos spacing: (CGSize)spacing;
52.43 +
52.44 +- (id) initWithStartPos: (CGPoint)startPos spacing: (CGSize)spacing
52.45 + wrapInterval: (int)wrapInterval wrapSpacing: (CGSize)wrapSpacing;
52.46 +
52.47 +@property CGPoint startPos; // Position where first Bit should go
52.48 +@property CGSize spacing; // Spacing between successive Bits
52.49 +@property CGSize wrapSpacing; // Spacing between wrapped-around sub-piles
52.50 +@property int wrapInterval; // How many Bits to add before wrapping
52.51 +@property BOOL dragAsStacks; // If set to YES, dragging a Bit drags a DraggedStack
52.52 +@property (readonly) NSArray *bits; // The Bits, in order
52.53 +@property (readonly) Bit *topBit; // The topmost Bit (last item in self.bits)
52.54 +
52.55 +/** Adds a Bit to the end */
52.56 +- (void) addBit: (Bit*)bit;
52.57 +
52.58 +@end
52.59 +
52.60 +
52.61 +/** A subset of a Stack, dragged out of it if its dragAsStacks flag is set.
52.62 + This is used in typical card solitaire games.
52.63 + A DraggedStack exists only during a drag; afterwards, its Cards
52.64 + are incorporated into the destination Stack. */
52.65 +@interface DraggedStack : Bit
52.66 +
52.67 +- (id) initWithBits: (NSArray*)bits;
52.68 +
52.69 +@property (readonly) NSArray *bits;
52.70 +
52.71 +@end
53.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
53.2 +++ b/Source/Stack.m Fri Mar 07 11:43:02 2008 -0800
53.3 @@ -0,0 +1,185 @@
53.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
53.5 + http://developer.apple.com/samplecode/GeekGameBoard/
53.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
53.7 +
53.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
53.9 + provided that the following conditions are met:
53.10 +
53.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
53.12 + and the following disclaimer.
53.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
53.14 + conditions and the following disclaimer in the documentation and/or other materials provided
53.15 + with the distribution.
53.16 +
53.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
53.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
53.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
53.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
53.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
53.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
53.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
53.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53.25 +*/
53.26 +#import "Stack.h"
53.27 +#import "QuartzUtils.h"
53.28 +
53.29 +
53.30 +@implementation Stack
53.31 +
53.32 +
53.33 +- (id) initWithStartPos: (CGPoint)startPos spacing: (CGSize)spacing
53.34 + wrapInterval: (int)wrapInterval wrapSpacing: (CGSize)wrapSpacing
53.35 +{
53.36 + self = [super init];
53.37 + if (self != nil) {
53.38 + _startPos = startPos;
53.39 + _spacing = spacing;
53.40 + _wrapInterval = wrapInterval;
53.41 + _wrapSpacing = wrapSpacing;
53.42 + self.cornerRadius = 8;
53.43 + self.backgroundColor = kAlmostInvisibleWhiteColor;
53.44 + self.borderColor = kHighlightColor;
53.45 + _bits = [[NSMutableArray alloc] init];
53.46 + }
53.47 + return self;
53.48 +}
53.49 +
53.50 +- (id) initWithStartPos: (CGPoint)startPos spacing: (CGSize)spacing;
53.51 +{
53.52 + return [self initWithStartPos: startPos spacing: spacing
53.53 + wrapInterval: INT_MAX wrapSpacing: CGSizeZero];
53.54 +}
53.55 +
53.56 +
53.57 +- (void) dealloc
53.58 +{
53.59 + [_bits release];
53.60 + [super dealloc];
53.61 +}
53.62 +
53.63 +
53.64 +@synthesize spacing=_spacing, wrapSpacing=_wrapSpacing, startPos=_startPos, wrapInterval=_wrapInterval;
53.65 +@synthesize dragAsStacks=_dragAsStacks;
53.66 +@synthesize bits=_bits;
53.67 +
53.68 +
53.69 +- (Bit*) topBit
53.70 +{
53.71 + return [_bits lastObject];
53.72 +}
53.73 +
53.74 +
53.75 +- (void) dump
53.76 +{
53.77 + printf("Stack = ");
53.78 + for( CALayer *layer in self.sublayers )
53.79 + printf("%s @z=%g ", [[layer description] UTF8String],layer.zPosition);
53.80 + printf("\n");
53.81 +}
53.82 +
53.83 +
53.84 +- (void) x_repositionBit: (Bit*)bit forIndex: (int)i
53.85 +{
53.86 + bit.position = CGPointMake(_startPos.x + _spacing.width *(i%_wrapInterval) + _wrapSpacing.width *(i/_wrapInterval),
53.87 + _startPos.y + _spacing.height*(i%_wrapInterval) + _wrapSpacing.height*(i/_wrapInterval));
53.88 +}
53.89 +
53.90 +- (void) addBit: (Bit*)bit
53.91 +{
53.92 + if( [bit isKindOfClass: [DraggedStack class]] ) {
53.93 + for( Bit *subBit in [(DraggedStack*)bit bits] )
53.94 + [self addBit: subBit];
53.95 + } else {
53.96 + int n = _bits.count;
53.97 + [_bits addObject: bit];
53.98 + ChangeSuperlayer(bit, self, n);
53.99 + [self x_repositionBit: bit forIndex: n];
53.100 + }
53.101 +}
53.102 +
53.103 +
53.104 +- (void) setHighlighted: (BOOL)highlighted
53.105 +{
53.106 + [super setHighlighted: highlighted];
53.107 + self.borderWidth = (highlighted ?6 :0);
53.108 +}
53.109 +
53.110 +
53.111 +- (Bit*) canDragBit: (Bit*)bit
53.112 +{
53.113 + NSInteger index = [_bits indexOfObjectIdenticalTo: bit];
53.114 + if( index==NSNotFound )
53.115 + return nil;
53.116 + if( _dragAsStacks && index < _bits.count-1 ) {
53.117 + // Move bit and those above it into a temporary DraggedStack:
53.118 + NSRange r = NSMakeRange(index,_bits.count-index);
53.119 + NSArray *bitsToDrag = [_bits subarrayWithRange: r];
53.120 + [_bits removeObjectsInRange: r];
53.121 + DraggedStack *stack = [[DraggedStack alloc] initWithBits: bitsToDrag];
53.122 + [self addSublayer: stack];
53.123 + [stack release];
53.124 + stack.anchorPoint = CGPointMake( bit.position.x/stack.bounds.size.width,
53.125 + bit.position.y/stack.bounds.size.height );
53.126 + stack.position = bit.position;
53.127 + return stack;
53.128 + } else {
53.129 + [bit retain];
53.130 + [_bits removeObjectIdenticalTo: bit];
53.131 + return [bit autorelease];
53.132 + }
53.133 +}
53.134 +
53.135 +
53.136 +- (void) cancelDragBit: (Bit*)bit
53.137 +{
53.138 + [self addBit: bit];
53.139 + if( [bit isKindOfClass: [DraggedStack class]] ) {
53.140 + [bit removeFromSuperlayer];
53.141 + }
53.142 +}
53.143 +
53.144 +
53.145 +- (void) draggedBit: (Bit*)bit to: (id<BitHolder>)dst
53.146 +{
53.147 + int i=0;
53.148 + for( Bit *bit in self.sublayers )
53.149 + [self x_repositionBit: bit forIndex: i++];
53.150 +}
53.151 +
53.152 +
53.153 +- (BOOL) dropBit: (Bit*)bit atPoint: (CGPoint)point
53.154 +{
53.155 + [self addBit: bit];
53.156 + return YES;
53.157 +}
53.158 +
53.159 +@end
53.160 +
53.161 +
53.162 +
53.163 +
53.164 +@implementation DraggedStack
53.165 +
53.166 +
53.167 +- (id) initWithBits: (NSArray*)bits
53.168 +{
53.169 + self = [super init];
53.170 + if( self ) {
53.171 + CGRect bounds = CGRectZero;
53.172 + for( Bit *bit in bits ) {
53.173 + bounds = CGRectUnion(bounds, bit.frame);
53.174 + [self addSublayer: bit];
53.175 + }
53.176 + self.bounds = bounds;
53.177 + self.anchorPoint = CGPointZero;
53.178 + self.position = CGPointZero;
53.179 + }
53.180 + return self;
53.181 +}
53.182 +
53.183 +- (NSArray*) bits
53.184 +{
53.185 + return [self.sublayers.copy autorelease];
53.186 +}
53.187 +
53.188 +@end
54.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
54.2 +++ b/Source/TicTacToeGame.h Fri Mar 07 11:43:02 2008 -0800
54.3 @@ -0,0 +1,34 @@
54.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
54.5 + http://developer.apple.com/samplecode/GeekGameBoard/
54.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
54.7 +
54.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
54.9 + provided that the following conditions are met:
54.10 +
54.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
54.12 + and the following disclaimer.
54.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
54.14 + conditions and the following disclaimer in the documentation and/or other materials provided
54.15 + with the distribution.
54.16 +
54.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
54.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
54.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
54.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
54.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
54.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
54.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
54.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54.25 +*/
54.26 +#import "Game.h"
54.27 +@class RectGrid, Dispenser;
54.28 +
54.29 +
54.30 +/** Officially the world's second-lamest board game.
54.31 + See: http://en.wikipedia.org/wiki/Tic-tac-toe */
54.32 +@interface TicTacToeGame : Game {
54.33 + RectGrid *_grid;
54.34 + Dispenser *_dispenser[2];
54.35 +}
54.36 +
54.37 +@end
55.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
55.2 +++ b/Source/TicTacToeGame.m Fri Mar 07 11:43:02 2008 -0800
55.3 @@ -0,0 +1,95 @@
55.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
55.5 + http://developer.apple.com/samplecode/GeekGameBoard/
55.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
55.7 +
55.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
55.9 + provided that the following conditions are met:
55.10 +
55.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
55.12 + and the following disclaimer.
55.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
55.14 + conditions and the following disclaimer in the documentation and/or other materials provided
55.15 + with the distribution.
55.16 +
55.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
55.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
55.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
55.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
55.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
55.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
55.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
55.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
55.25 +*/
55.26 +#import "TicTacToeGame.h"
55.27 +#import "Grid.h"
55.28 +#import "Dispenser.h"
55.29 +#import "Piece.h"
55.30 +#import "QuartzUtils.h"
55.31 +
55.32 +
55.33 +@implementation TicTacToeGame
55.34 +
55.35 +- (void) x_createDispenser: (NSString*)imageName forPlayer: (int)playerNumber x: (int)x
55.36 +{
55.37 + Piece *p = [[Piece alloc] initWithImageNamed: imageName scale: 80];
55.38 + p.owner = [self.players objectAtIndex: playerNumber];
55.39 + _dispenser[playerNumber] = [[Dispenser alloc] initWithPrototype: p quantity: 0
55.40 + frame: CGRectMake(x,16, 120,120)];
55.41 + [_board addSublayer: _dispenser[playerNumber]];
55.42 +}
55.43 +
55.44 +- (id) initWithBoard: (CALayer*)board
55.45 +{
55.46 + self = [super initWithBoard: board];
55.47 + if (self != nil) {
55.48 + [self setNumberOfPlayers: 2];
55.49 +
55.50 + // Create a 3x3 grid:
55.51 + CGFloat center = floor(CGRectGetMidX(board.bounds));
55.52 + _grid = [[RectGrid alloc] initWithRows: 3 columns: 3 frame: CGRectMake(center-150,16, 300,300)];
55.53 + [_grid addAllCells];
55.54 + _grid.allowsMoves = _grid.allowsCaptures = NO;
55.55 + _grid.cellColor = CGColorCreateGenericGray(1.0, 0.25);
55.56 + _grid.lineColor = kTranslucentLightGrayColor;
55.57 + [board addSublayer: _grid];
55.58 +
55.59 + // Create piece dispensers for the two players:
55.60 + [self x_createDispenser: @"/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/ToolbarUtilitiesFolderIcon.icns"
55.61 + forPlayer: 0 x: center-290];
55.62 + [self x_createDispenser: @"/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/ToolbarAdvanced.icns"
55.63 + forPlayer: 1 x: center+170];
55.64 +
55.65 + // And they're off!
55.66 + [self nextPlayer];
55.67 + }
55.68 + return self;
55.69 +}
55.70 +
55.71 +- (void) nextPlayer
55.72 +{
55.73 + [super nextPlayer];
55.74 + // Give the next player another piece to put down:
55.75 + _dispenser[self.currentPlayer.index].quantity = 1;
55.76 +}
55.77 +
55.78 +static Player* ownerAt( Grid *grid, int index )
55.79 +{
55.80 + return [grid cellAtRow: index/3 column: index%3].bit.owner;
55.81 +}
55.82 +
55.83 +/** Should return the winning player, if the current position is a win. */
55.84 +- (Player*) checkForWinner
55.85 +{
55.86 + static const int kWinningTriples[8][3] = { {0,1,2}, {3,4,5}, {6,7,8}, // rows
55.87 + {0,3,6}, {1,4,7}, {2,5,8}, // cols
55.88 + {0,4,8}, {2,4,6} }; // diagonals
55.89 + for( int i=0; i<8; i++ ) {
55.90 + const int *triple = kWinningTriples[i];
55.91 + Player *p = ownerAt(_grid,triple[0]);
55.92 + if( p && p == ownerAt(_grid,triple[1]) && p == ownerAt(_grid,triple[2]) )
55.93 + return p;
55.94 + }
55.95 + return nil;
55.96 +}
55.97 +
55.98 +@end
56.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
56.2 +++ b/Source/main.m Fri Mar 07 11:43:02 2008 -0800
56.3 @@ -0,0 +1,28 @@
56.4 +/* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
56.5 + http://developer.apple.com/samplecode/GeekGameBoard/
56.6 + Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
56.7 +
56.8 + Redistribution and use in source and binary forms, with or without modification, are permitted
56.9 + provided that the following conditions are met:
56.10 +
56.11 + * Redistributions of source code must retain the above copyright notice, this list of conditions
56.12 + and the following disclaimer.
56.13 + * Redistributions in binary form must reproduce the above copyright notice, this list of
56.14 + conditions and the following disclaimer in the documentation and/or other materials provided
56.15 + with the distribution.
56.16 +
56.17 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
56.18 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
56.19 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
56.20 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
56.21 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
56.22 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
56.23 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
56.24 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56.25 +*/
56.26 +#import <Cocoa/Cocoa.h>
56.27 +
56.28 +int main(int argc, char *argv[])
56.29 +{
56.30 + return NSApplicationMain(argc, (const char **) argv);
56.31 +}