Source/CheckersGame.m
author Jens Alfke <jens@mooseyard.com>
Wed Mar 12 15:51:32 2008 -0700 (2008-03-12)
changeset 6 af9b2b929b03
parent 0 e9f7ba4718e1
child 7 428a194e3e59
permissions -rw-r--r--
Fixed: An exception in the Go game if you mouse down on the board but then drag to the captured-pieces area and release the mouse.
jens@0
     1
/*  This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
jens@0
     2
    http://developer.apple.com/samplecode/GeekGameBoard/
jens@0
     3
    Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
jens@0
     4
jens@0
     5
    Redistribution and use in source and binary forms, with or without modification, are permitted
jens@0
     6
    provided that the following conditions are met:
jens@0
     7
jens@0
     8
    * Redistributions of source code must retain the above copyright notice, this list of conditions
jens@0
     9
      and the following disclaimer.
jens@0
    10
    * Redistributions in binary form must reproduce the above copyright notice, this list of
jens@0
    11
      conditions and the following disclaimer in the documentation and/or other materials provided
jens@0
    12
      with the distribution.
jens@0
    13
jens@0
    14
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
jens@0
    15
    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
jens@0
    16
    FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
jens@0
    17
    BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
jens@0
    18
    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
jens@0
    19
    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
jens@0
    20
    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
jens@0
    21
    THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
jens@0
    22
*/
jens@0
    23
#import "CheckersGame.h"
jens@0
    24
#import "Grid.h"
jens@0
    25
#import "Piece.h"
jens@0
    26
#import "QuartzUtils.h"
jens@1
    27
#import "GGBUtils.h"
jens@0
    28
jens@0
    29
jens@0
    30
@implementation CheckersGame
jens@0
    31
jens@0
    32
jens@0
    33
- (void) addPieces: (NSString*)imageName
jens@0
    34
            toGrid: (Grid*)grid
jens@0
    35
         forPlayer: (int)playerNum
jens@0
    36
              rows: (NSRange)rows
jens@0
    37
       alternating: (BOOL)alternating
jens@0
    38
{
jens@0
    39
    Piece *prototype = [[Piece alloc] initWithImageNamed: imageName scale: floor(grid.spacing.width * 0.8)];
jens@0
    40
    prototype.owner = [self.players objectAtIndex: playerNum];
jens@0
    41
    unsigned cols=grid.columns;
jens@0
    42
    for( unsigned row=rows.location; row<NSMaxRange(rows); row++ )
jens@0
    43
        for( unsigned col=0; col<cols; col++ ) {
jens@0
    44
            if( !alternating || ((row+col) & 1) == 0 ) {
jens@0
    45
                GridCell *cell = [grid cellAtRow: row column: col];
jens@0
    46
                if( cell ) {
jens@0
    47
                    Piece *piece = [prototype copy];
jens@0
    48
                    cell.bit = piece;
jens@0
    49
                    [piece release];
jens@0
    50
                    //cell.bit.rotation = random() % 360; // keeps pieces from looking too samey
jens@0
    51
                    _numPieces[playerNum]++;
jens@0
    52
                }
jens@0
    53
            }
jens@0
    54
        }
jens@0
    55
    [prototype release];
jens@0
    56
}
jens@0
    57
jens@0
    58
jens@0
    59
- (Grid*) x_makeGrid
jens@0
    60
{
jens@0
    61
    RectGrid *grid = [[[RectGrid alloc] initWithRows: 8 columns: 8 frame: _board.bounds] autorelease];
jens@0
    62
    CGPoint pos = grid.position;
jens@0
    63
    pos.x = floor((_board.bounds.size.width-grid.frame.size.width)/2);
jens@0
    64
    [grid addAllCells];
jens@0
    65
    grid.position = pos;
jens@0
    66
    grid.allowsMoves = YES;
jens@0
    67
    grid.allowsCaptures = NO;
jens@1
    68
    grid.cellColor = CreateGray(0.0, 0.25);
jens@1
    69
    grid.altCellColor = CreateGray(1.0, 0.25);
jens@0
    70
    grid.lineColor = nil;
jens@0
    71
    [self addPieces: @"Green Ball.png" toGrid: grid forPlayer: 0 rows: NSMakeRange(0,3) alternating: YES];
jens@0
    72
    [self addPieces: @"Red Ball.png"   toGrid: grid forPlayer: 1 rows: NSMakeRange(5,3) alternating: YES];
jens@0
    73
    return grid;
jens@0
    74
}
jens@0
    75
jens@0
    76
jens@1
    77
