Source/DemoBoardView.m
author Jens Alfke <jens@mooseyard.com>
Thu Jul 03 17:44:30 2008 -0700 (2008-07-03)
changeset 10 6c78cc6bd7a6
parent 8 45c82a071aca
child 11 436cbdf56810
permissions -rw-r--r--
Lots of reworking. Completed support for game history, including Turn class. Changed Game API around quite a bit.
     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 "DemoBoardView.h"
    24 #import "Game.h"
    25 #import "GGBTextLayer.h"
    26 #import "QuartzUtils.h"
    27 
    28 
    29 @implementation DemoBoardView
    30 
    31 
    32 /** Class names of available games */
    33 static NSString* const kMenuGameNames[] = {@"KlondikeGame", @"CheckersGame", @"HexchequerGame",
    34                                            @"TicTacToeGame", @"GoGame"};
    35 
    36 /** Class name of the current game. */
    37 static NSString* sCurrentGameName = @"CheckersGame";
    38 
    39 
    40 - (IBAction) toggleRemoteOpponent: (id)sender
    41 {
    42     NSAssert(self.game.currentTurn==0,@"Game has already begun");
    43     Player *opponent = [self.game.players objectAtIndex: 1];
    44     opponent.local = !opponent.local;
    45 }
    46 
    47 
    48 - (void) startGameNamed: (NSString*)gameClassName
    49 {
    50     [super startGameNamed: gameClassName];
    51     
    52     Game *game = self.game;
    53     [game addObserver: self 
    54            forKeyPath: @"currentPlayer"
    55               options: NSKeyValueObservingOptionInitial
    56               context: NULL];
    57     [game addObserver: self
    58            forKeyPath: @"winner"
    59               options: 0 
    60               context: NULL];
    61     
    62     self.window.title = [(id)[game class] displayName];
    63 }
    64 
    65 
    66 - (CGRect) gameBoardFrame
    67 {
    68     CGRect bounds = [super gameBoardFrame];
    69     bounds.size.height -= 32;                   // Leave room for headline
    70     return CGRectInset(bounds,4,4);
    71 }
    72 
    73 
    74 - (BOOL)canBecomeKeyView        {return YES;}
    75 - (BOOL)acceptsFirstResponder   {return YES;}
    76 
    77 
    78 - (void) awakeFromNib
    79 {
    80     srandomdev();
    81     
    82     [self registerForDraggedTypes: [NSImage imagePasteboardTypes]];
    83     [self registerForDraggedTypes: [NSArray arrayWithObject: NSFilenamesPboardType]];
    84     
    85     CGRect bounds = self.layer.bounds;
    86     self.layer.backgroundColor = GetCGPatternNamed(@"Background.png");
    87         
    88     bounds.size.height -= 32;
    89     _headline = [GGBTextLayer textLayerInSuperlayer: self.layer
    90                                            withText: nil
    91                                            fontSize: 24
    92                                           alignment: kCALayerWidthSizable | kCALayerMinYMargin];
    93     
    94     [self startGameNamed: sCurrentGameName];
    95     
    96     [_turnSlider bind: @"value"    toObject: self withKeyPath: @"game.currentTurn" options: nil];
    97 }
    98 
    99 
   100 - (IBAction) startGameFromMenu: (id)sender
   101 {
   102     sCurrentGameName = kMenuGameNames[ [sender tag] ];
   103     [self startGameNamed: sCurrentGameName];
   104 }
   105 
   106 
   107 - (void)observeValueForKeyPath:(NSString *)keyPath 
   108                       ofObject:(id)object 
   109                         change:(NSDictionary *)change
   110                        context:(void *)context
   111 {
   112     Game *game = self.game;
   113     if( object == game ) {
   114         NSLog(@"maxTurn = %u, currentTurn = %u", 
   115               self.game.maxTurn,self.game.currentTurn);
   116         NSLog(@"Game state = '%@'", self.game.stateString);
   117 
   118         _turnSlider.maxValue = self.game.maxTurn;
   119         _turnSlider.numberOfTickMarks = self.game.maxTurn+1;
   120         
   121         Player *p = game.winner;
   122         NSString *msg;
   123         if( p ) {
   124             // The game is won
   125             [[NSSound soundNamed: @"Sosumi"] play];
   126             if( self.game.local )
   127                 msg = @"%@ wins! Congratulations!";
   128             else
   129                 msg = p.local ?@"You Win! Congratulations!" :@"You Lose ... :-(";
   130         } else {
   131             // Otherwise go on to the next turn:
   132             p = game.currentPlayer;
   133             msg = @"Your turn, %@";
   134         }
   135         _headline.string = [NSString stringWithFormat: msg, p.name];
   136     }
   137 }
   138 
   139 
   140 - (IBAction) undo: (id)sender
   141 {
   142     if( self.game.currentTurn > 0 )
   143         self.game.currentTurn--;
   144     else
   145         NSBeep();
   146 }
   147 
   148 
   149 - (IBAction) redo: (id)sender
   150 {
   151     if( self.game.currentTurn < self.game.maxTurn )
   152         self.game.currentTurn++;
   153     else
   154         NSBeep();
   155 }
   156 
   157 
   158 #pragma mark -
   159 #pragma mark NSAPPLICATION DELEGATE:
   160 
   161 
   162 - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
   163 {
   164     return YES;
   165 }
   166 
   167 @end