home *** CD-ROM | disk | FTP | other *** search
/ Ragnaroek / Ragnaroek.img / OpponentApp / Balder.m < prev    next >
Text File  |  1991-12-09  |  7KB  |  295 lines

  1. #import <string.h>
  2. #import <appkit/Button.h>
  3. #import <appkit/NXBitmapImageRep.h>
  4. #import <appkit/NXImage.h>
  5. #import <appkit/TextField.h>
  6. #import "Balder.h"
  7. #import "RagnarokListener.h"
  8. #import "RagnarokSpeaker.h"
  9. #import "InvitationListener.h"
  10. #import "ReplySpeaker.h"
  11.  
  12. @implementation Balder
  13.  
  14. const char *portname(appname)
  15. const char *appname;
  16. {
  17.     static char result[40];
  18.     
  19.     strcpy(result,"Ragnarok");
  20.     strcat(result,"(");
  21.     strncat(result, appname,20);
  22.     strcat(result,")");
  23.     
  24.     return result;
  25. }
  26.  
  27. - appDidInit:sender
  28. {
  29.     publicListener = [[InvitationListener alloc] init];
  30.     [publicListener setDelegate:self];
  31.     [publicListener checkInAs:portname(appName)];
  32.     [publicListener addPort];
  33.     [statusText setStringValue:"Unconnected"];
  34.     connected = NO;
  35.     privateListener = [[RagnarokListener alloc] init];
  36.     [privateListener usePrivatePort];
  37.     [privateListener setDelegate:self];
  38.     [privateListener addPort];
  39.     privateSpeaker = [[RagnarokSpeaker alloc] init];
  40.     return self;
  41. }
  42.  
  43. - appWillTerminate:sender
  44. {
  45.     if (connected) {
  46.         [self disconnect];
  47.     }
  48.     return self;
  49. }
  50.  
  51. - (int)invitationFrom:(char *)username onHost:(char *)hostname RSVP:(port_t )rsvpPort Face:(char *)face length:(int)length
  52. {
  53.     id replySpeaker;
  54.     char *ourImageData;
  55.     int ourImageLength;
  56.     
  57.     replySpeaker = [[ReplySpeaker alloc] init];
  58.     [replySpeaker setSendPort:rsvpPort];
  59.  
  60.     if (connected) { /* we're already connected, reject the invitation */
  61.         [replySpeaker invitationRejected];
  62.     } else { /* accept the invitation */
  63.         ourImageData = [self writeImageToBuf:[NXImage findImageNamed:"app"] length:&ourImageLength];
  64.         [replySpeaker invitationAcceptedMyFace:ourImageData length:ourImageLength];
  65.     }
  66.     return 0;
  67. }
  68.  
  69. - (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
  70. {
  71.     NXStream *gameStream;
  72.     NXTypedStream *ts;
  73.  
  74.     /* free whatever old currentState there was */
  75.     [currentState free];
  76.     /* now we're connected */
  77.     connected = YES;
  78.     [statusText setStringValue:"Connected"];
  79.     [opponentName setStringValue:username];
  80.     [opponentFace setImage:[self readImageFromBuf:myFaceData length:mflen]];
  81.     /* read the GameState object from the message */
  82.     gameStream = NXOpenMemory(game,length,NX_READONLY);
  83.     ts = NXOpenTypedStream(gameStream, NX_READONLY);
  84.     currentState = NXReadObject(ts);
  85.     NXCloseTypedStream(ts);
  86.     NXClose(gameStream);
  87.     /* tell them how to contact us */
  88.     *yourPort = [privateListener listenPort];
  89.     /* connect our speaker to them */
  90.     [privateSpeaker setSendPort:myPort];
  91.     /* which side we're playing */
  92.     ourSide = !side;
  93.     /* if it's our turn... */
  94.     if (ourSide == currentState->whoseTurn) {
  95.         [statusText setStringValue:"Thinking"];
  96.         [self perform:@selector(decide:) with:self afterDelay:1 cancelPrevious:YES];
  97.     }
  98.     return 0;
  99. }
  100.  
  101. - (int)submitMoveFrom:(int)from To:(int)to
  102. {
  103.     struct move theMove;
  104.     
  105.     theMove.from = from;
  106.     theMove.to = to;
  107.     [currentState makeMove:theMove];
  108.     if (ourSide == currentState->whoseTurn) {
  109.         [statusText setStringValue:"Thinking"];
  110.         [self perform:@selector(decide:) with:self afterDelay:1 cancelPrevious:YES];
  111.     }
  112.     return 0;
  113. }
  114.  
  115. - (int)submitTentativeMoveFrom:(int)from To:(int)to
  116. {
  117.     /* do nothing */
  118.     return 0;
  119. }
  120.  
  121. - (int)submitNoTentativeMove
  122. {
  123.     /* do nothing */
  124.     return 0;
  125. }
  126.  
  127. - (int)submitUndos:(int)howMany
  128. {
  129.     int counter;
  130.     
  131.     for (counter=0; counter<howMany; counter++) {
  132.         [currentState undoMove];
  133.     }
  134.     if (ourSide == currentState->whoseTurn) {
  135.         [statusText setStringValue:"Thinking"];
  136.         [self perform:@selector(decide:) with:self afterDelay:1 cancelPrevious:YES];
  137.     }
  138.     return 0;
  139. }
  140.  
  141. - (int)submitResetGame
  142. {
  143.     [currentState resetState];
  144.     if (ourSide == currentState->whoseTurn) {
  145.         [statusText setStringValue:"Thinking"];
  146.         [self perform:@selector(decide:) with:self afterDelay:1 cancelPrevious:YES];
  147.     }
  148.     return 0;
  149. }
  150.  
  151. - (int)submitMessage:(char *)aString
  152. {
  153.     /* do nothing */
  154.     return 0;
  155. }
  156.  
  157. - (int)goodbye
  158. {
  159.     [self disconnect];
  160.     return 0;
  161. }
  162.  
  163. - (int)pleaseAllow:(int)tag Undo:(int)howMany
  164. {
  165.     int errorStatus;
  166.  
  167.     /* always allow */
  168.     errorStatus = [privateSpeaker allow:tag];
  169.     if (errorStatus != 0)
  170.         [self disconnect];
  171.     return 0;
  172. }
  173.  
  174. - (int)pleaseAllow:(int)tag StartOver:(int)ignored
  175. {
  176.     int errorStatus;
  177.  
  178.     /* always allow */
  179.     errorStatus = [privateSpeaker allow:tag];
  180.     if (errorStatus != 0)
  181.         [self disconnect];
  182.     return 0;
  183. }
  184.  
  185. - (int)pleaseHurryUp:(int)tag
  186. {
  187.     /* do nothing */
  188.     return 0;
  189. }
  190.  
  191. - (int)allow:(int)tag
  192. {
  193.     /* do nothing */
  194.     return 0;
  195. }
  196.  
  197. - (int)refuse:(int)tag
  198. {
  199.     /* do nothing */
  200.     return 0;
  201. }
  202.  
  203. - (int)ok:(int)tag
  204. {
  205.     /* do nothing */
  206.     return 0;
  207. }
  208.  
  209. - disconnect
  210. {
  211.     [privateSpeaker goodbye];
  212.     connected = NO;
  213.     port_deallocate(task_self(),[privateSpeaker sendPort]);
  214.     [statusText setStringValue:"Unconnected"];
  215.     [opponentName setStringValue:NULL];
  216.     [opponentFace setImage:nil];
  217.     return self;
  218. }
  219.  
  220. - (const char *)writeImageToBuf:theImage length:(int *)length
  221. {
  222.     static NXStream *s = NULL;
  223.     char *buf;
  224.     int ignored;
  225.     NXBitmapImageRep *theRep;
  226.     
  227.     if (s) { /* free last usage */
  228.         NXCloseMemory(s, NX_FREEBUFFER);
  229.     } 
  230.     s = NXOpenMemory(NULL, 0, NX_WRITEONLY);
  231.     theRep = (NXBitmapImageRep *)[theImage bestRepresentation];
  232.     [theRep writeTIFF:s];
  233.     NXGetMemoryBuffer(s, &buf, length, &ignored);
  234.     return buf;
  235. }
  236.  
  237. - readImageFromBuf:(const char *)theBuf length:(int)length
  238. {
  239.     NXStream *s;
  240.     id theRep, theImage;
  241.     
  242.     s = NXOpenMemory(theBuf, length, NX_READONLY);
  243.     theRep = [[NXBitmapImageRep alloc] initFromStream:s];
  244.     theImage = [[NXImage alloc] init];
  245.     [theImage useRepresentation:theRep];
  246.     NXCloseMemory(s, NX_FREEBUFFER);
  247.     return theImage;
  248. }
  249.  
  250. - doMove:(struct move)theMove
  251. {
  252.     int errorStatus;
  253.     
  254.     errorStatus = [privateSpeaker submitMoveFrom:(theMove.from) To:(theMove.to)];
  255.     [statusText setStringValue:"Connected"];
  256.     if (errorStatus == 0) {
  257.         [currentState makeMove:theMove];
  258.     } else {
  259.         [self disconnect];
  260.     }
  261.     return self;
  262. }
  263.  
  264. - decide:sender
  265. {
  266.     int fromX, fromY, toX, toY;
  267.     struct move theMove;
  268.     
  269.     /* just do the first legal move we find */
  270.     for (fromX=0; fromX<11; fromX++) {
  271.      for (fromY=0; fromY<11; fromY++) {
  272.       for (toX=0; toX<11; toX++) {
  273.        for (toY=0; toY<11; toY++) {
  274.          theMove.from = XYTONUM(fromX,fromY);
  275.          theMove.to = XYTONUM(toX,toY);
  276.          if (ourSide == WHITE) { /* look for white moves */
  277.              if ((currentState->pieces[theMove.from].who == W_PAWN) &&
  278.                     ([currentState checkMove:theMove])) {
  279.                  [self doMove:theMove];
  280.                 return self;
  281.             }
  282.          } else { /* look for black moves */
  283.              if (((currentState->pieces[theMove.from].who == B_PAWN) ||
  284.                     (currentState->pieces[theMove.from].who == LOKI)) &&
  285.                     ([currentState checkMove:theMove])) {
  286.                  [self doMove:theMove];
  287.                 return self;
  288.             }
  289.          }}}}}
  290.     /* we should never get here... */
  291.     return self;
  292. }
  293.  
  294. @end
  295.