Source/Stack.m
author Jens Alfke <jens@mooseyard.com>
Sun Mar 16 15:06:47 2008 -0700 (2008-03-16)
changeset 7 428a194e3e59
parent 0 e9f7ba4718e1
child 21 2eb229411d73
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 "Stack.h"
jens@0
    24
#import "QuartzUtils.h"
jens@0
    25
jens@0
    26
jens@0
    27
@implementation Stack
jens@0
    28
jens@0
    29
jens@0
    30
- (id) initWithStartPos: (CGPoint)startPos spacing: (CGSize)spacing
jens@0
    31
           wrapInterval: (int)wrapInterval wrapSpacing: (CGSize)wrapSpacing
jens@0
    32
{
jens@0
    33
    self = [super init];
jens@0
    34
    if (self != nil) {
jens@0
    35
        _startPos = startPos;
jens@0
    36
        _spacing = spacing;
jens@0
    37
        _wrapInterval = wrapInterval;
jens@0
    38
        _wrapSpacing = wrapSpacing;
jens@0
    39
        self.cornerRadius = 8;
jens@0
    40
        self.backgroundColor = kAlmostInvisibleWhiteColor;
jens@0
    41
        self.borderColor = kHighlightColor;
jens@0
    42
        _bits = [[NSMutableArray alloc] init];
jens@0
    43
    }
jens@0
    44
    return self;
jens@0
    45
}
jens@0
    46
jens@0
    47
- (id) initWithStartPos: (CGPoint)startPos spacing: (CGSize)spacing;
jens@0
    48
{
jens@0
    49
    return [self initWithStartPos: startPos spacing: spacing 
jens@0
    50
                     wrapInterval: INT_MAX wrapSpacing: CGSizeZero];
jens@0
    51
}
jens@0
    52
jens@0
    53
jens@0
    54
- (void) dealloc
jens@0
    55
{
jens@0
    56
    [_bits release];
jens@0
    57
    [super dealloc];
jens@0
    58
}
jens@0
    59
jens@0
    60
jens@0
    61
@synthesize spacing=_spacing, wrapSpacing=_wrapSpacing, startPos=_startPos, wrapInterval=_wrapInterval;
jens@0
    62
@synthesize dragAsStacks=_dragAsStacks;
jens@0
    63
@synthesize bits=_bits;
jens@0
    64
jens@0
    65
jens@0
    66
- (Bit*) topBit
jens@0
    67
{
jens@0
    68
    return [_bits lastObject];
jens@0
    69
}
jens@0
    70
jens@0
    71
jens@0
    72
- (void) dump
jens@0
    73
{
jens@0
    74
    printf("Stack = ");
jens@1
    75
    for( GGBLayer *layer in self.sublayers )
jens@0
    76
        printf("%s @z=%g   ", [[layer description] UTF8String],layer.zPosition);
jens@0
    77
    printf("\n");
jens@0
    78
}
jens@0
    79
jens@0
    80
jens@0
    81
- (void) x_repositionBit: (Bit*)bit forIndex: (int)i
jens@0
    82
{
jens@0
    83
    bit.position = CGPointMake(_startPos.x + _spacing.width *(i%_wrapInterval) + _wrapSpacing.width *(i/_wrapInterval),
jens@0
    84
                               _startPos.y + _spacing.height*(i%_wrapInterval) + _wrapSpacing.height*(i/_wrapInterval));
jens@0
    85
}
jens@0
    86
jens@0
    87
- (void) addBit: (Bit*)bit
jens@0
    88
{
jens@0
    89
    if( [bit isKindOfClass: [DraggedStack class]] ) {
jens@0
    90
        for( Bit *subBit in [(DraggedStack*)bit bits] )
jens@0
    91
            [self addBit: subBit];
jens@0
    92
    } else {
jens@0
    93
        int n = _bits.count;
jens@0
    94
        [_bits addObject: bit];
jens@0
    95
        ChangeSuperlayer(bit, self, n);
jens@0
    96
        [self x_repositionBit: bit forIndex: n];
jens@0
    97
    }
jens@0
    98
}
jens@0
    99
