home *** CD-ROM | disk | FTP | other *** search
- #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
-