This is AliceDoc.m in view mode; [Download] [Up]
/* Generated by Interface Builder */ #import "AliceDoc.h" #import "AliceApp.h" #import "CubeView.h" #import "CubePlane.h" #import "Plane.h" extern "Objective-C" { #import "BasicApp.h" #import <objc/List.h> #import <objc/Storage.h> #import <appkit/Window.h> #import <appkit/Matrix.h> #import <appkit/MenuCell.h> } extern "C" { #import <strings.h> } typedef struct _Action { CubeCoord plane; CubeDir dir; } Action; #define ZAlloc(CLASS) [CLASS allocFromZone:[self zone]] #ifndef DITCHDAY static id RandGen; static const int RandTurns = 8; #else #define CAPITAL 0x20 static const char Scrambler[] = "BmWjHbWLkkoGcggx"; static const int RandTurns = 16; #endif static const CubeInt SidesShown = 3; @implementation AliceDoc + initialize { #ifndef DITCHDAY RandGen = [ZAlloc(Random) init]; #endif [super initialize]; [self setContentsClass:[CubeView class]]; return self; } - getWindow { myCube = new Cube; for (CubeInt d=0; d < SidesShown; d++) { #ifdef THREED Plane *newPlane = myCube->plane(2*d+1); #else Plane *newPlane = myCube->plane(2*d+1, T); #endif [contents addSubview:[ZAlloc(CubePlane) initPlane:newPlane tag:d]]; } [contents resize:self]; undoActions = [ZAlloc(Storage) initCount:0 elementSize:sizeof(Action) description:"{ii}"]; [super getWindow]; [window addToEventMask:NX_KEYDOWNMASK]; return self; } - free { [undoActions free]; return [super free]; } - reset:sender { myCube->reset(); [undoActions empty]; scrambled = NO; return [self test:self]; } - scramble:sender { int n; [self reset:sender]; [contents setAutodisplay:NO]; for (n=0; n < RandTurns; n++) { #ifndef DITCHDAY [self twist:(int)[RandGen randMax:(CubeNSides-1)] :getDir([RandGen rand])]; #else char code = Scrambler[n]; CubeDir dir = (code & CAPITAL) ? 1 : 0; [self doTwist:code :dir]; #endif [undoActions empty]; } [contents setAutodisplay:YES]; scrambled = YES; return [self test:self]; } - unscramble:sender { while ([self undo:self]) { NXPing(); } return [self test:self]; } - undo:sender { int count; if (count = [undoActions count]) { Action *last; last = (Action*)[undoActions elementAt:(count-1)]; [self twist:last->plane :last->dir]; [undoActions removeLastElement]; /* Don't redo this! */ [undoActions removeLastElement]; /* Don't undo this! */ return [self test:self]; } return nil; } - test:sender { if (scrambled && [undoActions count] && !myCube->test()) { [NXApp successPanel:self]; scrambled = NO; } return [contents update]; } /* Modify State */ - twist:(CubeCoord) plane :(CubeDir) rot { Action next; #ifdef THREED CubeAxis axis2 = XYZTMAX; /* Use default */ Plane *twister = myCube->plane(plane); #else CubeAxis axis2 = getAxis(rot); Plane *twister = myCube->plane(plane,axis2); #endif #ifdef DEBUG1 printf("Twist:%d :%d\n",plane,rot); #endif twister[LO].rotate(getDir(rot),axis2); #ifndef THREED twister[HI].rotate(getDir(rot),axis2); #endif delete twister; next.plane = plane; /* Undo List */ next.dir = revDir(rot); [undoActions addElement:&next]; return self; } - rotate:(CubeCoord) plane :(CubeDir) dir { [self twist:plane :dir]; [self twist:otherSide(plane) :dir]; return self; } /* Rotate */ - rotateX:sender { CubeDir tag = [sender selectedTag]; [self rotate:X0 :tag]; return [self test:self]; } - rotateY:sender { CubeDir tag = [sender selectedTag]; [self rotate:Y0 :tag]; return [self test:self]; } - rotateZ:sender { CubeDir tag = [sender selectedTag]; [self rotate:Z0 :tag]; return [self test:self]; } - rotateT:sender { CubeDir tag = [sender selectedTag]; [self rotate:T0 :tag]; return [self test:self]; } #define POS_MASK ('\010') inline CubePos parsePos(CubeInt tag) {return (tag & POS_MASK) ? 1 : 0;} inline CubeDir parseDir(CubeInt tag) {return tag & (~POS_MASK);} /* Twist */ - twistX:sender { CubeInt tag = [sender selectedTag]; [self twist:X0+parsePos(tag) :parseDir(tag)]; return [self test:self]; } - twistY:sender { CubeInt tag = [sender selectedTag]; [self twist:Y0+parsePos(tag) :parseDir(tag)]; return [self test:self]; } - twistZ:sender { CubeInt tag = [sender selectedTag]; [self twist:Z0+parsePos(tag) :parseDir(tag)]; return [self test:self]; } - twistT:sender { CubeInt tag = [sender selectedTag]; [self twist:T0+parsePos(tag) :parseDir(tag)]; return [self test:self]; } #define COORD_MASK 0x01F /* Just use the bottom 31 */ #define WRAP(C) ((C & (COORD_MASK))-1) /* a =0, b = 1, ... x=31 */ /* 6 per plane, 3 per position */ #define NROTS (3) /* key Equivalents */ - doTwist:(unsigned short) charCode :(short)dir { unsigned char code = WRAP(charCode); CubeCoord coord = (code / NROTS) % CubeNCoords; CubeAxis axis = code % NROTS; if (axis == getAxis(coord)) axis = T; [self twist:coord :setDir(axis,dir)]; return [self test:self]; } - doRotate:(unsigned short) charCode :(short)dir { unsigned char code = WRAP(charCode); CubeCoord coord = (code / NROTS) % CubeNCoords; CubeAxis axis = code % NROTS; if (axis == getAxis(coord)) axis = T; [self rotate:coord :setDir(axis,dir)]; return [self test:self]; } /* Delegate Methods */ - (BOOL)validateCommand:menuCell /* * Validates whether a menu command that Document responds to * is valid at the current time. */ { SEL action = [menuCell action]; if (action == @selector(reset:) || action == @selector(scramble:) ) { return YES; } else if (action == @selector(undo:) || action==@selector(unscramble:)) { return (BOOL) [undoActions count]; } return YES; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.