jens@0
   100
jens@0
   101
- (void) setHighlighted: (BOOL)highlighted
jens@0
   102
{
jens@0
   103
    [super setHighlighted: highlighted];
jens@0
   104
    self.borderWidth = (highlighted ?6 :0);
jens@0
   105
}
jens@0
   106
jens@0
   107
jens@0
   108
- (Bit*) canDragBit: (Bit*)bit
jens@0
   109
{
jens@0
   110
    NSInteger index = [_bits indexOfObjectIdenticalTo: bit];
jens@0
   111
    if( index==NSNotFound )
jens@0
   112
        return nil;
jens@0
   113
    if( _dragAsStacks && index < _bits.count-1 ) {
jens@0
   114
        // Move bit and those above it into a temporary DraggedStack:
jens@0
   115
        NSRange r = NSMakeRange(index,_bits.count-index);
jens@0
   116
        NSArray *bitsToDrag = [_bits subarrayWithRange: r];
jens@0
   117
        [_bits removeObjectsInRange: r];
jens@0
   118
        DraggedStack *stack = [[DraggedStack alloc] initWithBits: bitsToDrag];
jens@0
   119
        [self addSublayer: stack];
jens@0
   120
        [stack release];
jens@0
   121
        stack.anchorPoint = CGPointMake( bit.position.x/stack.bounds.size.width,
jens@0
   122
                                         bit.position.y/stack.bounds.size.height );
jens@0
   123
        stack.position = bit.position;
jens@0
   124
        return stack;
jens@0
   125
    } else {
jens@0
   126
        [bit retain];
jens@0
   127
        [_bits removeObjectIdenticalTo: bit];
jens@0
   128
        return [bit autorelease];
jens@0
   129
    }
jens@0
   130
}
jens@0
   131
jens@0
   132
jens@0
   133
- (void) cancelDragBit: (Bit*)bit
jens@0
   134
{
jens@0
   135
    [self addBit: bit];
jens@0
   136
    if( [bit isKindOfClass: [DraggedStack class]] ) {
jens@0
   137
        [bit removeFromSuperlayer];
jens@0
   138
    }
jens@0
   139
}
jens@0
   140
jens@0
   141
jens@0
   142
- (void) draggedBit: (Bit*)bit to: (id<BitHolder>)dst
jens@0
   143
{
jens@0
   144
    int i=0;
jens@0
   145
    for( Bit *bit in self.sublayers )
jens@0
   146
        [self x_repositionBit: bit forIndex: i++];
jens@0
   147
}
jens@0
   148
jens@0
   149
jens@0
   150
- (BOOL) dropBit: (Bit*)bit atPoint: (CGPoint)point
jens@0
   151
{
jens@0
   152
    [self addBit: bit];
jens@0
   153
    return YES;
jens@0
   154
}
jens@0
   155
jens@0
   156
@end
jens@0
   157
jens@0
   158
jens@0
   159
jens@0
   160
jens@0
   161
@implementation DraggedStack
jens@0
   162
jens@0
   163
jens@0
   164
- (id) initWithBits: (NSArray*)bits
jens@0
   165
{
jens@0
   166
    self = [super init];
jens@0
   167
    if( self ) {
jens@0
   168
        CGRect bounds = CGRectZero;
jens@0
   169
        for( Bit *bit in bits ) {
jens@0
   170
            bounds = CGRectUnion(bounds, bit.frame);
jens@0
   171
            [self addSublayer: bit];
jens@0
   172
        }
jens@0
   173
        self.bounds = bounds;
jens@0
   174
        self.anchorPoint = CGPointZero;
jens@0
   175
        self.position = CGPointZero;
jens@0
   176
    }
jens@0
   177
    return self;
jens@0
   178
}
jens@0
   179
jens@0
   180
- (NSArray*) bits
jens@0
   181
{
jens@0
   182
    return [self.sublayers.copy autorelease];
jens@0
   183
}
jens@0
   184
jens@0
   185
@end