home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Ragnaroek
/
Ragnaroek.img
/
OpponentApp
/
Balder.m
< prev
next >
Wrap
Text File
|
1991-12-09
|
7KB
|
295 lines
#import <string.h>
#import <appkit/Button.h>
#import <appkit/NXBitmapImageRep.h>
#import <appkit/NXImage.h>
#import <appkit/TextField.h>
#import "Balder.h"
#import "RagnarokListener.h"
#import "RagnarokSpeaker.h"
#import "InvitationListener.h"
#import "ReplySpeaker.h"
@implementation Balder
const char *portname(appname)
const char *appname;
{
static char result[40];
strcpy(result,"Ragnarok");
strcat(result,"(");
strncat(result, appname,20);
strcat(result,")");
return result;
}
- appDidInit:sender
{
publicListener = [[InvitationListener alloc] init];
[publicListener setDelegate:self];
[publicListener checkInAs:portname(appName)];
[publicListener addPort];
[statusText setStringValue:"Unconnected"];
connected = NO;
privateListener = [[RagnarokListener alloc] init];
[privateListener usePrivatePort];
[privateListener setDelegate:self];
[privateListener addPort];
privateSpeaker = [[RagnarokSpeaker alloc] init];
return self;
}
- appWillTerminate:sender
{
if (connected) {
[self disconnect];
}
return self;
}
- (int)invitationFrom:(char *)username onHost:(char *)hostname RSVP:(port_t )rsvpPort Face:(char *)face length:(int)length
{
id replySpeaker;
char *ourImageData;
int ourImageLength;
replySpeaker = [[ReplySpeaker alloc] init];
[replySpeaker setSendPort:rsvpPort];
if (connected) { /* we're already connected, reject the invitation */
[replySpeaker invitationRejected];
} else { /* accept the invitation */
ourImageData = [self writeImageToBuf:[NXImage findImageNamed:"app"] length:&ourImageLength];
[replySpeaker invitationAcceptedMyFace:ourImageData length:ourImageLength];
}
return 0;
}
- (int)Game:(char *)game length:(int)length Side:(int)side YourPort:(port_t *)yourPort MyPort:(port_t)myPort MyFace:(char *)myFaceData length:(int)mflen From:(char *)username onHost:(char *)hostname
{
NXStream *gameStream;
NXTypedStream *ts;
/* free whatever old currentState there was */
[currentState free];
/* now we're connected */
connected = YES;
[statusText setStringValue:"Connected"];
[opponentName setStringValue:username];
[opponentFace setImage:[self readImageFromBuf:myFaceData length:mflen]];
/* read the GameState object from the message */
gameStream = NXOpenMemory(game,length,NX_READONLY);
ts = NXOpenTypedStream(gameStream, NX_READONLY);
currentState = NXReadObject(ts);
NXCloseTypedStream(ts);
NXClose(gameStream);
/* tell them how to contact us */
*yourPort = [privateListener listenPort];
/* connect our speaker to them */
[privateSpeaker setSendPort:myPort];
/* which side we're playing */
ourSide = !side;
/* if it's our turn... */
if (ourSide == currentState->whoseTurn) {
[statusText setStringValue:"Thinking"];
[self perform:@selector(decide:) with:self afterDelay:1 cancelPrevious:YES];
}
return 0;
}
- (int)submitMoveFrom:(int)from To:(int)to
{
struct move theMove;
theMove.from = from;
theMove.to = to;
[currentState makeMove:theMove];
if (ourSide == currentState->whoseTurn) {
[statusText setStringValue:"Thinking"];
[self perform:@selector(decide:) with:self afterDelay:1 cancelPrevious:YES];
}
return 0;
}
- (int)submitTentativeMoveFrom:(int)from To:(int)to
{
/* do nothing */
return 0;
}
- (int)submitNoTentativeMove
{
/* do nothing */
return 0;
}
- (int)submitUndos:(int)howMany
{
int counter;
for (counter=0; counter<howMany; counter++) {
[currentState undoMove];
}
if (ourSide == currentState->whoseTurn) {
[statusText setStringValue:"Thinking"];
[self perform:@selector(decide:) with:self afterDelay:1 cancelPrevious:YES];
}
return 0;
}
- (int)submitResetGame
{
[currentState resetState];
if (ourSide == currentState->whoseTurn) {
[statusText setStringValue:"Thinking"];
[self perform:@selector(decide:) with:self afterDelay:1 cancelPrevious:YES];
}
return 0;
}
- (int)submitMessage:(char *)aString
{
/* do nothing */
return 0;
}
- (int)goodbye
{
[self disconnect];
return 0;
}
- (int)pleaseAllow:(int)tag Undo:(int)howMany
{
int errorStatus;
/* always allow */
errorStatus = [privateSpeaker allow:tag];
if (errorStatus != 0)
[self disconnect];
return 0;
}
- (int)pleaseAllow:(int)tag StartOver:(int)ignored
{
int errorStatus;
/* always allow */
errorStatus = [privateSpeaker allow:tag];
if (errorStatus != 0)
[self disconnect];
return 0;
}
- (int)pleaseHurryUp:(int)tag
{
/* do nothing */
return 0;
}
- (int)allow:(int)tag
{
/* do nothing */
return 0;
}
- (int)refuse:(int)tag
{
/* do nothing */
return 0;
}
- (int)ok:(int)tag
{
/* do nothing */
return 0;
}
- disconnect
{
[privateSpeaker goodbye];
connected = NO;
port_deallocate(task_self(),[privateSpeaker sendPort]);
[statusText setStringValue:"Unconnected"];
[opponentName setStringValue:NULL];
[opponentFace setImage:nil];
return self;
}
- (const char *)writeImageToBuf:theImage length:(int *)length
{
static NXStream *s = NULL;
char *buf;
int ignored;
NXBitmapImageRep *theRep;
if (s) { /* free last usage */
NXCloseMemory(s, NX_FREEBUFFER);
}
s = NXOpenMemory(NULL, 0, NX_WRITEONLY);
theRep = (NXBitmapImageRep *)[theImage bestRepresentation];
[theRep writeTIFF:s];
NXGetMemoryBuffer(s, &buf, length, &ignored);
return buf;
}
- readImageFromBuf:(const char *)theBuf length:(int)length
{
NXStream *s;
id theRep, theImage;
s = NXOpenMemory(theBuf, length, NX_READONLY);
theRep = [[NXBitmapImageRep alloc] initFromStream:s];
theImage = [[NXImage alloc] init];
[theImage useRepresentation:theRep];
NXCloseMemory(s, NX_FREEBUFFER);
return theImage;
}
- doMove:(struct move)theMove
{
int errorStatus;
errorStatus = [privateSpeaker submitMoveFrom:(theMove.from) To:(theMove.to)];
[statusText setStringValue:"Connected"];
if (errorStatus == 0) {
[currentState makeMove:theMove];
} else {
[self disconnect];
}
return self;
}
- decide:sender
{
int fromX, fromY, toX, toY;
struct move theMove;
/* just do the first legal move we find */
for (fromX=0; fromX<11; fromX++) {
for (fromY=0; fromY<11; fromY++) {
for (toX=0; toX<11; toX++) {
for (toY=0; toY<11; toY++) {
theMove.from = XYTONUM(fromX,fromY);
theMove.to = XYTONUM(toX,toY);
if (ourSide == WHITE) { /* look for white moves */
if ((currentState->pieces[theMove.from].who == W_PAWN) &&
([currentState checkMove:theMove])) {
[self doMove:theMove];
return self;
}
} else { /* look for black moves */
if (((currentState->pieces[theMove.from].who == B_PAWN) ||
(currentState->pieces[theMove.from].who == LOKI)) &&
([currentState checkMove:theMove])) {
[self doMove:theMove];
return self;
}
}}}}}
/* we should never get here... */
return self;
}
@end