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