Source/HexchequerGame.m
author snej@snej.local
Sun Jan 11 00:02:27 2009 -0800 (2009-01-11)
changeset 26 e7a464fb6d39
parent 20 7c9ecb09a612
permissions -rw-r--r--
Added ball graphics to Xcode project, which fixes the Go game. Fixed Tic-Tac-Toe. Fixed an exception in the demo app when changing games.
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 "HexchequerGame.h"
jens@0
    24
#import "HexGrid.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 HexchequerGame
jens@0
    31
jens@0
    32
jens@10
    33
- (void) setUpBoard
jens@0
    34
{
jens@16
    35
    // Create a hex grid and rotate it 30 degrees so the cells are edge-up:
jens@16
    36
    CGRect tableBounds = _table.bounds;
jens@16
    37
    CGFloat s = tableBounds.size.height / 9;
jens@16
    38
    HexGrid *board = [[HexGrid alloc] initWithRows: 9 columns: 9
jens@16
    39
                                           spacing: CGSizeMake(s,s)
jens@16
    40
                                          position: GetCGRectCenter(tableBounds)];
jens@16
    41
    board.anchorPoint = CGPointMake(0.47,0.5);  // Missing half-cells on right edge perturb center pt
jens@22
    42
    board.transform = CATransform3DMakeRotation(M_PI/6, 0,0,1);
jens@22
    43
    board.bitTransform = CATransform3DMakeRotation(-M_PI/6, 0,0,1);    // counteract board rotation
jens@16
    44
    _board = board;
jens@16
    45
    [_table addSublayer: _board];
jens@22
    46
jens@16
    47
    board.allowsMoves = YES;
jens@16
    48
    board.allowsCaptures = NO;      // no land-on captures, that is
jens@16
    49
    board.cellColor = CreateGray(1.0, 0.25);
jens@16
    50
    board.lineColor = kTranslucentLightGrayColor;
jens@16
    51
    board.reversed = ! [[self.players objectAtIndex: 0] isLocal];
jens@16
    52
    [board addCellsInHexagon];
jens@10
    53
}
jens@10
    54
jens@10
    55
- (NSString*) initialStateString
jens@10
    56
{
jens@16
    57
      return @"1111-1111--1111---1111-----------------2222---2222--2222-2222";
jens@0
    58
}
jens@0
    59
jens@0
    60
jens@0
    61
- (BOOL) canBit: (Bit*)bit moveFrom: (id<BitHolder>)srcHolder to: (id<BitHolder>)dstHolder
jens@0
    62
{
jens@0
    63
    Hex *src=(Hex*)srcHolder, *dst=(Hex*)dstHolder;
jens@0
    64
    if( [bit valueForKey: @"King"] )
jens@16
    65
        if( dst==src.bl || dst==src.br || dst==src.l
jens@0
    66
           || (src.bl.bit.unfriendly && dst==src.bl.bl) || (src.br.bit.unfriendly && dst==src.br.br)
jens@16
    67
           || (src.l.bit.unfriendly  && dst==src.l.l) )
jens@0
    68
            return YES;    
jens@16
    69
    return dst==src.fl || dst==src.fr || dst==src.r
jens@16
    70
            || (src.fl.bit.unfriendly && dst==src.fl.fl) 
jens@16
    71
            || (src.fr.bit.unfriendly && dst==src.fr.fr) 
jens@16
    72
            || (src. r.bit.unfriendly && dst==src. r. r);
jens@0
    73
}
jens@0
    74
jens@0
    75
- (void) bit: (Bit*)bit movedFrom: (id<BitHolder>)srcHolder to: (id<BitHolder>)dstHolder
jens@0
    76
{
jens@0
    77
    Hex *src=(Hex*)srcHolder, *dst=(Hex*)dstHolder;
jens@7
    78
jens@10
    79
    Turn *turn = self.currentTurn;
jens@10
    80
    if( turn.move.length==0 )
jens@10
    81
        [turn addToMove: src.name];
jens@10
    82
    [turn addToMove: @"-"];
jens@10
    83
    [turn addToMove: dst.name];
jens@0
    84
    
jens@7
    85
    BOOL isKing = ([bit valueForKey: @"King"] != nil);    
jens@1
    86
    PlaySound(isKing ?@"Funk" :@"Tink");
jens@0
    87
jens@0
    88
    // "King" a piece that made it to the last row:
jens@16
    89
    if( dst.fr == nil )
jens@0
    90
        if( ! isKing ) {
jens@1
    91
            PlaySound(@"Blow");
jens@0
    92
            bit.scale = 1.4;
jens@0
    93
            [bit setValue: @"King" forKey: @"King"];
jens@0
    94
            // don't set isKing flag - piece can't capture again after being kinged.
jens@0
    95
        }
jens@0
    96
jens@0
    97
    // Check for a capture:
jens@0
    98
    Hex *capture = nil;
jens@0
    99
    if(dst==src.fl.fl)
jens@0
   100
        capture = src.fl;
jens@0
   101
    else if(dst==src.fr.fr)
jens@0
   102
        capture = src.fr;
jens@0
   103
    else if(dst==src.bl.bl)
jens@0
   104
        capture = src.bl;
jens@0
   105
    else if(dst==src.br.br)
jens@0
   106
        capture = src.br;
jens@0
   107
    else if(dst==src.l.l)
jens@0
   108
        capture = src.l;
jens@0
   109
    else if(dst==src.r.r)
jens@0
   110
        capture = src.r;
jens@0
   111
    
jens@0
   112
    if( capture ) {
jens@1
   113
        PlaySound(@"Pop");
jens@10
   114
        [turn addToMove: @"!"];
jens@10
   115
        [capture destroyBit];
jens@0
   116
        
jens@0
   117
        // Now check if another capture is possible. If so, don't end the turn:
jens@16
   118
        if( (dst.fl.bit.unfriendly && dst.fl.fl.empty) 
jens@16
   119
                || (dst.fr.bit.unfriendly && dst.fr.fr.empty) 
jens@16
   120
                || (dst. r.bit.unfriendly && dst. r. r.empty) )
jens@0
   121
            return;
jens@0
   122
        if( isKing )
jens@16
   123
            if( (dst.bl.bit.unfriendly && dst.bl.bl.empty)
jens@16
   124
                    || (dst.br.bit.unfriendly && dst.br.br.empty)
jens@16
   125
                    || (dst.l.bit.unfriendly && dst.l.l.empty) )
jens@0
   126
                return;
jens@0
   127
    }
jens@0
   128
    
jens@0
   129
    [self endTurn];
jens@0
   130
}
jens@0
   131
jens@20
   132
- (BOOL) canOpponentMoveFrom: (GridCell*)src
jens@20
   133
{
jens@20
   134
    if( ! src.bit.unfriendly )
jens@20
   135
        return NO;
jens@20
   136
    if( [super canOpponentMoveFrom: src] )
jens@20
   137
        return YES;
jens@20
   138
    Hex *hex = (Hex*)src;
jens@20
   139
    if( hex.bit.tag )           // remember, it's opponent's piece, so directions are reversed
jens@20
   140
        if( hex.r.empty || (hex.r.bit.friendly && hex.r.r.empty) )
jens@20
   141
            return YES;
jens@20
   142
    return hex.l.empty || (hex.l.bit.friendly && hex.l.l.empty);
jens@20
   143
}
jens@0
   144
jens@0
   145
@end