- (id) initWithBoard: (GGBLayer*)board
jens@0
    78
{
jens@0
    79
    self = [super initWithBoard: board];
jens@0
    80
    if (self != nil) {
jens@0
    81
        [self setNumberOfPlayers: 2];
jens@0
    82
        [board addSublayer: [self x_makeGrid]];
jens@0
    83
        [self nextPlayer];
jens@0
    84
    }
jens@0
    85
    return self;
jens@0
    86
}
jens@0
    87
jens@0
    88
jens@0
    89
- (BOOL) canBit: (Bit*)bit moveFrom: (id<BitHolder>)srcHolder to: (id<BitHolder>)dstHolder
jens@0
    90
{
jens@0
    91
    Square *src=(Square*)srcHolder, *dst=(Square*)dstHolder;
jens@0
    92
    if( [bit valueForKey: @"King"] )
jens@0
    93
        if( dst==src.bl || dst==src.br || dst==src.l || dst==src.r
jens@0
    94
           || (src.bl.bit.unfriendly && dst==src.bl.bl) || (src.br.bit.unfriendly && dst==src.br.br) )
jens@0
    95
            return YES;    
jens@0
    96
    return dst==src.fl || dst==src.fr
jens@0
    97
        || (src.fl.bit.unfriendly && dst==src.fl.fl) || (src.fr.bit.unfriendly && dst==src.fr.fr);
jens@0
    98
}
jens@0
    99
jens@0
   100
- (void) bit: (Bit*)bit movedFrom: (id<BitHolder>)srcHolder to: (id<BitHolder>)dstHolder
jens@0
   101
{
jens@0
   102
    Square *src=(Square*)srcHolder, *dst=(Square*)dstHolder;
jens@0
   103
    int playerIndex = self.currentPlayer.index;
jens@0
   104
    BOOL isKing = ([bit valueForKey: @"King"] != nil);
jens@0
   105
    
jens@1
   106
    PlaySound(isKing ?@"Funk" :@"Tink");
jens@0
   107
jens@0
   108
    // "King" a piece that made it to the last row:
jens@0
   109
    if( dst.row == (playerIndex ?0 :7) )
jens@0
   110
        if( ! isKing ) {
jens@1
   111
            PlaySound(@"Blow");
jens@0
   112
            bit.scale = 1.4;
jens@0
   113
            [bit setValue: @"King" forKey: @"King"];
jens@0
   114
            // don't set isKing flag - piece can't jump again after being kinged.
jens@0
   115
        }
jens@0
   116
jens@0
   117
    // Check for a capture:
jens@0
   118
    Square *capture = nil;
jens@0
   119
    if(dst==src.fl.fl)
jens@0
   120
        capture = src.fl;
jens@0
   121
    else if(dst==src.fr.fr)
jens@0
   122
        capture = src.fr;
jens@0
   123
    else if(dst==src.bl.bl)
jens@0
   124
        capture = src.bl;
jens@0
   125
    else if(dst==src.br.br)
jens@0
   126
        capture = src.br;
jens@0
   127
    
jens@0
   128
    if( capture ) {
jens@1
   129
        PlaySound(@"Pop");
jens@0
   130
        Bit *bit = capture.bit;
jens@0
   131
        _numPieces[bit.owner.index]--;
jens@0
   132
        [bit destroy];
jens@0
   133
        
jens@0
   134
        // Now check if another capture is possible. If so, don't end the turn:
jens@0
   135
        if( (dst.fl.bit.unfriendly && dst.fl.fl.empty) || (dst.fr.bit.unfriendly && dst.fr.fr.empty) )
jens@0
   136
            return;
jens@0
   137
        if( isKing )
jens@0
   138
            if( (dst.bl.bit.unfriendly && dst.bl.bl.empty) || (dst.br.bit.unfriendly && dst.br.br.empty) )
jens@0
   139
                return;
jens@0
   140
    }
jens@0
   141
    
jens@0
   142
    [self endTurn];
jens@0
   143
}
jens@0
   144
jens@0
   145
- (Player*) checkForWinner
jens@0
   146
{
jens@0
   147
    // Whoever runs out of pieces loses:
jens@0
   148
    if( _numPieces[0]==0 )
jens@0
   149
        return [self.players objectAtIndex: 1];
jens@0
   150
    else if( _numPieces[1]==0 )
jens@0
   151
        return [self.players objectAtIndex: 0];
jens@0
   152
    else
jens@0
   153
        return nil;
jens@0
   154
}
jens@0
   155
jens@0
   156
jens@0
   157
@end