* Got it working with latest iPhone SDK.
* Fixed some text alignment issues that showed up on PlayingCards.
* Working on persistence and move-tracking for Game.
1 /* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
2 http://developer.apple.com/samplecode/GeekGameBoard/
3 Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
5 Redistribution and use in source and binary forms, with or without modification, are permitted
6 provided that the following conditions are met:
8 * Redistributions of source code must retain the above copyright notice, this list of conditions
9 and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright notice, this list of
11 conditions and the following disclaimer in the documentation and/or other materials provided
12 with the distribution.
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
15 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
17 BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
19 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
20 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
21 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 #import "CheckersGame.h"
26 #import "QuartzUtils.h"
30 @implementation CheckersGame
33 - (Piece*) pieceForPlayer: (int)playerNum
35 Piece *p = [[Piece alloc] initWithImageNamed: (playerNum==0 ?@"Green Ball.png" :@"Red Ball.png")
36 scale: floor(_grid.spacing.width * 0.8)];
37 p.owner = [self.players objectAtIndex: playerNum];
38 p.name = playerNum ?@"2" :@"1";
39 return [p autorelease];
44 RectGrid *grid = [[[RectGrid alloc] initWithRows: 8 columns: 8 frame: _board.bounds] autorelease];
46 CGPoint pos = _grid.position;
47 pos.x = floor((_board.bounds.size.width-grid.frame.size.width)/2);
49 grid.allowsMoves = YES;
50 grid.allowsCaptures = NO;
51 grid.cellColor = CreateGray(0.0, 0.25);
52 grid.altCellColor = CreateGray(1.0, 0.25);
56 for( int i=0; i<32; i++ ) {
58 [_cells addObject: [_grid cellAtRow: row column: 2*(i%4) + (row&1)]];
60 self.stateString = @"111111111111--------222222222222";
65 - (id) initWithBoard: (GGBLayer*)board
67 self = [super initWithBoard: board];
69 [self setNumberOfPlayers: 2];
70 _cells = [[NSMutableArray alloc] init];
72 [board addSublayer: _grid];
75 PreloadSound(@"Tink");
76 PreloadSound(@"Funk");
77 PreloadSound(@"Blow");
91 - (NSString*) stateString
93 unichar state[_cells.count];
95 for( GridCell *cell in _cells ) {
96 NSString *ident = cell.bit.name;
98 state[i++] = [ident characterAtIndex: 0];
102 return [NSString stringWithCharacters: state length: i];
105 - (void) setStateString: (NSString*)state
107 _numPieces[0] = _numPieces[1] = 0;
109 for( GridCell *cell in _cells ) {
111 switch( [state characterAtIndex: i++] ) {
112 case '1': piece = [self pieceForPlayer: 0]; _numPieces[0]++; break;
113 case '2': piece = [self pieceForPlayer: 1]; _numPieces[1]++; break;
114 default: piece = nil; break;
121 - (BOOL) canBit: (Bit*)bit moveFrom: (id<BitHolder>)srcHolder to: (id<BitHolder>)dstHolder
123 Square *src=(Square*)srcHolder, *dst=(Square*)dstHolder;
124 if( [bit valueForKey: @"King"] )
125 if( dst==src.bl || dst==src.br || dst==src.l || dst==src.r
126 || (src.bl.bit.unfriendly && dst==src.bl.bl) || (src.br.bit.unfriendly && dst==src.br.br) )
128 return dst==src.fl || dst==src.fr
129 || (src.fl.bit.unfriendly && dst==src.fl.fl) || (src.fr.bit.unfriendly && dst==src.fr.fr);
132 - (void) bit: (Bit*)bit movedFrom: (id<BitHolder>)srcHolder to: (id<BitHolder>)dstHolder
134 Square *src=(Square*)srcHolder, *dst=(Square*)dstHolder;
135 int playerIndex = self.currentPlayer.index;
137 if( self.currentMove.length==0 )
138 [self.currentMove appendString: src.name];
139 [self.currentMove appendString: dst.name];
141 BOOL isKing = ([bit valueForKey: @"King"] != nil);
142 PlaySound(isKing ?@"Funk" :@"Tink");
144 // "King" a piece that made it to the last row:
145 if( dst.row == (playerIndex ?0 :7) )
149 [bit setValue: @"King" forKey: @"King"];
150 // don't set isKing flag - piece can't jump again after being kinged.
153 // Check for a capture:
154 Square *capture = nil;
157 else if(dst==src.fr.fr)
159 else if(dst==src.bl.bl)
161 else if(dst==src.br.br)
166 Bit *bit = capture.bit;
167 _numPieces[bit.owner.index]--;
170 // Now check if another capture is possible. If so, don't end the turn:
171 if( (dst.fl.bit.unfriendly && dst.fl.fl.empty) || (dst.fr.bit.unfriendly && dst.fr.fr.empty) )
174 if( (dst.bl.bit.unfriendly && dst.bl.bl.empty) || (dst.br.bit.unfriendly && dst.br.br.empty) )
181 - (Player*) checkForWinner
183 // Whoever runs out of pieces loses:
184 if( _numPieces[0]==0 )
185 return [self.players objectAtIndex: 1];
186 else if( _numPieces[1]==0 )
187 return [self.players objectAtIndex: 0];
193 - (BOOL) applyMoveString: (NSString*)move
195 int length = move.length;
196 if( length<4 || (length&1) )
199 for( int i=0; i<length; i+=2 ) {
200 NSString *ident = [move substringWithRange: NSMakeRange(i,2)];
201 GridCell *dst = [_grid cellWithName: ident];
203 if( ! [self animateMoveFrom: src to: dst] )