This is MapView.m in view mode; [Download] [Up]
// MapView.m // Part of Risk by Mike Ferris #import "MapView.h" #import "mapWraps.h" #import "Country.h" #import "GameSetup.h" #import "Mover.h" #import "LanguageApp.h" #import "DefaultManager.h" #import <dpsclient/psops.h> #import <appkit/Panel.h> #import <appkit/TextField.h> #import <appkit/NXImage.h> #import <appkit/graphics.h> #import <objc/List.h> #import <dpsclient/psops.h> #define BOARDBACKING "BoardBacking" #define COUNTRYFILE "Country.data" @implementation MapView + initialize // set our version { if (self == [MapView class]) { [self setVersion:1]; } return self; } - initFrame:(NXRect *)frm // designated initializer { self = [super initFrame:frm]; // get the backdrop boardBackingImage = [NXImage findImageNamed:BOARDBACKING]; // get the countries [self populateGlobe]; selectedCountry = nil; return self; } - free // free all our lists { [northAmerica free]; [southAmerica free]; [europe free]; [asia free]; [africa free]; [australia free]; [countryList freeObjects]; [countryList free]; return [super free]; } - appDidInit:sender // post init initialization stuff { [countryNameTextField removeFromSuperview]; [self addSubview:countryNameTextField]; return self; } - displayCountry:country // have a single country display itself (actually draw everything that // intersects the countries bounds.) { NXRect r[3]; [country getBounds:&r[0]]; [self display:r :1 :YES]; return self; } - drawSelf:(NXRect *)rects :(int)rectCount // the meet of the display methods { NXPoint o = {0.0, 0.0}; int i, p; NXColor color; BOOL sel; id temp; NXRect b; // draw backing if (rectCount == 1) { [boardBackingImage composite:NX_COPY fromRect:&rects[0] toPoint:&rects[0].origin]; } else if (rectCount == 3) { [boardBackingImage composite:NX_COPY fromRect:&rects[1] toPoint:&rects[1].origin]; [boardBackingImage composite:NX_COPY fromRect:&rects[2] toPoint:&rects[2].origin]; } else { [boardBackingImage composite:NX_COPY toPoint:&o]; } // draw countries only if they intersect the update rects sel = NO; for (i=0; i<[countryList count]; i++) { temp = [countryList objectAt:i]; [temp getBounds:&b]; if (rectCount == 1) { if (NXIntersectsRect(&b, &rects[0])) { p=[temp player]; if (p==-1) { color = NX_COLORWHITE; } else { color = [theGameSetup colorOfPlayer:p]; } [temp drawSelfInView:self withColor:color isSelected:sel]; } } else { if ((NXIntersectsRect(&b, &rects[1])) || (NXIntersectsRect(&b, &rects[2]))) { p=[temp player]; if (p==-1) { color = NX_COLORWHITE; } else { color = [theGameSetup colorOfPlayer:p]; } [temp drawSelfInView:self withColor:color isSelected:sel]; } } } // redraw the selected country if (selectedCountry != nil) { sel = YES; p = [selectedCountry player]; if (p==-1) { color = NX_COLORWHITE; } else { color = [theGameSetup colorOfPlayer:p]; } [selectedCountry drawSelfInView:self withColor:color isSelected:sel]; } return self; } - mouseDown:(NXEvent *)e // figure out which country got hit and inform Mover { int i; BOOL found=NO; int c = [countryList count]; for (i=0; (i<c && found==NO); i++) { found = [[countryList objectAt:i] ptInCountry:&e->location]; if (found) { [countryNameTextField setStringValue: [[countryList objectAt:i] name]]; [self setSelectedCountry:[countryList objectAt:i]]; [theMover countryClick:[countryList objectAt:i] num:i event:e]; } } return self; } - setSelectedCountry:country // change the selected country and redraw if necessary { NXRect r[3]; BOOL r1=NO, r2=NO; if (country != selectedCountry) { if (selectedCountry != nil) { [selectedCountry getBounds:&r[1]]; r1 = YES; } if (country != nil) { [country getBounds:&r[2]]; r2 = YES; } selectedCountry = country; if ((r1) && (r2)) { NXSetRect(&r[0], r[1].origin.x, r[1].origin.y, r[1].size.width, r[1].size.height); NXUnionRect(&r[2], &r[0]); [self display:r :3 :YES]; } else if (r1) { NXSetRect(&r[0], r[1].origin.x, r[1].origin.y, r[1].size.width, r[1].size.height); [self display:r :1 :YES]; } else if (r2) { NXSetRect(&r[0], r[2].origin.x, r[2].origin.y, r[2].size.width, r[2].size.height); [self display:r :1 :YES]; } } return self; } - (BOOL)doesPlayerWin:(int)pNum // returns YES if pNum is the only player left with countries { int i, c = [countryList count]; for (i=0; i<c; i++) { if ([[countryList objectAt:i] player] != pNum) { return NO; } } return YES; } - (BOOL)playerOccupiesCountries:(int)pNum // return YES if pNum owns any countries at all { int i, c = [countryList count]; for (i=0; i<c; i++) { if ([[countryList objectAt:i] player] == pNum) { return YES; } } return NO; } - (BOOL)countriesAreUnoccupied // returns YES if any countries don't have players { int i, c = [countryList count]; for (i=0; i<c; i++) { if ([[countryList objectAt:i] player] == -1) { return YES; } } return NO; } - makeAllCountriesUnoccupied // clear the map in preparation for a new game. { int i, c = [countryList count]; for (i=0; i<c; i++) { [[countryList objectAt:i] setPlayer:-1 andArmies:0]; } [self update]; return self; } - (int)numCountriesForPlayer:(int)p // return the number of countries player p owns { int num = 0; int i,c = [countryList count]; for (i=0;i<c;i++) { if ([[countryList objectAt:i] player] == p) { num++; } } return num; } - (int)armiesForPlayer:(int)p // returns the number of armies player p should get based on how many // countries and continents he occupies { int numCountries=0; int i, c = [countryList count]; int list[42]; int continentals; BOOL sa=YES, na=YES, eu=YES, af=YES, as=YES, au=YES; int numArmies; for (i=0;i<c;i++) { if ([[countryList objectAt:i] player] == p) { list[i]=YES; numCountries++; } else { list[i]=NO; } } // check continents for (i=0;i<=3;i++) { if (list[i]==NO) { sa=NO; } } for (i=4;i<=12;i++) { if (list[i]==NO) { na=NO; } } for (i=13;i<=19;i++) { if (list[i]==NO) { eu=NO; } } for (i=20;i<=25;i++) { if (list[i]==NO) { af=NO; } } for (i=26;i<=37;i++) { if (list[i]==NO) { as=NO; } } for (i=38;i<=41;i++) { if (list[i]==NO) { au=NO; } } continentals = (sa?2:0)+(na?5:0)+(eu?5:0)+(af?3:0)+(as?7:0)+(au?2:0); numArmies = (numCountries/3); if (numArmies<3) numArmies=3; numArmies += continentals; return numArmies; } - makeContinentLists // init the continent lists { int i; northAmerica = [[List allocFromZone:[self zone]] init]; southAmerica = [[List allocFromZone:[self zone]] init]; europe = [[List allocFromZone:[self zone]] init]; africa = [[List allocFromZone:[self zone]] init]; asia = [[List allocFromZone:[self zone]] init]; australia = [[List allocFromZone:[self zone]] init]; for (i=0;i<=3;i++) { [southAmerica addObject:[countryList objectAt:i]]; } for (i=4;i<=12;i++) { [northAmerica addObject:[countryList objectAt:i]]; } for (i=13;i<=19;i++) { [europe addObject:[countryList objectAt:i]]; } for (i=20;i<=25;i++) { [africa addObject:[countryList objectAt:i]]; } for (i=26;i<=37;i++) { [asia addObject:[countryList objectAt:i]]; } for (i=38;i<=41;i++) { [australia addObject:[countryList objectAt:i]]; } return self; } - populateGlobe // init the country list by reading it from the typed stream file. { NXTypedStream *ts; ts = NXOpenTypedStreamForFile([NXApp applicationFile:COUNTRYFILE], NX_READONLY); countryList = NXReadObject(ts); NXCloseTypedStream(ts); WSInitArray([countryList count]); [countryList makeObjectsPerform:@selector(windowServerInit)]; [self update]; [self makeContinentLists]; return self; } - countryList { return countryList; } - northAmerica { return northAmerica; } - southAmerica { return southAmerica; } - europe { return europe; } - africa { return africa; } - asia { return asia; } - australia { return australia; } - theDefaultManager // for use by the countries who sometimes need to know defaults { return theDefaultManager; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.