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.