Source/DemoBoardView.m
author Jens Alfke <jens@mooseyard.com>
Sun Mar 16 15:06:47 2008 -0700 (2008-03-16)
changeset 7 428a194e3e59
parent 1 3eb7be1dd7b6
child 8 45c82a071aca
permissions -rw-r--r--
Game class now tracks board state and moves, as strings, and can step through its history.
Fixed another bug in Go (you could drag your captured stones back to the board!)
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 "DemoBoardView.h"
jens@0
    24
#import "Game.h"
jens@1
    25
#import "GGBTextLayer.h"
jens@0
    26
#import "QuartzUtils.h"
jens@0
    27
jens@0
    28
jens@0
    29
/**  WARNING: THIS CODE REQUIRES GARBAGE COLLECTION!
jens@0
    30
 **  This sample application uses Objective-C 2.0 garbage collection.
jens@0
    31
 **  Therefore, the source code in this file does NOT perform manual object memory management.
jens@0
    32
 **  If you reuse any of this code in a process that isn't garbage collected, you will need to
jens@0
    33
 **  add all necessary retain/release/autorelease calls, and implement -dealloc methods,
jens@0
    34
 **  otherwise unpleasant leakage will occur!
jens@0
    35
 **/
jens@0
    36
jens@0
    37
jens@0
    38
@implementation DemoBoardView
jens@0
    39
jens@0
    40
jens@0
    41
/** Class names of available games */
jens@0
    42
static NSString* const kMenuGameNames[] = {@"KlondikeGame", @"CheckersGame", @"HexchequerGame",
jens@0
    43
                                           @"TicTacToeGame", @"GoGame"};
jens@0
    44
jens@0
    45
/** Class name of the current game. */
jens@7
    46
static NSString* sCurrentGameName = @"CheckersGame";
jens@0
    47
jens@0
    48
jens@0
    49
- (void) startGameNamed: (NSString*)gameClassName
jens@0
    50
{
jens@0
    51
    [super startGameNamed: gameClassName];
jens@0
    52
    
jens@0
    53
    Game *game = self.game;
jens@0
    54
    [game addObserver: self 
jens@0
    55
           forKeyPath: @"currentPlayer"
jens@0
    56
              options: NSKeyValueObservingOptionInitial
jens@0
    57
              context: NULL];
jens@0
    58
    [game addObserver: self
jens@0
    59
           forKeyPath: @"winner"
jens@0
    60
              options: 0 
jens@0
    61
              context: NULL];
jens@0
    62
    
jens@0
    63
    self.window.title = [(id)[game class] displayName];
jens@0
    64
}
jens@0
    65
jens@0
    66
jens@0
    67
- (CGRect) gameBoardFrame
jens@0
    68
{
jens@0
    69
    CGRect bounds = [super gameBoardFrame];
jens@0
    70
    bounds.size.height -= 32;                   // Leave room for headline
jens@0
    71
    return CGRectInset(bounds,4,4);
jens@0
    72
}
jens@0
    73
jens@0
    74
jens@0
    75
- (void) awakeFromNib
jens@0
    76
{
jens@0
    77
    srandomdev();
jens@0
    78
    
jens@0
    79
    [self registerForDraggedTypes: [NSImage imagePasteboardTypes]];
jens@0
    80
    [self registerForDraggedTypes: [NSArray arrayWithObject: NSFilenamesPboardType]];
jens@0
    81
    
jens@0
    82
    CGRect bounds = self.layer.bounds;
jens@1
    83
    self.layer.backgroundColor = GetCGPatternNamed(@"Background.png");
jens@0
    84
        
jens@0
    85
    bounds.size.height -= 32;
jens@1
    86
    _headline = [GGBTextLayer textLayerInSuperlayer: self.layer
jens@1
    87
                                           withText: nil
jens@1
    88
                                           fontSize: 24
jens@1
    89
                                          alignment: kCALayerWidthSizable | kCALayerMinYMargin];
jens@0
    90
    
jens@0
    91
    [self startGameNamed: sCurrentGameName];
jens@7
    92
    
jens@7
    93
    [_turnSlider bind: @"value"    toObject: self withKeyPath: @"game.currentTurn" options: nil];
jens@0
    94
}
jens@0
    95
jens@0
    96
jens@0
    97
- (void) startGameFromMenu: (id)sender
jens@0
    98
{
jens@0
    99
    sCurrentGameName = kMenuGameNames[ [sender tag] ];
jens@0
   100
    [self startGameNamed: sCurrentGameName];
jens@0
   101
}
jens@0
   102
jens@0
   103
jens@0
   104
- (void)observeValueForKeyPath:(NSString *)keyPath 
jens@0
   105
                      ofObject:(id)object 
jens@0
   106
                        change:(NSDictionary *)change
jens@0
   107
                       context:(void *)context
jens@0
   108
{
jens@0
   109
    Game *game = self.game;
jens@0
   110
    if( object == game ) {
jens@7
   111
        NSLog(@"maxTurn = %u, currentTurn=%u", self.game.maxTurn,self.game.currentTurn);
jens@7
   112
        _turnSlider.maxValue = self.game.maxTurn;
jens@7
   113
        _turnSlider.numberOfTickMarks = self.game.maxTurn+1;
jens@7
   114
        
jens@0
   115
        Player *p = game.winner;
jens@0
   116
        NSString *msg;
jens@0
   117
        if( p ) {
jens@0
   118
            [[NSSound soundNamed: @"Sosumi"] play];
jens@0
   119
            msg = @"%@ wins! Congratulations!";
jens@0
   120
        } else {
jens@0
   121
            p = game.currentPlayer;
jens@0
   122
            msg = @"Your turn, %@";
jens@7
   123
            NSLog(@"Game state = '%@'", self.game.stateString);
jens@0
   124
        }
jens@0
   125
        _headline.string = [NSString stringWithFormat: msg, p.name];
jens@0
   126
    }
jens@0
   127
}
jens@0
   128
jens@0
   129
jens@0
   130
- (IBAction) enterFullScreen: (id)sender
jens@0
   131
{
jens@0
   132
    [super enterFullScreen: sender];
jens@0
   133
    [self startGameNamed: sCurrentGameName];        // restart game so it'll use the new size
jens@0
   134
}
jens@0
   135
jens@0
   136
jens@0
   137
#pragma mark -
jens@0
   138
#pragma mark NSAPPLICATION DELEGATE:
jens@0
   139
jens@0
   140
jens@0
   141
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
jens@0
   142
{
jens@0
   143
    return YES;
jens@0
   144
}
jens@0
   145
jens@0
   146
@end