home *** CD-ROM | disk | FTP | other *** search
/ Giga Games 1 / Giga Games.iso / net / go / comp / xamigo11.sh < prev   
Encoding:
Linux/UNIX/POSIX Shell Script  |  1993-06-20  |  218.0 KB  |  7,501 lines

  1. #! /bin/sh
  2. # This is a shell archive, meaning:
  3. # 1. Remove everything above the #! /bin/sh line.
  4. # 2. Save the resulting text in a file.
  5. # 3. Execute the file with /bin/sh (not csh) to create:
  6. #    CHANGES
  7. #    Goban.c
  8. #    Goban.h
  9. #    GobanP.h
  10. #    Imakefile
  11. #    Makefile
  12. #    Makefile.hand
  13. #    README
  14. #    README.AMIGO
  15. #    TODO
  16. #    Xamigo.ad
  17. #    amigo.c
  18. #    amigo.h
  19. #    blackstone.bm
  20. #    check16.xbm
  21. #    go.h
  22. #    goplayer.c
  23. #    goplayutils.c
  24. #    goplayutils.h
  25. #    graystone.bm
  26. #    killable.c
  27. #    main.c
  28. #    menus.c
  29. #    stonemask.bm
  30. #    whitestone.bm
  31. #    xamigo.h
  32. #    xamigo.man
  33. #    xinterface.c
  34. # This archive created: Thu Aug 20 16:51:28 1992
  35. export PATH; PATH=/bin:/usr/bin:$PATH
  36. if test -f 'CHANGES'
  37. then
  38.     echo shar: "will not over-write existing file 'CHANGES'"
  39. else
  40. cat << \SHAR_EOF > 'CHANGES'
  41.  
  42. Changes from xamigo-1.0 to xamigo-1.1
  43. -------------------------------------
  44.  
  45.     o    mouse pointer changes according to player's color.
  46.         changes to grey stone when game over.
  47.  
  48.     o    tweaked Imakefile.
  49.  
  50.     o    fixed bug which let you play a suicide move.
  51.  
  52.     o    added end-of-game support: removing dead stones
  53.         and counting up.
  54.  
  55.     o    the 'P' key can be used as a short-cut for `pass' on the
  56.         Move menu.  Any other shortcuts you can think of?
  57.  
  58.     o    "I'm thinking..." is displayed in the message window,
  59.         so you know when it is AmiGo's turn.
  60.  
  61.     o    the last stone placed by each player is marked on the board.
  62.  
  63.     o    changed the menu organisation
  64.  
  65.     o    added a checkmark bitmap, rather than using xlogo16,
  66.         it looks nice (IMHO) and someone reported problems with
  67.         xlogo16 anyway.
  68.  
  69.  
  70. First release of xamigo-1.0
  71. ---------------------------
  72.  
  73. Quick and dirty job to get AmiGo ported and a simple X interface to it.
  74.  
  75. SHAR_EOF
  76. fi
  77. if test -f 'Goban.c'
  78. then
  79.     echo shar: "will not over-write existing file 'Goban.c'"
  80. else
  81. cat << \SHAR_EOF > 'Goban.c'
  82. /****************************************************************************************************************
  83.  *
  84.  *  Copyright (c) 1992 by Antoine Dumesnil de Maricourt. All rights reserved.
  85.  *
  86.  *  This program is distributed in the hope that it will be useful.
  87.  *  Use and copying of this software and preparation of derivative works
  88.  *  based upon this software are permitted, so long as the following
  89.  *  conditions are met:
  90.  *       o credit to the authors is acknowledged following current
  91.  *         academic behaviour
  92.  *       o no fees or compensation are charged for use, copies, or
  93.  *         access to this software
  94.  *       o this copyright notice is included intact.
  95.  *  This software is made available AS IS, and no warranty is made about 
  96.  *  the software or its performance. 
  97.  * 
  98.  *  Bug descriptions, use reports, comments or suggestions are welcome.
  99.  *  Send them to    dumesnil@etca.fr   or to:
  100.  *       
  101.  *       Antoine de Maricourt
  102.  *       ETCA CREA-SP
  103.  *       16 bis, avenue Prieur de la Cote d'Or
  104.  *       94114 Arcueil Cedex
  105.  *       France
  106.  */
  107.  
  108. #include <X11/IntrinsicP.h>
  109. #include <X11/StringDefs.h>
  110. #include <X11/Xlib.h>
  111. #include <X11/cursorfont.h>
  112.  
  113. #include "GobanP.h"
  114.  
  115. #include "whitestone.bm"
  116. #include "blackstone.bm"
  117. #include "graystone.bm"
  118. #include "stonemask.bm"
  119.  
  120. #define offset(field) XtOffset (GobanWidget, goban.field)
  121.  
  122. static XtResource resources[] = {
  123.   { XtNautoRedisplay     , XtCAutoRedisplay     , XtRBoolean   , sizeof (Boolean)      ,
  124.       offset (auto_redisplay)     , XtRImmediate     , (caddr_t) TRUE         },
  125.   { XtNviewBottom        , XtCPosition          , XtRPosition  , sizeof (Position)     ,
  126.       offset (bottom)             , XtRImmediate     , (caddr_t) 1            },
  127.   { XtNcursor            , XtCCursor            , XtRInt       , sizeof (int)          ,
  128.       offset (cursor)             , XtRImmediate     , (caddr_t) GbCGrayStone },
  129.   { XtNfont              , XtCFont              , XtRFontStruct, sizeof (XFontStruct *),
  130.       offset (font)               , XtRString        , "fixed"                },
  131.   { XtNforeground        , XtCForeground        , XtRPixel     , sizeof (Pixel)        ,
  132.       offset (foreground)         , XtRString   , XtDefaultForeground    },
  133.   { XtNgameSize          , XtCSize              , XtRDimension , sizeof (Dimension)    ,
  134.       offset (game_size)          , XtRImmediate, (caddr_t) 19           },
  135.   { XtNviewLeft          , XtCPosition          , XtRPosition  , sizeof (Position)     ,
  136.       offset (left)               , XtRImmediate, (caddr_t) 1            },
  137.   { XtNdisplayCoordinates, XtCDisplayCoordinates, XtRBoolean   , sizeof (Boolean)      ,
  138.       offset (display_coordinates), XtRImmediate, (caddr_t) TRUE         },
  139.   { XtNpointSize         , XtCSize              , XtRDimension , sizeof (Dimension)    ,
  140.       offset (point_size)         , XtRImmediate     , (caddr_t) 26           },
  141.   { XtNviewRight         , XtCPosition          , XtRPosition  , sizeof (Position)     ,
  142.       offset (right)              , XtRImmediate     , (caddr_t) 19           },
  143.   { XtNviewTop           , XtCPosition          , XtRPosition  , sizeof (Position)     , 
  144.       offset (top)                , XtRImmediate     , (caddr_t) 19           },
  145.   { XtNwhiteStoneForeground, XtCForeground        , XtRPixel     , sizeof (Pixel)        ,
  146.       offset (white_fg)           , XtRString   , "black"    },
  147.   { XtNwhiteStoneBackground, XtCBackground        , XtRPixel     , sizeof (Pixel)        ,
  148.       offset (white_bg)           , XtRString   , "white"    },
  149.   { XtNwhiteStoneBorder    , XtCBorderColor       , XtRPixel     , sizeof (Pixel)        ,
  150.       offset (white_bd)           , XtRString   , "black"    },
  151.   { XtNblackStoneForeground, XtCForeground        , XtRPixel     , sizeof (Pixel)        ,
  152.       offset (black_fg)           , XtRString   , "white"    },
  153.   { XtNblackStoneBackground, XtCBackground        , XtRPixel     , sizeof (Pixel)        ,
  154.       offset (black_bg)           , XtRString   , "black"    },
  155.   { XtNblackStoneBorder    , XtCBorderColor       , XtRPixel     , sizeof (Pixel)        ,
  156.       offset (black_bd)           , XtRString   , "black"    },
  157. };
  158.  
  159. static void    ClassInitialize ();
  160. static void    Initialize      ();
  161. static void    Redisplay       ();
  162. static void    Realize         ();
  163. static void    Destroy         ();
  164. static void    Resize          ();
  165. static void    DrawPoint       ();
  166. static Boolean SetValues       ();
  167.  
  168. GobanClassRec gobanClassRec = {
  169.   { /* core fields */
  170.     /* superclass        */    (WidgetClass) &widgetClassRec,
  171.     /* class_name        */    "Goban",
  172.     /* widget_size        */    sizeof (GobanRec),
  173.     /* class_initialize        */    ClassInitialize,
  174.     /* class_part_initialize    */    NULL,
  175.     /* class_inited        */    FALSE,
  176.     /* initialize        */    Initialize,
  177.     /* initialize_hook        */    NULL,
  178.     /* realize            */    Realize,
  179.     /* actions            */    NULL,
  180.     /* num_actions        */    0,
  181.     /* resources        */    resources,
  182.     /* num_resources        */    XtNumber (resources),
  183.     /* xrm_class        */    NULLQUARK,
  184.     /* compress_motion        */    TRUE,
  185.     /* compress_exposure    */    TRUE,
  186.     /* compress_enterleave    */    TRUE,
  187.     /* visible_interest        */    FALSE,
  188.     /* destroy            */    Destroy,
  189.     /* resize            */    Resize,
  190.     /* expose            */    Redisplay,
  191.     /* set_values        */    SetValues,
  192.     /* set_values_hook        */    NULL,
  193.     /* set_values_almost    */    XtInheritSetValuesAlmost,
  194.     /* get_values_hook        */    NULL,
  195.     /* accept_focus        */    NULL,
  196.     /* version            */    XtVersion,
  197.     /* callback_private        */    NULL,
  198.     /* tm_table            */    NULL,
  199.     /* query_geometry        */    XtInheritQueryGeometry,
  200.     /* display_accelerator    */    XtInheritDisplayAccelerator,
  201.     /* extension        */    NULL
  202.   }
  203. };
  204.  
  205. WidgetClass gobanWidgetClass = (WidgetClass) &gobanClassRec;
  206.  
  207. /****************************************************************************************************************
  208.  */
  209.  
  210. void GbRedisplayBoard (w)
  211. Widget w;
  212. {
  213.   GobanWidget gw      = (GobanWidget) w;
  214.   Dimension   width   = w->core.width;
  215.   Dimension   height  = w->core.height;
  216.  
  217.   if (XtIsRealized (w))
  218.     XCopyArea (XtDisplay (w), gw->goban.picture, XtWindow (w), gw->goban.copy_gc, 0, 0, width, height, 0, 0);
  219. }
  220.  
  221. /****************************************************************************************************************
  222.  */
  223.  
  224. void GbClearBoard (w)
  225. Widget w;
  226. {
  227.   GobanWidget gw        = (GobanWidget) w;
  228.   Boolean     redisplay = gw->goban.auto_redisplay;
  229.   Position    x;
  230.   Position    y;
  231.  
  232.   gw->goban.auto_redisplay = FALSE;
  233.  
  234.   for (x = 1; x <= gw->goban.game_size; x++)
  235.     for (y = 1; y <= gw->goban.game_size; y++)
  236.       GbSetPoint (w, x, y, GbEmptyPoint);
  237.  
  238.   gw->goban.auto_redisplay = redisplay;
  239.  
  240.   if (redisplay == TRUE)
  241.     GbRedisplayBoard (w);
  242. }
  243.  
  244. /****************************************************************************************************************
  245.  */
  246.  
  247. void GbClearMarks (w)
  248. Widget w;
  249. {
  250.   GobanWidget gw        = (GobanWidget) w;
  251.   Boolean     redisplay = gw->goban.auto_redisplay;
  252.   Position    x;
  253.   Position    y;
  254.  
  255.   gw->goban.auto_redisplay = FALSE;
  256.  
  257.   for (x = 1; x <= gw->goban.game_size; x++)
  258.     for (y = 1; y <= gw->goban.game_size; y++) {
  259.  
  260.       gw->goban.points[x][y].mark1 = 0;
  261.       gw->goban.points[x][y].mark2 = 0;
  262.       gw->goban.points[x][y].num   = 0;
  263.     
  264.       if (x >= gw->goban.left && y >= gw->goban.bottom && x <= gw->goban.right && y <= gw->goban.top)
  265.     if (gw->goban.points[x][y].free == 1)
  266.       DrawPoint (w, x, y, GbEmptyPoint);
  267.     else
  268.       if (gw->goban.points[x][y].black == 1)
  269.         DrawPoint (w, x, y, GbBlackStone);
  270.       else
  271.         DrawPoint (w, x, y, GbWhiteStone);
  272.     }
  273.  
  274.   gw->goban.auto_redisplay = redisplay;
  275.  
  276.   if (redisplay == TRUE)
  277.     GbRedisplayBoard (w);
  278. }
  279.  
  280. /****************************************************************************************************************
  281.  */
  282.  
  283. /* ARGSUSED */
  284.  
  285. void GbSetPoint (w, x, y, color)
  286. Widget       w;
  287. Position     x;
  288. Position     y;
  289. GbPointState color;
  290. {
  291.   GobanWidget gw = (GobanWidget) w;
  292.  
  293.   if (x >= 1 && y >= 1 && x <= gw->goban.game_size && y <= gw->goban.game_size) {
  294.     switch (color) {
  295.  
  296.     case GbBlackStone :
  297.       gw->goban.points[x][y].free  = 0;
  298.       gw->goban.points[x][y].black = 1;
  299.       break;
  300.  
  301.     case GbWhiteStone :
  302.       gw->goban.points[x][y].free  = 0;
  303.       gw->goban.points[x][y].black = 0;
  304.       break;
  305.  
  306.     case GbEmptyPoint :
  307.       gw->goban.points[x][y].free  = 1;
  308.       break;
  309.     }
  310.     
  311.     gw->goban.points[x][y].num   = 0;
  312.     gw->goban.points[x][y].mark1 = 0;
  313.     gw->goban.points[x][y].mark2 = 0;
  314.  
  315.     if (x >= gw->goban.left && y >= gw->goban.bottom && x <= gw->goban.right && y <= gw->goban.top)
  316.       DrawPoint (w, x, y, color);
  317.   }
  318. }
  319.  
  320. /****************************************************************************************************************
  321.  */
  322.  
  323. /* ARGSUSED */
  324.  
  325. Boolean GbGetPositionFromStone (w, x, y)
  326. GobanWidget   w;
  327. Position     *x;
  328. Position     *y;
  329. {
  330.   if (*x >= w->goban.left && *y >= w->goban.bottom && *x <= w->goban.right && *y <= w->goban.top) {
  331.     
  332.     *x = ((w->goban.x_offset + w->goban.point_size * *x) * 2 + w->goban.point_size) / 2;
  333.     *y = ((w->goban.y_offset - w->goban.point_size * *y) * 2 + w->goban.point_size) / 2;
  334.     
  335.     return TRUE;
  336.   }
  337.   
  338.   else 
  339.     return FALSE;
  340. }
  341.  
  342. /****************************************************************************************************************
  343.  */
  344.  
  345. /* ARGSUSED */
  346.  
  347. Boolean GbGetStoneFromPosition (w, x, y)
  348. Widget     w;
  349. Position  *x;
  350. Position  *y;
  351. {
  352.   GobanWidget gw         = (GobanWidget) w;
  353.   Dimension   point_size = gw->goban.point_size;
  354.   Position    xmin       = gw->goban.x_offset + point_size * gw->goban.left + 1;
  355.   Position    ymin       = gw->goban.y_offset - point_size * gw->goban.top  + 1;
  356.   Position    xmax       = gw->goban.x_offset + point_size * (gw->goban.right  + 1) - 1;
  357.   Position    ymax       = gw->goban.y_offset - point_size * (gw->goban.bottom - 1) - 1;
  358.  
  359.   if (*x > xmin && *x < xmax && *y > ymin && *y < ymax) {
  360.  
  361.     *x = (*x - gw->goban.x_offset - 1) / point_size;
  362.     *y = (gw->goban.y_offset - *y + point_size + 1) / point_size;
  363.  
  364.     return TRUE;
  365.   }
  366.  
  367.   return FALSE;
  368. }
  369.  
  370. /****************************************************************************************************************
  371.  */
  372.  
  373. void GbSetNum (w, x, y, num)
  374. Widget      w;
  375. Position    x;
  376. Position    y;
  377. int         num;
  378. {
  379.   GobanWidget  gw      = (GobanWidget) w;
  380.   Display     *display = XtDisplay (w);
  381.   GC           draw_gc;
  382.   GC           undraw_gc;
  383.   XCharStruct  extent;
  384.   XExposeEvent event;
  385.   int          ascent;
  386.   int          descent;
  387.   int          direction;
  388.   int          X;
  389.   int          Y;
  390.   char         s[3];
  391.   int          len = 0;
  392.  
  393.   if (num >= 0 && num <= 999 && x >= 1 && y >= 1  && x <= gw->goban.game_size && y <= gw->goban.game_size) {
  394.     
  395.     gw->goban.points[x][y].num   = num;
  396.     gw->goban.points[x][y].mark1 = 0;
  397.     gw->goban.points[x][y].mark2 = 0;
  398.     
  399.     if (x >= gw->goban.left && y >= gw->goban.bottom && x <= gw->goban.right && y <= gw->goban.top) {
  400.       
  401.       if (gw->goban.points[x][y].free == 0) {
  402.     
  403.     if (num == 0) {
  404.       if (gw->goban.points[x][y].black == 1)
  405.         DrawPoint (w, x, y, GbBlackStone);
  406.       else
  407.         DrawPoint (w, x, y, GbWhiteStone);
  408.     }
  409.     
  410.     else {
  411.       if (gw->goban.points[x][y].black == 1) {
  412.         draw_gc   = gw->goban.black_fg_gc;
  413.         undraw_gc = gw->goban.black_bg_gc;
  414.       } else {
  415.         draw_gc   = gw->goban.white_fg_gc;
  416.         undraw_gc = gw->goban.white_bg_gc;
  417.       }
  418.       
  419.       X = (gw->goban.x_offset + gw->goban.point_size * x) * 2 + gw->goban.point_size;
  420.       Y = (gw->goban.y_offset - gw->goban.point_size * y) * 2 + gw->goban.point_size;
  421.       
  422.       if (num > 99)
  423.         s[len++] = '0' + (num % 1000) / 100;
  424.       if (num > 9)
  425.         s[len++] = '0' + (num % 100) / 10;
  426.       s[len++] = '0' + num % 10;
  427.       
  428.       XQueryTextExtents (display, XGContextFromGC (draw_gc),
  429.                  s, len, &direction, &ascent, &descent, &extent);
  430.       
  431.       if (extent.width + extent.descent + extent.ascent < gw->goban.point_size - 1) {
  432.         XFillArc (display, gw->goban.picture, undraw_gc, 
  433.               (int) (X - gw->goban.point_size) / 2 + 2, (int) (Y - gw->goban.point_size) / 2 + 2, 
  434.               (unsigned int) gw->goban.point_size - 4, (unsigned int) gw->goban.point_size - 4, 
  435.               0, 360 * 64);
  436.         XDrawString (display, gw->goban.picture, draw_gc,
  437.              (X - extent.width) / 2 - extent.lbearing + 1, 
  438.              (Y + extent.ascent - extent.descent) / 2 + 1, s, len);
  439.       }
  440.     
  441.       if (gw->goban.auto_redisplay == TRUE && XtIsRealized (w) == TRUE) {
  442.         event.x      = (X - gw->goban.point_size) / 2;
  443.         event.y      = (Y - gw->goban.point_size) / 2;
  444.         event.width  = gw->goban.point_size;
  445.         event.height = gw->goban.point_size;
  446.         
  447.         Redisplay (w, &event, (Region) NULL);
  448.       }
  449.     }
  450.       }
  451.     }
  452.   }
  453. }
  454.  
  455. /****************************************************************************************************************
  456.  */
  457.  
  458. void GbSetMark (w, x, y, c1, c2)
  459. Widget        w;
  460. Position      x;
  461. Position      y;
  462. unsigned char c1;
  463. unsigned char c2;
  464. {
  465.   GobanWidget  gw      = (GobanWidget) w;
  466.   Display     *display = XtDisplay (w);
  467.   int          len     = 0;
  468.   XCharStruct  extent;
  469.   XExposeEvent event;
  470.   int          ascent;
  471.   int          descent;
  472.   int          direction;
  473.   int          X;
  474.   int          Y;
  475.   int          radius;
  476.   char         s[2];
  477.   XSegment     segment[4];
  478.   GC           mark_gc;
  479.   GC           erase_gc;
  480.   
  481.   if (x >= 1 && y >= 1 && x <= gw->goban.game_size && y <= gw->goban.game_size) {
  482.    
  483.     if (c1 != 0 || c2 != 0)
  484.       GbSetMark (w, x, y, 0, 0);
  485.      
  486.     gw->goban.points[x][y].mark1 = c1;
  487.     gw->goban.points[x][y].mark2 = c2;
  488.     gw->goban.points[x][y].num   = 0;
  489.  
  490.     if (x >= gw->goban.left && y >= gw->goban.bottom && x <= gw->goban.right && y <= gw->goban.top) {
  491.       
  492.       if (c1 == 0 && c2 == 0) {
  493.     if (gw->goban.points[x][y].free == 0)
  494.       if (gw->goban.points[x][y].black == 1)
  495.         DrawPoint (w, x, y, GbBlackStone);
  496.       else
  497.         DrawPoint (w, x, y, GbWhiteStone);
  498.     else
  499.       DrawPoint (w, x, y, GbEmptyPoint);
  500.       }
  501.       
  502.       else {
  503.     X = (gw->goban.x_offset + gw->goban.point_size * x) * 2 + gw->goban.point_size;
  504.     Y = (gw->goban.y_offset - gw->goban.point_size * y) * 2 + gw->goban.point_size;
  505.               
  506.     if (gw->goban.points[x][y].free == 0)
  507.       if (gw->goban.points[x][y].black == 1) {
  508.         mark_gc  = gw->goban.black_fg_gc;
  509.         erase_gc = gw->goban.black_bg_gc;
  510.       }
  511.       else {
  512.         mark_gc  = gw->goban.white_fg_gc;
  513.         erase_gc = gw->goban.white_bg_gc;
  514.       }
  515.  
  516.     else {
  517.       mark_gc  = gw->goban.foreground_gc;
  518.       erase_gc = gw->goban.background_gc;
  519.     }
  520.     
  521.     if (c1 == 0) {
  522.       radius = 10 * gw->goban.point_size / 15;
  523.       
  524.       if (gw->goban.points[x][y].free == 0)
  525.           XFillArc (display, gw->goban.picture, erase_gc, 
  526.             (int) (X - gw->goban.point_size) / 2 + 2, (int) (Y - gw->goban.point_size) / 2 + 2, 
  527.             (unsigned int) gw->goban.point_size - 4, (unsigned int) gw->goban.point_size - 4, 
  528.             0, 360 * 64);
  529.       else
  530.         XFillArc (display, gw->goban.picture, erase_gc,
  531.               (int) (X - radius) / 2, (int) (Y - radius) / 2, 
  532.               (unsigned int) radius, (unsigned int) radius, 
  533.               0, 360 * 64);
  534.  
  535.       switch (c2) {
  536.         
  537.       case GbMTriangleMark :
  538.         radius -= 4;
  539.  
  540.         segment[0].x1 = (short) X / 2;
  541.         segment[0].x2 = (short) (X / 2 + (86 * radius + 100) / 200);
  542.         segment[0].y1 = (short) (Y / 2 - (radius - 1) / 2);
  543.         segment[0].y2 = (short) (Y / 2 + (radius + 4) / 4);
  544.         
  545.         segment[1].x1 = (short) segment[0].x2;
  546.         segment[1].x2 = (short) (X / 2 - (86 * radius + 100) / 200);
  547.         segment[1].y1 = (short) segment[0].y2;
  548.         segment[1].y2 = (short) (Y / 2 + (radius + 4) / 4);
  549.         
  550.         segment[2].x1 = (short) segment[1].x2;
  551.         segment[2].x2 = (short) segment[0].x1;
  552.         segment[2].y1 = (short) segment[1].y2;
  553.         segment[2].y2 = (short) segment[0].y1;
  554.  
  555.         XDrawSegments (display, gw->goban.picture, mark_gc, segment, 3);
  556.         break;
  557.  
  558.       case GbMSquareMark  :
  559.         radius = 10 * radius / 14 - 2;
  560.         
  561.         XDrawRectangle (display, gw->goban.picture, mark_gc, 
  562.                 (X - radius) / 2, (Y - radius) / 2, 
  563.                 (unsigned int) radius, (unsigned int) radius);
  564.         break;
  565.     
  566.       case GbMDCrossMark  :
  567.         radius = 10 * radius / 14 - 2;
  568.  
  569.         segment[0].x1 = (short) (X - radius) / 2;
  570.         segment[0].x2 = (short) segment[0].x1    + radius;
  571.         segment[0].y1 = (short) (Y - radius) / 2;
  572.         segment[0].y2 = (short) segment[0].y1    + radius;
  573.  
  574.         segment[1].x1 = (short) (X - radius) / 2 + radius;
  575.         segment[1].x2 = (short) segment[1].x1    - radius;
  576.         segment[1].y1 = (short) (Y - radius) / 2;
  577.         segment[1].y2 = (short) segment[1].y1    + radius;
  578.         
  579.         XDrawSegments (display, gw->goban.picture, mark_gc, segment, 2);
  580.         break;
  581.         
  582.       case GbMVCrossMark  :
  583.         radius -= 4;
  584.  
  585.         segment[0].x1 = (short) X / 2;
  586.         segment[0].x2 = (short) segment[0].x1;
  587.         segment[0].y1 = (short) (Y - radius) / 2;
  588.         segment[0].y2 = (short) segment[0].y1 + radius;
  589.  
  590.         segment[1].x1 = (short) (X - radius) / 2;
  591.         segment[1].x2 = (short) segment[1].x1 + radius;
  592.         segment[1].y1 = (short) Y / 2;
  593.         segment[1].y2 = (short) segment[1].y1;
  594.         
  595.         XDrawSegments (display, gw->goban.picture, mark_gc, segment, 2);
  596.         break;
  597.  
  598.       case GbMDiamondMark :
  599.         radius -= 4;
  600.  
  601.         segment[0].x1 = (short) X / 2;
  602.         segment[0].x2 = (short) segment[0].x1 + radius / 2;
  603.         segment[0].y1 = (short) (Y - radius) / 2;
  604.         segment[0].y2 = (short) segment[0].y1 + radius / 2;
  605.  
  606.         segment[1].x1 = (short) segment[0].x2;
  607.         segment[1].x2 = (short) segment[0].x1;
  608.         segment[1].y1 = (short) segment[0].y2;
  609.         segment[1].y2 = (short) segment[1].y1 + radius / 2;
  610.         
  611.         segment[2].x1 = (short) segment[1].x2;
  612.         segment[2].x2 = (short) segment[2].x1 - radius / 2;
  613.         segment[2].y1 = (short) segment[1].y2;
  614.         segment[2].y2 = (short) segment[1].y1;
  615.         
  616.         segment[3].x1 = (short) segment[2].x2;
  617.         segment[3].x2 = (short) segment[0].x1;
  618.         segment[3].y1 = (short) segment[2].y2;
  619.         segment[3].y2 = (short) segment[0].y1;
  620.         
  621.         XDrawSegments (display, gw->goban.picture, mark_gc, segment, 4);
  622.         break;
  623.       }
  624.     }
  625.     
  626.     else {
  627.       s[len++] = c1;
  628.       if (c2 != 0)
  629.         s[len++] = c2;
  630.       
  631.       XQueryTextExtents (display, XGContextFromGC (mark_gc), s, len, &direction, &ascent, &descent, &extent);
  632.       
  633.       radius = extent.width + extent.descent + extent.ascent;
  634.       
  635.       if (radius < gw->goban.point_size - 1) {
  636.         if (gw->goban.points[x][y].free == 0)
  637.           XFillArc (display, gw->goban.picture, erase_gc, 
  638.             (int) (X - gw->goban.point_size) / 2 + 2, (int) (Y - gw->goban.point_size) / 2 + 2, 
  639.             (unsigned int) gw->goban.point_size - 4, (unsigned int) gw->goban.point_size - 4, 
  640.             0, 360 * 64);
  641.         else
  642.           XFillArc (display, gw->goban.picture, erase_gc,
  643.             (int) (X - radius) / 2, (int) (Y - radius) / 2, 
  644.             (unsigned int) radius, (unsigned int) radius, 
  645.             0, 360 * 64);
  646.         
  647.         XDrawString (display, gw->goban.picture, mark_gc,
  648.              (X - extent.width) / 2 - extent.lbearing + 1, 
  649.              (Y + extent.ascent - extent.descent) / 2 + 1, s, len);
  650.       }
  651.     }
  652.       
  653.     if (gw->goban.auto_redisplay == TRUE && XtIsRealized (w) == TRUE) {
  654.       event.x      = (X - gw->goban.point_size) / 2;
  655.       event.y      = (Y - gw->goban.point_size) / 2;
  656.       event.width  = gw->goban.point_size;
  657.       event.height = gw->goban.point_size;
  658.       
  659.       Redisplay (w, &event, (Region) NULL);
  660.     }
  661.       }
  662.     }
  663.   }
  664. }
  665.  
  666. /****************************************************************************************************************
  667.  */
  668.  
  669. /* ARGSUSED */
  670.  
  671. static void Redisplay (w, event, region)
  672. Widget        w;
  673. XExposeEvent *event;
  674. Region        region;
  675. {
  676.   GobanWidget gw     = (GobanWidget) w;
  677.   Position    x      = event->x;
  678.   Position    y      = event->y;
  679.   Dimension   width  = event->width;
  680.   Dimension   height = event->height;
  681.  
  682.   XCopyArea (XtDisplay (w), gw->goban.picture, XtWindow (w), gw->goban.copy_gc, x, y, width, height, x, y);
  683. }
  684.  
  685. /****************************************************************************************************************
  686.  */
  687.  
  688. /* ARGSUSED */
  689.  
  690. static void CvtStringToCursor (args, num_args, fromVal, toVal)
  691. XrmValuePtr   args;        /* unused */
  692. Cardinal     *num_args;    /* unused */
  693. XrmValuePtr   fromVal;
  694. XrmValuePtr   toVal;
  695. {
  696.   static int       cursor;
  697.   static XrmQuark  QWhiteStone;
  698.   static XrmQuark  QBlackStone;
  699.   static XrmQuark  QGrayStone;
  700.   XrmQuark         quark;
  701.   char             lowerName[256];
  702.   static Boolean   inited = FALSE;
  703.     
  704.   if (inited == FALSE) {
  705.     QWhiteStone  = XrmStringToQuark (XtEgbWhiteStone);
  706.     QBlackStone  = XrmStringToQuark (XtEgbBlackStone);
  707.     QGrayStone   = XrmStringToQuark (XtEgbGrayStone);
  708.     inited       = TRUE;
  709.   }
  710.  
  711.   XmuCopyISOLatin1Lowered  (lowerName, (String) fromVal->addr);
  712.   quark = XrmStringToQuark (lowerName);
  713.  
  714.   if (quark == QWhiteStone)
  715.     cursor = GbCWhiteStone;
  716.   else if (quark == QBlackStone)       
  717.     cursor = GbCBlackStone;
  718.   else if (quark == QGrayStone)         
  719.     cursor = GbCGrayStone;
  720.   else {
  721.     toVal->size = 0;
  722.     toVal->addr = NULL;
  723.     return;
  724.   }
  725.  
  726.   toVal->size = sizeof (cursor);
  727.   toVal->addr = (caddr_t) &cursor;
  728. }
  729.  
  730. /****************************************************************************************************************
  731.  */
  732.  
  733. static void ClassInitialize()
  734. {
  735.   XtAddConverter (XtRString, XtRInt, (XtConverter) CvtStringToCursor, NULL, 0);
  736. }
  737.  
  738. /****************************************************************************************************************
  739.  */
  740.  
  741. static void InitializePixmap (w)
  742. Widget w;
  743. {
  744.   GobanWidget  gw      = (GobanWidget) w;
  745.   Display     *display = XtDisplay (w);
  746.   Drawable     window  = RootWindowOfScreen (XtScreen (w));
  747.   Dimension    width   = w->core.width;
  748.   Dimension    height  = w->core.height;
  749.  
  750.   gw->goban.board   = XCreatePixmap (display, window, width, height, (unsigned int) DefaultDepthOfScreen (XtScreen (w)));
  751.   gw->goban.picture = XCreatePixmap (display, window, width, height, (unsigned int) DefaultDepthOfScreen (XtScreen (w)));
  752. }
  753.  
  754. /****************************************************************************************************************
  755.  */
  756.  
  757. static void InitializeGC (w)
  758. Widget w;
  759. {
  760.   GobanWidget  gw      = (GobanWidget) w;
  761.   Display     *display = XtDisplay (w);
  762.   XtGCMask     mask    = GCForeground | GCBackground | GCFont;
  763.   XGCValues    values;
  764.  
  765.   values.font             = gw->goban.font->fid;
  766.   values.background       = w->core.background_pixel;
  767.  
  768.   values.foreground       = gw->goban.white_fg;
  769.   gw->goban.white_fg_gc   = XCreateGC  (display, gw->goban.picture, mask, &values);
  770.   values.foreground       = gw->goban.white_bg;
  771.   gw->goban.white_bg_gc   = XCreateGC  (display, gw->goban.picture, mask, &values);
  772.   values.foreground       = gw->goban.white_bd;
  773.   gw->goban.white_bd_gc   = XCreateGC  (display, gw->goban.picture, mask, &values);
  774.  
  775.   values.foreground       = gw->goban.black_fg;
  776.   gw->goban.black_fg_gc   = XCreateGC  (display, gw->goban.picture, mask, &values);
  777.   values.foreground       = gw->goban.black_bg;
  778.   gw->goban.black_bg_gc   = XCreateGC  (display, gw->goban.picture, mask, &values);
  779.   values.foreground       = gw->goban.black_bd;
  780.   gw->goban.black_bd_gc   = XCreateGC  (display, gw->goban.picture, mask, &values);
  781.  
  782.   values.foreground       = gw->goban.foreground;
  783.   gw->goban.foreground_gc = XCreateGC  (display, gw->goban.picture, mask, &values);
  784.  
  785.   if (gw->core.background_pixmap != XtUnspecifiedPixmap) {
  786.     values.tile           = gw->core.background_pixmap;
  787.     values.fill_style     = FillTiled;
  788.     mask                 |= GCTile | GCFillStyle;
  789.   }
  790.  
  791.   values.foreground       = w->core.background_pixel;
  792.   values.background       = gw->goban.foreground;
  793.   gw->goban.background_gc = XCreateGC  (display, gw->goban.picture, mask, &values);
  794.  
  795.   gw->goban.copy_gc       = XCreateGC  (display, gw->goban.picture, (XtGCMask) 0, (XGCValues *) NULL);
  796. }
  797.  
  798. /****************************************************************************************************************
  799.  */ 
  800. static void InitializeCursor (w)
  801. Widget w;
  802. {
  803.   GobanWidget  gw      = (GobanWidget) w;
  804.   Display     *display = XtDisplay (w);
  805.   Drawable     window  = RootWindowOfScreen (XtScreen (w));
  806.   Pixel        black   = BlackPixel (display, DefaultScreen (display));
  807.   Pixel        white   = WhitePixel (display, DefaultScreen (display));
  808.  
  809.   static XColor black_color = { 0,    0,     0,     0  };  /* black */
  810.   static XColor white_color = { 0, 65535, 65535, 65535 };  /* white */
  811.  
  812.   /* Some teminals invert the mask with BlackPixel and WhitePixel     */
  813.   /* should use black and white instead of 1 and 0 but depth is 1 ... */
  814.   /* will probably have trouble with some special colormaps           */
  815.  
  816.   gw->goban.white_stone = XCreatePixmapFromBitmapData
  817.     (display, window, whitestone_bits, whitestone_width, whitestone_height, 1, 0, 1);
  818.   gw->goban.black_stone = XCreatePixmapFromBitmapData
  819.     (display, window, blackstone_bits, blackstone_width, blackstone_height, 1, 0, 1);
  820.   gw->goban.gray_stone  = XCreatePixmapFromBitmapData
  821.     (display, window, graystone_bits , graystone_width , graystone_height , 1, 0, 1);
  822.   gw->goban.mouse_mask  = XCreatePixmapFromBitmapData
  823.     (display, window, stonemask_bits , stonemask_width , stonemask_height , 1, 0, 1);
  824.  
  825.   gw->goban.white_cursor = 
  826.     XCreatePixmapCursor (display, gw->goban.white_stone, gw->goban.mouse_mask, 
  827.              &black_color, &white_color, whitestone_x_hot, whitestone_y_hot);
  828.   gw->goban.black_cursor = 
  829.     XCreatePixmapCursor (display, gw->goban.black_stone, gw->goban.mouse_mask, 
  830.              &black_color, &white_color, blackstone_x_hot, blackstone_y_hot);
  831.   gw->goban.gray_cursor  = 
  832.     XCreatePixmapCursor (display, gw->goban.gray_stone, gw->goban.mouse_mask,  
  833.              &black_color, &white_color, graystone_x_hot , graystone_y_hot );
  834.  
  835.   gw->goban.font_cursor  = XCreateFontCursor (display, XC_question_arrow);
  836. }
  837.   
  838. /****************************************************************************************************************
  839.  */
  840.  
  841. static void DestroyPixmap (w)
  842. Widget w;
  843. {
  844.   GobanWidget  gw      = (GobanWidget) w;
  845.   Display     *display = XtDisplay (w);
  846.  
  847.   XFreePixmap (display, gw->goban.picture);
  848.   XFreePixmap (display, gw->goban.board  );
  849. }
  850.  
  851. /****************************************************************************************************************
  852.  */
  853.  
  854. static void DestroyGC (w)
  855. Widget w;
  856. {
  857.   GobanWidget  gw      = (GobanWidget) w;
  858.   Display     *display = XtDisplay (w);
  859.  
  860.   XFreeGC (display, gw->goban.black_fg_gc  );
  861.   XFreeGC (display, gw->goban.black_bg_gc  );
  862.   XFreeGC (display, gw->goban.black_bd_gc  );
  863.   XFreeGC (display, gw->goban.white_fg_gc  );
  864.   XFreeGC (display, gw->goban.white_bg_gc  );
  865.   XFreeGC (display, gw->goban.white_bd_gc  );
  866.   XFreeGC (display, gw->goban.foreground_gc);
  867.   XFreeGC (display, gw->goban.background_gc);
  868.   XFreeGC (display, gw->goban.copy_gc      );
  869. }
  870.  
  871. /****************************************************************************************************************
  872.  */
  873.  
  874. static void Destroy (w)
  875. Widget w;
  876. {
  877.   GobanWidget  gw      = (GobanWidget) w;
  878.   Display     *display = XtDisplay (w);
  879.  
  880.   DestroyPixmap (w);
  881.   DestroyGC     (w);
  882.  
  883.   XFreePixmap (display, gw->goban.white_stone  );
  884.   XFreePixmap (display, gw->goban.black_stone  );
  885.   XFreePixmap (display, gw->goban.gray_stone   );
  886.   XFreePixmap (display, gw->goban.mouse_mask   );
  887.  
  888.   XFreeCursor (display, gw->goban.white_cursor );
  889.   XFreeCursor (display, gw->goban.black_cursor );
  890.   XFreeCursor (display, gw->goban.gray_cursor  );
  891.   XFreeCursor (display, gw->goban.font_cursor  );
  892. }
  893.  
  894. /****************************************************************************************************************
  895.  */
  896.  
  897. static void Realize (w, valuemaskp, attr)
  898. Widget                w;
  899. XtValueMask          *valuemaskp;
  900. XSetWindowAttributes *attr;
  901. {
  902.   GobanWidget  gw      = (GobanWidget) w;
  903.   
  904.   *valuemaskp |= CWCursor;
  905.  
  906.   switch (gw->goban.cursor) {
  907.   case GbCGrayStone  : attr->cursor = gw->goban.gray_cursor ; break;
  908.   case GbCBlackStone : attr->cursor = gw->goban.black_cursor; break;
  909.   case GbCWhiteStone : attr->cursor = gw->goban.white_cursor; break;
  910.   default            : attr->cursor = gw->goban.font_cursor ; break;
  911.   }
  912.   
  913.   XtCreateWindow (w, InputOutput, (Visual *) CopyFromParent, *valuemaskp, attr);
  914. }
  915.  
  916. /****************************************************************************************************************
  917.  */
  918.  
  919. static char *stars[18] = {
  920.   "",                /*  2  */  
  921.   "",                /*  3  */  
  922.   "",                /*  4  */  
  923.   "",                /*  5  */  
  924.   "",                /*  6  */  
  925.   "",                /*  7  */  
  926.   "cccffcff",            /*  8  */    
  927.   "cccgeegcgg",            /*  9  */  
  928.   "ccchhchh",            /* 10  */  
  929.   "cccfcifcfffiicifii",        /* 11  */  
  930.   "dddiidii",            /* 12  */  
  931.   "dddjggjdjj",            /* 13  */  
  932.   "dddkkdkk",            /* 14  */  
  933.   "dddhdlhdhhhlldlhll",        /* 15  */  
  934.   "dddmmdmm",            /* 16  */  
  935.   "dddidnidiiinndninn",        /* 17  */  
  936.   "dddoodoo",            /* 18  */  
  937.   "dddjdpjdjjjppdpjpp",        /* 19  */  
  938. };
  939.  
  940. static void DrawBoard (w)
  941. Widget w;
  942. {
  943.   GobanWidget  gw         = (GobanWidget) w;
  944.   Display     *display    = XtDisplay (w);
  945.   XSegment     segment[44];
  946.   int          segc;
  947.   Position     game_size  = (Position) gw->goban.game_size;
  948.   Position     point_size = (Position) gw->goban.point_size;
  949.   Position     star_size  = 4;
  950.   Position     xbase      = gw->goban.x_offset + point_size / 2;
  951.   Position     ybase      = gw->goban.y_offset - point_size / 2;
  952.   Position     xmin       = gw->goban.x_offset + point_size * gw->goban.left + 1;
  953.   Position     ymin       = gw->goban.y_offset - point_size * gw->goban.top  + 1;
  954.   Position     xmax       = gw->goban.x_offset + point_size * (gw->goban.right  + 1) - 1;
  955.   Position     ymax       = gw->goban.y_offset - point_size * (gw->goban.bottom - 1) - 1;
  956.   char        *star;
  957.   int          x;
  958.   int          y;
  959.  
  960.   XFillRectangle (display, gw->goban.board, gw->goban.background_gc, 0, 0, w->core.width, w->core.height);
  961.  
  962.   if (point_size > 0) {
  963.     segc = 0;
  964.     for (y = gw->goban.bottom - 1; y < gw->goban.top; y++, segc++) {
  965.       segment[segc].x1 = (short) Max ((int) xbase + point_size , xmin);
  966.       segment[segc].x2 = (short) Min ((int) xbase + point_size * game_size, xmax);
  967.       segment[segc].y1 = (short) (ybase - point_size * y);
  968.       segment[segc].y2 = (short) (ybase - point_size * y);
  969.     }
  970.     
  971.     for (x = gw->goban.left; x <= gw->goban.right; x++, segc++) {
  972.       segment[segc].x1 = (short) (xbase + point_size * x);
  973.       segment[segc].x2 = (short) (xbase + point_size * x);
  974.       segment[segc].y1 = (short) Max (ybase - point_size * (game_size - 1), ymin);
  975.       segment[segc].y2 = (short) Min (ybase, ymax);
  976.     }
  977.     
  978.     if (gw->goban.top == gw->goban.game_size) {
  979.       segment[segc].x1 = (short) Max (xbase + point_size - 1, xmin);
  980.       segment[segc].x2 = (short) Min (xbase + point_size * game_size + 1, xmax);
  981.       segment[segc].y1 = (short) (ybase - point_size * (game_size - 1) - 1);
  982.       segment[segc].y2 = (short) (ybase - point_size * (game_size - 1) - 1);
  983.       segc++;
  984.     }
  985.     
  986.     if (gw->goban.bottom == 1) {
  987.       segment[segc].x1 = (short) Max (xbase + point_size - 1, xmin);
  988.       segment[segc].x2 = (short) Min (xbase + point_size * game_size + 1, xmax);
  989.       segment[segc].y1 = (short) (ybase + 1);
  990.       segment[segc].y2 = (short) (ybase + 1);
  991.       segc++;
  992.     }
  993.     
  994.     if (gw->goban.left == 1) {
  995.       segment[segc].x1 = (short) (xbase + point_size - 1);
  996.       segment[segc].x2 = (short) (xbase + point_size - 1);
  997.       segment[segc].y1 = (short) Max (ybase - point_size * (game_size - 1) - 1, ymin); 
  998.       segment[segc].y2 = (short) Min (ybase + 1, ymax);
  999.       segc++;
  1000.     }
  1001.     
  1002.     if (gw->goban.right == gw->goban.game_size) {
  1003.       segment[segc].x1 = (short) (xbase + point_size * game_size + 1);
  1004.       segment[segc].x2 = (short) (xbase + point_size * game_size + 1);
  1005.       segment[segc].y1 = (short) Max (ybase - point_size * (game_size - 1) - 1, ymin);
  1006.       segment[segc].y2 = (short) Min (ybase + 1, ymax);
  1007.       segc++;
  1008.     }
  1009.     
  1010.     XDrawSegments (display, gw->goban.board, gw->goban.foreground_gc, segment, segc);
  1011.     
  1012.     if (point_size > 8) {
  1013.       star_size = (point_size > 10) ? 4 : 2;
  1014.       star      = stars[game_size - 2];
  1015.       
  1016.       while (*star != '\0') {
  1017.     x = *star++ - 'a' + 1;
  1018.     y = *star++ - 'a' + 1;
  1019.     
  1020.     if (x >= gw->goban.left && x <= gw->goban.right && y >= gw->goban.bottom && y <= gw->goban.top) {
  1021.       x = gw->goban.x_offset + (point_size * (2 * x + 1)) / 2;
  1022.       y = gw->goban.y_offset - (point_size * (2 * y - 1)) / 2;
  1023.       
  1024.       XDrawArc (display, gw->goban.board, gw->goban.foreground_gc, 
  1025.             (int) x - star_size / 2, (int) y - star_size / 2, 
  1026.             (unsigned int) star_size, (unsigned int) star_size, 
  1027.             0, 64 * 360);
  1028.       XFillArc (display, gw->goban.board, gw->goban.foreground_gc, 
  1029.             (int) x - star_size / 2, (int) y - star_size / 2, 
  1030.             (unsigned int) star_size, (unsigned int) star_size, 
  1031.             0, 64 * 360);
  1032.     }
  1033.       }
  1034.     }
  1035.   }
  1036.  
  1037.   XCopyArea (display, gw->goban.board, gw->goban.picture, gw->goban.copy_gc, 0, 0, 
  1038.          w->core.width, w->core.height, 0, 0);
  1039. }
  1040.  
  1041. /****************************************************************************************************************
  1042.  */
  1043.  
  1044. static void DrawCoordinates (w)
  1045. Widget w;
  1046. {
  1047.   GobanWidget  gw         = (GobanWidget) w;
  1048.   Display     *display    = XtDisplay (w);
  1049.   XCharStruct  extent;
  1050.   int          point_size = gw->goban.point_size;
  1051.   char         s[2];
  1052.   int          len;
  1053.   int          ascent;
  1054.   int          descent;
  1055.   int          direction;
  1056.   int          xbase;
  1057.   int          ybase;
  1058.   int          x;
  1059.   int          y;
  1060.   unsigned int width;
  1061.   unsigned int height;
  1062.  
  1063.   s[0] = s[1] = '8';
  1064.   XQueryTextExtents (display, XGContextFromGC (gw->goban.foreground_gc),
  1065.              s, 2, &direction, &ascent, &descent, &extent);
  1066.  
  1067.   if ((point_size > extent.width + 2) && (point_size > extent.ascent + extent.descent + 2)) {
  1068.     xbase = 2 * gw->goban.x_offset + point_size;
  1069.     ybase = 2 * gw->goban.y_offset - point_size;
  1070.  
  1071.     if (gw->goban.display_coordinates == TRUE) {
  1072.     
  1073.       for (x = gw->goban.left; x <= gw->goban.right; x++) {
  1074.     s[0] = 'A' - 1 + ((x > 8) ? (x + 1) : x);
  1075.     XQueryTextExtents (display, XGContextFromGC (gw->goban.foreground_gc),
  1076.                s, 1, &direction, &ascent, &descent, &extent);
  1077.  
  1078.     XDrawString (display, gw->goban.board, gw->goban.foreground_gc, 
  1079.              (xbase - extent.width) / 2 + point_size * x - extent.lbearing + 1, 
  1080.              (ybase + extent.ascent - extent.descent) / 2 - point_size * gw->goban.top + 1, s, 1);
  1081.     XDrawString (display, gw->goban.board, gw->goban.foreground_gc, 
  1082.              (xbase - extent.width) / 2 + point_size * x - extent.lbearing + 1, 
  1083.              (ybase + extent.ascent - extent.descent) / 2 - point_size * (gw->goban.bottom - 2) + 1, s, 1);
  1084.       }
  1085.     }
  1086.  
  1087.     x      = gw->goban.x_offset + point_size * gw->goban.left;
  1088.     y      = gw->goban.y_offset - point_size * (gw->goban.top + 1);
  1089.     width  = point_size * (gw->goban.right - gw->goban.left + 1);
  1090.     height = point_size;
  1091.     
  1092.     if (gw->goban.display_coordinates == FALSE)
  1093.       XFillRectangle (display, gw->goban.board, gw->goban.background_gc, x, y, width, height);
  1094.     XCopyArea (display, gw->goban.board, gw->goban.picture, gw->goban.copy_gc, x, y, width, height, x, y);
  1095.  
  1096.     y      = gw->goban.y_offset - point_size * (gw->goban.bottom - 1);
  1097.  
  1098.     if (gw->goban.display_coordinates == FALSE)
  1099.       XFillRectangle (display, gw->goban.board, gw->goban.background_gc, x, y, width, height);
  1100.     XCopyArea (display, gw->goban.board, gw->goban.picture, gw->goban.copy_gc, x, y, width, height, x, y);
  1101.     
  1102.     ybase += 2 * point_size;
  1103.  
  1104.     for (y = gw->goban.bottom; y <= gw->goban.top; y++) {
  1105.       if (gw->goban.display_coordinates == TRUE) {
  1106.     len = 0;
  1107.     if (y > 9)
  1108.       s[len++] = '1';
  1109.     s[len++] = '0' + y % 10;
  1110.     XQueryTextExtents (display, XGContextFromGC (gw->goban.foreground_gc),
  1111.                s, len, &direction, &ascent, &descent, &extent);
  1112.  
  1113.     XDrawString (display, gw->goban.board, gw->goban.foreground_gc, 
  1114.              (xbase - extent.width) / 2 + point_size * (gw->goban.left  - 1) - extent.lbearing + 1, 
  1115.              (ybase + extent.ascent - extent.descent) / 2 - point_size * y + 1, s, len);
  1116.     XDrawString (display, gw->goban.board, gw->goban.foreground_gc, 
  1117.              (xbase - extent.width) / 2 + point_size * (gw->goban.right + 1) - extent.lbearing + 1, 
  1118.              (ybase + extent.ascent - extent.descent) / 2 - point_size * y + 1, s, len);
  1119.       }
  1120.     }
  1121.  
  1122.     x      = gw->goban.x_offset + point_size * (gw->goban.left  - 1);
  1123.     y      = gw->goban.y_offset - point_size * gw->goban.top;
  1124.     width  = point_size;
  1125.     height = point_size * (gw->goban.top - gw->goban.bottom + 1);;
  1126.     
  1127.     if (gw->goban.display_coordinates == FALSE)
  1128.       XFillRectangle (display, gw->goban.board, gw->goban.background_gc, x, y, width, height);
  1129.     XCopyArea (display, gw->goban.board, gw->goban.picture, gw->goban.copy_gc, x, y, width, height, x, y);
  1130.  
  1131.     x      = gw->goban.x_offset + point_size * (gw->goban.right + 1);
  1132.     
  1133.     if (gw->goban.display_coordinates == FALSE)
  1134.       XFillRectangle (display, gw->goban.board, gw->goban.background_gc, x, y, width, height);
  1135.     XCopyArea (display, gw->goban.board, gw->goban.picture, gw->goban.copy_gc, x, y, width, height, x, y);
  1136.   }
  1137.  
  1138. }
  1139.  
  1140. /****************************************************************************************************************
  1141.  */
  1142.  
  1143. static void InitializeSize (w)
  1144. Widget w;
  1145. {  
  1146.   GobanWidget  gw        = (GobanWidget) w;
  1147.   Position     bottom    = Min (gw->goban.bottom, gw->goban.top  );
  1148.   Position     left      = Min (gw->goban.left  , gw->goban.right);
  1149.   Position     top       = Max (gw->goban.bottom, gw->goban.top  );
  1150.   Position     right     = Max (gw->goban.left  , gw->goban.right);
  1151.   Dimension    game_size = gw->goban.game_size;
  1152.   Dimension    width;
  1153.   Dimension    height;
  1154.  
  1155.   game_size = (game_size > 1      && game_size <  20       ) ? game_size : 19;
  1156.   bottom    = (bottom    > 0      && bottom    <  game_size) ? bottom    : 1;
  1157.   left      = (left      > 0      && left      <  game_size) ? left      : 1;
  1158.   top       = (top       > bottom && top       <= game_size) ? top       : game_size;
  1159.   right     = (right     > left   && right     <= game_size) ? right     : game_size;
  1160.  
  1161.   width     = right - left   + 3;
  1162.   height    = top   - bottom + 3;
  1163.  
  1164.   if ((w->core.height == 0) && (w->core.width == 0)) {
  1165.     w->core.width  = gw->goban.point_size * width ;
  1166.     w->core.height = gw->goban.point_size * height;
  1167.   } 
  1168.  
  1169.   else 
  1170.     gw->goban.point_size = Min (w->core.width / width, w->core.height / height);
  1171.  
  1172.   gw->goban.game_size = game_size;
  1173.   gw->goban.bottom    = bottom;
  1174.   gw->goban.left      = left;
  1175.   gw->goban.top       = top;
  1176.   gw->goban.right     = right;
  1177.   gw->goban.x_offset  = (int) (w->core.width  - gw->goban.point_size * (width  + 2 * left - 2)) / 2;
  1178.   gw->goban.y_offset  = (int) (w->core.height - gw->goban.point_size * (height - 2 * top  - 2)) / 2;
  1179. }
  1180.  
  1181. /****************************************************************************************************************
  1182.  */
  1183.  
  1184. /* ARGSUSED */
  1185.  
  1186. static void Initialize (request, new)
  1187. Widget request;
  1188. Widget new;
  1189. {
  1190.   InitializeSize   (new);
  1191.   InitializePixmap (new);
  1192.   InitializeGC     (new);
  1193.   InitializeCursor (new);
  1194.   DrawBoard        (new);
  1195.   DrawCoordinates  (new);
  1196.   GbClearBoard     (new);
  1197. }
  1198.  
  1199. /****************************************************************************************************************
  1200.  */
  1201.  
  1202. static void DrawPoint (w, x, y, color)
  1203. Widget      w;
  1204. int         x;
  1205. int         y;
  1206. GbPointState color;
  1207. {
  1208.   GobanWidget   gw      = (GobanWidget) w;
  1209.   Display      *display = XtDisplay (w);
  1210.   unsigned int  size    = (unsigned int) gw->goban.point_size - 2;
  1211.   XExposeEvent  event;
  1212.   int           X;
  1213.   int           Y;
  1214.  
  1215.   if (size > 1) {
  1216.     X = gw->goban.x_offset + gw->goban.point_size * x + 1;
  1217.     Y = gw->goban.y_offset - gw->goban.point_size * y + 1;
  1218.     
  1219.     switch (color)
  1220.       {
  1221.       case GbBlackStone :
  1222.     XFillArc (display, gw->goban.picture, gw->goban.black_bg_gc, X, Y, size, size, 0, 360 * 64);
  1223.     XDrawArc (display, gw->goban.picture, gw->goban.black_bd_gc, X, Y, size, size, 0, 360 * 64);
  1224.     XDrawArc (display, gw->goban.picture, gw->goban.black_fg_gc, X + (int) size / 6, Y + (int) size / 6, 
  1225.           (size * 2) / 3, (size * 2) / 3, -15 * 64, -60 * 64);
  1226.     break;
  1227.       case GbWhiteStone :
  1228.     XFillArc (display, gw->goban.picture, gw->goban.white_bg_gc, X, Y, size, size, 0, 360 * 64);
  1229.     XDrawArc (display, gw->goban.picture, gw->goban.white_bd_gc, X, Y, size, size, 0, 360 * 64);
  1230.     XDrawArc (display, gw->goban.picture, gw->goban.white_fg_gc, X + (int) size / 6, Y + (int) size / 6, 
  1231.           (size * 2) / 3, (size * 2) / 3, -15 * 64, -60 * 64);
  1232.     break;
  1233.       case GbEmptyPoint :
  1234.     XCopyArea (XtDisplay (w), gw->goban.board, gw->goban.picture, gw->goban.copy_gc,
  1235.            X, Y, gw->goban.point_size, gw->goban.point_size, X, Y); 
  1236.     break;
  1237.       }
  1238.     
  1239.     if (gw->goban.auto_redisplay == TRUE && XtIsRealized (w) == TRUE) {
  1240.       event.x      = X - 1;
  1241.       event.y      = Y - 1;
  1242.       event.width  = gw->goban.point_size;
  1243.       event.height = gw->goban.point_size;
  1244.  
  1245.       Redisplay (w, &event, (Region) NULL);
  1246.     }
  1247.   }
  1248. }
  1249.  
  1250. /****************************************************************************************************************
  1251.  */
  1252.  
  1253. static void RedrawStones (w)
  1254. Widget w;
  1255. {
  1256.   GobanWidget  gw         = (GobanWidget) w;
  1257.   Boolean      redisplay  = gw->goban.auto_redisplay;
  1258.   Position     x;
  1259.   Position     y;
  1260.  
  1261.   gw->goban.auto_redisplay = FALSE;
  1262.  
  1263.   for (x = gw->goban.left; x <= gw->goban.right; x++)
  1264.     for (y = gw->goban.bottom; y <= gw->goban.top; y++) {
  1265.       if (gw->goban.points[x][y].free == 0) {
  1266.     if (gw->goban.points[x][y].black == 1)
  1267.       DrawPoint (w, x, y, GbBlackStone);
  1268.     else
  1269.       DrawPoint (w, x, y, GbWhiteStone);
  1270.     if (gw->goban.points[x][y].num > 0)
  1271.       GbSetNum (w, x, y, (int) gw->goban.points[x][y].num);
  1272.       }
  1273.  
  1274.       if (gw->goban.points[x][y].mark1 != 0 || gw->goban.points[x][y].mark2 != 0)
  1275.     GbSetMark (w, x, y, gw->goban.points[x][y].mark1, gw->goban.points[x][y].mark2);
  1276.     }
  1277.  
  1278.   gw->goban.auto_redisplay = redisplay;
  1279.  
  1280.   if (redisplay == TRUE)
  1281.     GbRedisplayBoard (w);
  1282. }
  1283.  
  1284. /****************************************************************************************************************
  1285.  */
  1286.  
  1287. static void Resize (w)
  1288. Widget w;
  1289. {
  1290.   DestroyPixmap    (w);
  1291.   DestroyGC        (w);
  1292.   InitializeSize   (w);
  1293.   InitializePixmap (w);
  1294.   InitializeGC     (w);
  1295.   DrawBoard        (w);
  1296.   DrawCoordinates  (w);
  1297.   RedrawStones     (w);
  1298. }
  1299.  
  1300. /****************************************************************************************************************
  1301.  */
  1302.  
  1303. /* ARGSUSED */
  1304.  
  1305. static Boolean SetValues (current, request, new)
  1306. Widget current;
  1307. Widget request;
  1308. Widget new;
  1309. {
  1310.   GobanWidget gnew      = (GobanWidget) new;
  1311.   GobanWidget gcurrent  = (GobanWidget) current;
  1312.   Boolean     redisplay = FALSE;
  1313.  
  1314.   if (gnew->goban.point_size != gcurrent->goban.point_size)
  1315.     gnew->goban.point_size = gcurrent->goban.point_size;
  1316.  
  1317.   if (XtIsRealized (new)) {
  1318.     if (gnew->goban.cursor != gcurrent->goban.cursor) {
  1319.  
  1320.       switch (gnew->goban.cursor) {
  1321.  
  1322.       case GbCGrayStone  : 
  1323.     XDefineCursor (XtDisplay (new), XtWindow (new), gnew->goban.gray_cursor);
  1324.     break;
  1325.       case GbCBlackStone : 
  1326.     XDefineCursor (XtDisplay (new), XtWindow (new), gnew->goban.black_cursor);
  1327.     break;
  1328.       case GbCWhiteStone : 
  1329.     XDefineCursor (XtDisplay (new), XtWindow (new), gnew->goban.white_cursor);
  1330.     break;
  1331.       default :
  1332.     XFreeCursor (XtDisplay (new), gnew->goban.font_cursor );
  1333.     gnew->goban.font_cursor = XCreateFontCursor (XtDisplay (new), (unsigned int) gnew->goban.cursor);
  1334.     XDefineCursor (XtDisplay (new), XtWindow (new), gnew->goban.font_cursor);
  1335.       }
  1336.     }
  1337.   }
  1338.  
  1339.   if (gnew->goban.game_size != gcurrent->goban.game_size) 
  1340.     if (gnew->goban.game_size > 1 && gnew->goban.game_size < 20) {
  1341.  
  1342.       gnew->goban.bottom = 1;
  1343.       gnew->goban.left   = 1;
  1344.       gnew->goban.top    = gnew->goban.game_size;
  1345.       gnew->goban.right  = gnew->goban.game_size;
  1346.       
  1347.       InitializeSize   (new);
  1348.       DrawBoard        (new);
  1349.       DrawCoordinates  (new);
  1350.       GbClearBoard     (new);
  1351.       
  1352.       redisplay = TRUE;
  1353.     }
  1354.     else
  1355.       gnew->goban.game_size = gcurrent->goban.game_size;
  1356.  
  1357.   else if (gnew->goban.top    != gcurrent->goban.top   ||
  1358.        gnew->goban.left   != gcurrent->goban.left  ||
  1359.        gnew->goban.right  != gcurrent->goban.right ||
  1360.        gnew->goban.bottom != gcurrent->goban.bottom) {
  1361.  
  1362.     InitializeSize  (new);
  1363.     DrawBoard       (new);
  1364.     DrawCoordinates (new);
  1365.     RedrawStones    (new);
  1366.  
  1367.     redisplay = TRUE;
  1368.   }
  1369.  
  1370.   else if (new->core.background_pixel != current->core.background_pixel || 
  1371.            gnew->goban.foreground     != gcurrent->goban.foreground     ||
  1372.            gnew->goban.white_fg       != gcurrent->goban.white_fg       ||
  1373.            gnew->goban.white_bg       != gcurrent->goban.white_bg       ||
  1374.            gnew->goban.white_bd       != gcurrent->goban.white_bd       ||
  1375.            gnew->goban.black_fg       != gcurrent->goban.black_fg       ||
  1376.            gnew->goban.black_bg       != gcurrent->goban.black_bg       ||
  1377.            gnew->goban.black_bd       != gcurrent->goban.black_bd       ) {
  1378.  
  1379.     DestroyGC        (new);
  1380.     InitializeGC     (new);
  1381.     DrawBoard        (new);
  1382.     DrawCoordinates  (new);
  1383.     RedrawStones     (new);
  1384.  
  1385.     redisplay = TRUE;
  1386.   }
  1387.  
  1388.   if (gnew->goban.display_coordinates != gcurrent->goban.display_coordinates) {
  1389.     DrawCoordinates (new);
  1390.  
  1391.     redisplay = TRUE;
  1392.   }
  1393.  
  1394.   return (gnew->goban.auto_redisplay == True) ? redisplay : False;
  1395. }
  1396.  
  1397. /****************************************************************************************************************
  1398.  */
  1399. SHAR_EOF
  1400. fi
  1401. if test -f 'Goban.h'
  1402. then
  1403.     echo shar: "will not over-write existing file 'Goban.h'"
  1404. else
  1405. cat << \SHAR_EOF > 'Goban.h'
  1406. /****************************************************************************************************************
  1407.  *
  1408.  *  Copyright (c) 1992 by Antoine Dumesnil de Maricourt. All rights reserved.
  1409.  *
  1410.  *  This program is distributed in the hope that it will be useful.
  1411.  *  Use and copying of this software and preparation of derivative works
  1412.  *  based upon this software are permitted, so long as the following
  1413.  *  conditions are met:
  1414.  *       o credit to the authors is acknowledged following current
  1415.  *         academic behaviour
  1416.  *       o no fees or compensation are charged for use, copies, or
  1417.  *         access to this software
  1418.  *       o this copyright notice is included intact.
  1419.  *  This software is made available AS IS, and no warranty is made about 
  1420.  *  the software or its performance. 
  1421.  * 
  1422.  *  Bug descriptions, use reports, comments or suggestions are welcome.
  1423.  *  Send them to    dumesnil@etca.fr   or to:
  1424.  *       
  1425.  *       Antoine de Maricourt
  1426.  *       ETCA CREA-SP
  1427.  *       16 bis, avenue Prieur de la Cote d'Or
  1428.  *       94114 Arcueil Cedex
  1429.  *       France
  1430.  */
  1431.  
  1432. #ifndef _Goban_h
  1433. #define _Goban_h
  1434.  
  1435. /* Resources:
  1436.  
  1437.  Name               Class          RepType        Default Value
  1438.  ----               -----          -------        -------------
  1439.  autoRedisplay         AutoRedisplay      Boolean         True
  1440.  background           Background      Pixel          XtDefaultBackground
  1441.  blackStoneBackground  Background      Pixel          black
  1442.  blackStoneBorder      BorderColor      Pixel          black
  1443.  blackStoneForeground  Foreground      Pixel          white
  1444.  border               BorderColor      Pixel          XtDefaultForeground
  1445.  borderWidth           BorderWidth      Dimension      1
  1446.  cursor                Cursor             Integer         GbGrayCursor
  1447.  destroyCallback       Callback          Pointer      NULL
  1448.  displayCoordinates    DisplayCoordinates Boolean      True
  1449.  font                  Font               XFontStruct*    fixed
  1450.  foreground            Foreground         Pixel           XtDefaultForeground
  1451.  gameSize              Size               Dimension       19
  1452.  height               Height          Dimension      computed at create
  1453.  mappedWhenManaged     MappedWhenManaged  Boolean      True
  1454.  pointSize             Size               Dimension       24
  1455.  sensitive           Sensitive      Boolean      True
  1456.  viewBottom            Position           Position        computed at create
  1457.  viewLeft              Position           Position        computed at create
  1458.  viewRight             Position           Position        computed at create
  1459.  viewTop               Position           Position        computed at create
  1460.  whiteStoneBackground  Background      Pixel          white
  1461.  whiteStoneBorder      BorderColor      Pixel          black
  1462.  whiteStoneForeground  Foreground      Pixel          black
  1463.  width               Width          Dimension      computed at create
  1464.  x               Position          Position      0
  1465.  y               Position          Position      0
  1466. */
  1467.  
  1468. /* define any special resource names here that are not in <X11/StringDefs.h> */
  1469.  
  1470. #define XtNautoRedisplay         "autoRedisplay"
  1471. #define XtNviewBottom            "viewBottom"
  1472.  
  1473. #ifndef XtNcursor
  1474. #define XtNcursor                "cursor"
  1475. #endif
  1476.  
  1477. #define XtNgameSize              "gameSize"
  1478. #define XtNviewLeft              "viewLeft"
  1479. #define XtNdisplayCoordinates    "displayCoordinates"
  1480. #define XtNpointSize             "pointSize"
  1481. #define XtNviewRight             "viewRight"
  1482. #define XtNviewTop               "viewTop"
  1483. #define XtNblackStoneBorder      "blackStoneBorder"
  1484. #define XtNblackStoneForeground  "blackStoneForeground"
  1485. #define XtNblackStoneBackground  "blackStoneBackground"
  1486. #define XtNwhiteStoneBorder      "whiteStoneBorder"
  1487. #define XtNwhiteStoneForeground  "whiteStoneForeground"
  1488. #define XtNwhiteStoneBackground  "whiteStoneBackground"
  1489.  
  1490. #define XtCAutoRedisplay         "AutoRedisplay"
  1491. #define XtCDisplayCoordinates    "DisplayCoordinates"
  1492. #define XtCSize                  "Size"
  1493.  
  1494. #define XtEgbWhiteStone          "white"
  1495. #define XtEgbBlackStone          "black"
  1496. #define XtEgbGrayStone           "gray"
  1497.  
  1498. /* declare specific GobanWidget class and instance datatypes */
  1499.  
  1500. typedef struct _GobanClassRec*     GobanWidgetClass;
  1501. typedef struct _GobanRec*     GobanWidget;
  1502.  
  1503. /* declare the class constant */
  1504.  
  1505. extern WidgetClass gobanWidgetClass;
  1506.  
  1507. /* cursors */
  1508.  
  1509. #define GbCGrayStone         256
  1510. #define GbCBlackStone        257
  1511. #define GbCWhiteStone        258
  1512.  
  1513. /* special marks */
  1514.  
  1515. #define GbMSquareMark        1
  1516. #define GbMTriangleMark      2
  1517. #define GbMVCrossMark        3
  1518. #define GbMDCrossMark        4
  1519. #define GbMDiamondMark       5
  1520.  
  1521. /* colors */
  1522.  
  1523. typedef enum { GbEmptyPoint, GbBlackStone, GbWhiteStone } GbPointState;
  1524.  
  1525. /* user functions */
  1526.  
  1527. #define GbRemoveMark(w,x,y)  GbSetMark (w, x, y, 0, 0)
  1528.  
  1529. extern void GbRedisplayBoard ( /* Widget w */ );
  1530. extern void GbClearBoard     ( /* Widget w */ );
  1531. extern void GbSetPoint       ( /* Widget w, Position x, Position y, GbPointState color */ );
  1532. extern void GbSetNum         ( /* Widget w, Position x, Position y, int num   */ );
  1533. extern void GbSetMark        ( /* Widget w, Position x, Position y, unsigned char mark1, unsigned char mark2 */ );
  1534.  
  1535. extern Boolean GbGetPositionFromStone ( /* Widget w, Position *x, Position *y */ );
  1536. extern Boolean GbGetStoneFromPosition ( /* Widget w, Position *x, Position *y */ );
  1537.  
  1538. #endif /* _Goban_h */
  1539.  
  1540. SHAR_EOF
  1541. fi
  1542. if test -f 'GobanP.h'
  1543. then
  1544.     echo shar: "will not over-write existing file 'GobanP.h'"
  1545. else
  1546. cat << \SHAR_EOF > 'GobanP.h'
  1547. /****************************************************************************************************************
  1548.  *
  1549.  *  Copyright (c) 1992 by Antoine Dumesnil de Maricourt. All rights reserved.
  1550.  *
  1551.  *  This program is distributed in the hope that it will be useful.
  1552.  *  Use and copying of this software and preparation of derivative works
  1553.  *  based upon this software are permitted, so long as the following
  1554.  *  conditions are met:
  1555.  *       o credit to the authors is acknowledged following current
  1556.  *         academic behaviour
  1557.  *       o no fees or compensation are charged for use, copies, or
  1558.  *         access to this software
  1559.  *       o this copyright notice is included intact.
  1560.  *  This software is made available AS IS, and no warranty is made about 
  1561.  *  the software or its performance. 
  1562.  * 
  1563.  *  Bug descriptions, use reports, comments or suggestions are welcome.
  1564.  *  Send them to    dumesnil@etca.fr   or to:
  1565.  *       
  1566.  *       Antoine de Maricourt
  1567.  *       ETCA CREA-SP
  1568.  *       16 bis, avenue Prieur de la Cote d'Or
  1569.  *       94114 Arcueil Cedex
  1570.  *       France
  1571.  */
  1572.  
  1573. #ifndef _GobanP_h
  1574. #define _GobanP_h
  1575.  
  1576. #include "Goban.h"
  1577.  
  1578. /* include superclass private header file */
  1579. #include <X11/CoreP.h>
  1580.  
  1581. /* define unique representation types not found in <X11/StringDefs.h> */
  1582.  
  1583. #define XtRGobanResource "GobanResource"
  1584.  
  1585. typedef struct {
  1586.     int empty;
  1587. } GobanClassPart;
  1588.  
  1589. typedef struct _GobanClassRec {
  1590.     CoreClassPart    core_class;
  1591.     GobanClassPart    goban_class;
  1592. } GobanClassRec;
  1593.  
  1594. extern GobanClassRec gobanClassRec;
  1595.  
  1596. typedef struct {
  1597.   unsigned int free  : 1;
  1598.   unsigned int black : 1;
  1599.   unsigned int mark1 : 8;
  1600.   unsigned int mark2 : 8;
  1601.   unsigned int num   : 10;
  1602. } PointState;
  1603.  
  1604. typedef struct {
  1605.     /* resources */
  1606.  
  1607.   Boolean       auto_redisplay;
  1608.   Position      bottom;
  1609.   int           cursor;
  1610.   XFontStruct  *font;
  1611.   Pixel         foreground;
  1612.   Dimension     game_size;
  1613.   Position      left;
  1614.   Boolean       display_coordinates;
  1615.   Dimension     point_size;
  1616.   Position      right;
  1617.   Position      top;
  1618.  
  1619.     /* private state */
  1620.  
  1621.   PointState    points[20][20];
  1622.   Position      x_offset;
  1623.   Position      y_offset;
  1624.  
  1625.   Pixmap        black_stone;
  1626.   Pixmap        board;
  1627.   Pixmap        gray_stone;
  1628.   Pixmap        mouse_mask;
  1629.   Pixmap        picture;
  1630.   Pixmap        white_stone;
  1631.  
  1632.   GC            background_gc;
  1633.   GC            foreground_gc;
  1634.   GC            black_fg_gc;
  1635.   GC            black_bg_gc;
  1636.   GC            black_bd_gc;
  1637.   GC            white_fg_gc;
  1638.   GC            white_bg_gc;
  1639.   GC            white_bd_gc;
  1640.   GC            copy_gc;
  1641.  
  1642.   Cursor        black_cursor;
  1643.   Cursor        gray_cursor;
  1644.   Cursor        white_cursor;
  1645.   Cursor        font_cursor;
  1646.  
  1647.   Pixel         white_bg;
  1648.   Pixel         white_fg;
  1649.   Pixel         white_bd;
  1650.   Pixel         black_bg;
  1651.   Pixel         black_fg;
  1652.   Pixel         black_bd;
  1653. } GobanPart;
  1654.  
  1655. typedef struct _GobanRec {
  1656.     CorePart    core;
  1657.     GobanPart    goban;
  1658. } GobanRec;
  1659.  
  1660. #define Min(x,y)      ((x) > (y) ? (y) : (x))
  1661. #define Max(x,y)      ((x) > (y) ? (x) : (y))
  1662.  
  1663. #endif /* _GobanP_h */
  1664. SHAR_EOF
  1665. fi
  1666. if test -f 'Imakefile'
  1667. then
  1668.     echo shar: "will not over-write existing file 'Imakefile'"
  1669. else
  1670. cat << \SHAR_EOF > 'Imakefile'
  1671. LOCAL_LIBRARIES = $(XAWLIB) $(XTOOLLIB) $(XMULIB) $(XLIB)
  1672.  
  1673. OBJS=        main.o Goban.o amigo.o goplayer.o goplayutils.o \
  1674.         killable.o xinterface.o menus.o
  1675. SRCS=        $(OBJS:%.o=%.c)
  1676.  
  1677. ComplexProgramTarget(xamigo)
  1678. InstallAppDefaults(Xamigo)
  1679. SHAR_EOF
  1680. fi
  1681. if test -f 'Makefile'
  1682. then
  1683.     echo shar: "will not over-write existing file 'Makefile'"
  1684. else
  1685. cat << \SHAR_EOF > 'Makefile'
  1686. # Makefile generated by imake - do not edit!
  1687. #
  1688. # The cpp used on this machine replaces all newlines and multiple tabs and
  1689. # spaces in a macro expansion with a single space.  Imake tries to compensate
  1690. # for this, but is not always successful.
  1691. #
  1692.  
  1693. # -------------------------------------------------------------------------
  1694. # Makefile generated from "Imake.tmpl" and <Imakefile>
  1695. # $XConsortium: Imake.tmpl,v 1.139 91/09/16 08:52:48 rws Exp $
  1696. #
  1697. # Platform-specific parameters may be set in the appropriate <vendor>.cf
  1698. # configuration files.  Site-specific parameters should be set in the file
  1699. # site.def.  Full rebuilds are recommended if any parameters are changed.
  1700. #
  1701. # If your C preprocessor does not define any unique symbols, you will need
  1702. # to set BOOTSTRAPCFLAGS when rebuilding imake (usually when doing
  1703. # "make World" the first time).
  1704. #
  1705.  
  1706. # -------------------------------------------------------------------------
  1707. # site-specific configuration parameters that need to come before
  1708. # the platform-specific parameters - edit site.def to change
  1709.  
  1710. # site:  $XConsortium: site.def,v 1.2 91/07/30 20:26:44 rws Exp $
  1711.  
  1712. # -------------------------------------------------------------------------
  1713. # platform-specific configuration parameters - edit sun.cf to change
  1714.  
  1715. # platform:  $XConsortium: sun.cf,v 1.71 91/12/20 11:18:34 rws Exp $
  1716.  
  1717. # operating system:  SunOS 4.1.1
  1718.  
  1719. # $XConsortium: sunLib.rules,v 1.7 91/12/20 11:19:47 rws Exp $
  1720.  
  1721. # -------------------------------------------------------------------------
  1722. # site-specific configuration parameters that go after
  1723. # the platform-specific parameters - edit site.def to change
  1724.  
  1725. # site:  $XConsortium: site.def,v 1.2 91/07/30 20:26:44 rws Exp $
  1726.  
  1727.             SHELL = /bin/sh
  1728.  
  1729.               TOP = .
  1730.       CURRENT_DIR = .
  1731.  
  1732.                AR = ar clq
  1733.   BOOTSTRAPCFLAGS =
  1734.                CC = cc
  1735.                AS = as
  1736.  
  1737.          COMPRESS = compress
  1738.               CPP = /lib/cpp $(STD_CPP_DEFINES)
  1739.     PREPROCESSCMD = cc -E $(STD_CPP_DEFINES)
  1740.           INSTALL = install
  1741.                LD = ld
  1742.              LINT = lint
  1743.       LINTLIBFLAG = -C
  1744.          LINTOPTS = -axz
  1745.                LN = ln -s
  1746.              MAKE = make
  1747.                MV = mv
  1748.                CP = cp
  1749.  
  1750.            RANLIB = ranlib
  1751.   RANLIBINSTFLAGS =
  1752.  
  1753.                RM = rm -f
  1754.             TROFF = psroff
  1755.          MSMACROS = -ms
  1756.               TBL = tbl
  1757.               EQN = eqn
  1758.      STD_INCLUDES =
  1759.   STD_CPP_DEFINES =
  1760.       STD_DEFINES =
  1761.  EXTRA_LOAD_FLAGS =
  1762.   EXTRA_LIBRARIES =
  1763.              TAGS = ctags
  1764.  
  1765.     SHAREDCODEDEF = -DSHAREDCODE
  1766.          SHLIBDEF = -DSUNSHLIB
  1767.  
  1768.     PROTO_DEFINES =
  1769.  
  1770.      INSTPGMFLAGS =
  1771.  
  1772.      INSTBINFLAGS = -m 0755
  1773.      INSTUIDFLAGS = -m 4755
  1774.      INSTLIBFLAGS = -m 0644
  1775.      INSTINCFLAGS = -m 0444
  1776.      INSTMANFLAGS = -m 0444
  1777.      INSTDATFLAGS = -m 0444
  1778.     INSTKMEMFLAGS = -g kmem -m 2755
  1779.  
  1780.       CDEBUGFLAGS = -O
  1781.         CCOPTIONS = -pipe
  1782.  
  1783.       ALLINCLUDES = $(INCLUDES) $(EXTRA_INCLUDES) $(TOP_INCLUDES) $(STD_INCLUDES)
  1784.        ALLDEFINES = $(ALLINCLUDES) $(STD_DEFINES) $(EXTRA_DEFINES) $(PROTO_DEFINES) $(DEFINES)
  1785.            CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLDEFINES)
  1786.         LINTFLAGS = $(LINTOPTS) -DLINT $(ALLDEFINES)
  1787.  
  1788.            LDLIBS = $(SYS_LIBRARIES) $(EXTRA_LIBRARIES)
  1789.  
  1790.         LDOPTIONS = $(CDEBUGFLAGS) $(CCOPTIONS) $(LOCAL_LDFLAGS)
  1791.  
  1792.    LDCOMBINEFLAGS = -X -r
  1793.       DEPENDFLAGS =
  1794.  
  1795.         MACROFILE = sun.cf
  1796.            RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *~ *.a .emacs_* tags TAGS make.log MakeOut
  1797.  
  1798.     IMAKE_DEFINES =
  1799.  
  1800.          IRULESRC = $(CONFIGDIR)
  1801.         IMAKE_CMD = $(IMAKE) -DUseInstalled -I$(IRULESRC) $(IMAKE_DEFINES)
  1802.  
  1803.      ICONFIGFILES = $(IRULESRC)/Imake.tmpl $(IRULESRC)/Imake.rules \
  1804.             $(IRULESRC)/Project.tmpl $(IRULESRC)/site.def \
  1805.             $(IRULESRC)/$(MACROFILE) $(EXTRA_ICONFIGFILES)
  1806.  
  1807. # -------------------------------------------------------------------------
  1808. # X Window System Build Parameters
  1809. # $XConsortium: Project.tmpl,v 1.138 91/09/10 09:02:12 rws Exp $
  1810.  
  1811. # -------------------------------------------------------------------------
  1812. # X Window System make variables; this need to be coordinated with rules
  1813.  
  1814.           PATHSEP = /
  1815.         USRLIBDIR = /usr/lib
  1816.              BINDIR = /usr/users/staff/xtools/bin/$(TARGET_ARCH:-%=%)
  1817.              INCROOT = /usr/include
  1818.         BUILDINCROOT = $(TOP)
  1819.          BUILDINCDIR = $(BUILDINCROOT)/X11
  1820.          BUILDINCTOP = ..
  1821.               INCDIR = $(INCROOT)/X11
  1822.               ADMDIR = /usr/adm
  1823.               LIBDIR = /usr/users/staff/xtools/lib
  1824.            CONFIGDIR = $(LIBDIR)/config
  1825.           LINTLIBDIR = $(USRLIBDIR)/lint
  1826.  
  1827.           FONTDIR = $(LIBDIR)/fonts
  1828.          XINITDIR = $(LIBDIR)/xinit
  1829.            XDMDIR = $(LIBDIR)/xdm
  1830.            TWMDIR = $(LIBDIR)/twm
  1831.           MANPATH = /usr/users/staff/xtools/man
  1832.     MANSOURCEPATH = $(MANPATH)/man
  1833.         MANSUFFIX = n
  1834.      LIBMANSUFFIX = 3
  1835.            MANDIR = $(MANSOURCEPATH)$(MANSUFFIX)
  1836.         LIBMANDIR = $(MANSOURCEPATH)$(LIBMANSUFFIX)
  1837.            NLSDIR = $(LIBDIR)/nls
  1838.         PEXAPIDIR = $(LIBDIR)/PEX
  1839.       XAPPLOADDIR = /usr/users/staff/xtools/lib/app-defaults
  1840.        FONTCFLAGS = -t
  1841.  
  1842.      INSTAPPFLAGS = $(INSTDATFLAGS)
  1843.  
  1844.             IMAKE = imake
  1845.            DEPEND = makedepend
  1846.               RGB = rgb
  1847.  
  1848.             FONTC = bdftopcf
  1849.  
  1850.         MKFONTDIR = mkfontdir
  1851.         MKDIRHIER = /bin/sh $(BINDIR)/mkdirhier
  1852.  
  1853.         CONFIGSRC = $(TOP)/config
  1854.        DOCUTILSRC = $(TOP)/doc/util
  1855.         CLIENTSRC = $(TOP)/clients
  1856.           DEMOSRC = $(TOP)/demos
  1857.            LIBSRC = $(TOP)/lib
  1858.           FONTSRC = $(TOP)/fonts
  1859.        INCLUDESRC = $(TOP)/X11
  1860.         SERVERSRC = $(TOP)/server
  1861.           UTILSRC = $(TOP)/util
  1862.         SCRIPTSRC = $(UTILSRC)/scripts
  1863.        EXAMPLESRC = $(TOP)/examples
  1864.        CONTRIBSRC = $(TOP)/../contrib
  1865.            DOCSRC = $(TOP)/doc
  1866.            RGBSRC = $(TOP)/rgb
  1867.         DEPENDSRC = $(UTILSRC)/makedepend
  1868.          IMAKESRC = $(CONFIGSRC)
  1869.          XAUTHSRC = $(LIBSRC)/Xau
  1870.           XLIBSRC = $(LIBSRC)/X
  1871.            XMUSRC = $(LIBSRC)/Xmu
  1872.        TOOLKITSRC = $(LIBSRC)/Xt
  1873.        AWIDGETSRC = $(LIBSRC)/Xaw
  1874.        OLDXLIBSRC = $(LIBSRC)/oldX
  1875.       XDMCPLIBSRC = $(LIBSRC)/Xdmcp
  1876.       BDFTOSNFSRC = $(FONTSRC)/bdftosnf
  1877.       BDFTOSNFSRC = $(FONTSRC)/clients/bdftosnf
  1878.       BDFTOPCFSRC = $(FONTSRC)/clients/bdftopcf
  1879.      MKFONTDIRSRC = $(FONTSRC)/clients/mkfontdir
  1880.          FSLIBSRC = $(FONTSRC)/lib/fs
  1881.     FONTSERVERSRC = $(FONTSRC)/server
  1882.      EXTENSIONSRC = $(TOP)/extensions
  1883.          XILIBSRC = $(EXTENSIONSRC)/lib/xinput
  1884.       PHIGSLIBSRC = $(EXTENSIONSRC)/lib/PEX
  1885.  
  1886. # $XConsortium: sunLib.tmpl,v 1.14 91/12/20 11:19:05 rws Exp $
  1887.  
  1888. SHLIBLDFLAGS = -assert pure-text
  1889. PICFLAGS = -pic
  1890.  
  1891.   DEPEXTENSIONLIB =
  1892.      EXTENSIONLIB = -lXext
  1893.  
  1894.           DEPXLIB = $(DEPEXTENSIONLIB)
  1895.              XLIB = $(EXTENSIONLIB) -lX11
  1896.  
  1897.         DEPXMULIB = $(USRLIBDIR)/libXmu.sa.$(SOXMUREV)
  1898.        XMULIBONLY = -lXmu
  1899.            XMULIB = -lXmu
  1900.  
  1901.        DEPOLDXLIB =
  1902.           OLDXLIB = -loldX
  1903.  
  1904.       DEPXTOOLLIB = $(USRLIBDIR)/libXt.sa.$(SOXTREV)
  1905.          XTOOLLIB = -lXt
  1906.  
  1907.         DEPXAWLIB = $(USRLIBDIR)/libXaw.sa.$(SOXAWREV)
  1908.            XAWLIB = -lXaw
  1909.  
  1910.         DEPXILIB =
  1911.            XILIB = -lXi
  1912.  
  1913.         SOXLIBREV = 4.10
  1914.           SOXTREV = 4.10
  1915.          SOXAWREV = 5.0
  1916.         SOOLDXREV = 4.10
  1917.          SOXMUREV = 4.10
  1918.         SOXEXTREV = 4.10
  1919.       SOXINPUTREV = 4.10
  1920.  
  1921.       DEPXAUTHLIB = $(USRLIBDIR)/libXau.a
  1922.          XAUTHLIB =  -lXau
  1923.       DEPXDMCPLIB = $(USRLIBDIR)/libXdmcp.a
  1924.          XDMCPLIB =  -lXdmcp
  1925.  
  1926.         DEPPHIGSLIB = $(USRLIBDIR)/libphigs.a
  1927.            PHIGSLIB =  -lphigs
  1928.  
  1929.        DEPXBSDLIB = $(USRLIBDIR)/libXbsd.a
  1930.           XBSDLIB =  -lXbsd
  1931.  
  1932.  LINTEXTENSIONLIB = $(LINTLIBDIR)/llib-lXext.ln
  1933.          LINTXLIB = $(LINTLIBDIR)/llib-lX11.ln
  1934.           LINTXMU = $(LINTLIBDIR)/llib-lXmu.ln
  1935.         LINTXTOOL = $(LINTLIBDIR)/llib-lXt.ln
  1936.           LINTXAW = $(LINTLIBDIR)/llib-lXaw.ln
  1937.            LINTXI = $(LINTLIBDIR)/llib-lXi.ln
  1938.         LINTPHIGS = $(LINTLIBDIR)/llib-lphigs.ln
  1939.  
  1940.           DEPLIBS = $(DEPXAWLIB) $(DEPXMULIB) $(DEPXTOOLLIB) $(DEPXLIB)
  1941.  
  1942.          DEPLIBS1 = $(DEPLIBS)
  1943.          DEPLIBS2 = $(DEPLIBS)
  1944.          DEPLIBS3 = $(DEPLIBS)
  1945.  
  1946. # -------------------------------------------------------------------------
  1947. # Imake rules for building libraries, programs, scripts, and data files
  1948. # rules:  $XConsortium: Imake.rules,v 1.123 91/09/16 20:12:16 rws Exp $
  1949.  
  1950. # -------------------------------------------------------------------------
  1951. # start of Imakefile
  1952.  
  1953. LOCAL_LIBRARIES = $(XAWLIB) $(XTOOLLIB) $(XMULIB) $(XLIB)
  1954.  
  1955. OBJS=        main.o Goban.o amigo.o goplayer.o goplayutils.o \
  1956.         killable.o xinterface.o menus.o
  1957. SRCS=        $(OBJS:%.o=%.c)
  1958.  
  1959.  PROGRAM = xamigo
  1960.  
  1961. all:: xamigo
  1962.  
  1963. xamigo: $(OBJS) $(DEPLIBS)
  1964.     $(RM) $@
  1965.     $(CC) -o $@ $(OBJS) $(LDOPTIONS) $(LOCAL_LIBRARIES) $(LDLIBS) $(EXTRA_LOAD_FLAGS)
  1966.  
  1967. saber_xamigo:: $(SRCS)
  1968.     # load $(ALLDEFINES) $(SRCS) $(LOCAL_LIBRARIES) $(SYS_LIBRARIES) $(EXTRA_LIBRARIES)
  1969.  
  1970. osaber_xamigo:: $(OBJS)
  1971.     # load $(ALLDEFINES) $(OBJS) $(LOCAL_LIBRARIES) $(SYS_LIBRARIES) $(EXTRA_LIBRARIES)
  1972.  
  1973. install:: xamigo
  1974.     @if [ -d $(DESTDIR)$(BINDIR) ]; then set +x; \
  1975.     else (set -x; $(MKDIRHIER) $(DESTDIR)$(BINDIR)); fi
  1976.     $(INSTALL) -c $(INSTPGMFLAGS)  xamigo $(DESTDIR)$(BINDIR)
  1977.  
  1978. install.man:: xamigo.man
  1979.     @if [ -d $(DESTDIR)$(MANDIR) ]; then set +x; \
  1980.     else (set -x; $(MKDIRHIER) $(DESTDIR)$(MANDIR)); fi
  1981.     $(INSTALL) -c $(INSTMANFLAGS) xamigo.man $(DESTDIR)$(MANDIR)/xamigo.$(MANSUFFIX)
  1982.  
  1983. depend::
  1984.     $(DEPEND) $(DEPENDFLAGS) -s "# DO NOT DELETE" -- $(ALLDEFINES) -- $(SRCS)
  1985.  
  1986. lint:
  1987.     $(LINT) $(LINTFLAGS) $(SRCS) $(LINTLIBS)
  1988. lint1:
  1989.     $(LINT) $(LINTFLAGS) $(FILE) $(LINTLIBS)
  1990.  
  1991. clean::
  1992.     $(RM) $(PROGRAM)
  1993.  
  1994. install:: Xamigo.ad
  1995.     @if [ -d $(DESTDIR)$(XAPPLOADDIR) ]; then set +x; \
  1996.     else (set -x; $(MKDIRHIER) $(DESTDIR)$(XAPPLOADDIR)); fi
  1997.     $(INSTALL) -c $(INSTAPPFLAGS) Xamigo.ad $(DESTDIR)$(XAPPLOADDIR)/Xamigo
  1998.  
  1999. # -------------------------------------------------------------------------
  2000. # common rules for all Makefiles - do not edit
  2001.  
  2002. emptyrule::
  2003.  
  2004. clean::
  2005.     $(RM_CMD) "#"*
  2006.  
  2007. Makefile::
  2008.     -@if [ -f Makefile ]; then set -x; \
  2009.     $(RM) Makefile.bak; $(MV) Makefile Makefile.bak; \
  2010.     else exit 0; fi
  2011.     $(IMAKE_CMD) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT_DIR)
  2012.  
  2013. tags::
  2014.     $(TAGS) -w *.[ch]
  2015.     $(TAGS) -xw *.[ch] > TAGS
  2016.  
  2017. saber:
  2018.     # load $(ALLDEFINES) $(SRCS)
  2019.  
  2020. osaber:
  2021.     # load $(ALLDEFINES) $(OBJS)
  2022.  
  2023. # -------------------------------------------------------------------------
  2024. # empty rules for directories that do not have SUBDIRS - do not edit
  2025.  
  2026. install::
  2027.     @echo "install in $(CURRENT_DIR) done"
  2028.  
  2029. install.man::
  2030.     @echo "install.man in $(CURRENT_DIR) done"
  2031.  
  2032. Makefiles::
  2033.  
  2034. includes::
  2035.  
  2036. # -------------------------------------------------------------------------
  2037. # dependencies generated by makedepend
  2038.  
  2039. SHAR_EOF
  2040. fi
  2041. if test -f 'Makefile.hand'
  2042. then
  2043.     echo shar: "will not over-write existing file 'Makefile.hand'"
  2044. else
  2045. cat << \SHAR_EOF > 'Makefile.hand'
  2046. #
  2047. # Example makefile for xamigo
  2048. #
  2049.  
  2050. CFLAGS=        -O
  2051. LIBS=        -lXaw -lXt -lXmu -lXext -lX11 -lm
  2052. TARGET=        xamigo
  2053. OBJS=        main.o Goban.o amigo.o goplayer.o goplayutils.o \
  2054.         killable.o xinterface.o menus.o
  2055.  
  2056. $(TARGET): $(OBJS) Makefile
  2057.     cc -o $(TARGET) $(OBJS) $(LIBS)
  2058.  
  2059. clean:
  2060.     /bin/rm -f $(OBJS) $(TARGET)
  2061.  
  2062.  
  2063. main.o:        Goban.h xamigo.h amigo.h
  2064.  
  2065. Goban.o:    GobanP.h Goban.h
  2066.  
  2067. amigo.o:    go.h amigo.h
  2068.  
  2069. goplayer.o:    go.h amigo.h goplayutils.h
  2070.  
  2071. goplayutils.o:    goplayutils.h amigo.h go.h
  2072.  
  2073. killable.o:    go.h amigo.h goplayutils.h
  2074.  
  2075. xinterface.o:    Goban.h amigo.h
  2076.  
  2077. menus.o:    xamigo.h
  2078. SHAR_EOF
  2079. fi
  2080. if test -f 'README'
  2081. then
  2082.     echo shar: "will not over-write existing file 'README'"
  2083. else
  2084. cat << \SHAR_EOF > 'README'
  2085.  
  2086.             Xamigo 1.1
  2087.  
  2088. This is an alpha release of xamigo --- a port (read: quick hack) of the
  2089. Amiga Go program AmiGo.  I don't have time to get it real nice now,
  2090. but will spend some more time on it when my thesis is out of the way.
  2091. Sadly this is the second time I've said that :-)
  2092.  
  2093. The `readme' from the original distribution is included as README.AMIGO
  2094.  
  2095. An Imakefile is included, so you should be able to type
  2096.     xmkmf
  2097.     make
  2098. to build xamigo.  Let me know if you have problems with the Imakefile,
  2099. preferably with fixes :-)
  2100.  
  2101. You *have* to install the app-defaults file (Xamigo.ad) before you use
  2102. xamigo.  This should either go in /usr/lib/X11/app-defaults,
  2103. or in your own app-defaults directory, as file Xamigo (ie lose the '.ad')
  2104. If you do the latter, you have to:
  2105.     setenv XAPPLRESDIR <full path of your app-defaults directory>
  2106.  
  2107. Feel free to mail me any comments and suggestions for improvements.
  2108.  
  2109. Neil
  2110. neilb@scs.leeds.ac.uk
  2111. SHAR_EOF
  2112. fi
  2113. if test -f 'README.AMIGO'
  2114. then
  2115.     echo shar: "will not over-write existing file 'README.AMIGO'"
  2116. else
  2117. cat << \SHAR_EOF > 'README.AMIGO'
  2118.     This is version 1.0 of AmiGo --- a Go board and player for the Amiga.
  2119. The Amiga interface and board manager were written by Todd R. Johnson.
  2120. The player is a C port of a Pascal player written by Stoney Ballard.
  2121. The interface allows you to play human vs. human, human vs. Amiga, or
  2122. Amiga vs. Amiga.
  2123.  
  2124.     The board manager and player could both use some work.  Currently,
  2125. you cannot save/load games, take back a move, or automatically score a
  2126. game.  It is also limited to a 19 by 19 board.  I'm releasing AmiGo
  2127. now because 1) I'm in the final phases of my dissertation and probably
  2128. won't have much time to do any further work on AmiGo, and 2) a lot of
  2129. people have been asking for an Amiga Go player.  I am also releasing
  2130. all of the source code so that others can add to and modify AmiGo.
  2131. Note that all of my code in this release is public domain, while the
  2132. ported go player retains the original copyright. 
  2133.  
  2134.     If you distribute AmiGo, I urge you to include the source
  2135. code.  If anyone makes changes, I would appreciate a copy.  In fact, I
  2136. am willing to act as a clearinghouse for AmiGo changes.
  2137.  
  2138. Todd R. Johnson
  2139. tj@cis.ohio-state.edu
  2140. 8/8/89
  2141.  
  2142. Here is the message attached to the original USENET posting of Stoney
  2143. Ballard's Pascal code.  Note that the board manager mentioned here is
  2144. not included in this distribution.
  2145.  
  2146. This go board manager and rudimentary go player was written by
  2147. Stoney Ballard at Perq Systems in 1983-1984.  It is written in
  2148. Perq Pascal and utilizes some Perq libraries for I/O.  The code
  2149. is offered here if someone is interested to convert it to Unix.
  2150.  
  2151. The wonderful part about it is that a game is recorded as a tree
  2152. and can be played forward or backward, branching at any point
  2153. where there were alternate moves.
  2154.  
  2155. For some time, this program was also used to generate the go
  2156. boards displayed in the American Go Journal.  For this it used
  2157. some large font digits which are now lost.
  2158.  
  2159. Fred Hansen
  2160. SHAR_EOF
  2161. fi
  2162. if test -f 'TODO'
  2163. then
  2164.     echo shar: "will not over-write existing file 'TODO'"
  2165. else
  2166. cat << \SHAR_EOF > 'TODO'
  2167.  
  2168. There are lots of things which need adding/improving.
  2169.  
  2170.     o    smaller board sizes (only supports 19x19 right now)
  2171.  
  2172.     o    take back last move
  2173.  
  2174.     o    log the game/save position
  2175.  
  2176.     o    tidy up the code & include files
  2177.  
  2178.     o    stopwatch cursor when it is AmiGo's turn?
  2179.  
  2180. If you have any additions to this list, please mail them to me!
  2181.  
  2182. Neil
  2183. neilb@scs.leeds.ac.uk
  2184. SHAR_EOF
  2185. fi
  2186. if test -f 'Xamigo.ad'
  2187. then
  2188.     echo shar: "will not over-write existing file 'Xamigo.ad'"
  2189. else
  2190. cat << \SHAR_EOF > 'Xamigo.ad'
  2191. !
  2192. ! Application defaults file for xamigo 1.1
  2193. !
  2194. Xamigo.title:                    Xamigo v1.1
  2195.  
  2196. Xamigo.form.background:                burlywood4
  2197. Xamigo.form.buttonBox.background:        burlywood4
  2198. Xamigo.form.buttonBox.borderWidth:        0
  2199.  
  2200. Xamigo.form.buttonBox.orientation:        horizontal
  2201. Xamigo.form.buttonBox.MenuButton.leftBitmap:    menu12
  2202. Xamigo.form.buttonBox.gameButton.label:        Game
  2203. Xamigo.form.buttonBox.infoButton.label:        Info
  2204. Xamigo.form.buttonBox.moveButton.label:        Move
  2205. Xamigo.form.buttonBox.MenuButton.shapeStyle:    oval
  2206. Xamigo.form.buttonBox.top:            chainTop
  2207. Xamigo.form.buttonBox.bottom:            chainTop
  2208. Xamigo.form.buttonBox.left:            chainLeft
  2209. Xamigo.form.buttonBox.right:            chainLeft
  2210.  
  2211. Xamigo*statsPopup.title:            Game Statistics
  2212. Xamigo*statsPopup.allowResize:            TRUE
  2213. Xamigo*statForm.background:            tan
  2214. Xamigo*statForm*resizable:            TRUE
  2215.  
  2216. Xamigo*statForm*background:            tan
  2217. Xamigo*statForm.borderWidth:            0
  2218. Xamigo*statForm.resizable:            TRUE
  2219.  
  2220. Xamigo*statForm*Label.background:        tan
  2221. Xamigo*statForm*Label.borderWidth:        0
  2222. Xamigo*blackStatForm.borderWidth:        1
  2223. Xamigo*blackStatForm.borderColor:        brown
  2224. Xamigo*whiteStatForm.borderWidth:        1
  2225. Xamigo*whiteStatForm.borderColor:        brown
  2226. Xamigo*blackStatForm.playerLabel.label:        black
  2227. Xamigo*whiteStatForm.playerLabel.label:        white
  2228. Xamigo*blackStatForm.playerScore.label:        0
  2229. Xamigo*whiteStatForm.playerScore.label:        0
  2230.  
  2231. Xamigo*scoreLabel.fromHoriz:            playerLabel
  2232. Xamigo*scoreLabel.horizDistance:        20
  2233. Xamigo*scoreLabel.label:            Captures  :
  2234. Xamigo*playerScore.foreground:            maroon
  2235. Xamigo*playerScore.fromHoriz:            scoreLabel
  2236. Xamigo*playerScore.horizDistance:        10
  2237.  
  2238. Xamigo*lastMoveLabel.fromHoriz:            playerLabel
  2239. Xamigo*lastMoveLabel.horizDistance:        20
  2240. Xamigo*lastMoveLabel.fromVert:            playerScore
  2241. Xamigo*lastMoveLabel.label:            Last Move :
  2242. Xamigo*lastMove.fromHoriz:            lastMoveLabel
  2243. Xamigo*lastMove.horizDistance:            10
  2244. Xamigo*lastMove.foreground:            sea green
  2245. Xamigo*lastMove.fromVert:            playerScore
  2246. Xamigo*lastMove.label:                \ \ \ \ \ \ 
  2247.  
  2248. Xamigo*whiteStatForm.fromHoriz:            blackStatForm
  2249.  
  2250. Xamigo*messageWindow.fromVert:            blackStatForm
  2251. Xamigo*messageWindow.borderWidth:        1
  2252. Xamigo*messageWindow.borderColor:        brown
  2253. Xamigo*messageWindow.width:            400
  2254. Xamigo*messageWindow.height:            70
  2255. Xamigo*messageWindow.displayCaret:        FALSE
  2256. Xamigo*messageWindow.scrollVertical:        whenNeeded
  2257. Xamigo*messageWindow*font:            6x13
  2258. Xamigo*messageWindow*wrap:            word
  2259.  
  2260. Xamigo*statDone.fromVert:            messageWindow
  2261. Xamigo*statDone.fromHoriz:            blackStatForm
  2262. Xamigo*statDone.label:                Done
  2263. Xamigo*statDone.shapeStyle:            oval
  2264.  
  2265. Xamigo.form.goban.width:            400
  2266. Xamigo.form.goban.height:            400
  2267. Xamigo.form.goban.fromVert:            buttonBox
  2268. Xamigo.form.goban.vertDistance:            10
  2269. Xamigo.form.goban.top:                chainTop
  2270. Xamigo.form.goban.bottom:            chainBottom
  2271. Xamigo.form.goban.left:                chainLeft
  2272. Xamigo.form.goban.right:            chainRight
  2273. Xamigo.form.goban.background:            tan
  2274. Xamigo.form.goban.translations:            #augment \
  2275.                         <BtnDown> : inputStone()\n\
  2276.                         <Key>P : pass()\n\
  2277.                         <Key>p : pass()
  2278.  
  2279. Xamigo*SmeBSB.leftMargin:            16
  2280. Xamigo*SmeBSB.rightMargin:            16
  2281. Xamigo*SmeBSB.vertMargin:            30
  2282.  
  2283. Xamigo*gameMenu.newGame.label:            New Game
  2284. Xamigo*gameMenu.stats.label:            Game Stats
  2285. Xamigo*gameMenu.about.label:            About...
  2286. Xamigo*gameMenu.quit.label:            Quit
  2287.  
  2288. Xamigo*gameMenu.aWhite.label:            Amigo Plays White
  2289. Xamigo*gameMenu.aBlack.label:            Amigo Plays Black
  2290. Xamigo*gameMenu.group.label:            Group Info
  2291. Xamigo*gameMenu.reason.label:            Move Reason
  2292. Xamigo*gameMenu.lookahead.label:        Show Lookahead
  2293. Xamigo*gameMenu*leftMargin:            24
  2294.  
  2295. Xamigo*levelMenu.level1.label:            1
  2296. Xamigo*levelMenu.level2.label:            2
  2297. Xamigo*levelMenu.level3.label:            3
  2298. Xamigo*levelMenu.level4.label:            4
  2299. Xamigo*levelMenu.level5.label:            5
  2300. Xamigo*levelMenu.level6.label:            6
  2301. Xamigo*levelMenu.level7.label:            7
  2302. Xamigo*levelMenu.leftMargin:            24
  2303. Xamigo*levelButton.label:            Level
  2304.  
  2305. Xamigo*moveMenu.pass.label:            Pass
  2306. Xamigo*moveMenu.takeback.label:            Take Back Move
  2307. Xamigo*moveMenu.resign.label:            Resign
  2308.  
  2309. Xamigo*handicapButton.label:            Handicap
  2310. Xamigo*handicapMenu*leftMargin:            24
  2311. Xamigo*handicapMenu.handicap0.label:        0
  2312. Xamigo*handicapMenu.handicap2.label:        2
  2313. Xamigo*handicapMenu.handicap3.label:        3
  2314. Xamigo*handicapMenu.handicap4.label:        4
  2315. Xamigo*handicapMenu.handicap5.label:        5
  2316. Xamigo*handicapMenu.handicap6.label:        6
  2317. Xamigo*handicapMenu.handicap7.label:        7
  2318. Xamigo*handicapMenu.handicap8.label:        8
  2319. Xamigo*handicapMenu.handicap9.label:        9
  2320. SHAR_EOF
  2321. fi
  2322. if test -f 'amigo.c'
  2323. then
  2324.     echo shar: "will not over-write existing file 'amigo.c'"
  2325. else
  2326. cat << \SHAR_EOF > 'amigo.c'
  2327. /* Go started 4/17/88 by Todd R. Johnson */
  2328. /* 8/8/89 cleaned up for first release */
  2329. /* Public Domain */
  2330.  
  2331. #include <X11/Intrinsic.h>
  2332. #include <X11/StringDefs.h>
  2333. #include "go.h"
  2334. #include "amigo.h"
  2335.  
  2336.  
  2337. extern char    *playReason;
  2338. extern short    playLevel, showTrees;
  2339. extern Widget    message;
  2340.  
  2341. struct bRec    goboard[19][19];    /*-- The main go board        --*/
  2342.  
  2343. struct Group    GroupList[MAXGROUPS];    /*-- The list of Groups        --*/
  2344. short        DeletedGroups[4];    /*-- Codes of deleted groups    --*/
  2345.  
  2346. short        GroupCount = 0;        /*-- The total number of groups    --*/
  2347. short        DeletedGroupCount;    /*-- The total number of groups    --*/
  2348.                     /*-- deleted on a move        --*/
  2349. short        ko, koX, koY;
  2350. short        blackTerritory,whiteTerritory;
  2351. short        blackPrisoners, whitePrisoners;
  2352. short        showMoveReason    = FALSE,
  2353.         groupInfo    = FALSE,
  2354.         whitePassed    = FALSE,
  2355.         blackPassed    = FALSE;
  2356.  
  2357.  
  2358. /* Arrays for use when checking around a point */
  2359. short        xVec[4] = {0, 1, 0, -1};
  2360. short        yVec[4] = {-1, 0, 1, 0};
  2361.  
  2362. short
  2363. member(group, grouplist, cnt)
  2364.     short        group;
  2365.     short        grouplist[4];
  2366.     short        cnt;
  2367. {
  2368.     unsigned short    i;
  2369.  
  2370.  
  2371.     for (i = 0; i < cnt; i++)
  2372.         if (grouplist[i] == group)
  2373.             return TRUE;
  2374.     return FALSE;
  2375. }
  2376.  
  2377. /* Does a stone at x, y connect to any groups of color? */
  2378. short
  2379. Connect( color, x, y, fGroups, fCnt, eGroups, eCnt)
  2380.     enum bVal    color;
  2381.     short        x, y;
  2382.     short        fGroups[4], eGroups[4];
  2383.     short        *fCnt, *eCnt;
  2384. {
  2385.     unsigned short    point = 0;
  2386.     short        tx, ty, total = 0;
  2387.     enum bVal    opcolor = WHITE;
  2388.  
  2389.  
  2390.     *fCnt = 0;
  2391.     *eCnt = 0;
  2392.     if (color == WHITE)
  2393.         opcolor = BLACK;
  2394.     for (point = 0; point <= 3; point++ )  
  2395.     {
  2396.         tx = x + xVec[point];
  2397.         ty = y + yVec[point];
  2398.         if (!LegalPoint(tx,ty))
  2399.             continue;
  2400.         if (goboard[tx][ty].Val == color)
  2401.         {
  2402.             total++;
  2403.             if (!member(goboard[tx][ty].GroupNum, fGroups, *fCnt))
  2404.                 fGroups[(*fCnt)++] = goboard[tx][ty].GroupNum;
  2405.         }
  2406.         else if (goboard[tx][ty].Val == opcolor)
  2407.         {
  2408.             total++;
  2409.             if (!member(goboard[tx][ty].GroupNum, eGroups, *eCnt))
  2410.                 eGroups[(*eCnt)++] = goboard[tx][ty].GroupNum;
  2411.         }
  2412.     }
  2413.     return total;
  2414. }
  2415.  
  2416. /* Returns the maximum number of liberties for a given intersection */
  2417. short
  2418. Maxlibs(x, y)
  2419.     short    x, y;
  2420. {
  2421.     short    cnt = 4;
  2422.  
  2423.  
  2424.     if (x == 0 || x == 18)
  2425.         cnt--;
  2426.     if (y == 0 || y == 18)
  2427.         cnt--;
  2428.     return cnt;
  2429. }
  2430.  
  2431. DeleteGroupFromStone(x,y)
  2432.     short    x,y;
  2433. {
  2434.     if (goboard[x][y].Val != EMPTY)
  2435.         GroupCapture(goboard[x][y].GroupNum);
  2436. }
  2437.  
  2438. /* Determine whether x, y is suicide for color */
  2439. short
  2440. Suicide(color, x, y)
  2441.     enum bVal    color;
  2442.     short        x, y;
  2443. {
  2444.     enum bVal    opcolor = BLACK;
  2445.     short        friendlycnt, friendlygroups[4],
  2446.             enemycnt, enemygroups[4],
  2447.             total;
  2448.     short        maxlibs, i, libcnt = 0;
  2449.  
  2450.  
  2451.     if (color == BLACK)
  2452.         opcolor = WHITE;
  2453.     maxlibs = Maxlibs( x, y);
  2454.     total = Connect(color, x, y, friendlygroups, &friendlycnt,
  2455.                     enemygroups, &enemycnt);
  2456.  
  2457.     if (total < maxlibs)
  2458.         return FALSE;
  2459.  
  2460.     /* Check for a capture */
  2461.     for (i = 0; i < enemycnt; i++)
  2462.         if (GroupList[enemygroups[i]].liberties == 1)
  2463.             return FALSE;
  2464.     for (i = 0; i < friendlycnt; i++)
  2465.         libcnt += (GroupList[friendlygroups[i]].liberties - 1);
  2466.     if (libcnt != 0)
  2467.         return FALSE;
  2468.     return TRUE;
  2469. }
  2470.    
  2471. /* Returns the number of liberties for x, y */
  2472. short
  2473. StoneLibs(x, y)
  2474.     short        x, y;
  2475. {
  2476.     short        cnt = 0, tx, ty;
  2477.     unsigned short    point;
  2478.  
  2479.  
  2480.     for (point = 0; point <= 3; point++)
  2481.     {
  2482.         tx = x + xVec[point];
  2483.         ty = y + yVec[point];
  2484.         if (LegalPoint(tx,ty) && goboard[tx][ty].Val == EMPTY)
  2485.             cnt++;
  2486.     }
  2487.     return cnt;
  2488. }
  2489.    
  2490. void
  2491. EraseMarks()
  2492. {
  2493.     register short        i;
  2494.     register struct bRec    *gpt    = &goboard[0][0];
  2495.  
  2496.  
  2497.     for (i=0; i<361; gpt++,i++)
  2498.             gpt->marked = FALSE;
  2499. }
  2500.  
  2501. /* Place a stone of color at x, y */
  2502. short
  2503. GoPlaceStone(color, x, y)
  2504.     enum bVal    color;
  2505.     short        x, y;
  2506. {
  2507.     short    fgroups[4], egroups[4];    /* group codes surrounding stone */
  2508.     short    fcnt, ecnt, i;
  2509.     short    lowest = GroupCount + 1;
  2510.  
  2511.  
  2512.     DeletedGroupCount = 0;
  2513.     if (goboard[x][y].Val != EMPTY || Suicide(color,x,y))
  2514.         return FALSE;
  2515.  
  2516.     if (ko && koX == x && koY == y)
  2517.         return FALSE;
  2518.  
  2519.     ko = FALSE;
  2520.     placestone(color, x, y);
  2521.     goboard[x][y].Val = color;
  2522.     /* Does the new stone connect to any friendly stone(s)? */
  2523.     Connect(color, x, y, fgroups, &fcnt, egroups, &ecnt);
  2524.     if (fcnt)
  2525.     {
  2526.         /* Find the connecting friendly group with the lowest code */
  2527.         for (i = 0; i < fcnt; i++)
  2528.             if (fgroups[i] <= lowest)
  2529.                 lowest = fgroups[i];
  2530.         /*-- Renumber resulting group --*/
  2531.         /*-- Raise the stone count of the lowest by one to account --*/
  2532.         /*-- for new stone --*/
  2533.         goboard[x][y].GroupNum = lowest;
  2534.         GroupList[lowest].count++;
  2535.         for (i = 0; i < fcnt; i++)
  2536.             if (fgroups[i] != lowest)
  2537.                 MergeGroups(lowest, fgroups[i]);
  2538.         /* Fix the liberties of the resulting group */
  2539.         CountLiberties(lowest);
  2540.     }
  2541.     else
  2542.     {
  2543.         /* Isolated stone.  Create new group. */
  2544.         GroupCount++;
  2545.         lowest = GroupCount;
  2546.         GroupList[lowest].color = color;
  2547.         GroupList[lowest].count = 1;
  2548.         GroupList[lowest].internal = 0;
  2549.         GroupList[lowest].external = StoneLibs( x, y);
  2550.         GroupList[lowest].liberties = GroupList[lowest].external;
  2551.         GroupList[lowest].eyes = 0;
  2552.         GroupList[lowest].alive = 0;
  2553.         GroupList[lowest].territory = 0;
  2554.         goboard[x][y].GroupNum = lowest;
  2555.     }
  2556.     /* Now fix the liberties of enemy groups adjacent to played stone */
  2557.     FixLibs(color, x, y, PLACED);  /* Fix the liberties of opcolor */
  2558.     ReEvalGroups(color, x, y, lowest);
  2559.     RelabelGroups();
  2560.     return TRUE;
  2561. }
  2562.  
  2563. /* Remove a stone from the board */
  2564. void
  2565. GoRemoveStone(x, y)
  2566.     short    x, y;
  2567. {
  2568.     goboard[x][y].Val = EMPTY;
  2569.     goboard[x][y].GroupNum = 0;
  2570.     removestone( x, y);
  2571. }
  2572.  
  2573. /* Merges two groups -- Renumbers stones and deletes second group from
  2574. list.  Fixes stone count of groups.  This does not fix anything else. 
  2575. FixLibs must be called to fix liberties, etc. */
  2576. void
  2577. MergeGroups(g1, g2)
  2578.     short    g1, g2;
  2579. {
  2580.     short    x, y;
  2581.  
  2582.  
  2583.     ForeachPoint(y,x)
  2584.         if (goboard[x][y].GroupNum == g2)
  2585.             goboard[x][y].GroupNum = g1;
  2586.     GroupList[g1].count += GroupList[g2].count;
  2587.     DeleteGroup( g2 );  /* Removes group from GroupList */
  2588. }
  2589.  
  2590. /* Stores a group code to be deleted */
  2591. void
  2592. DeleteGroup(code)
  2593.     short    code;
  2594. {
  2595.     DeletedGroups[DeletedGroupCount++] = code;
  2596. }
  2597.  
  2598. /* Re-evaluate the groups given the last move.  This assumes that the
  2599. last move has been merged into adjoining groups and all liberty counts
  2600. are correct.  Handles capture. Checks for Ko.  Keeps track of captured
  2601. stones. code is the group number of the stone just played. */
  2602. void
  2603. ReEvalGroups(color, x, y, code)
  2604.     enum bVal    color;
  2605.     short        x, y, code;
  2606. {
  2607.     short        fgroups[4], egroups[4],
  2608.             fcnt, ecnt, i, killcnt = 0, count = 0;
  2609.     enum bVal    opcolor = BLACK;
  2610.  
  2611.     if (color == BLACK)
  2612.         opcolor = WHITE;
  2613.     /* Check for capture */
  2614.     Connect( color, x, y, fgroups, &fcnt, egroups, &ecnt);
  2615.     if (ecnt)
  2616.     {
  2617.         /* See if any of the groups have no liberties */
  2618.         for (i = 0; i < ecnt; i++)
  2619.             if (GroupList[egroups[i]].liberties == 0)
  2620.             {
  2621.                 killcnt++;
  2622.                 count = GroupList[egroups[i]].count;
  2623.                 GroupCapture( egroups[i]);
  2624.             }
  2625.     }
  2626.     /* Check for ko.  koX and koY are set in GroupCapture above. */
  2627.     if (killcnt == 1 && count == 1 && GroupList[ code  ].count == 1
  2628.                 && GroupList[ code ].liberties == 1)
  2629.     {
  2630.         ko = TRUE;
  2631.     }
  2632.     if (killcnt)
  2633.         intrPrisonerReport( blackPrisoners, whitePrisoners);
  2634.     /* Set eye count for groups */
  2635.     CountEyes();
  2636. }
  2637.  
  2638. /* Remove a captured group from the board and fix the liberties of any
  2639.    adjacent groups.  Fixes prisoner count. Sets KoX and KoY */
  2640. /*-- update display of captured stones -neilb --*/
  2641. void
  2642. GroupCapture(code)
  2643.     short    code;
  2644. {
  2645.     short    x, y;
  2646.  
  2647.     if (GroupList[code].color == BLACK)
  2648.         blackPrisoners += GroupList[code].count;
  2649.     else
  2650.         whitePrisoners += GroupList[code].count;
  2651.     intrPrisonerReport(blackPrisoners, whitePrisoners);
  2652.     ForeachPoint(y,x)
  2653.         if (goboard[x][y].GroupNum == code)
  2654.         {
  2655.             FixLibs(GroupList[code].color,x,y,REMOVED);
  2656.             GoRemoveStone(x, y);
  2657.             koX = x;
  2658.             koY = y;
  2659.         }
  2660.     DeleteGroup( code);
  2661. }
  2662.  
  2663. /* Fix the liberties of groups adjacent to x, y.  move indicates
  2664.   whether a stone of color was placed or removed at x, y
  2665.   This does not change liberty counts of friendly groups when a stone
  2666.   is placed.  Does not do captures. */
  2667. void
  2668. FixLibs( color, x, y, move)
  2669.     enum    bVal color;
  2670.     short    x, y, move;
  2671. {
  2672.     short    fgroups[4], fcnt, egroups[4], ecnt, i;
  2673.     enum    bVal opcolor = BLACK;
  2674.  
  2675.     if (color == BLACK)
  2676.         opcolor = WHITE;
  2677.     Connect( color, x, y, fgroups, &fcnt, egroups, &ecnt);
  2678.     if (move == PLACED)
  2679.         for (i = 0; i < ecnt; i++)
  2680.             GroupList[egroups[i]].liberties--;
  2681.     else /* Stone removed so increment opcolor */
  2682.         for (i = 0; i < ecnt; i++)
  2683.             GroupList[egroups[i]].liberties++;
  2684. }
  2685.  
  2686. void
  2687. goSetHandicap(handicap)
  2688. {
  2689.     if (handicap < 2)
  2690.         return;
  2691.  
  2692.     GoPlaceStone(BLACK,3,3);
  2693.     GoPlaceStone(BLACK,15,15);
  2694.  
  2695.     if (handicap >= 3)
  2696.         GoPlaceStone(BLACK,15,3);
  2697.     if (handicap >= 4)
  2698.         GoPlaceStone(BLACK,3,15);
  2699.     if (handicap == 5 || handicap == 7 || handicap == 9)
  2700.         GoPlaceStone(BLACK,9,9);
  2701.     if (handicap >= 6)
  2702.     {
  2703.         GoPlaceStone(BLACK,15,9);
  2704.         GoPlaceStone(BLACK,3,9);
  2705.     }
  2706.     if (handicap >= 8)
  2707.     {
  2708.         GoPlaceStone(BLACK,9,15);
  2709.         GoPlaceStone(BLACK,9,3);
  2710.     }
  2711. }
  2712.  
  2713. void
  2714. goRestart(handicap)
  2715.     int    handicap;
  2716. {
  2717.     register short        i;
  2718.     register struct bRec    *gpt    = &goboard[0][0];
  2719.  
  2720.  
  2721.     GroupCount = 0;
  2722.     ko = FALSE;
  2723.     blackPrisoners = whitePrisoners = 0;
  2724.     intrPrisonerReport(0, 0);
  2725.     for (i=0; i<361; gpt++,i++)
  2726.     {
  2727.         gpt->Val = EMPTY;
  2728.         gpt->GroupNum = 0;
  2729.     }
  2730.     goSetHandicap(handicap);
  2731. }
  2732.  
  2733.  
  2734. /* if any groups have been deleted as a result of the last move, this
  2735.    routine will delete the old group numbers from GroupList and
  2736.    reassign group numbers. */
  2737. void
  2738. RelabelGroups()
  2739. {
  2740.     unsigned    short i, j, x, y;
  2741.  
  2742.     for (i = 0; i < DeletedGroupCount; i++)
  2743.     {
  2744.         /* Relabel all higher groups */
  2745.         ForeachPoint(y,x)
  2746.             if (goboard[x][y].GroupNum > DeletedGroups[i])
  2747.                 goboard[x][y].GroupNum--;
  2748.         /* Move the groups down */
  2749.         for (y = DeletedGroups[i]; y < GroupCount; y++)
  2750.             GroupList[y] = GroupList[y+1];
  2751.         /* fix the group numbers stored in the deleted list */
  2752.         for (j = i+1; j < DeletedGroupCount; j++)
  2753.             if (DeletedGroups[j] > DeletedGroups[i])
  2754.                 DeletedGroups[j]--;
  2755.         GroupCount--;
  2756.     }
  2757. }
  2758.  
  2759. /* Returns liberty count for x, y intersection.  Sets marked to true
  2760.    for each liberty */
  2761. short
  2762. CountAndMarkLibs( x, y)
  2763.     short    x, y;
  2764. {
  2765.     short    tx,ty,i;
  2766.     short    cnt = 0;
  2767.  
  2768.  
  2769.     for (i=0;i<4;i++)
  2770.     {
  2771.                 tx = x + xVec[i];
  2772.                 ty = y + yVec[i];
  2773.                 if (LegalPoint(tx,ty) && goboard[tx][ty].Val == EMPTY
  2774.                     && goboard[tx][ty].marked == FALSE)
  2775.         {
  2776.             cnt++;
  2777.             goboard[tx][ty].marked = TRUE;
  2778.         }
  2779.     }
  2780.     return cnt;
  2781. }
  2782.  
  2783. /* Determine the number of liberties for a group given the group code
  2784.    num */
  2785. void
  2786. CountLiberties( code)
  2787.     short    code;
  2788. {
  2789.     short    x, y, libcnt = 0;
  2790.  
  2791.     ForeachPoint(y,x)
  2792.         if (goboard[x][y].GroupNum == code)
  2793.             libcnt += CountAndMarkLibs( x, y);
  2794.     EraseMarks();
  2795.     GroupList[code].liberties = libcnt;
  2796. }
  2797.  
  2798. void
  2799. CheckForEye( x, y, groups, cnt, recheck)
  2800.     short    x, y, groups[4], cnt, *recheck;
  2801. {
  2802.     short    i;
  2803.  
  2804.     for (i = 0; i < (cnt-1); i++)
  2805.         if (groups[i] != groups[i+1])
  2806.         {
  2807.             /* Mark liberty for false eye check */
  2808.             goboard[x][y].marked = TRUE;
  2809.             (*recheck)++;
  2810.             return;
  2811.         }
  2812.     /* It is an eye */
  2813.     GroupList[groups[i]].eyes += 1;
  2814. }
  2815.    
  2816. /* Set the eye count for the groups */
  2817. void CountEyes()
  2818. {
  2819.     short    i, x, y,
  2820.         wgroups[4], bgroups[4], wcnt, bcnt, max, cnt, recheck = 0, eye;
  2821.  
  2822.     for (i = 1; i <= GroupCount; i++)
  2823.         GroupList[i].eyes = 0;
  2824.  
  2825.     ForeachPoint(y,x)
  2826.     {
  2827.         if (goboard[x][y].Val != EMPTY)
  2828.             continue;
  2829.         cnt = Connect(WHITE,x,y,wgroups,&wcnt,bgroups,&bcnt);
  2830.         max = Maxlibs( x, y);
  2831.         if (cnt == max && wcnt == 1 && bcnt == 0)
  2832.             GroupList[wgroups[0]].eyes++;
  2833.         else if (cnt == max && bcnt == 1 && wcnt == 0)
  2834.             GroupList[bgroups[0]].eyes++;
  2835.         else if (cnt == max && ( bcnt == 0 || wcnt == 0 ))
  2836.         {
  2837.             goboard[x][y].marked = TRUE;
  2838.             recheck++;
  2839.         }
  2840.     }
  2841.  
  2842.     /*-- Now recheck marked liberties to see if two or more one eye --*/
  2843.     /*-- groups contribute to a false eye */
  2844.     if (recheck == 0)
  2845.         return;
  2846.  
  2847.     ForeachPoint(y,x)
  2848.         if (goboard[x][y].marked)
  2849.         {
  2850.             recheck--;
  2851.             goboard[x][y].marked = FALSE;
  2852.             Connect( WHITE, x, y, wgroups, &wcnt, bgroups, &bcnt);
  2853.             /* If all the groups have at least one eye then all the
  2854.             groups are safe from capture because of the common
  2855.             liberty at x, y */
  2856.             eye = TRUE;
  2857.             for (i = 0; i < wcnt; i++)
  2858.                 if (GroupList[wgroups[i]].eyes == 0)
  2859.                     eye = FALSE;
  2860.             if (eye)
  2861.                 for (i = 0; i < wcnt; i++)
  2862.                     GroupList[wgroups[i]].eyes++;
  2863.             for (i = 0; i < bcnt; i++)
  2864.                 if (GroupList[bgroups[i]].eyes == 0)
  2865.                     eye = FALSE;
  2866.             if (eye)
  2867.                 for (i = 0; i < bcnt; i++)
  2868.                     GroupList[bgroups[i]].eyes++;
  2869.             if (recheck == 0)
  2870.                 return;
  2871.         }
  2872. }
  2873.  
  2874.  
  2875. short    foo[19][19];
  2876.  
  2877. /*----------------------------------------------------------------
  2878. -- CountUp()                            --
  2879. --    Count up final scores at the end of the game.        --
  2880. ----------------------------------------------------------------*/
  2881. CountUp()
  2882. {
  2883.     short    x,y;
  2884.     short    CountFromPoint();
  2885.     short    vv;
  2886.     int    btotal,wtotal;
  2887.     char    buff[512];
  2888.  
  2889.  
  2890.     blackTerritory = whiteTerritory = 0;
  2891.     ForeachPoint(y,x)
  2892.     {
  2893.         goboard[x][y].marked = FALSE;
  2894.         foo[x][y] = CNT_UNDECIDED;
  2895.     }
  2896.     ForeachPoint(y,x)
  2897.         if (goboard[x][y].Val==EMPTY && foo[x][y]==CNT_UNDECIDED)
  2898.         {
  2899.             FillPoints(x,y,CountFromPoint(x,y));
  2900.         }
  2901.  
  2902.     wtotal = whiteTerritory + blackPrisoners;
  2903.     btotal = blackTerritory + whitePrisoners;
  2904.     sprintf(buff,"White : %3d territory + %3d prisoners = %d\n\
  2905. Black : %3d territory + %3d prisoners = %d\n\n%s.",
  2906.             whiteTerritory,blackPrisoners,wtotal,
  2907.             blackTerritory,whitePrisoners,btotal,
  2908.             (btotal>wtotal?"Black wins":(wtotal>btotal?"White wins":
  2909.             "A draw")));
  2910.     XtVaSetValues(message,XtNstring,buff,0);
  2911. }
  2912.  
  2913. FillPoints(x,y,val)
  2914.     short    x,y,val;
  2915. {
  2916.     int    i;
  2917.     short    tx,ty;
  2918.  
  2919.  
  2920.     if ((foo[x][y] = val) == CNT_BLACK_TERR)
  2921.         blackTerritory++;
  2922.     else if (val == CNT_WHITE_TERR)
  2923.         whiteTerritory++;
  2924.     for (i=0;i<4;i++)
  2925.     {
  2926.         tx = x + xVec[i];
  2927.         ty = y + yVec[i];
  2928.         if (!LegalPoint(tx,ty))
  2929.             continue;
  2930.         if (goboard[tx][ty].Val==EMPTY && foo[tx][ty]==CNT_UNDECIDED)
  2931.             FillPoints(tx,ty,val);
  2932.     }
  2933. }
  2934.  
  2935. short
  2936. CountFromPoint(x,y)
  2937.     short    x,y;
  2938. {
  2939.     int    i;
  2940.     short    tx,ty;
  2941.     short    blkcnt=0,whtcnt=0;
  2942.     short    baz;
  2943.  
  2944.  
  2945.     goboard[x][y].marked = TRUE;
  2946.     for (i=0;i<4;i++)
  2947.     {
  2948.         tx = x + xVec[i];
  2949.         ty = y + yVec[i];
  2950.         if (!LegalPoint(tx,ty))
  2951.             continue;
  2952.         if (goboard[tx][ty].Val == BLACK)
  2953.             blkcnt++;
  2954.         else if (goboard[tx][ty].Val == WHITE)
  2955.             whtcnt++;
  2956.         else
  2957.         {
  2958.             if (goboard[tx][ty].marked)
  2959.                 continue;
  2960.             baz = CountFromPoint(tx,ty);
  2961.             if (baz == CNT_NOONE)
  2962.                 return CNT_NOONE;
  2963.             else if (baz == CNT_BLACK_TERR)
  2964.                 blkcnt++;
  2965.             else if (baz == CNT_WHITE_TERR)
  2966.                 whtcnt++;
  2967.         }
  2968.         if (blkcnt && whtcnt)
  2969.             return CNT_NOONE;
  2970.     }
  2971.     if (blkcnt && !whtcnt)
  2972.         return CNT_BLACK_TERR;
  2973.     else if (whtcnt && !blkcnt)
  2974.         return CNT_WHITE_TERR;
  2975.     else
  2976.         return CNT_UNDECIDED;
  2977. }
  2978. SHAR_EOF
  2979. fi
  2980. if test -f 'amigo.h'
  2981. then
  2982.     echo shar: "will not over-write existing file 'amigo.h'"
  2983. else
  2984. cat << \SHAR_EOF > 'amigo.h'
  2985. /*=========================================================================
  2986. ===                                    ===
  2987. === FILE    amigo.h                            ===
  2988. ===                                    ===
  2989. === CONTENTS    prototypes for the various AmiGo routines.        ===
  2990. ===        added by neilb                        ===
  2991. ===                                    ===
  2992. =========================================================================*/
  2993.  
  2994. #ifndef __amigo_h
  2995. #define __amigo_h
  2996.  
  2997. #include "go.h"
  2998.  
  2999. #ifdef __STDC__
  3000. #define PROTO(fp)    fp
  3001. #else
  3002. #define PROTO(fp)    ()
  3003. #endif
  3004.  
  3005.  
  3006. /* From goplayer.c */
  3007.  
  3008.  
  3009. /* Procedures from amigo.c */
  3010.  
  3011. short    Connect PROTO((enum bVal, short, short, short[4], short[4], short *, short * ));
  3012. short    Maxlibs PROTO((short, short));
  3013. short    Suicide PROTO((enum bVal, short, short));
  3014. short    StoneLibs PROTO((short, short));
  3015. void    EraseMarks PROTO(());
  3016. short    GoPlaceStone PROTO((enum bVal, short, short));
  3017. void    GoRemoveStone PROTO((short, short));
  3018. void    MergeGroups PROTO((short, short));
  3019. void    DeleteGroup PROTO((short));
  3020. void    ReEvalGroups PROTO((enum bVal, short, short, short));
  3021. void    GroupCapture PROTO((short));
  3022. void    FixLibs PROTO((enum bVal, short, short, short));
  3023. void    main PROTO(());
  3024. void    goRestart PROTO(());
  3025. void    RelabelGroups PROTO(());
  3026. short    CountAndMarkLibs PROTO((short, short));
  3027. void    CountLiberties PROTO((short));
  3028. void    CheckForEye PROTO((short, short, short[4], short, short *));
  3029. void    CountEyes PROTO(());
  3030. void    printGroupReport PROTO((short, short));
  3031.  
  3032.  
  3033. /* killable.c */
  3034.  
  3035. int    tryPlay PROTO(( short, short, short ));
  3036. int    sSpanGroup PROTO(( short, short, sPointList * ));
  3037. int    spanGroup PROTO(( short, short, pointList *));
  3038. int    pause PROTO(());
  3039.  
  3040. int    genState PROTO(());
  3041. int    initGPUtils PROTO(());
  3042. int    genBord PROTO((enum bVal));
  3043.  
  3044. short    genMove PROTO(( enum bVal, short *, short * ));
  3045. short    checkPos PROTO(( short, short, short ));
  3046. short    takeCorner PROTO(( short *, short * ));
  3047. short    extend PROTO(( short *, short * ));
  3048. short    noNbrs PROTO(( short, short ));
  3049. short    extend2 PROTO(( short *, short * ));
  3050. short    lookForSave PROTO(( short *, short * ));
  3051. short    lookForSaveN PROTO(( short *, short * ));
  3052. short    lookForKill PROTO(( short *, short * ));
  3053. short    doubleAtari PROTO(( short *, short * ));
  3054. short    lookForAttack PROTO(( short *, short * ));
  3055. short    threaten PROTO(( short *, short * ));
  3056. short    connectCut PROTO(( short *, short * ));
  3057. short    heCanCut PROTO(( short, short ));
  3058. short    safeMove PROTO(( short, short ));
  3059. short    extendWall PROTO(( short *, short * ));
  3060. short    findAttack2 PROTO(( short *, short * ));
  3061. short    blockCut PROTO(( short *, short * ));
  3062. short    cutHim PROTO(( short *, short * ));
  3063. short    atariAnyway PROTO(( short *, short * ));
  3064. short    underCut PROTO(( short *, short * ));
  3065. short    dropToEdge PROTO(( short *, short * ));
  3066. short    pushWall PROTO(( short *, short * ));
  3067. short    reduceHisLiberties PROTO(( short *, short * ));
  3068. short    dropToEdge2 PROTO(( short *, short * ));
  3069.  
  3070. void    removestone PROTO((short, short));
  3071. void    placestone PROTO((enum bVal, short, short));
  3072.  
  3073. /* goplayutils.c */
  3074.  
  3075. short    saveable PROTO((short, short, short *, short *));
  3076. short    killable PROTO((short, short, short *, short *));
  3077. int    initBoolBoard PROTO((boolBoard));
  3078. int    intersectPlist PROTO((pointList *, pointList *, pointList *));
  3079. int    initArray PROTO((intBoard));
  3080. int    initState PROTO(());
  3081. int    copyArray PROTO((intBoard, intBoard));
  3082. int    stake PROTO(());
  3083. int    spread PROTO(());
  3084. int    respreicen PROTO(());
  3085. int    tryPlay PROTO((short, short, short));
  3086. int    saveState PROTO(());
  3087. int    restoreState PROTO(());
  3088. short    tencen PROTO((short, short));
  3089. int    genConnects PROTO(());
  3090. int    sortLibs PROTO(());
  3091.  
  3092.  
  3093. /*-- from xinterface.c --*/
  3094.  
  3095. void    intrMoveReport PROTO((enum bVal,char *,char *));
  3096. void    intrPrisonerReport PROTO(( short, short ));
  3097.  
  3098.  
  3099. #endif
  3100. SHAR_EOF
  3101. fi
  3102. if test -f 'blackstone.bm'
  3103. then
  3104.     echo shar: "will not over-write existing file 'blackstone.bm'"
  3105. else
  3106. cat << \SHAR_EOF > 'blackstone.bm'
  3107. #define blackstone_width 16
  3108. #define blackstone_height 16
  3109. #define blackstone_x_hot 7
  3110. #define blackstone_y_hot 8
  3111. static char blackstone_bits[] = {
  3112.    0xc0, 0x03, 0xf0, 0x0f, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xfe, 0x7f,
  3113.    0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xfe, 0x77, 0xfe, 0x7b,
  3114.    0xfc, 0x3c, 0xf8, 0x1f, 0xf0, 0x0f, 0xc0, 0x03};
  3115. SHAR_EOF
  3116. fi
  3117. if test -f 'check16.xbm'
  3118. then
  3119.     echo shar: "will not over-write existing file 'check16.xbm'"
  3120. else
  3121. cat << \SHAR_EOF > 'check16.xbm'
  3122. #define check16_width 16
  3123. #define check16_height 16
  3124. static char check16_bits[] = {
  3125.    0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x18, 0x00, 0x08, 0x00, 0x0c,
  3126.    0x00, 0x04, 0x00, 0x06, 0x00, 0x02, 0x00, 0x03, 0x18, 0x01, 0xb0, 0x01,
  3127.    0xe0, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00};
  3128. SHAR_EOF
  3129. fi
  3130. if test -f 'go.h'
  3131. then
  3132.     echo shar: "will not over-write existing file 'go.h'"
  3133. else
  3134. cat << \SHAR_EOF > 'go.h'
  3135. /* AmiGo Include */
  3136. /* MSG types for getinput() */
  3137.  
  3138. #ifndef __go_h
  3139. #define __go_h
  3140.  
  3141.  
  3142. #define INTERSECTIONMSG 1    /* User buttoned an intersection */
  3143. #define QUITMSG 2        /* User buttoned QUIT icon */
  3144. #define PLAYMSG 3
  3145. #define RESTARTMSG 4
  3146. #define PASSMSG 5
  3147.  
  3148. #define TRUE 1
  3149. #define FALSE 0
  3150.  
  3151. #define MAXGROUPS 100
  3152.  
  3153. #define PLACED 0
  3154. #define REMOVED 1
  3155.  
  3156. #define numPoints 19
  3157. #define maxPoint numPoints - 1
  3158.  
  3159. /*-- definitions used when counting up --*/
  3160.  
  3161. #define CNT_UNDECIDED    0
  3162. #define CNT_BLACK_TERR    1
  3163. #define CNT_WHITE_TERR    2
  3164. #define CNT_NOONE    3
  3165.  
  3166. /*-- macro functions --*/
  3167.  
  3168. #define LegalPoint(x,y)        (x>=0 && x<=18 && y>=0 && y<=18)
  3169. #define ForeachPoint(a,b)    for(a=0;a<19;a++) for (b=0;b<19;b++)
  3170.  
  3171. enum bVal {BLACK, WHITE, EMPTY};
  3172. typedef enum bVal sType;
  3173. struct Group
  3174. {
  3175.    enum bVal color;    /* The color of the group */
  3176.    short code,        /* The code used to mark stones in the group */
  3177.          count,        /* The number of stones in the group */
  3178.          internal,    /* The number of internal liberties */
  3179.          external,    /* The number of external liberties */
  3180.      liberties,    /* The total number of liberties */
  3181.          eyes,        /* The number of eyes */
  3182.          alive,        /* A judgement of how alive this group is */
  3183.          territory;    /* The territory this group controls */
  3184. };
  3185.  
  3186. struct bRec
  3187. {
  3188.     enum bVal    Val;    /* What is at this intersection */
  3189.     short        xOfs,
  3190.             yOfs;
  3191.     short        mNum;
  3192.     short        GroupNum;    /* What group the stone belongs to */
  3193.     short        marked;    /* TRUE or FALSE */
  3194. };
  3195.  
  3196. #endif
  3197. SHAR_EOF
  3198. fi
  3199. if test -f 'goplayer.c'
  3200. then
  3201.     echo shar: "will not over-write existing file 'goplayer.c'"
  3202. else
  3203. cat << \SHAR_EOF > 'goplayer.c'
  3204. /* The go player */
  3205. /* Ported from Pascal to C by Todd R. Johnson 4/17/88 */
  3206. /* From the original pascal file:
  3207. Go Move Generator
  3208. Copyright (c) 1983 by Three Rivers Computer Corp.
  3209.  
  3210. Written: January 17, 1983 by Stoney Ballard
  3211. Edit History:
  3212. */
  3213.  
  3214. #include "go.h"
  3215. #include "amigo.h"
  3216. #include "goplayutils.h"
  3217.  
  3218. #define BIGGEST 32767    /* maximum value for short */
  3219.  
  3220. /* From go.c */
  3221. extern struct bRec goboard[19][19];
  3222. extern short ko, koX, koY;
  3223.  
  3224. /* From goplayutils.c */
  3225. extern intBoard bord;
  3226. extern intBoard ndbord;
  3227. extern intBoard claim;
  3228. extern intBoard legal;
  3229. extern intBoard connectMap;
  3230. extern intBoard threatBord;
  3231. extern short maxGroupID;
  3232. extern short treeLibLim;
  3233. extern short killFlag;
  3234. extern short depthLimit;
  3235. extern short showTrees;
  3236. extern short utilPlayLevel;
  3237. extern groupRec gList[maxGroup];
  3238. extern short sGlist[maxGroup + 1];
  3239. extern pointList pList;
  3240. extern pointList pList1;
  3241. extern pointList plist2;
  3242. extern pointList plist3;
  3243. extern intBoard groupIDs;
  3244. extern intBoard protPoints;
  3245. extern sType mySType;
  3246.  
  3247.  
  3248. short saveNLibs;
  3249. pointList dapList1, dapList2, dapList3;
  3250. char *playReason;
  3251. short maxPlayLevel = 7;
  3252. short playLevel = 7;
  3253.  
  3254. genBord(color)
  3255.     enum bVal    color;
  3256. {
  3257.     short        x, y, nomoves = TRUE;
  3258.     char        mv[8];
  3259.  
  3260.     maxPlayLevel = 7;
  3261.     utilPlayLevel = playLevel;
  3262.     mySType = color;
  3263.     if (playLevel < 2)
  3264.         treeLibLim = 2;
  3265.     else
  3266.         treeLibLim = 3;
  3267.     depthLimit = 100;
  3268.     for (y = 0; y <= 18; y++)
  3269.         for (x = 0; x <= 18; x++)
  3270.             if (goboard[x][y].Val == color)
  3271.             {
  3272.                 bord[x][y] = 1;
  3273.                 legal[x][y] = FALSE;
  3274.                 nomoves = FALSE;
  3275.             }
  3276.             else if (goboard[x][y].Val == EMPTY)
  3277.             {
  3278.                 bord[x][y] = 0;
  3279.                 legal[x][y] = TRUE;
  3280.             }
  3281.             else
  3282.             {
  3283.                 bord[x][y] = -1;
  3284.                 legal[x][y] = FALSE;
  3285.                 nomoves = FALSE;
  3286.             }
  3287.     if (ko)
  3288.     {
  3289.         legal[koX][koY] = FALSE;
  3290.     }
  3291.  
  3292.     if (! nomoves) 
  3293.         genState();
  3294.     else
  3295.         initGPUtils();
  3296. }
  3297.  
  3298.  
  3299. short getMove( x, y )
  3300. short *x, *y;
  3301. {
  3302.    if (takeCorner(x, y)) return TRUE;
  3303.    if (lookForSave(x, y)) return TRUE;
  3304.    if (lookForSaveN(x, y)) return TRUE;
  3305.    if (extend(x, y)) return TRUE;
  3306.    if (lookForKill(x, y)) return TRUE;
  3307.    if (doubleAtari(x, y)) return TRUE;
  3308.    if (lookForAttack(x, y)) return TRUE;
  3309.    if (threaten(x, y)) return TRUE;
  3310.    if (extend2(x, y)) return TRUE;
  3311.    if (connectCut(x, y)) return TRUE;
  3312.    if (blockCut(x, y)) return TRUE;
  3313.    if (cutHim(x, y)) return TRUE;
  3314.    if (extendWall(x, y)) return TRUE;
  3315.    if (findAttack2(x, y)) return TRUE;
  3316.    if (atariAnyway(x, y)) return TRUE;
  3317.    if (underCut(x, y)) return TRUE;
  3318.    if (dropToEdge(x, y)) return TRUE;
  3319.    if (pushWall(x, y)) return TRUE;
  3320.    if (reduceHisLiberties(x, y)) return TRUE;
  3321.    if (dropToEdge2(x, y)) return TRUE;
  3322.    return FALSE;
  3323. }
  3324.  
  3325. short genMove( color, x, y )
  3326. enum bVal color;
  3327. short *x, *y;
  3328. {
  3329.    if (playLevel > 2)
  3330.       saveNLibs = TRUE;
  3331.    else
  3332.       saveNLibs = FALSE;
  3333.    genBord(color);
  3334.    if (getMove(x, y)) 
  3335.       return TRUE;
  3336.    return FALSE;
  3337. }
  3338.    
  3339. short checkPos(x, y, field)
  3340. short x, y, field;
  3341. {
  3342.    short ok;
  3343.    ok = (((field == 0) && (claim[x][y] == 0)) ||
  3344.          ((field > 0) &&
  3345.       (claim[x][y] >= 0) && (claim[x][y] <= field)) ||
  3346.      ((field < 0) &&
  3347.       (claim[x][y] <= 0) && (claim[x][y] >= field))) &&
  3348.      (bord[x-1][y] == 0) &&
  3349.      (bord[x+1][y] == 0) &&
  3350.      (bord[x][y-1] == 0) &&
  3351.      (bord[x][y+1] == 0);
  3352.    if (ok) return TRUE; else return FALSE;
  3353. }
  3354.  
  3355. short takeCorner( x, y )
  3356. short *x, *y;
  3357. {
  3358.    short field = -1, i;
  3359.    i = 18 - 3;
  3360.    playReason = "takeCorner";
  3361.    while (field != -4)
  3362.    {
  3363.       if (field == -1) field = 0;
  3364.       else if (field == 0) field = 4;
  3365.       else field = -4;
  3366.       if (checkPos(2, 3, field)) { *x = 2; *y = 3; return TRUE; }
  3367.       if (checkPos(3, 2, field)) { *x = 3; *y = 2; return TRUE; }
  3368.       if (checkPos(2, i, field)) { *x = 2; *y = i; return TRUE; }
  3369.       if (checkPos(3, i + 1, field)) { *x = 3; *y = i+1; return TRUE; }
  3370.       if (checkPos(i, i + 1, field)) { *x = i; *y = i+1; return TRUE; }
  3371.       if (checkPos(i + 1, i, field)) { *x = i+1; *y = i; return TRUE; }
  3372.       if (checkPos(i, 2, field)) { *x = i; *y = 2; return TRUE; }
  3373.       if (checkPos(i + 1, 3, field)) { *x = i+1; *y = 3; return TRUE; }
  3374.       if (checkPos(2, 4, field)) { *x = 2; *y = 4; return TRUE; }
  3375.       if (checkPos(4, 2, field)) { *x = 4; *y = 2; return TRUE; }
  3376.       if (checkPos(2, i - 1, field)) { *x = 2; *y = i-1; return TRUE; }
  3377.       if (checkPos(4, i + 1, field)) { *x = 4; *y = i+1; return TRUE; }
  3378.       if (checkPos(i - 1, i + 1, field)) { *x = i-1; *y = i+1; return TRUE; }
  3379.       if (checkPos(i + 1, i - 1, field)) { *x = i+1; *y = i-1; return TRUE; }
  3380.       if (checkPos(i + 1, 4, field)) { *x = i+1; *y = 4; return TRUE; }
  3381.       if (checkPos(i - 1, 2, field)) { *x = i-1; *y = 2; return TRUE; }
  3382.    }
  3383.    return FALSE;
  3384. }
  3385.  
  3386. printBoard(brd, name)
  3387. intBoard brd;
  3388. char *name;
  3389. {
  3390.    short x, y;
  3391.    printf( "%s\n", name );
  3392.    for (y = 0; y <= 18; y++)
  3393.    {
  3394.       for (x = 0; x <= 18; x++)
  3395.          printf("%d ", brd[x][y]);
  3396.       printf("\n");
  3397.    }
  3398. }
  3399.  
  3400. short noNbrs( x, y )
  3401. short x, y;
  3402. {
  3403.    if (x > 0 && bord[x-1][y] != 0) return FALSE;
  3404.    if (x < 18 && bord[x+1][y] != 0) return FALSE;
  3405.    if (y > 0 && bord[x][y-1] != 0) return FALSE;
  3406.    if (y < 18 && bord[x][y+1] != 0) return FALSE;
  3407.    return TRUE;
  3408. }
  3409.  
  3410. short extend(x, y)
  3411. short *x, *y;
  3412. {
  3413.    short i;
  3414.    playReason = "extend";
  3415.    for (i = 2; i <= 18-2; i++)
  3416.       if (claim[2][i] == 0 && noNbrs( 2, i ))
  3417.       {
  3418.          *x = 2;
  3419.      *y = i;
  3420.      return TRUE;
  3421.       }
  3422.    for (i = 2; i <= 18-2; i++)
  3423.       if (claim[i][18-2] == 0 && noNbrs( 2, i ))
  3424.       {
  3425.          *x = i;
  3426.      *y = 18-2;
  3427.      return TRUE;
  3428.       }
  3429.    for (i = 18-2; i >= 2; i--)
  3430.       if (claim[18-2][i] == 0 && noNbrs( 18-2, i ))
  3431.       {
  3432.          *x = 18-2;
  3433.      *y = i;
  3434.      return TRUE;
  3435.       }
  3436.    for (i = 18-2; i >= 2; i--)
  3437.       if (claim[i][2] == 0 && noNbrs( i, 2 ))
  3438.       {
  3439.          *x = i;
  3440.      *y = 2;
  3441.      return TRUE;
  3442.       }
  3443.    return FALSE;
  3444. }
  3445.  
  3446. short extend2( x, y )
  3447. short *x, *y;
  3448. {
  3449.    short i, lowest = BIGGEST, value;
  3450.    playReason = "extend2";
  3451.    for (i = 3; i <= 18-3; i++)
  3452.       if (legal[2][i])         /* if there is nobody there */
  3453.       {
  3454.           value = claim[2][i];     /* get influence */
  3455.           if ((value < 7) &&        /* a reasonable hole in my wall */
  3456.              (value > -5) &&       /* or a reasonable gap in his */
  3457.              (bord[2][i + 1] == 0) && /* not in contact with any stones */
  3458.              (bord[2][i - 1] == 0))
  3459.             if (value < lowest) 
  3460.               {
  3461.                 lowest = value;     /* lowest gets the smallest value */
  3462.                 *x = 2;              /* that was seen along all the 3-lines */
  3463.                 *y = i;              /* x and y save that location */
  3464.               }
  3465.         }
  3466.    for (i = 3; i <= 18-3; i++)
  3467.       if (legal[i][2])
  3468.         {
  3469.           value = claim[i][2];
  3470.           if ((value < 7) &&
  3471.              (value > -5) && 
  3472.              (bord[i + 1][2] == 0) &&
  3473.              (bord[i - 1][2] == 0))
  3474.             if (value < lowest) 
  3475.               {
  3476.                 lowest = value;
  3477.                 *x = i;
  3478.                 *y = 2;
  3479.               }
  3480.         }
  3481.    for (i = 18-3; i >= 3; i--)
  3482.       if (legal[18 - 2][i])
  3483.         {
  3484.           value = claim[18 - 2][i];
  3485.           if ((value < 7) &&
  3486.              (value > -5) && 
  3487.              (bord[18 - 2][i + 1] == 0) &&
  3488.              (bord[18 - 2][i - 1] == 0))
  3489.             if (value < lowest) 
  3490.               {
  3491.                 lowest = value;
  3492.                 *x = 18 - 2;
  3493.                 *y = i;
  3494.               }
  3495.         }
  3496.    for (i = 3; i <= 18-3; i++)
  3497.       if (legal[i][18 - 2])
  3498.         {
  3499.           value = claim[i][18 - 2];
  3500.           if ((value < 7) &&
  3501.              (value > -5) && 
  3502.              (bord[i + 1][18 - 2] == 0) &&
  3503.              (bord[i - 1][18 - 2] == 0))
  3504.             if (value < lowest) 
  3505.               {
  3506.                 lowest = value;
  3507.                 *x = i;
  3508.                 *y = 18 - 2;
  3509.               }
  3510.         }
  3511.    if (lowest == BIGGEST) return FALSE;
  3512.    return TRUE;
  3513. }
  3514.  
  3515.   /*
  3516.     check to see if I can save anything in atari
  3517.   */
  3518. short lookForSave(x, y)
  3519. short *x, *y;
  3520.   { /* lookForSave */
  3521.     short i;
  3522.     playReason = "lookForSave";
  3523.     for (i = 1; i <= maxGroupID; i++)       /* scan the group list */
  3524.         if ((gList[i].libC == 1) &&
  3525.            (ndbord[gList[i].lx][gList[i].ly] == 1))
  3526.               if (saveable(gList[i].lx, gList[i].ly, x, y)) /* see if I can save it */
  3527.                 return TRUE;
  3528.     return FALSE;
  3529.   } /* lookForSave */
  3530.  
  3531.   /*
  3532.     check to see if I can save anything with n libs
  3533.   */
  3534. short lookForSaveN(x, y)
  3535. short *x, *y;
  3536.   { /* lookForSaveN */
  3537.     short i;
  3538.     if (saveNLibs)
  3539.       {
  3540.         playReason = "lookForSaveN";
  3541.         for (i = 1; i <= maxGroupID; i++)       /* scan the group list */
  3542.             if ((gList[i].libC > 1) &&
  3543.                (gList[i].libC <= treeLibLim) &&
  3544.                (ndbord[gList[i].lx][gList[i].ly] == 1))
  3545.                 {
  3546.                   if (killable(gList[i].lx, gList[i].ly, x, y))
  3547.                     if (saveable(gList[i].lx, gList[i].ly, x, y)) /* see if I can save it */
  3548.                       return TRUE;
  3549.                 }
  3550.       }
  3551.     return FALSE;
  3552.   } /* lookForSaveN */
  3553.  
  3554.  
  3555. /*----------------------------------------------------------------
  3556. -- lookForKill()                        --
  3557. --    check to see if I can kill anything.            --
  3558. ----------------------------------------------------------------*/
  3559. short
  3560. lookForKill(x, y)
  3561.     short    *x, *y;
  3562. {
  3563.     short    i;
  3564.     char    mv[8];
  3565.  
  3566.     playReason = "lookForKill";
  3567.     for (i = 1; i <= maxGroupID; i++)       /* scan the group list */
  3568.         if ((gList[i].libC == 1) &&
  3569.                 (ndbord[gList[i].lx][gList[i].ly] == -1)) 
  3570.     {    /* we found a live enemy group with one liberty */
  3571.         /* find the liberty */
  3572.         spanGroup(gList[i].lx, gList[i].ly, &pList);
  3573.         *x = pList.p[1].px;
  3574.         *y = pList.p[1].py;
  3575.         if (legal[*x][*y])
  3576.         {
  3577.             return TRUE;
  3578.         }
  3579.     }
  3580.     return FALSE;
  3581. }
  3582.  
  3583. short doubleAtari(x, y)
  3584. short *x, *y;
  3585.   { /* doubleAtari */
  3586.     short i, j;
  3587.     playReason = "doubleAtari";
  3588.     for (i = 1; i <= maxGroupID - 1; i++)
  3589.         if ((gList[i].libC == 2) &&
  3590.            (ndbord[gList[i].lx][gList[i].ly] == -1)) /* found an atariable group of his */
  3591.           {
  3592.             spanGroup(gList[i].lx, gList[i].ly, &dapList1);
  3593.             for (j = i + 1; j <= maxGroupID; j++)
  3594.                 if ((gList[j].libC == 2) &&
  3595.                    (ndbord[gList[j].lx][gList[j].ly] == -1))
  3596.                 {
  3597.                   spanGroup(gList[j].lx, gList[j].ly, &dapList2);
  3598.                   intersectPlist(&dapList1, &dapList2, &dapList3);
  3599.                   if (dapList3.indx > 0)
  3600.                       if (legal[dapList3.p[1].px][dapList3.p[1].py])
  3601.                         {
  3602.                           tryPlay(dapList3.p[1].px, dapList3.p[1].py, 1);
  3603.                           if (gList[groupIDs[dapList3.p[1].px][
  3604.                 dapList3.p[1].py]].libC > 1)
  3605.                             {
  3606.                               *x = dapList3.p[1].px;
  3607.                               *y = dapList3.p[1].py;
  3608.                               restoreState();
  3609.                   return TRUE;
  3610.                             }
  3611.                           restoreState();
  3612.                         }
  3613.                 }
  3614.           } 
  3615.     return FALSE;
  3616.   } /* doubleAtari */
  3617.  
  3618. short lookForAttack(x, y)
  3619. short *x, *y;
  3620.   { /* lookForAttack */
  3621.     short tx, ty, i;
  3622.     playReason = "lookForAttack";
  3623.     for (i = 1; i <= maxGroupID; i++)       /* scan the group list */
  3624.         if ((! gList[i].isLive) &&
  3625.            (gList[i].libC > 1) &&
  3626.            (gList[i].libC <= (treeLibLim + 1)) &&
  3627.            (ndbord[gList[i].lx][gList[i].ly] == -1)) 
  3628.               {
  3629.                 if (killable(gList[i].lx, gList[i].ly, &tx, &ty)) /* can we kill it? */
  3630.                   {
  3631.                     *x = tx;        /* yep - do so */
  3632.                     *y = ty;
  3633.                     return TRUE;
  3634.                   }
  3635.               }
  3636.     return FALSE;
  3637.   } /* lookForAttack */
  3638.  
  3639.   /*
  3640.     Plays a move that requires a response on the opponent's part
  3641.   */
  3642. short threaten(x, y)
  3643. short *x, *y;
  3644.   { /* threaten */
  3645.     short i, j, gx, gy, tNum;
  3646.     playReason = "threaten";
  3647.     initArray(threatBord);
  3648.     for (i = 1; i <= maxGroupID; i++)
  3649.         if ((! gList[i].isLive) &&
  3650.            (ndbord[gList[i].lx][gList[i].ly] == -1))
  3651.           {
  3652.             spanGroup(gList[i].lx, gList[i].ly, &pList);
  3653.             for (j = 1; j <= pList.indx; j++)
  3654.                 if (legal[pList.p[j].px][pList.p[j].py])
  3655.                   {
  3656.                     tryPlay(pList.p[j].px, pList.p[j].py, 1);
  3657.                     if (gList[groupIDs[pList.p[j].px][pList.p[j].py]].libC > 1)
  3658.                       if (killable(gList[i].lx, gList[i].ly, &gx, &gy))
  3659.                         threatBord[pList.p[j].px][pList.p[j].py] += 1;
  3660.                     restoreState();
  3661.                   }
  3662.           }
  3663.     tNum = 0;
  3664.     for (i = 0; i <= maxPoint; i++)
  3665.       for (j = 0; j <= maxPoint; j++)
  3666.         if ((threatBord[i][j] > tNum) &&
  3667.            ((threatBord[i][j] > 1) ||
  3668.             (connectMap[i][j] > 0)))
  3669.           {
  3670.             tNum = threatBord[i][j];
  3671.             *x = i;
  3672.             *y = j;
  3673.           }
  3674.     if (tNum > 0) return TRUE;
  3675.     else return FALSE;
  3676.   } /* threaten */
  3677.  
  3678.   /*
  3679.     connects against enemy cuts
  3680.   */
  3681. short connectCut(x, y)
  3682. short *x, *y;
  3683.   { /* connectCut */
  3684.     short i, j, nap, gid, infl;
  3685.     playReason = "connectCut";
  3686.     for (i = 0; i <= maxPoint; i++)
  3687.       for (j = 0; j <= maxPoint; j++)
  3688.         if (legal[i][j] &&
  3689.            (protPoints[i][j] == 0))   /* not a protected point */
  3690.           {
  3691.             nap = 0;     /* how many of my stones am I adjacent to? */
  3692.             if ((i > 0) && (bord[i - 1][j] == 1))
  3693.               {
  3694.                 nap = nap + 1;
  3695.                 pList.p[nap].px = i - 1;
  3696.                 pList.p[nap].py = j;
  3697.               }
  3698.             if ((j > 0) && (bord[i][j - 1] == 1))
  3699.               {
  3700.                 nap = nap + 1;
  3701.                 pList.p[nap].px = i;
  3702.                 pList.p[nap].py = j - 1;
  3703.               }
  3704.             if ((i < maxPoint) && (bord[i + 1][j] == 1))
  3705.               {
  3706.                 nap = nap + 1;
  3707.                 pList.p[nap].px = i + 1;
  3708.                 pList.p[nap].py = j;
  3709.               }
  3710.             if ((j < maxPoint) && (bord[i][j + 1] == 1))
  3711.               {
  3712.                 nap = nap + 1;
  3713.                 pList.p[nap].px = i;
  3714.                 pList.p[nap].py = j + 1;
  3715.               }
  3716.             if (nap == 1) /* possible knight's || 2-point extention */
  3717.                 {
  3718.                   gid = groupIDs[pList.p[1].px][pList.p[1].py];
  3719.                   if ((i > 0) && (i < maxPoint) &&
  3720.                      (ndbord[i - 1][j] == 1) &&
  3721.                      (ndbord[i + 1][j] == 0)) /* contact on left */
  3722.                     {
  3723.                       if (((j > 0) && (ndbord[i][j - 1] == -1) &&
  3724.                           (ndbord[i + 1][j - 1] == 1) &&
  3725.                           (gid != groupIDs[i + 1][j - 1])) ||
  3726.                          ((j < maxPoint) && (ndbord[i][j + 1] == -1) &&
  3727.                           (ndbord[i + 1][j + 1] == 1) &&
  3728.                           (gid != groupIDs[i + 1][j + 1])) ||
  3729.                          ((((j > 0) && (ndbord[i][j - 1] == -1)) ||
  3730.                            ((j < maxPoint) && (ndbord[i][j + 1] == -1))) &&
  3731.                           (i < (maxPoint - 1)) &&
  3732.                           (ndbord[i + 2][j] == 1) &&
  3733.                           (gid != groupIDs[i + 2][j])))
  3734.                         {
  3735.                           *x = i;
  3736.                           *y = j;
  3737.                           if (safeMove(*x, *y))
  3738.                             return TRUE;
  3739.                         }
  3740.                     }
  3741.                   else if ((i < maxPoint) && (i > 0) &&
  3742.                           (ndbord[i + 1][j] == 1) &&
  3743.                           (ndbord[i - 1][j] == 0)) /* r */
  3744.                     {
  3745.                       if (((j > 0) && (ndbord[i][j - 1] == -1) &&
  3746.                           (ndbord[i - 1][j - 1] == 1) &&
  3747.                           (gid != groupIDs[i - 1][j - 1])) ||
  3748.                          ((j < maxPoint) && (ndbord[i][j + 1] == -1) &&
  3749.                           (ndbord[i - 1][j + 1] == 1) &&
  3750.                           (gid != groupIDs[i - 1][j + 1])) ||
  3751.                          ((((j > 0) && (ndbord[i][j - 1] == -1)) ||
  3752.                            ((j < maxPoint) && (ndbord[i][j + 1] == -1))) &&
  3753.                           (i > 1) &&
  3754.                           (ndbord[i - 2][j] == 1) &&
  3755.                           (gid != groupIDs[i - 2][j])))
  3756.                         {
  3757.                           *x = i;
  3758.                           *y = j;
  3759.                           if (safeMove(*x, *y))
  3760.                             return TRUE;
  3761.                         }
  3762.                     }
  3763.                   else if ((j > 0) && (j < maxPoint) &&
  3764.                           (ndbord[i][j - 1] == 1) &&
  3765.                           (ndbord[i][j + 1] == 0)) /* top */
  3766.                     {
  3767.                       if (((i > 0) && (ndbord[i - 1][j] == -1) &&
  3768.                           (ndbord[i - 1][j + 1] == 1) &&
  3769.                           (gid != groupIDs[i - 1][j + 1])) ||
  3770.                          ((i < maxPoint) && (ndbord[i + 1][j] == -1) &&
  3771.                           (ndbord[i + 1][j + 1] == 1) &&
  3772.                           (gid != groupIDs[i + 1][j + 1])) ||
  3773.                          ((((i > 0) && (ndbord[i - 1][j] == -1)) ||
  3774.                            ((i < maxPoint) && (ndbord[i + 1][j] == -1))) &&
  3775.                           (j < (maxPoint - 1)) &&
  3776.                           (ndbord[i][j + 2] == 1) &&
  3777.                           (gid != groupIDs[i][j + 2])))
  3778.                         {
  3779.                           *x = i;
  3780.                           *y = j;
  3781.                           if (safeMove(*x, *y))
  3782.                             return TRUE;
  3783.                         }
  3784.                     }
  3785.                   else if ((j > 0) && (j < maxPoint) &&
  3786.                           (ndbord[i][j + 1] == 1) &&
  3787.                           (ndbord[i][j - 1] == 0)) /* bottom */
  3788.                     {
  3789.                       if (((i > 0) && (ndbord[i - 1][j] == -1) &&
  3790.                           (ndbord[i - 1][j - 1] == 1) &&
  3791.                           (gid != groupIDs[i - 1][j - 1])) ||
  3792.                          ((i < maxPoint) && (ndbord[i + 1][j] == -1) &&
  3793.                           (ndbord[i + 1][j - 1] == 1) &&
  3794.                           (gid != groupIDs[i + 1][j - 1])) ||
  3795.                          ((((i > 0) && (ndbord[i - 1][j] == -1)) ||
  3796.                            ((i < maxPoint) && (ndbord[i + 1][j] == -1))) &&
  3797.                           (j > 1) &&
  3798.                           (ndbord[i][j - 2] == 1) &&
  3799.                           (gid != groupIDs[i][j - 2])))
  3800.                         {
  3801.                           *x = i;
  3802.                           *y = j;
  3803.                           if (safeMove(*x, *y))
  3804.                             return TRUE;
  3805.                         }
  3806.                     }
  3807.                 }
  3808.             else if (nap == 2) /* diagonal or 1-point extention */
  3809.               {
  3810.                 if (groupIDs[pList.p[1].px][pList.p[1].py] !=
  3811.                    groupIDs[pList.p[2].px][pList.p[2].py])
  3812.                   {
  3813.                     if ((pList.p[1].px != pList.p[2].px) &&
  3814.                        (pList.p[1].py != pList.p[2].py)) /* diag */
  3815.                       {
  3816.                         spanGroup(pList.p[1].px,
  3817.                                   pList.p[1].py, &pList1);
  3818.                         spanGroup(pList.p[2].px,
  3819.                                   pList.p[2].py, &plist2);
  3820.                         intersectPlist(&pList1, &plist2, &plist3);
  3821.                         if (plist3.indx == 1)
  3822.                           if ((i > 0) && (ndbord[i - 1][j] == -1) ||
  3823.                              (i < maxPoint) && (ndbord[i + 1][j] == -1) ||
  3824.                              (j > 0) && (ndbord[i][j - 1] == -1) ||
  3825.                              (j < maxPoint) && (ndbord[i][j + 1] == -1))
  3826.                             { /* must make direct connection */
  3827.                               *x = i;
  3828.                               *y = j;
  3829.                               if (heCanCut(*x, *y))
  3830.                                 if (safeMove(*x, *y))
  3831.                                   return TRUE;
  3832.                             }
  3833.                           else if (heCanCut(i, j))
  3834.                             {     /* protect point if possible */
  3835.                               infl = 1000;
  3836.                               if ((i > 0) && legal[i - 1][j] &&
  3837.                                  ((i == 1) || (ndbord[i - 2][j] == 0)) &&
  3838.                                  ((j == 0) || (ndbord[i - 1][j - 1] == 0)) &&
  3839.                                  ((j == maxPoint) ||
  3840.                                   (ndbord[i - 1][j + 1] == 0)))
  3841.                                 if (safeMove(i - 1, j))
  3842.                                   if (claim[i - 1][j] < infl)
  3843.                                     {
  3844.                                       *x = i - 1;
  3845.                                       *y = j;
  3846.                                       infl = claim[i - 1][j];
  3847.                                     }
  3848.                               if ((j > 0) && legal[i][j - 1] &&
  3849.                                  ((j == 1) || (ndbord[i][j - 2] == 0)) &&
  3850.                                  ((i == 0) || (ndbord[i - 1][j - 1] == 0)) &&
  3851.                                  ((i == maxPoint) ||
  3852.                                   (ndbord[i + 1][j - 1] == 0)))
  3853.                                 if (safeMove(i, j - 1))
  3854.                                   if (claim[i][j - 1] < infl)
  3855.                                     {
  3856.                                       *x = i;
  3857.                                       *y = j - 1;
  3858.                                       infl = claim[i][j - 1];
  3859.                                     }
  3860.                               if ((i < maxPoint) && legal[i + 1][j] &&
  3861.                                  ((i == (maxPoint - 1)) ||
  3862.                                   (ndbord[i + 2][j] == 0)) &&
  3863.                                  ((j == 0) || (ndbord[i + 1][j - 1] == 0)) &&
  3864.                                  ((j == maxPoint) ||
  3865.                                   (ndbord[i + 1][j + 1] == 0)))
  3866.                                 if (safeMove(i + 1, j))
  3867.                                   if (claim[i + 1][j] < infl)
  3868.                                     {
  3869.                                       *x = i + 1;
  3870.                                       *y = j;
  3871.                                       infl = claim[i + 1][j];
  3872.                                     }
  3873.                               if ((j < maxPoint) && legal[i][j + 1] &&
  3874.                                  ((j == (maxPoint - 1)) ||
  3875.                                   (ndbord[i][j + 2] == 0)) &&
  3876.                                  ((i == 0) || (ndbord[i - 1][j + 1] == 0)) &&
  3877.                                  ((i == maxPoint) ||
  3878.                                   (ndbord[i + 1][j + 1] == 0)))
  3879.                                 if (safeMove(i, j + 1))
  3880.                                   if (claim[i][j + 1] < infl)
  3881.                                     {
  3882.                                       *x = i;
  3883.                                       *y = j + 1;
  3884.                                       infl = claim[i][j + 1];
  3885.                                     }
  3886.                               if (infl < 1000)
  3887.                                 return TRUE;
  3888.                               *x = i;      /* direct connection */
  3889.                               *y = j;
  3890.                               if (safeMove(*x, *y))
  3891.                                 return TRUE;
  3892.                             }
  3893.                       }
  3894.                     else /* 1-point extension, only protect if threatened */
  3895.                       {
  3896.                         if ((i > 0) && (ndbord[i - 1][j] == -1) ||
  3897.                            (j > 0) && (ndbord[i][j - 1] == -1) ||
  3898.                            (i < maxPoint) && (ndbord[i + 1][j] == -1) ||
  3899.                            (j < maxPoint) && (ndbord[i][j + 1] == -1))
  3900.                           {
  3901.                             *x = i;
  3902.                             *y = j;
  3903.                             if (heCanCut(*x, *y))
  3904.                               if (safeMove(*x, *y))
  3905.                                 return TRUE;
  3906.                           }
  3907.                       }
  3908.                   }
  3909.               }
  3910.             else if (nap == 3) /* unprotected, but me on 3 sides */
  3911.               {
  3912.                 if ((groupIDs[pList.p[1].px][pList.p[1].py] !=
  3913.                     groupIDs[pList.p[2].px][pList.p[2].py]) ||
  3914.                    (groupIDs[pList.p[1].px][pList.p[1].py] !=
  3915.                     groupIDs[pList.p[3].px][pList.p[3].py]) ||
  3916.                    (groupIDs[pList.p[3].px][pList.p[3].py] !=
  3917.                     groupIDs[pList.p[2].px][pList.p[2].py]))
  3918.                   {
  3919.                     spanGroup(pList.p[1].px, pList.p[1].py, &pList1);
  3920.                     spanGroup(pList.p[2].px, pList.p[2].py, &plist2);
  3921.                     intersectPlist(&pList1, &plist2, &plist3);
  3922.                     spanGroup(pList.p[3].px, pList.p[3].py, &plist2);
  3923.                     intersectPlist(&plist2, &plist3, &pList1);
  3924.                     if (pList1.indx == 1) /* a common connect point */
  3925.                       if (heCanCut(i, j))
  3926.                         if (safeMove(i, j))
  3927.                           {
  3928.                             *x = i;
  3929.                             *y = j;
  3930.                             return TRUE;
  3931.                           }
  3932.                   }
  3933.               }
  3934.           }
  3935.     return FALSE;
  3936.   } /* connectCut */
  3937.  
  3938. short heCanCut(x, y)
  3939. short x, y;
  3940.   { /* heCanCut */
  3941.     short gx, gy, result;
  3942.     if (playLevel > 3)
  3943.       {
  3944.         tryPlay(x, y, -1);  /* try his cut */
  3945.         result = ! killable(x, y, &gx, &gy);
  3946.         restoreState();
  3947.         return result;
  3948.       }
  3949.     else
  3950.       return FALSE;
  3951.   } /* heCanCut */
  3952.  
  3953.   /*
  3954.     Checks out a move.
  3955.     If my stone is not killable then true.
  3956.   */
  3957. short safeMove(x, y)
  3958. short x, y;
  3959.   { /* safeMove */
  3960.     short gbx, gby, result;
  3961.     tryPlay(x, y, 1);              /* try playing at point */
  3962.     if (killFlag) /* I shouldn't kill if lookForKill didn't */
  3963.       result = FALSE;
  3964.     else if (gList[groupIDs[x][y]].libC < 2)
  3965.       {                   /* if it is in atari or dead */
  3966.         result = FALSE;      /* reject it */
  3967.       }
  3968.     else if (gList[groupIDs[x][y]].libC <= treeLibLim) /* see if killable */
  3969.       if (playLevel > 0)
  3970.         result = ! killable(x, y, &gbx, &gby);
  3971.       else
  3972.         result = TRUE;
  3973.     else
  3974.       result = TRUE;
  3975.     restoreState();
  3976.     return result;
  3977.   } /* safeMove */
  3978.  
  3979.   /*
  3980.     Extends walls in a connected fashion.
  3981.     Finds the lowest influence (mine) point that is connected to one
  3982.     of my groups.
  3983.     Only looks in the center of the board.
  3984.   */
  3985. short extendWall(x, y)
  3986. short *x, *y;
  3987.   { /* extendWall */
  3988.     short infl, i, j;
  3989.     playReason = "extendWall";
  3990.     *x = iNil;
  3991.     *y = iNil;
  3992.     infl = 11;
  3993.     for (i = 2; i <= maxPoint - 2; i++)
  3994.       for (j = 2; j <= maxPoint - 2; j++)
  3995.         if (legal[i][j])
  3996.           if (connectMap[i][j] > 0)
  3997.             if ((claim[i][j] < infl) &&
  3998.                (ndbord[i - 1][j] < 1) &&
  3999.                (ndbord[i + 1][j] < 1) &&
  4000.                (ndbord[i][j - 1] < 1) &&
  4001.                (ndbord[i][j + 1] < 1) &&
  4002.                ((claim[i - 1][j] < 0) ||
  4003.                 (claim[i + 1][j] < 0) ||
  4004.                 (claim[i][j - 1] < 0) ||
  4005.                 (claim[i][j + 1] < 0)))
  4006.               if (safeMove(i, j))
  4007.                 {
  4008.                   infl = claim[i][j];
  4009.                   *x = i;
  4010.                   *y = j;
  4011.                 }
  4012.     if (*x != iNil) return TRUE;
  4013.     return FALSE;
  4014.   } /* extendWall */
  4015.  
  4016.  
  4017.   /*
  4018.     check to see if I can attack one of his groups
  4019.     uses limited depth search so that it can work on larger lib counts
  4020.   */
  4021. short findAttack2(x, y)
  4022. short *x, *y;
  4023.   { /* findAttack2 */
  4024.     short tx, ty, i, otll;
  4025.     if (playLevel < 7)
  4026.       return FALSE;
  4027.     playReason = "findAttack2";
  4028.     depthLimit = 8;
  4029.     otll = treeLibLim;
  4030.     for (i = 1; i <= maxGroupID; i++)       /* scan the group list */
  4031.         if ((! gList[i].isLive) &&
  4032.            (ndbord[gList[i].lx][gList[i].ly] == -1) &&
  4033.            (gList[i].libC > 1))
  4034.               {
  4035.                 treeLibLim = 6;
  4036.                 if (killable(gList[i].lx, gList[i].ly, &tx, &ty)) /* can we kill it? */
  4037.                   {
  4038.                     *x = tx;        /* yep - do so */
  4039.                     *y = ty;
  4040.                     return TRUE;
  4041.                   }
  4042.                 treeLibLim = otll;
  4043.               }
  4044.     depthLimit = 100;
  4045.     return FALSE;
  4046.   } /* findAttack2 */
  4047.  
  4048.  
  4049.   /*
  4050.     blocks enemy cuts thru 1-point extensions
  4051.   */
  4052. short blockCut(x, y)
  4053. short *x, *y;
  4054.   { /* blockCut */
  4055.     short i, j;
  4056.     playReason = "blockCut";
  4057.     for (i = 0; i <= maxPoint; i++)
  4058.       for (j = 0; j <= maxPoint; j++)
  4059.         if (legal[i][j])
  4060.           {
  4061.             if ((i > 0) && (j > 0) && (j < maxPoint))
  4062.               {
  4063.                 if ((ndbord[i - 1][j] == -1) &&
  4064.                    (ndbord[i - 1][j - 1] == 1) &&
  4065.                    (ndbord[i - 1][j + 1] == 1) &&
  4066.                    (groupIDs[i - 1][j - 1] != groupIDs[i - 1][j + 1]))
  4067.                   {
  4068.                     *x = i;
  4069.                     *y = j;
  4070.                     if (heCanCut(*x, *y))
  4071.                       if (safeMove(*x, *y))
  4072.                         return TRUE;
  4073.                   }
  4074.               }
  4075.             if ((i < maxPoint) && (j > 0) && (j < maxPoint))
  4076.               {
  4077.                 if ((ndbord[i + 1][j] == -1) &&
  4078.                    (ndbord[i + 1][j - 1] == 1) &&
  4079.                    (ndbord[i + 1][j + 1] == 1) &&
  4080.                    (groupIDs[i + 1][j - 1] != groupIDs[i + 1][j + 1]))
  4081.                   {
  4082.                     *x = i;
  4083.                     *y = j;
  4084.                     if (heCanCut(*x, *y))
  4085.                       if (safeMove(*x, *y))
  4086.                         return TRUE;
  4087.                   }
  4088.               }
  4089.             if ((j > 0) && (i > 0) && (i < maxPoint))
  4090.               {
  4091.                 if ((ndbord[i][j - 1] == -1) &&
  4092.                    (ndbord[i - 1][j - 1] == 1) &&
  4093.                    (ndbord[i + 1][j - 1] == 1) &&
  4094.                    (groupIDs[i - 1][j - 1] != groupIDs[i + 1][j - 1]))
  4095.                   {
  4096.                     *x = i;
  4097.                     *y = j;
  4098.                     if (heCanCut(*x, *y))
  4099.                       if (safeMove(*x, *y))
  4100.                         return TRUE;
  4101.                   }
  4102.               }
  4103.             if ((j < maxPoint) && (i > 0) && (i < maxPoint))
  4104.               {
  4105.                 if ((ndbord[i][j + 1] == -1) &&
  4106.                    (ndbord[i - 1][j + 1] == 1) &&
  4107.                    (ndbord[i + 1][j + 1] == 1) &&
  4108.                    (groupIDs[i - 1][j + 1] != groupIDs[i + 1][j + 1]))
  4109.                   {
  4110.                    *x = i;
  4111.                    *y = j;
  4112.                     if (heCanCut(*x, *y))
  4113.                       if (safeMove(*x, *y))
  4114.                         return TRUE;
  4115.                   }
  4116.               }
  4117.           }
  4118.     return FALSE;
  4119.   } /* blockCut */
  4120.  
  4121.  
  4122.   /*
  4123.     cuts the enemy
  4124.   */
  4125. short cutHim(x, y)
  4126. short *x, *y;
  4127.   { /* cutHim */
  4128.     short i, j, nap, gid;
  4129.     playReason = "cutHim";
  4130.     for (i = 0; i <= maxPoint; i++)
  4131.       for (j = 0; j <= maxPoint; j++)
  4132.         if (legal[i][j])
  4133.           {
  4134.             nap = 0;     /* how many of his stones am I adjacent to? */
  4135.             if ((i > 0) && (ndbord[i - 1][j] == -1))
  4136.               {
  4137.                 nap = nap + 1;
  4138.                 pList.p[nap].px = i - 1;
  4139.                 pList.p[nap].py = j;
  4140.               }
  4141.             if ((j > 0) && (ndbord[i][j - 1] == -1))
  4142.               {
  4143.                 nap = nap + 1;
  4144.                 pList.p[nap].px = i;
  4145.                 pList.p[nap].py = j - 1;
  4146.               }
  4147.             if ((i < maxPoint) && (ndbord[i + 1][j] == -1))
  4148.               {
  4149.                 nap = nap + 1;
  4150.                 pList.p[nap].px = i + 1;
  4151.                 pList.p[nap].py = j;
  4152.               }
  4153.             if ((j < maxPoint) && (ndbord[i][j + 1] == -1))
  4154.               {
  4155.                 nap = nap + 1;
  4156.                 pList.p[nap].px = i;
  4157.                 pList.p[nap].py = j + 1;
  4158.               }
  4159.             if (nap == 1) /* possible knight's or 2-point extention */
  4160.                 {
  4161.                   gid = groupIDs[pList.p[1].px][pList.p[1].py];
  4162.                   if ((i > 0) && (i < maxPoint) &&
  4163.                      (ndbord[i - 1][j] == -1) &&
  4164.                      (connectMap[i][j] > 0)) /* contact on left */
  4165.                     {
  4166.                       if (((j > 0) &&
  4167.                           (ndbord[i + 1][j - 1] == -1) &&
  4168.                           (gid != groupIDs[i + 1][j - 1])) ||
  4169.                          ((j < maxPoint) &&
  4170.                           (ndbord[i + 1][j + 1] == -1) &&
  4171.                           (gid != groupIDs[i + 1][j + 1])) ||
  4172.                          ((i < (maxPoint - 1)) &&
  4173.                           (ndbord[i + 1][j] == 0) &&
  4174.                           (ndbord[i + 2][j] == -1) &&
  4175.                           (gid != groupIDs[i + 2][j])))
  4176.                         {
  4177.                           *x = i;
  4178.                           *y = j;
  4179.                           if (safeMove(*x, *y))
  4180.                             return TRUE;
  4181.                         }
  4182.                     }
  4183.                   else if ((i < maxPoint) && (i > 0) &&
  4184.                           (ndbord[i + 1][j] == -1) &&
  4185.                           (connectMap[i][j] > 0)) /* r */
  4186.                     {
  4187.                       if (((j > 0) &&
  4188.                           (ndbord[i - 1][j - 1] == -1) &&
  4189.                           (gid != groupIDs[i - 1][j - 1])) ||
  4190.                          ((j < maxPoint) &&
  4191.                           (ndbord[i - 1][j + 1] == -1) &&
  4192.                           (gid != groupIDs[i - 1][j + 1])) ||
  4193.                          ((i > 1) &&
  4194.                           (ndbord[i - 1][j] == 0) &&
  4195.                           (ndbord[i - 2][j] == -1) &&
  4196.                           (gid != groupIDs[i - 2][j])))
  4197.                         {
  4198.                           *x = i;
  4199.                           *y = j;
  4200.                           if (safeMove(*x, *y))
  4201.                             return TRUE;
  4202.                         }
  4203.                     }
  4204.                   else if ((j > 0) && (j < maxPoint) &&
  4205.                           (ndbord[i][j - 1] == -1) &&
  4206.                           (connectMap[i][j] > 0)) /* top */
  4207.                     {
  4208.                       if (((i > 0) &&
  4209.                           (ndbord[i - 1][j + 1] == -1) &&
  4210.                           (gid != groupIDs[i - 1][j + 1])) ||
  4211.                          ((i < maxPoint) &&
  4212.                           (ndbord[i + 1][j + 1] == -1) &&
  4213.                           (gid != groupIDs[i + 1][j + 1])) ||
  4214.                          ((j < (maxPoint - 1)) &&
  4215.                           (ndbord[i][j + 1] == 0) &&
  4216.                           (ndbord[i][j + 2] == -1) &&
  4217.                           (gid != groupIDs[i][j + 2])))
  4218.                         {
  4219.                           *x = i;
  4220.                           *y = j;
  4221.                           if (safeMove(*x, *y))
  4222.                             return TRUE;
  4223.                         }
  4224.                     }
  4225.                   else if ((j > 0) && (j < maxPoint) &&
  4226.                           (ndbord[i][j + 1] == -1) &&
  4227.                           (connectMap[i][j] > 0)) /* bottom */
  4228.                     {
  4229.                       if (((i > 0) &&
  4230.                           (ndbord[i - 1][j - 1] == -1) &&
  4231.                           (gid != groupIDs[i - 1][j - 1])) ||
  4232.                          ((i < maxPoint) &&
  4233.                           (ndbord[i + 1][j - 1] == -1) &&
  4234.                           (gid != groupIDs[i + 1][j - 1])) ||
  4235.                          ((j > 1) &&
  4236.                           (ndbord[i][j - 1] == 0) &&
  4237.                           (ndbord[i][j - 2] == -1) &&
  4238.                           (gid != groupIDs[i][j - 2])))
  4239.                         {
  4240.                           *x = i;
  4241.                           *y = j;
  4242.                           if (safeMove(*x, *y))
  4243.                             return TRUE;
  4244.                         }
  4245.                     }
  4246.                 }
  4247.             else if (nap == 2) /* diagonal or 1-point extention */
  4248.               {
  4249.                 if (groupIDs[pList.p[1].px][pList.p[1].py] !=
  4250.                    groupIDs[pList.p[2].px][pList.p[2].py])
  4251.                   {
  4252.                     if ((pList.p[1].px != pList.p[2].px) &&
  4253.                        (pList.p[1].py != pList.p[2].py)) /* diag */
  4254.                       {
  4255.                         spanGroup(pList.p[1].px,
  4256.                                   pList.p[1].py, &pList1);
  4257.                         spanGroup(pList.p[2].px,
  4258.                                   pList.p[2].py, &plist2);
  4259.                         intersectPlist(&pList1, &plist2, &plist3);
  4260.                         if (plist3.indx == 1)
  4261.                           {
  4262.                             *x = i;
  4263.                             *y = j;
  4264.                             if (safeMove(*x, *y))
  4265.                               return TRUE;
  4266.                           }
  4267.                       }
  4268.                     else /* 1-point extension, only cut if connected */
  4269.                       {
  4270.                         if (connectMap[i][j] > 0)
  4271.                           {
  4272.                             *x = i;
  4273.                             *y = j;
  4274.                             if (safeMove(*x, *y))
  4275.                               return TRUE;
  4276.                           }
  4277.                       }
  4278.                   }
  4279.               }
  4280.             else if (nap == 3) /* unprotected, but him on 3 sides */
  4281.               {
  4282.                 if ((groupIDs[pList.p[1].px][pList.p[1].py] !=
  4283.                     groupIDs[pList.p[2].px][pList.p[2].py]) ||
  4284.                    (groupIDs[pList.p[1].px][pList.p[1].py] !=
  4285.                     groupIDs[pList.p[3].px][pList.p[3].py]) ||
  4286.                    (groupIDs[pList.p[3].px][pList.p[3].py] !=
  4287.                     groupIDs[pList.p[2].px][pList.p[2].py]))
  4288.                   {
  4289.                     spanGroup(pList.p[1].px, pList.p[1].py, &pList1);
  4290.                     spanGroup(pList.p[2].px, pList.p[2].py, &plist2);
  4291.                     intersectPlist(&pList1, &plist2, &plist3);
  4292.                     spanGroup(pList.p[3].px, pList.p[3].py, &plist2);
  4293.                     intersectPlist(&plist2, &plist3, &pList1);
  4294.                     if (pList1.indx == 1) /* a common connect point */
  4295.                       if (safeMove(i, j))
  4296.                         {
  4297.                           *x = i;
  4298.                           *y = j;
  4299.                           return TRUE;
  4300.                         }
  4301.                   }
  4302.               }
  4303.           }
  4304.     return FALSE;
  4305.   } /* cutHim */
  4306.  
  4307.  
  4308.   /*
  4309.     ataris a group just for the hell of it
  4310.   */
  4311. short atariAnyway(x, y)
  4312. short *x, *y;
  4313.   { /* atariAnyway */
  4314.     short i;
  4315.     playReason = "atariAnyway";
  4316.     for (i = 1; i <= maxGroupID; i++)       /* scan the group list */
  4317.         if ((gList[i].libC == 2) &&
  4318.            (ndbord[gList[i].lx][gList[i].ly] == -1)) 
  4319.               {
  4320.                 spanGroup(gList[i].lx, gList[i].ly, &pList);
  4321.                   if (legal[pList.p[1].px][pList.p[1].py] &&
  4322.                      ((connectMap[pList.p[1].px][pList.p[1].py] > 0) ||
  4323.                       ((pList.p[1].px > 0) &&
  4324.                (connectMap[pList.p[1].px - 1][pList.p[1].py] > 0)) ||
  4325.                       ((pList.p[1].px < maxPoint) &&
  4326.                (connectMap[pList.p[1].px + 1][pList.p[1].py] > 0)) ||
  4327.                       ((pList.p[1].py > 0) &&
  4328.                (connectMap[pList.p[1].px][pList.p[1].py - 1] > 0)) ||
  4329.                       ((pList.p[1].py < maxPoint) &&
  4330.                (connectMap[pList.p[1].px][pList.p[1].py + 1] > 0))))
  4331.                     if (safeMove(pList.p[1].px, pList.p[1].py))
  4332.                       {
  4333.                         *x = pList.p[1].px;
  4334.                         *y = pList.p[1].py;
  4335.                         return TRUE;
  4336.                       }
  4337.                   if (legal[pList.p[2].px][pList.p[2].py] &&
  4338.                      ((connectMap[pList.p[2].px][pList.p[2].py] > 0) ||
  4339.                       ((pList.p[2].px > 0) &&
  4340.                (connectMap[pList.p[2].px - 1][pList.p[2].py] > 0)) ||
  4341.                       ((pList.p[2].px < maxPoint) &&
  4342.                (connectMap[pList.p[2].px + 1][pList.p[2].py] > 0)) ||
  4343.                       ((pList.p[2].py > 0) &&
  4344.                (connectMap[pList.p[2].px][pList.p[2].py - 1] > 0)) ||
  4345.                       ((pList.p[2].py < maxPoint) &&
  4346.                (connectMap[pList.p[2].px][pList.p[2].py + 1] > 0))))
  4347.                     if (safeMove(pList.p[2].px, pList.p[2].py))
  4348.                       {
  4349.                         *x = pList.p[2].px;
  4350.                         *y = pList.p[2].py;
  4351.                         return TRUE;
  4352.                       }
  4353.               }
  4354.     return FALSE;
  4355.   } /* atariAnyway */
  4356.  
  4357.  
  4358.   /*
  4359.     undercuts his groups
  4360.   */
  4361. short underCut(x, y)
  4362. short *x, *y;
  4363.   { /* underCut */
  4364.     short i, j;
  4365.     playReason = "underCut";
  4366.     for (i = 1; i <= maxPoint - 1; i++)
  4367.       {
  4368.         if (legal[0][i])
  4369.           {
  4370.             if (ndbord[1][i] == -1)
  4371.               if (safeMove(0, i))
  4372.                 {
  4373.                   *x = 0;
  4374.                   *y = i;
  4375.                   return TRUE;
  4376.                 }
  4377.           }
  4378.         if (legal[maxPoint][i])
  4379.           {
  4380.             if (ndbord[maxPoint - 1][i] == -1)
  4381.               if (safeMove(maxPoint, i))
  4382.                 {
  4383.                   *x = maxPoint;
  4384.                   *y = i;
  4385.                   return TRUE;
  4386.                 }
  4387.           }
  4388.         if (legal[i][0])
  4389.           {
  4390.             if (ndbord[i][1] == -1)
  4391.               if (safeMove(i, 0))
  4392.                 {
  4393.                   *x = i;
  4394.                   *y = 0;
  4395.                   return TRUE;
  4396.                 }
  4397.           }
  4398.         if (legal[i][maxPoint])
  4399.           {
  4400.             if (ndbord[i][maxPoint - 1] == -1)
  4401.               if (safeMove(i, maxPoint))
  4402.                 {
  4403.                   *x = i;
  4404.                   *y = maxPoint;
  4405.                   return TRUE;
  4406.                 }
  4407.           }
  4408.       }
  4409.     return FALSE;
  4410.   } /* underCut */
  4411.  
  4412.   /*
  4413.     drops to the edge of the board if threatened
  4414.   */
  4415. short dropToEdge(x, y)
  4416. short *x, *y;
  4417.   { /* dropToEdge */
  4418.     short i;
  4419.     playReason = "dropToEdge";
  4420.     for (i = 1; i <= maxPoint - 1; i++)
  4421.       {
  4422.         if (legal[1][i])
  4423.           if ((ndbord[2][i] == 1) &&
  4424.              (ndbord[0][i] == 0) &&
  4425.              (ndbord[1][i - 1] < 1) &&
  4426.              (ndbord[1][i + 1] < 1) &&
  4427.              ((ndbord[2][i - 1] == -1) ||
  4428.               (ndbord[2][i + 1] == -1) ||
  4429.               (ndbord[1][i - 1] == -1) ||
  4430.               (ndbord[1][i + 1] == -1)))
  4431.             {
  4432.               *x = 1;
  4433.               *y = i;
  4434.               if (safeMove(*x, *y))
  4435.                 return TRUE;
  4436.             }
  4437.         if (legal[maxPoint - 1][i])
  4438.           if ((ndbord[maxPoint - 2][i] == 1) &&
  4439.              (ndbord[maxPoint][i] == 0) &&
  4440.              (ndbord[maxPoint - 1][i - 1] < 1) &&
  4441.              (ndbord[maxPoint - 1][i + 1] < 1) &&
  4442.              ((ndbord[maxPoint - 2][i - 1] == -1) ||
  4443.               (ndbord[maxPoint - 2][i + 1] == -1) ||
  4444.               (ndbord[maxPoint - 1][i - 1] == -1) ||
  4445.               (ndbord[maxPoint - 1][i + 1] == -1)))
  4446.             {
  4447.               *x = maxPoint - 1;
  4448.               *y = i;
  4449.               if (safeMove(*x, *y))
  4450.                 return TRUE;
  4451.             }
  4452.         if (legal[i][1])
  4453.           if ((ndbord[i][2] == 1) &&
  4454.              (ndbord[i][0] == 0) &&
  4455.              (ndbord[i - 1][1] < 1) &&
  4456.              (ndbord[i + 1][1] < 1) &&
  4457.              ((ndbord[i - 1][2] == -1) ||
  4458.               (ndbord[i + 1][2] == -1) ||
  4459.               (ndbord[i - 1][1] == -1) ||
  4460.               (ndbord[i + 1][1] == -1)))
  4461.             {
  4462.               *x = i;
  4463.               *y = 1;
  4464.               if (safeMove(*x, *y))
  4465.                 return TRUE;
  4466.             }
  4467.         if (legal[i][maxPoint - 1])
  4468.           if ((ndbord[i][maxPoint - 2] == 1) &&
  4469.              (ndbord[i][maxPoint] == 0) &&
  4470.              (ndbord[i - 1][maxPoint - 1] < 1) &&
  4471.              (ndbord[i + 1][maxPoint - 1] < 1) &&
  4472.              ((ndbord[i - 1][maxPoint - 2] == -1) ||
  4473.               (ndbord[i + 1][maxPoint - 2] == -1) ||
  4474.               (ndbord[i - 1][maxPoint - 1] == -1) ||
  4475.               (ndbord[i + 1][maxPoint - 1] == -1)))
  4476.             {
  4477.               *x = i;
  4478.               *y = maxPoint - 1;
  4479.               if (safeMove(*x, *y))
  4480.                 return TRUE;
  4481.             }
  4482.         if (legal[0][i])
  4483.           if ((ndbord[1][i] == 1) &&
  4484.              (ndbord[0][i - 1] < 1) &&
  4485.              (ndbord[0][i + 1] < 1) &&
  4486.              (((ndbord[1][i - 1] == -1) &&
  4487.                (ndbord[1][i + 1] == -1)) ||
  4488.               (ndbord[0][i - 1] == -1) ||
  4489.               (ndbord[0][i + 1] == -1)))
  4490.             {
  4491.               *x = 0;
  4492.               *y = i;
  4493.               if (safeMove(*x, *y))
  4494.                 return TRUE;
  4495.             }
  4496.         if (legal[maxPoint][i])
  4497.           if ((ndbord[maxPoint - 1][i] == 1) &&
  4498.              (ndbord[maxPoint][i - 1] < 1) &&
  4499.              (ndbord[maxPoint][i + 1] < 1) &&
  4500.              (((ndbord[maxPoint - 1][i - 1] == -1) &&
  4501.                (ndbord[maxPoint - 1][i + 1] == -1)) ||
  4502.               (ndbord[maxPoint][i - 1] == -1) ||
  4503.               (ndbord[maxPoint][i + 1] == -1)))
  4504.             {
  4505.               *x = maxPoint;
  4506.               *y = i;
  4507.               if (safeMove(*x, *y))
  4508.                 return TRUE;
  4509.             }
  4510.         if (legal[i][0])
  4511.           if ((ndbord[i][1] == 1) &&
  4512.              (ndbord[i - 1][0] < 1) &&
  4513.              (ndbord[i + 1][0] < 1) &&
  4514.              (((ndbord[i - 1][1] == -1) &&
  4515.                (ndbord[i + 1][1] == -1)) ||
  4516.               (ndbord[i - 1][0] == -1) ||
  4517.               (ndbord[i + 1][0] == -1)))
  4518.             {
  4519.               *x = i;
  4520.               *y = 0;
  4521.               if (safeMove(*x, *y))
  4522.                 return TRUE;
  4523.             }
  4524.         if (legal[i][maxPoint])
  4525.           if ((ndbord[i][maxPoint - 1] == 1) &&
  4526.              (ndbord[i - 1][maxPoint] < 1) &&
  4527.              (ndbord[i + 1][maxPoint] < 1) &&
  4528.              (((ndbord[i - 1][maxPoint - 1] == -1) &&
  4529.                (ndbord[i + 1][maxPoint - 1] == -1)) ||
  4530.               (ndbord[i - 1][maxPoint] == -1) ||
  4531.               (ndbord[i + 1][maxPoint] == -1)))
  4532.             {
  4533.               *x = i;
  4534.               *y = maxPoint;
  4535.               if (safeMove(*x, *y))
  4536.                 return TRUE;
  4537.             }
  4538.       }
  4539.     return FALSE;
  4540.   } /* dropToEdge */
  4541.  
  4542.   /*
  4543.     Pushes walls in a tightly connected fashion.
  4544.     Finds the lowest influence (mine) point that is connected to one
  4545.     of my groups.
  4546.   */
  4547. short pushWall(x, y)
  4548. short *x, *y;
  4549.   { /* pushWall */
  4550.     short infl, i, j, na;
  4551.     playReason = "pushWall";
  4552.     *x = iNil;
  4553.     *y = iNil;
  4554.     infl = 11;
  4555.     for (i = 0; i <= maxPoint; i++)
  4556.       for (j = 0; j <= maxPoint; j++)
  4557.         if (legal[i][j])
  4558.           if (connectMap[i][j] > 0)
  4559.             if ((claim[i][j] < infl) &&
  4560.                (((i > 0) && (ndbord[i - 1][j] == 1)) ||
  4561.                 ((i < maxPoint) && (ndbord[i + 1][j] == 1)) ||
  4562.                 ((j > 0) && (ndbord[i][j - 1] == 1)) ||
  4563.                 ((j < maxPoint) && (ndbord[i][j + 1] == 1)) ||
  4564.                 ((i > 0) && (j > 0) && (ndbord[i - 1][j - 1] == 1)) ||
  4565.                 ((i < maxPoint) && (j > 0) && (ndbord[i + 1][j - 1] == 1)) ||
  4566.                 ((i > 0) && (j < maxPoint) && (ndbord[i - 1][j + 1] == 1)) ||
  4567.                 ((i < maxPoint) && (j < maxPoint) &&
  4568.                  (ndbord[i + 1][j + 1] == 1))) &&
  4569.                (((i > 0) && (claim[i - 1][j] < 0)) ||
  4570.                 ((i < maxPoint) && (claim[i + 1][j] < 0)) ||
  4571.                 ((j > 0) && (claim[i][j - 1] < 0)) ||
  4572.                 ((j < maxPoint) && (claim[i][j + 1] < 0))))
  4573.               {
  4574.                 na = 0;
  4575.                 if ((i > 0) && (ndbord[i - 1][j] != 0))
  4576.                   na = na + 1;
  4577.                 if ((i < maxPoint) && (ndbord[i + 1][j] != 0))
  4578.                   na = na + 1;
  4579.                 if ((j > 0) && (ndbord[i][j - 1] != 0))
  4580.                   na = na + 1;
  4581.                 if ((j < maxPoint) && (ndbord[i][j + 1] != 0))
  4582.                   na = na + 1;
  4583.                 if (na < 3)
  4584.                   if (safeMove(i, j))
  4585.                     {
  4586.                       infl = claim[i][j];
  4587.                       *x = i;
  4588.                       *y = j;
  4589.                     }
  4590.               }
  4591.     if (*x != iNil) return TRUE;
  4592.     return FALSE;
  4593.   } /* pushWall */
  4594.  
  4595.  
  4596.   /*
  4597.     reduces the liberty count of one of his groups
  4598.   */
  4599. short reduceHisLiberties(x, y)
  4600. short *x, *y;
  4601.   { /* reduceHisLiberties */
  4602.     short i, j;
  4603.     playReason = "reduceHisLiberties";
  4604.     sortLibs();
  4605.     for (i = 1; i <= maxGroupID; i++)
  4606.         if ((! gList[sGlist[i]].isLive) &&
  4607.            (gList[sGlist[i]].libC > 2) &&
  4608.            (ndbord[gList[sGlist[i]].lx][gList[sGlist[i]].ly] == -1))
  4609.           {
  4610.             spanGroup(gList[sGlist[i]].lx, gList[sGlist[i]].ly, &pList);
  4611.             for (j = 1; j <= pList.indx; j++)
  4612.                 if (legal[pList.p[j].px][pList.p[j].py] &&
  4613.                    (connectMap[pList.p[j].px][pList.p[j].py] > 0))
  4614.                   if (safeMove(pList.p[j].px, pList.p[j].py))
  4615.                     {
  4616.                       *x = pList.p[j].px;
  4617.                       *y = pList.p[j].py;
  4618.                       return TRUE;
  4619.                     }
  4620.           }
  4621.     return FALSE;
  4622.   } /* reduceHisLiberties */
  4623.  
  4624.  
  4625.   /*
  4626.     connects a group to the edge
  4627.   */
  4628. short dropToEdge2(x, y)
  4629. short *x, *y;
  4630.   { /* dropToEdge2 */
  4631.     short i;
  4632.     playReason = "dropToEdge2";
  4633.     for (i = 1; i <= maxPoint - 1; i++)
  4634.       {
  4635.         if (legal[i][0])
  4636.           {
  4637.             if ((ndbord[i][1] == 1) &&
  4638.                ((ndbord[i - 1][0] < 1) ||
  4639.                 (groupIDs[i - 1][0] != groupIDs[i][1])) &&
  4640.                ((ndbord[i + 1][0] < 1) ||
  4641.                 (groupIDs[i + 1][0] != groupIDs[i][1])) &&
  4642.                ((ndbord[i - 1][1] == -1) ||
  4643.                 (ndbord[i + 1][1] == -1)))
  4644.               {
  4645.                 *x = i;
  4646.                 *y = 0;
  4647.                 if (safeMove(*x, *y))
  4648.                   return TRUE;
  4649.               }
  4650.           }
  4651.         if (legal[0][i])
  4652.           {
  4653.             if ((ndbord[1][i] == 1) &&
  4654.                ((ndbord[0][i - 1] < 1) ||
  4655.                 (groupIDs[0][i - 1] != groupIDs[1][i])) &&
  4656.                ((ndbord[0][i + 1] < 1) ||
  4657.                 (groupIDs[0][i + 1] != groupIDs[1][i])) &&
  4658.                ((ndbord[1][i - 1] == -1) ||
  4659.                 (ndbord[1][i + 1] == -1)))
  4660.               {
  4661.                 *x = 0;
  4662.                 *y = i;
  4663.                 if (safeMove(*x, *y))
  4664.                   return TRUE;
  4665.               }
  4666.           }
  4667.         if (legal[i][maxPoint])
  4668.           {
  4669.             if ((ndbord[i][maxPoint - 1] == 1) &&
  4670.                ((ndbord[i - 1][maxPoint] < 1) ||
  4671.                 (groupIDs[i - 1][maxPoint] != groupIDs[i][maxPoint - 1])) &&
  4672.                ((ndbord[i + 1][maxPoint] < 1) ||
  4673.                 (groupIDs[i + 1][maxPoint] != groupIDs[i][maxPoint - 1])) &&
  4674.                ((ndbord[i - 1][maxPoint - 1] == -1) ||
  4675.                 (ndbord[i + 1][maxPoint - 1] == -1)))
  4676.               {
  4677.                 *x = i;
  4678.                 *y = maxPoint;
  4679.                 if (safeMove(*x, *y))
  4680.                   return TRUE;
  4681.               }
  4682.           }
  4683.         if (legal[maxPoint][i])
  4684.           {
  4685.             if ((ndbord[maxPoint - 1][i] == 1) &&
  4686.                ((ndbord[maxPoint][i - 1] < 1) ||
  4687.                 (groupIDs[maxPoint][i - 1] != groupIDs[maxPoint - 1][i])) &&
  4688.                ((ndbord[maxPoint][i + 1] < 1) ||
  4689.                 (groupIDs[maxPoint][i + 1] != groupIDs[maxPoint - 1][i])) &&
  4690.                ((ndbord[maxPoint - 1][i - 1] == -1) ||
  4691.                 (ndbord[maxPoint - 1][i + 1] == -1)))
  4692.               {
  4693.                 *x = maxPoint;
  4694.                 *y = i;
  4695.                 if (safeMove(*x, *y))
  4696.                   return TRUE;
  4697.               }
  4698.           }
  4699.       }
  4700.     return FALSE;
  4701.   } /* dropToEdge2 */
  4702.  
  4703. SHAR_EOF
  4704. fi
  4705. if test -f 'goplayutils.c'
  4706. then
  4707.     echo shar: "will not over-write existing file 'goplayutils.c'"
  4708. else
  4709. cat << \SHAR_EOF > 'goplayutils.c'
  4710. /* The go player utilities */
  4711. /* Ported from Pascal to C by Todd R. Johnson */
  4712. /* From the original Pascal file:
  4713. Copyright (c) 1983 by Three Rivers Computer Corp.
  4714.  
  4715. Written: January 17, 1983 by Stoney Ballard
  4716. */
  4717.  
  4718. #include "goplayutils.h"
  4719. #include "amigo.h"
  4720. #include "go.h"
  4721.  
  4722. extern struct bRec goboard[19][19];
  4723.  
  4724. intBoard  claim, extra, bord, ndbord, sGroups, threatBord,
  4725.           groupIDs, connectMap, protPoints;
  4726. boolBoard  groupSeen, legal;
  4727. short maxGroupID;
  4728. pointList pList, pList1, plist2, plist3, pPlist;
  4729. intList nlcGroup, aList;
  4730. sgRec sList[401];
  4731. groupRec gList[maxGroup];
  4732. short killFlag,
  4733.       numCapt,
  4734.       utilPlayLevel,
  4735.       treeLibLim;
  4736. sType mySType;
  4737. short showTrees;
  4738. short sGlist[maxGroup+1];
  4739. short depthLimit;
  4740. intBoard markBoard;
  4741. short marker;
  4742.  
  4743. short adjInAtari, adj2Libs,
  4744.   intersectNum, spanNum, libMark;
  4745. playRec playStack[1025];
  4746. short playMark,
  4747.   newGID,
  4748.   tryLevel,
  4749.   grpMark,
  4750.   gMap[maxGroup];
  4751. short dbStop, inGenState;
  4752.  
  4753.  pause()
  4754. { /* pause */
  4755. /*  if (dbStop and ! inGenState)
  4756.     {
  4757.       while ! tabswitch do;
  4758.       repeat
  4759.         if (tabYellow)
  4760.           dbStop = false;
  4761.       until ! tabswitch;
  4762.     }     */
  4763. } /* pause */
  4764.  
  4765. sstone(w, x, y, numb)
  4766. short w, x, y, numb;
  4767. { /* sstone */
  4768.   if (w == 1)
  4769.     placestone(mySType, x, y);
  4770.   else if (mySType == WHITE)
  4771.     placestone(BLACK, x, y);
  4772.   else
  4773.     placestone(WHITE, x, y);
  4774. } /* sstone */
  4775.  
  4776. rstone(x, y)
  4777. short x, y;
  4778. { /* rstone */
  4779.   removestone(x, y);
  4780. } /* rstone */
  4781.  
  4782. initBoolBoard(bb)
  4783. boolBoard bb;
  4784. { /* initBoolBoard */
  4785.   short i, j;
  4786. #ifdef DEBUG
  4787.   printf( "initBoolBoard\n" );
  4788. #endif
  4789.   for (i = 0; i <= maxPoint; i++)
  4790.     for (j = 0; j <= maxPoint; j++)
  4791.       bb[i][j] = FALSE;
  4792. } /* initBoolBoard */
  4793.  
  4794. sortLibs()
  4795. { /* sortLibs */
  4796.   short i, j, t;
  4797. #ifdef DEBUG
  4798.   printf( "sortLibs\n" );
  4799. #endif
  4800.   for (i = 1; i <= maxGroupID; i++)
  4801.     sGlist[i] = i;
  4802.   for (i = 1; i < maxGroupID; i++)
  4803.     for (j = i + 1; j <= maxGroupID; j++)
  4804.       if (gList[sGlist[i]].libC > gList[sGlist[j]].libC)
  4805.         {
  4806.           t = sGlist[i];
  4807.           sGlist[i] = sGlist[j];
  4808.           sGlist[j] = t;
  4809.         }
  4810. } /* sortLibs */
  4811.  
  4812. spanGroupspan(x, y, libs, lookFor)
  4813. short x, y, lookFor;
  4814. pointList *libs;
  4815.   { /* span */
  4816.     markBoard[x][y] = marker;
  4817.     if (bord[x][y] == 0)
  4818.       {
  4819.         libs->indx = libs->indx + 1;
  4820.         libs->p[libs->indx].px = x;
  4821.         libs->p[libs->indx].py = y;
  4822.       }
  4823.     else if (bord[x][y] == lookFor)
  4824.       {
  4825.         groupSeen[x][y] = TRUE;
  4826.         if ((x > 0) && (markBoard[x - 1][y] != marker))
  4827.           spanGroupspan(x - 1, y, libs, lookFor);
  4828.         if ((y > 0) && (markBoard[x][y - 1] != marker))
  4829.           spanGroupspan(x, y - 1, libs, lookFor);
  4830.         if ((x < maxPoint) && (markBoard[x + 1][y] != marker))
  4831.           spanGroupspan(x + 1, y, libs, lookFor);
  4832.         if ((y < maxPoint) && (markBoard[x][y + 1] != marker))
  4833.           spanGroupspan(x, y + 1, libs, lookFor);
  4834.       }
  4835.     else if (gList[gMap[groupIDs[x][y]]].libC == 1)
  4836.       adjInAtari = TRUE;
  4837.     else if ((gList[gMap[groupIDs[x][y]]].libC == 2) &&
  4838.             (! gList[gMap[groupIDs[x][y]]].isLive))
  4839.       adj2Libs = TRUE; 
  4840.   } /* span */
  4841.  
  4842. spanGroup(x, y, libs)
  4843. short x, y;
  4844. pointList *libs;
  4845. { /* spanGroup */
  4846.   short lookFor;
  4847. #ifdef DEBUG
  4848.   printf( "spanGroup\n" );
  4849. #endif
  4850.   marker = marker + 1;
  4851.   if (marker == 0)
  4852.     {
  4853.       initArray(markBoard);
  4854.       marker = 1;
  4855.     }
  4856.   adjInAtari = FALSE;
  4857.   adj2Libs = FALSE;
  4858.   lookFor = bord[x][y];
  4859.   libs->indx = 0;
  4860.   spanGroupspan(x, y, libs, lookFor);
  4861. } /* spanGroup */
  4862.  
  4863. sSpanGroupspan(x, y, libs, lookFor)
  4864. short x, y, lookFor;
  4865. sPointList *libs;
  4866.   { /* span */
  4867.     markBoard[x][y] = marker;
  4868.     if (bord[x][y] == 0)
  4869.       {
  4870.         libs->indx += 1;
  4871.         if (libs->indx <= maxSPoint)
  4872.           {
  4873.             libs->p[libs->indx].px = x;
  4874.             libs->p[libs->indx].py = y;
  4875.           }
  4876.       }
  4877.     else if (bord[x][y] == lookFor)
  4878.       {
  4879.         groupSeen[x][y] = TRUE;
  4880.         if ((x > 0) && (markBoard[x - 1][y] != marker))
  4881.           sSpanGroupspan(x - 1, y, libs, lookFor);
  4882.         if ((y > 0) && (markBoard[x][y - 1] != marker))
  4883.           sSpanGroupspan(x, y - 1, libs, lookFor);
  4884.         if ((x < maxPoint) && (markBoard[x + 1][y] != marker))
  4885.           sSpanGroupspan(x + 1, y, libs, lookFor);
  4886.         if ((y < maxPoint) && (markBoard[x][y + 1] != marker))
  4887.           sSpanGroupspan(x, y + 1, libs, lookFor);
  4888.       }
  4889.     else if (gList[gMap[groupIDs[x][y]]].libC == 1)
  4890.       adjInAtari = TRUE;
  4891.     else if ((gList[gMap[groupIDs[x][y]]].libC == 2) &&
  4892.             (! gList[gMap[groupIDs[x][y]]].isLive)) 
  4893.       adj2Libs = TRUE; 
  4894.   } /* span */
  4895.  
  4896. sSpanGroup(x, y, libs)
  4897. short x, y;
  4898. sPointList *libs;
  4899. { /* sSpanGroup */
  4900.   short lookFor;
  4901. #ifdef DEBUG
  4902.   printf( "sSpanGroup\n" );
  4903. #endif
  4904.   marker = marker + 1;
  4905.   if (marker == 0)
  4906.     {
  4907.       initArray(markBoard);
  4908.       marker = 1;
  4909.     }
  4910.   adjInAtari = FALSE;
  4911.   adj2Libs = FALSE;
  4912.   lookFor = bord[x][y];
  4913.   libs->indx = 0;
  4914.   sSpanGroupspan(x, y, libs, lookFor);
  4915. } /* sSpanGroup */
  4916.  
  4917. LAspan(x, y, me, him, iL)
  4918. short x, y, me, him;
  4919. intList *iL;
  4920.   { /* span */
  4921. #ifdef DEBUG
  4922.   printf( "LAspan\n" );
  4923. #endif
  4924.     markBoard[x][y] = marker;
  4925.     if (bord[x][y] == me)
  4926.       {
  4927.         if ((x > 0) && (markBoard[x - 1][y] != marker))
  4928.           LAspan(x - 1, y, me, him, iL);
  4929.         if ((x < maxPoint) && (markBoard[x + 1][y] != marker))
  4930.           LAspan(x + 1, y, me, him, iL);
  4931.         if ((y > 0) && (markBoard[x][y - 1] != marker))
  4932.           LAspan(x, y - 1, me, him, iL);
  4933.         if ((y < maxPoint) && (markBoard[x][y + 1] != marker))
  4934.           LAspan(x, y + 1, me, him, iL);
  4935.       }
  4936.     else if (bord[x][y] == him)
  4937.       if (gList[gMap[groupIDs[x][y]]].groupMark != grpMark)
  4938.         {
  4939.           gList[gMap[groupIDs[x][y]]].groupMark = grpMark;
  4940.           iL->indx = iL->indx + 1;
  4941.           iL->v[iL->indx] = gMap[groupIDs[x][y]];
  4942.         }
  4943.   } /* span */
  4944.  
  4945. listAdjacents(x, y, iL)
  4946. short x, y;
  4947. intList *iL;
  4948. { /* listAdjacents */
  4949.   short me, him;
  4950. #ifdef DEBUG
  4951.   printf( "listAdjacents\n" );
  4952. #endif
  4953.   grpMark = grpMark + 1;
  4954.   marker = marker + 1;
  4955.   if (marker == 0)
  4956.     {
  4957.       initArray(markBoard);
  4958.       marker = 1;
  4959.     }
  4960.   iL->indx = 0;
  4961.   me = bord[x][y];
  4962.   him = -me;
  4963.   LAspan(x, y, me , him, iL);
  4964. } /* listAdjacents */
  4965.  
  4966. LDspan(x, y, me, diags)
  4967. short x, y, me;
  4968. sPointList *diags;
  4969.   { /* span */
  4970. #ifdef DEBUG
  4971.   printf( "LDspan\n" );
  4972. #endif
  4973.     markBoard[x][y] = marker;
  4974.     if ((x > 0) && (y > 0) &&
  4975.        (bord[x - 1][y - 1] == 0) &&
  4976.        (bord[x][y - 1] != me) &&
  4977.        (bord[x - 1][y] != me) &&
  4978.        (markBoard[x - 1][y - 1] != marker))
  4979.       {
  4980.         markBoard[x - 1][y - 1] = marker;
  4981.         diags->indx = diags->indx + 1;
  4982.         if (diags->indx <= maxSPoint)
  4983.             {
  4984.               diags->p[diags->indx].px = x - 1;
  4985.               diags->p[diags->indx].py = y - 1;
  4986.             }
  4987.       }
  4988.     if ((x < maxPoint) && (y > 0) &&
  4989.        (bord[x + 1][y - 1] == 0) &&
  4990.        (bord[x][y - 1] != me) &&
  4991.        (bord[x + 1][y] != me) &&
  4992.        (markBoard[x + 1][y - 1] != marker))
  4993.       {
  4994.         markBoard[x + 1][y - 1] = marker;
  4995.         diags->indx = diags->indx + 1;
  4996.         if (diags->indx <= maxSPoint)
  4997.        {
  4998.               diags->p[diags->indx].px = x + 1;
  4999.               diags->p[diags->indx].py = y - 1;
  5000.            }
  5001.       }
  5002.     if ((x > 0) && (y < maxPoint) &&
  5003.        (bord[x - 1][y + 1] == 0) &&
  5004.        (bord[x][y + 1] != me) &&
  5005.        (bord[x - 1][y] != me) &&
  5006.        (markBoard[x - 1][y + 1] != marker))
  5007.       {
  5008.         markBoard[x - 1][y + 1] = marker;
  5009.         diags->indx = diags->indx + 1;
  5010.         if (diags->indx <= maxSPoint)
  5011.             {
  5012.               diags->p[diags->indx].px = x - 1;
  5013.               diags->p[diags->indx].py = y + 1;
  5014.             }
  5015.       }
  5016.     if ((x < maxPoint) && (y < maxPoint) &&
  5017.        (bord[x + 1][y + 1] == 0) &&
  5018.        (bord[x][y + 1] != me) &&
  5019.        (bord[x + 1][y] != me) &&
  5020.        (markBoard[x + 1][y + 1] != marker))
  5021.       {
  5022.         markBoard[x + 1][y + 1] = marker;
  5023.         diags->indx = diags->indx + 1;
  5024.         if (diags->indx <= maxSPoint)
  5025.             {
  5026.               diags->p[diags->indx].px = x + 1;
  5027.               diags->p[diags->indx].py = y + 1;
  5028.             }
  5029.       }
  5030.     if ((x > 0) && (bord[x - 1][y] == me) &&
  5031.        (markBoard[x - 1][y] != marker))
  5032.       LDspan(x - 1, y, me, diags);
  5033.     if ((x < maxPoint) && (bord[x + 1][y] == me) &&
  5034.        (markBoard[x + 1][y] != marker))
  5035.       LDspan(x + 1, y, me, diags);
  5036.     if ((y > 0) && (bord[x][y - 1] == me) &&
  5037.        (markBoard[x][y - 1] != marker))
  5038.       LDspan(x, y - 1, me, diags);
  5039.     if ((y < maxPoint) && (bord[x][y + 1] == me) &&
  5040.        (markBoard[x][y + 1] != marker))
  5041.       LDspan(x, y + 1, me , diags);
  5042. } /* span */
  5043.  
  5044. listDiags(x, y, diags)
  5045. short x, y;
  5046. sPointList *diags;
  5047. { /* listDiags */
  5048.   short me;
  5049. #ifdef DEBUG
  5050.   printf( "listDiags\n" );
  5051. #endif
  5052.   me = bord[x][y];
  5053.   diags->indx = 0;
  5054.   marker = marker + 1;
  5055.   if (marker == 0)
  5056.     {
  5057.       initArray(markBoard);
  5058.       marker = 1;
  5059.     }
  5060.   LDspan(x, y, me, diags);
  5061. } /* listDiags */
  5062.  
  5063. intersectPlist(p1, p2, pr)
  5064. pointList *p1, *p2, *pr;
  5065. { /* intersectPlist */
  5066.   short i, j, k;
  5067. #ifdef DEBUG
  5068.   printf( "intersectPlist\n" );
  5069. #endif
  5070.   marker = marker + 1;
  5071.   if (marker == 0)
  5072.     {
  5073.       initArray(markBoard);
  5074.       marker = 1;
  5075.     }
  5076.   pr->indx = 0;
  5077.   for (i = 1; i <= p1->indx; i++)
  5078.       markBoard[p1->p[i].px][p1->p[i].py] = marker;
  5079.   j = 0;
  5080.   for (i = 1; i <= p2->indx; i++)
  5081.       if (markBoard[p2->p[i].px][p2->p[i].py] == marker)
  5082.         {
  5083.           j = j + 1;
  5084.           pr->p[j] = p2->p[i];
  5085.         }
  5086.   pr->indx = j;
  5087. } /* intersectPlist */
  5088.  
  5089. initArray(ary)
  5090. intBoard ary;
  5091. { /* initArray */
  5092.   short i, j;
  5093.   for (i = 0; i <= maxPoint; i++)
  5094.     for (j = 0; j <= maxPoint; j++)
  5095.       ary[i][j] = 0;
  5096. } /* initArray */
  5097.  
  5098. initState()
  5099. { /* initState */
  5100.   short i, j;
  5101.   for (i = 0; i <= maxPoint; i++)
  5102.     for (j = 0; j <=  maxPoint; j++)
  5103.       {
  5104.         extra[i][j] = 0;
  5105.         claim[i][j] = 0;
  5106.         groupIDs[i][j] = 0;
  5107.         connectMap[i][j] = 0;
  5108.         protPoints[i][j] = 0;
  5109.       }
  5110. } /* initState */
  5111.  
  5112. copyArray( dest, src )
  5113. intBoard dest, src;
  5114. {
  5115.    short x, y;
  5116.    for (y = 0; y <= maxPoint; y++)
  5117.       for (x = 0; x <= maxPoint; x++)
  5118.          dest[x][y] = src[x][y];
  5119. }
  5120.  
  5121. /*
  5122.   generates a one-point spread in the force field array (claim)
  5123.  
  5124.   the spread from a single point after four calls is:
  5125.  
  5126.               1
  5127.            2  2  2
  5128.         2  4  6  4  2
  5129.      2  4  8 10  8  4  2
  5130.   1  2  6 10 62 10  6  2  1  
  5131.      2  4  8 10  8  4  2
  5132.         2  4  6  4  2
  5133.            2  2  2
  5134.               1
  5135.  
  5136. */
  5137. stake()
  5138. {
  5139.    short x, y;
  5140.    initArray( extra );
  5141.    for (y = 0; y <= maxPoint; y++)
  5142.       for (x = 0; x <= maxPoint; x++)
  5143.       {
  5144.          extra[x][y] = extra[x][y] + claim[x][y];
  5145.      if (claim[x][y] > 0)
  5146.      {
  5147.         if (x > 0) extra[x-1][y] += 1;
  5148.         if (y > 0) extra[x][y-1] += 1;
  5149.         if (x < maxPoint) extra[x+1][y] += 1;
  5150.         if (y < maxPoint) extra[x][y+1] += 1;
  5151.      }
  5152.          else if (claim[x][y] < 0)
  5153.      {
  5154.         if (x > 0) extra[x-1][y] -= 1;
  5155.         if (y > 0) extra[x][y-1] -= 1;
  5156.         if (x < maxPoint) extra[x+1][y] -= 1;
  5157.         if (y < maxPoint) extra[x][y+1] -= 1;
  5158.      }
  5159.       }
  5160.    copyArray( claim, extra );
  5161. } /* stake */
  5162.  
  5163. /*
  5164.   sets up claim from the current board position
  5165. */
  5166. spread()
  5167. {
  5168.    short x, y;
  5169.    for (y = 0; y <= maxPoint; y++)
  5170.       for (x = 0; x <= maxPoint; x++)
  5171.          claim[x][y] = ndbord[x][y] * 50;
  5172.    stake();
  5173.    stake();
  5174.    stake();
  5175.    stake();
  5176. } /* spread */
  5177.  
  5178. /*
  5179.   gList is initialized with the size, loc, and libCount of each group
  5180.   groupIDs contains the serial numbers of the groups.
  5181. */
  5182. Resspan(x, y, gID, gSize, libCount, who)
  5183. short x, y, gID, *gSize, *libCount, who;
  5184.   { /* span */
  5185.     if ((bord[x][y] == 0) &&
  5186.        (markBoard[x][y] != marker)) /* a liberty */
  5187.       {
  5188.         markBoard[x][y] = marker;
  5189.         *libCount = *libCount + 1;
  5190.       }
  5191.     else if ((bord[x][y] == who) &&
  5192.             (groupIDs[x][y] == 0))
  5193.       {
  5194.         groupIDs[x][y] = gID;
  5195.         *gSize = *gSize + 1;
  5196.         if (x > 0)
  5197.           Resspan(x - 1, y, gID, gSize, libCount, who);
  5198.         if (x < maxPoint)
  5199.           Resspan(x + 1, y, gID, gSize, libCount, who);
  5200.         if (y > 0)
  5201.           Resspan(x, y - 1, gID, gSize, libCount, who);
  5202.         if (y < maxPoint)
  5203.           Resspan(x, y + 1, gID, gSize, libCount, who);
  5204.       }
  5205.   } /* span */
  5206.  
  5207. respreicen()
  5208. { /* respreicen */
  5209.   short i, j, gID, libCount, gSize, who;
  5210.   gID = 0;
  5211. #ifdef DEBUG
  5212.   printf( "respreicen\n" );
  5213. #endif
  5214.   for (i = 0; i <= maxPoint; i++)
  5215.     for (j = 0; j <= maxPoint; j++)
  5216.       groupIDs[i][j] = 0;
  5217.   for (i = 0; i <= maxPoint; i++)
  5218.     for (j = 0; j <= maxPoint; j++)
  5219.       if ((bord[i][j] != 0) &&   /* a stone there */
  5220.          (groupIDs[i][j] == 0)) /* not seen yet */
  5221.         {
  5222.           marker = marker + 1;
  5223.           if (marker == 0)
  5224.             {
  5225.               initArray(markBoard);
  5226.               marker = 1;
  5227.             }
  5228.           gID = gID + 1;
  5229.           libCount = 0;
  5230.           gSize = 0;
  5231.           who = bord[i][j];
  5232.           Resspan(i, j, gID, &gSize, &libCount, who); /* span the group, collecting info */
  5233.               gList[gID].groupMark = 0;
  5234.               gList[gID].atLevel = 0;
  5235.               gList[gID].isLive = FALSE; /* we don't know yet */
  5236.               gList[gID].isDead = FALSE;
  5237.               gList[gID].numEyes = -1;
  5238.               gList[gID].size = gSize;
  5239.               gList[gID].libC = libCount;
  5240.               gList[gID].lx = i;
  5241.               gList[gID].ly = j;
  5242.           gMap[gID] = gID; /* set up identity map */
  5243.         }
  5244.   maxGroupID = gID;
  5245.   newGID = gID;
  5246.   grpMark = 0;
  5247. } /* respreicen */
  5248.  
  5249. /*
  5250.   play z at [x, y].
  5251.   killFlag is set true if anything is killed.
  5252. */
  5253. killGroup(x, y, me, him)
  5254. short x, y, me, him;
  5255.   { /* killGroup */
  5256. #ifdef DEBUG
  5257.   printf( "killGroup\n" );
  5258. #endif
  5259.     playMark = playMark + 1;
  5260.                 /* record this kill */
  5261.         playStack[playMark].kind = rem;
  5262.         playStack[playMark].uval.rem.who = him;
  5263.         playStack[playMark].uval.rem.xl = x;
  5264.         playStack[playMark].uval.rem.yl = y;
  5265.         playStack[playMark].gID = groupIDs[x][y];
  5266.         playStack[playMark].uval.rem.sNumber = goboard[x][y].mNum;
  5267.         if (showTrees)
  5268.           rstone(x, y);
  5269.     numCapt = numCapt + 1;
  5270.     bord[x][y] = 0;
  5271.     groupIDs[x][y] = 0;
  5272.     if (x > 0)
  5273.       {
  5274.         if (bord[x - 1][y] == me)
  5275.           {
  5276.             nlcGroup.indx = nlcGroup.indx + 1;
  5277.             nlcGroup.v[nlcGroup.indx] = gMap[groupIDs[x - 1][y]];
  5278.           }
  5279.         else if (bord[x - 1][y] == him)
  5280.           killGroup(x - 1, y, me , him);
  5281.       }
  5282.     if (x < maxPoint)
  5283.       {
  5284.         if (bord[x + 1][y] == me)
  5285.           {
  5286.             nlcGroup.indx = nlcGroup.indx + 1;
  5287.             nlcGroup.v[nlcGroup.indx] = gMap[groupIDs[x + 1][y]];
  5288.           }
  5289.         else if (bord[x + 1][y] == him)
  5290.           killGroup(x + 1, y, me, him);
  5291.       }
  5292.     if (y > 0)
  5293.       {
  5294.         if (bord[x][y - 1] == me)
  5295.           {
  5296.             nlcGroup.indx = nlcGroup.indx + 1;
  5297.             nlcGroup.v[nlcGroup.indx] = gMap[groupIDs[x][y - 1]];
  5298.           }
  5299.         else if (bord[x][y - 1] == him)
  5300.           killGroup(x, y - 1, me, him);
  5301.       }
  5302.     if (y < maxPoint)
  5303.       {
  5304.         if (bord[x][y + 1] == me)
  5305.           {
  5306.             nlcGroup.indx = nlcGroup.indx + 1;
  5307.             nlcGroup.v[nlcGroup.indx] = gMap[groupIDs[x][y + 1]];
  5308.           }
  5309.         else if (bord[x][y + 1] == him)
  5310.           killGroup(x, y + 1, me, him);
  5311.       }
  5312.   } /* killGroup */
  5313.  
  5314. mergeGroup(sGID, myGID)
  5315. short sGID, myGID;
  5316.   { /* mergeGroup */
  5317.     short i;
  5318. #ifdef DEBUG
  5319.   printf( "mergeGroup\n" );
  5320. #endif
  5321.     for (i = 1; i <= newGID; i++)
  5322.       if (gMap[i] == sGID)
  5323.         {
  5324.           playMark = playMark + 1;
  5325.               playStack[playMark].kind = reMap;
  5326.               playStack[playMark].gID = i;
  5327.               playStack[playMark].uval.reMap.oldGID = sGID;
  5328.           gMap[i] = myGID;
  5329.         }
  5330.   } /* mergeGroup */
  5331.  
  5332. tryPlay(x, y, z)
  5333. short x, y, z;
  5334. { /* plei */
  5335.   short i, me, him, myGID;
  5336.   short isNew;
  5337. #ifdef DEBUG
  5338.   printf( "tryPlay\n" );
  5339. #endif
  5340.   me = z;
  5341.   him = -me;
  5342.   killFlag = FALSE;  /* set true if something is killed */
  5343.   numCapt = 0;
  5344.   tryLevel = tryLevel + 1;
  5345.   isNew = FALSE;
  5346.   bord[x][y] = z;  /* play the stone */
  5347.   if ((x > 0) && (bord[x - 1][y] == me))   /* connect to adjacent group */
  5348.     myGID = gMap[groupIDs[x - 1][y]];
  5349.   else if ((x < maxPoint) && (bord[x + 1][y] == me))
  5350.     myGID = gMap[groupIDs[x + 1][y]];
  5351.   else if ((y > 0) && (bord[x][y - 1] == me))
  5352.     myGID = gMap[groupIDs[x][y - 1]];
  5353.   else if ((y < maxPoint) && (bord[x][y + 1] == me))
  5354.     myGID = gMap[groupIDs[x][y + 1]];
  5355.   else  /* nobody to connect to */
  5356.     {
  5357.       newGID = newGID + 1;
  5358.       isNew = TRUE;
  5359.       myGID = newGID;
  5360.           gList[myGID].groupMark = 0;
  5361.           gList[myGID].atLevel = tryLevel;
  5362.           gList[myGID].isLive = FALSE;
  5363.           gList[myGID].numEyes = -1;
  5364.           gList[myGID].size = -1;
  5365.           gList[myGID].lx = x;
  5366.           gList[myGID].ly = y;
  5367.       gMap[myGID] = myGID;
  5368.     }
  5369.   groupIDs[x][y] = myGID;
  5370.   playMark = playMark + 1;
  5371.       /* record this move */
  5372.       playStack[playMark].kind = add;
  5373.       playStack[playMark].uval.add.who = me;
  5374.       playStack[playMark].uval.add.xl = x;
  5375.       playStack[playMark].uval.add.yl = y;
  5376.       playStack[playMark].gID = myGID;
  5377.       playStack[playMark].uval.add.sNumber = 0;
  5378.       if (isNew)
  5379.         playStack[playMark].uval.add.nextGID = newGID - 1;
  5380.       else
  5381.         playStack[playMark].uval.add.nextGID = newGID;
  5382.       if (showTrees)
  5383.         sstone(me, x, y, 0);
  5384.   /* merge adjacent groups */
  5385.   if ((x > 0) && (bord[x - 1][y] == me) &&
  5386.      (gMap[groupIDs[x - 1][y]] != myGID))
  5387.     mergeGroup(gMap[groupIDs[x - 1][y]], myGID);
  5388.   if ((x < maxPoint) && (bord[x + 1][y] == me) &&
  5389.      (gMap[groupIDs[x + 1][y]] != myGID))
  5390.     mergeGroup(gMap[groupIDs[x + 1][y]], myGID);
  5391.   if ((y > 0) && (bord[x][y - 1] == me) &&
  5392.      (gMap[groupIDs[x][y - 1]] != myGID))
  5393.     mergeGroup(gMap[groupIDs[x][y - 1]], myGID);
  5394.   if ((y < maxPoint) && (bord[x][y + 1] == me) &&
  5395.      (gMap[groupIDs[x][y + 1]] != myGID))
  5396.     mergeGroup(gMap[groupIDs[x][y + 1]], myGID);
  5397.   /* kill opposing groups, listing affected groups */
  5398.   nlcGroup.indx = 1;
  5399.   nlcGroup.v[1] = myGID; /* init list to include me */
  5400.   if ((x > 0) && (bord[x - 1][y] == him) &&
  5401.      (gList[gMap[groupIDs[x - 1][y]]].libC == 1))
  5402.     {
  5403.       killFlag = TRUE;
  5404.       killGroup(x - 1, y, me, him);
  5405.     }
  5406.   if ((x < maxPoint) && (bord[x + 1][y] == him) &&
  5407.      (gList[gMap[groupIDs[x + 1][y]]].libC == 1))
  5408.     {
  5409.       killFlag = TRUE;
  5410.       killGroup(x + 1, y, me, him);
  5411.     }
  5412.   if ((y > 0) && (bord[x][y - 1] == him) &&
  5413.      (gList[gMap[groupIDs[x][y - 1]]].libC == 1))
  5414.     {
  5415.       killFlag = TRUE;
  5416.       killGroup(x, y - 1, me, him);
  5417.     }
  5418.   if ((y < maxPoint) && (bord[x][y + 1] == him) &&
  5419.      (gList[gMap[groupIDs[x][y + 1]]].libC == 1))
  5420.     {
  5421.       killFlag = TRUE;
  5422.       killGroup(x, y + 1, me, him);
  5423.     }
  5424.   /* list groups adjacent to me */
  5425.   if ((x > 0) && (bord[x - 1][y] == him))
  5426.     {
  5427.       nlcGroup.indx = nlcGroup.indx + 1;
  5428.       nlcGroup.v[nlcGroup.indx] = gMap[groupIDs[x - 1][y]];
  5429.     }
  5430.   if ((x < maxPoint) && (bord[x + 1][y] == him))
  5431.     {
  5432.       nlcGroup.indx = nlcGroup.indx + 1;
  5433.       nlcGroup.v[nlcGroup.indx] = gMap[groupIDs[x + 1][y]];
  5434.     }
  5435.   if ((y > 0) && (bord[x][y - 1] == him))
  5436.     {
  5437.       nlcGroup.indx = nlcGroup.indx + 1;
  5438.       nlcGroup.v[nlcGroup.indx] = gMap[groupIDs[x][y - 1]];
  5439.     }
  5440.   if ((y < maxPoint) && (bord[x][y + 1] == him))
  5441.     {
  5442.       nlcGroup.indx = nlcGroup.indx + 1;
  5443.       nlcGroup.v[nlcGroup.indx] = gMap[groupIDs[x][y + 1]];
  5444.     }
  5445.   /* fix liberty count for affected groups */
  5446.   grpMark = grpMark + 1;
  5447.   for (i = 1; i <= nlcGroup.indx; i++)
  5448.       if (gList[nlcGroup.v[i]].groupMark != grpMark)
  5449.         {
  5450.           if (gList[nlcGroup.v[i]].atLevel != tryLevel)
  5451.             {
  5452.               playMark = playMark + 1;
  5453.                   playStack[playMark].kind = chLib;
  5454.                   playStack[playMark].gID = nlcGroup.v[i];
  5455.                   playStack[playMark].uval.chLib.oldLevel = 
  5456.                        gList[nlcGroup.v[i]].atLevel;
  5457.                   playStack[playMark].uval.chLib.oldLC =
  5458.                        gList[nlcGroup.v[i]].libC;
  5459.             }
  5460.           gList[nlcGroup.v[i]].groupMark = grpMark;
  5461.           gList[nlcGroup.v[i]].atLevel = tryLevel;
  5462.           spanGroup(gList[nlcGroup.v[i]].lx, gList[nlcGroup.v[i]].ly, &pPlist);
  5463.           gList[nlcGroup.v[i]].libC = pPlist.indx;
  5464.         }
  5465. } /* plei */
  5466.  
  5467. saveState()
  5468. { /* saveState */
  5469.   playMark = 0;
  5470.   tryLevel = 0;
  5471.   newGID = maxGroupID;
  5472. } /* saveState */
  5473.  
  5474. /*
  5475.   undoes a move sequence back to uMark
  5476. */
  5477. undoTo(uMark)
  5478. short uMark;
  5479. { /* undoTo */
  5480.   short i, xl, yl;
  5481. #ifdef DEBUG
  5482.   printf( "undoTo\n" );
  5483. #endif
  5484.   for (i = playMark; i >= uMark + 1; i--)
  5485.       if (playStack[i].kind == rem)
  5486.         {
  5487.           xl = playStack[i].uval.rem.xl;
  5488.           yl = playStack[i].uval.rem.yl;
  5489.           bord[xl][yl] = playStack[i].uval.rem.who;
  5490.           groupIDs[xl][yl] = playStack[i].gID;
  5491.           if (showTrees)
  5492.             sstone(playStack[i].uval.rem.who, xl, yl,
  5493.                playStack[i].uval.rem.sNumber);
  5494.         }
  5495.       else if (playStack[i].kind == add)
  5496.         {
  5497.           xl = playStack[i].uval.add.xl;
  5498.           yl = playStack[i].uval.add.yl;
  5499.           bord[xl][yl] = 0;
  5500.           groupIDs[xl][yl] = 0;
  5501.           tryLevel = tryLevel - 1;
  5502.           newGID = playStack[i].uval.add.nextGID;
  5503.           if (showTrees)
  5504.             rstone(xl, yl);
  5505.         }
  5506.       else if (playStack[i].kind == reMap)
  5507.         gMap[playStack[i].gID] = playStack[i].uval.reMap.oldGID;
  5508.       else /* change libs of group - gID is pre-mapped */
  5509.           {
  5510.             gList[playStack[i].gID].libC = playStack[i].uval.chLib.oldLC;
  5511.             gList[playStack[i].gID].atLevel = playStack[i].uval.chLib.oldLevel;
  5512.           }
  5513.   playMark = uMark;
  5514. } /* undoTo */
  5515.  
  5516. /*
  5517.   restores the state of the world after trying a move sequence
  5518. */
  5519. restoreState()
  5520. { /* restoreState */
  5521. #ifdef DEBUG
  5522.   printf( "restoreState\n" );
  5523. #endif
  5524.   if (playMark > 0)
  5525.     {
  5526.       undoTo(0);
  5527.       playMark = 0;
  5528.       tryLevel = 0;
  5529.     }
  5530. } /* restoreState */
  5531.  
  5532. /* exception bpt; */
  5533.  
  5534.  
  5535. /*
  5536.   returns true if (the group (at gx, gy) is saveable.
  5537.   if so, returns the point to play at in savex, savey
  5538. */
  5539. short saveable(gx, gy, savex, savey)
  5540. short gx, gy, *savex, *savey;
  5541. { /* saveable */
  5542.   short me, him, gx1, gx2, i, j, smark, mark2, tl, result;
  5543.   char sChar;
  5544.   sPointList dList;
  5545.   point tp;
  5546.   short libList[maxSPoint+1];
  5547. #ifdef DEBUG
  5548.   printf( "saveable\n" );
  5549. #endif
  5550.   dbStop = TRUE;
  5551.   me = bord[gx][gy];
  5552.   him = -me;
  5553.   if (me == 1)
  5554.     sChar = '|';
  5555.   else
  5556.     sChar = '>';
  5557. /*  write(sChar); */
  5558.   spanGroup(gx, gy, &plist3); /* find my liberties */
  5559.   if (adjInAtari) /* one of my options is to kill */
  5560.     {
  5561.       listAdjacents(gx, gy, &aList);
  5562.       for (i = 1; i <= aList.indx; i++)
  5563.         if (gList[aList.v[i]].libC == 1)
  5564.             {
  5565.               spanGroup(gList[aList.v[i]].lx, gList[aList.v[i]].ly,
  5566.                  &pList1); /* find it's liberty */
  5567.               plist3.indx = plist3.indx + 1;
  5568.               plist3.p[plist3.indx].px = pList1.p[1].px;
  5569.               plist3.p[plist3.indx].py = pList1.p[1].py;
  5570.             }
  5571.     }
  5572.   for (i = 1; i <= maxSPoint; i++)
  5573.     libList[i] = -1;
  5574.   if ((utilPlayLevel > 4) &&
  5575.      (gList[gMap[groupIDs[gx][gy]]].libC > 1)) /* account for diags */
  5576.     {
  5577.       listDiags(gx, gy, &dList);
  5578.       j = 0;
  5579.       i = plist3.indx;
  5580.       while ((j < dList.indx) &&
  5581.             (i < maxSPoint))
  5582.         {
  5583.           j = j + 1;
  5584.           i = i + 1;
  5585.           libList[i] = 100;
  5586.               plist3.p[i].px = dList.p[j].px;
  5587.               plist3.p[i].py = dList.p[j].py;
  5588.         }
  5589.       plist3.indx = i;
  5590.     }
  5591.   if (plist3.indx > 1) /* sort by decreasing lib count */
  5592.     {
  5593.       for (i = 1; i <= plist3.indx; i++)
  5594.         if (libList[i] != 100)
  5595.             {
  5596.               mark2 = playMark;
  5597.               tryPlay(plist3.p[i].px, plist3.p[i].py, me);
  5598.               libList[i] = gList[gMap[groupIDs[gx][gy]]].libC;
  5599.               if (libList[i] > treeLibLim) /* i'm safe */
  5600.                 {
  5601.                   *savex = plist3.p[i].px;
  5602.                   *savey = plist3.p[i].py;
  5603.                   result = TRUE;
  5604.                   goto one;
  5605.                 }
  5606.               undoTo(mark2);
  5607.             }
  5608.       for (i = 1; i <= plist3.indx - 1; i++)
  5609.         for (j = i + 1; j <= plist3.indx; j++)
  5610.           if (libList[i] < libList[j])
  5611.             {
  5612.               tl = libList[i];
  5613.               libList[i] = libList[j];
  5614.               libList[j] = tl;
  5615.               tp = plist3.p[i];
  5616.               plist3.p[i] = plist3.p[j];
  5617.               plist3.p[j] = tp;
  5618.             }
  5619.     }
  5620.   for (i = 1; i <= plist3.indx; i++)
  5621.     {
  5622.       *savex = plist3.p[i].px;
  5623.       *savey = plist3.p[i].py;
  5624.       if (legal[*savex][*savey])
  5625.         {
  5626.           smark = playMark;
  5627.           tryPlay(*savex, *savey, me);
  5628.           pause();
  5629.           if (gList[gMap[groupIDs[*savex][*savey]]].libC > 1)
  5630.             if (gList[gMap[groupIDs[gx][gy]]].libC > treeLibLim)
  5631.               {
  5632.                 restoreState();
  5633. /*                sClearChar(sChar, rXor); */
  5634.                 return TRUE;
  5635.               }
  5636.             else if (gList[gMap[groupIDs[gx][gy]]].libC > 1)
  5637.               if (! killable(gx, gy, &gx1, &gx2))
  5638.                 {
  5639.                   restoreState();
  5640. /*                  sClearChar(sChar, rXor); */
  5641.                   return TRUE;
  5642.                 }
  5643.           undoTo(smark);
  5644.         }
  5645.     }
  5646.   result = FALSE;
  5647. one:
  5648.   restoreState();
  5649. /*  sClearChar(sChar, rXor); */
  5650.   return result;
  5651. } /* saveable */
  5652.  
  5653. /*
  5654.   marks unsavable groups as dead
  5655. */
  5656. markDead()
  5657. { /* markDead */
  5658.   short i, j, gx, gy, result;
  5659. #ifdef DEBUG
  5660.   printf( "markDead\n" );
  5661. #endif
  5662.   for (i = 1; i <= maxGroupID; i++)
  5663.       if (killable(gList[i].lx, gList[i].ly, &gx, &gy))
  5664.         result = ! saveable(gList[i].lx, gList[i].ly, &gx, &gy);
  5665.       else
  5666.         result = FALSE;
  5667.   for (i = 0; i <= maxPoint; i++)
  5668.     for (j = 0; j <= maxPoint; j++)
  5669.       if (bord[i][j] == 0)
  5670.         ndbord[i][j] = 0;
  5671.       else if (gList[groupIDs[i][j]].isDead)
  5672.         ndbord[i][j] = 0;
  5673.       else
  5674.         ndbord[i][j] = bord[i][j];
  5675. } /* markDead */
  5676.  
  5677. /*
  5678.   marks groups with two eyes as live
  5679. */
  5680. MLspan(x, y, saw1, sawm1, size, sMark)
  5681. short x, y, *saw1, *sawm1, *size, sMark;
  5682.   { /* span */
  5683.     if (ndbord[x][y] == 1)
  5684.       *saw1 = TRUE;
  5685.     else if (ndbord[x][y] == -1)
  5686.       *sawm1 = TRUE;
  5687.     else if (sGroups[x][y] == 0)
  5688.       {
  5689.         sGroups[x][y] = sMark;
  5690.         *size = *size + 1;
  5691.         if (x > 0)
  5692.           MLspan(x - 1, y, saw1, sawm1, size, sMark);
  5693.         if (x < maxPoint)
  5694.           MLspan(x + 1, y, saw1, sawm1, size, sMark);
  5695.         if (y > 0)
  5696.           MLspan(x, y - 1, saw1, sawm1, size, sMark);
  5697.         if (y < maxPoint)
  5698.           MLspan(x, y + 1, saw1, sawm1, size, sMark);
  5699.       }
  5700.   } /* span */
  5701.  
  5702. short CLspan(x, y, numEyes, who)
  5703. short x, y, *numEyes, who;
  5704.     { /* span */
  5705.       markBoard[x][y] = marker;
  5706.       if (ndbord[x][y] == 0)
  5707.           {
  5708.             if ((sList[sGroups[x][y]].sm != marker) &&
  5709.                (sList[sGroups[x][y]].w == who))
  5710.               {
  5711.                 sList[sGroups[x][y]].sm = marker;
  5712.                 if (sList[sGroups[x][y]].s > 6)
  5713.                   return TRUE;
  5714.                 *numEyes = *numEyes + 1;
  5715.                 if (*numEyes > 1)
  5716.                   return TRUE;
  5717.               }  
  5718.           }
  5719.       else if (bord[x][y] == who)
  5720.         {
  5721.           if ((x > 0) &&
  5722.              (markBoard[x - 1][y] != marker))
  5723.             if (CLspan(x - 1, y, numEyes, who)) return TRUE;
  5724.           if ((x < maxPoint) &&
  5725.              (markBoard[x + 1][y] != marker))
  5726.             if (CLspan(x + 1, y, numEyes, who)) return TRUE;
  5727.           if ((y > 0) &&
  5728.              (markBoard[x][y - 1] != marker))
  5729.             if (CLspan(x, y - 1, numEyes, who)) return TRUE;
  5730.           if ((y < maxPoint) &&
  5731.              (markBoard[x][y + 1] != marker))
  5732.             if (CLspan(x, y + 1, numEyes, who)) return TRUE;
  5733.         }
  5734.     return FALSE;
  5735.     } /* span */
  5736.  
  5737. short checkLive(x, y)
  5738. short x, y;
  5739.   { /* checkLive */
  5740.     short numEyes, who;
  5741. #ifdef DEBUG
  5742.   printf( "checkLive\n" );
  5743. #endif
  5744.     numEyes = 0;
  5745.     who = bord[x][y];
  5746.     marker = marker + 1;
  5747.     return CLspan(x, y, &numEyes, who);
  5748.   } /* checkLive */
  5749.  
  5750. markLive()
  5751. { /* markLive */
  5752.   short i, j, size, sMark = 0;
  5753.   short saw1, sawm1;
  5754. #ifdef DEBUG
  5755.   printf( "markLive\n" );
  5756. #endif
  5757.   initArray(sGroups);
  5758.   for (i = 0; i <= maxPoint; i++)
  5759.     for (j = 0; j <= maxPoint; j++)
  5760.       if ((sGroups[i][j] == 0) &&
  5761.          (ndbord[i][j] == 0))
  5762.         {
  5763.           size = 0;
  5764.           sMark = sMark + 1;
  5765.           sawm1 = FALSE;
  5766.           saw1 = FALSE;
  5767.           MLspan(i, j, &saw1, &sawm1, &size, sMark);
  5768.           sList[sMark].s = size;
  5769.           sList[sMark].sm = 0;
  5770.           if (sawm1)
  5771.             if (saw1)
  5772.               sList[sMark].w = 0;
  5773.             else
  5774.               sList[sMark].w = -1;
  5775.           else if (saw1)
  5776.             sList[sMark].w = 1;
  5777.           else
  5778.             sList[sMark].w = 0;
  5779.         }
  5780.   for (i = 1; i <= maxGroupID; i++)
  5781.       if (! gList[i].isDead)
  5782.         gList[i].isLive = checkLive(gList[i].lx, gList[i].ly);
  5783. } /* markLive */
  5784.  
  5785. /*
  5786.   generates the connection map and the protected point map.
  5787. */
  5788. genConnects()
  5789. { /* genConnects */
  5790.   short x, y, numStones;
  5791. #ifdef DEBUG
  5792.   printf( "genConnects\n" );
  5793. #endif
  5794.   for (x = 0; x <= maxPoint; x++)
  5795.     for (y = 0; y <= maxPoint; y++)
  5796.       {
  5797.         connectMap[x][y] = 0;
  5798.         protPoints[x][y] = 0;
  5799.       }
  5800.   for (x = 0; x <= maxPoint; x++)
  5801.     for (y = 0; y <= maxPoint; y++)
  5802.       if (bord[x][y] == 1)   /* map connections to this stone */
  5803.         {
  5804.           if (x > 0)        /* direct connection */
  5805.             connectMap[x - 1][y] += 1;
  5806.           if (x < maxPoint)
  5807.             connectMap[x + 1][y] += 1;
  5808.           if (y > 0)
  5809.             connectMap[x][y - 1] += 1;
  5810.           if (y < maxPoint)
  5811.             connectMap[x][y + 1] += 1;
  5812.           if ((x > 0) && (y > 0) &&   /* diagonal connection */
  5813.              (bord[x - 1][y] == 0) && (bord[x][y - 1] == 0))
  5814.             connectMap[x - 1][y - 1] += 1;
  5815.           if ((x < maxPoint) && (y > 0) &&
  5816.              (bord[x + 1][y] == 0) && (bord[x][y - 1] == 0))
  5817.             connectMap[x + 1][y - 1] += 1;
  5818.           if ((x < maxPoint) && (y < maxPoint) &&
  5819.              (bord[x + 1][y] == 0) && (bord[x][y + 1] == 0))
  5820.             connectMap[x + 1][y + 1] += 1;
  5821.           if ((x > 0) && (y < maxPoint) &&
  5822.              (bord[x - 1][y] == 0) && (bord[x][y + 1] == 0))
  5823.             connectMap[x - 1][y + 1] += 1;
  5824.           if ((x > 1) && (claim[x - 1][y] > 3))   /* one point jump */
  5825.             connectMap[x - 2][y] += 1;
  5826.           if ((x < (maxPoint - 1)) && (claim[x + 1][y] > 3))
  5827.             connectMap[x + 2][y] += 1;
  5828.           if ((y > 1) && (claim[x][y - 1] > 3))
  5829.             connectMap[x][y - 2] += 1;
  5830.           if ((y < (maxPoint - 1)) && (claim[x][y + 1] > 3))
  5831.             connectMap[x][y + 2] += 1;
  5832.           if ((x > 1) && (y > 0) &&        /* knight's move */
  5833.              (claim[x - 1][y] > 3) && (claim[x - 1][y - 1] > 3))
  5834.             connectMap[x - 2][y - 1] += 1;
  5835.           if ((x > 0) && (y > 1) &&
  5836.              (claim[x][y - 1] > 3) && (claim[x - 1][y - 1] > 3))
  5837.             connectMap[x - 1][y - 2] += 1;
  5838.           if ((x < (maxPoint - 1)) && (y > 0) &&
  5839.              (claim[x + 1][y] > 3) && (claim[x + 1][y - 1] > 3))
  5840.             connectMap[x + 2][y - 1] += 1;
  5841.           if ((x < maxPoint) && (y > 1) &&
  5842.              (claim[x][y - 1] > 3) && (claim[x + 1][y - 1] > 3))
  5843.             connectMap[x + 1][y - 2] += 1;
  5844.           if ((x > 1) && (y < maxPoint) &&
  5845.              (claim[x - 1][y] > 3) && (claim[x - 1][y + 1] > 3))
  5846.             connectMap[x - 2][y + 1] += 1;
  5847.           if ((x > 0) && (y < (maxPoint - 1)) &&
  5848.              (claim[x][y + 1] > 3) && (claim[x - 1][y + 1] > 3))
  5849.             connectMap[x - 1][y + 2] += 1;
  5850.           if ((x < (maxPoint - 1)) && (y < maxPoint) &&
  5851.              (claim[x + 1][y] > 3) && (claim[x + 1][y + 1] > 3))
  5852.             connectMap[x + 2][y + 1] += 1;
  5853.           if ((x < maxPoint) && (y < (maxPoint - 1)) &&
  5854.              (claim[x][y + 1] > 3) && (claim[x + 1][y + 1] > 3))
  5855.             connectMap[x + 1][y + 2] += 1;
  5856.         }
  5857.       else if (bord[x][y] == 0) /* see if protected point */
  5858.         {
  5859.           numStones = 0;
  5860.           if (x == 0)
  5861.             numStones = numStones + 1;
  5862.           if (y == 0)
  5863.             numStones = numStones + 1;
  5864.           if (x == maxPoint)
  5865.             numStones = numStones + 1;
  5866.           if (y == maxPoint)
  5867.             numStones = numStones + 1;
  5868.           if ((x > 0) && (bord[x - 1][y] == 1))
  5869.             numStones = numStones + 1;
  5870.           if ((y > 0) && (bord[x][y - 1] == 1))
  5871.             numStones = numStones + 1;
  5872.           if ((x < maxPoint) && (bord[x + 1][y] == 1))
  5873.             numStones = numStones + 1;
  5874.           if ((y < maxPoint) && (bord[x][y + 1] == 1))
  5875.             numStones = numStones + 1;
  5876.           if (numStones == 4)
  5877.             protPoints[x][y] = 1;
  5878.           else if (numStones == 3)
  5879.             {
  5880.               if ((x > 0) &&
  5881.                  ((bord[x - 1][y] == 0) ||
  5882.                   ((bord[x - 1][y] == -1) &&
  5883.                    (gList[groupIDs[x - 1][y]].libC == 1))))
  5884.                  protPoints[x][y] = 1;
  5885.               else if ((x < maxPoint) &&
  5886.                       ((bord[x + 1][y] == 0) ||
  5887.                        ((bord[x + 1][y] == -1) &&
  5888.                         (gList[groupIDs[x + 1][y]].libC == 1))))
  5889.                  protPoints[x][y] = 1;
  5890.               else if ((y > 0) &&
  5891.                       ((bord[x][y - 1] == 0) ||
  5892.                        ((bord[x][y - 1] == -1) &&
  5893.                         (gList[groupIDs[x][y - 1]].libC == 1))))
  5894.                  protPoints[x][y] = 1;
  5895.               else if ((y < maxPoint) &&
  5896.                       ((bord[x][y + 1] == 0) ||
  5897.                        ((bord[x][y + 1] == -1) &&
  5898.                         (gList[groupIDs[x][y + 1]].libC == 1))))
  5899.                  protPoints[x][y] = 1;
  5900.             }
  5901.         } 
  5902.   for (x = 0; x <= maxPoint; x++)
  5903.     for (y = 0; y <= maxPoint; y++)
  5904.       if (bord[x][y] != 0)
  5905.         {
  5906.           connectMap[x][y] = 0;
  5907.           protPoints[x][y] = 0;
  5908.         }
  5909. } /* genConnects */
  5910.  
  5911. /*
  5912.   generates the whole state of the game.
  5913. */
  5914. genState()
  5915. { /* genState */
  5916. #ifdef DEBUG
  5917.   printf( "genState\n" );
  5918. #endif
  5919.   inGenState = TRUE;
  5920.   respreicen();
  5921.   markDead();
  5922.   markLive();
  5923.   spread();
  5924.   genConnects();
  5925. #ifdef DEBUG
  5926. /*  printBoard( claim, "claim" ); */
  5927. /*  printBoard( bord, "bord" ); */
  5928. /*  printBoard( ndbord, "ndbord" );
  5929.   printBoard( sGroups, "sGroups" );
  5930.   printBoard( groupIDs, "groupIDs" );
  5931.   printBoard( connectMap, "connectMap" );
  5932.   printBoard( protPoints, "protPoints" ); */
  5933. #endif
  5934.   inGenState = FALSE;
  5935. } /* genState */
  5936.  
  5937. /*
  5938.   generates a value for the [x, y] location that appears to get larger
  5939.   for points that are saddle points in the influence graph (klein)
  5940. */
  5941. short tencen(x, y)
  5942. short x, y;
  5943. { /* tencen */
  5944.   short a, b, c, d, w, z;
  5945. #ifdef DEBUG
  5946.   printf( "tencen\n" );
  5947. #endif
  5948.   if (claim[x][y] > -1)  /* if (he does not influence this area, return 50 */
  5949.     {
  5950.       return 50;
  5951.     }
  5952.   w = claim[x][y]; /* w <= -1 */
  5953.   a = iNil;
  5954.   if (x > 0)
  5955.     if (claim[x - 1][y] > -1)  /* if (neighbor is not influenced by him */
  5956.       a = claim[x - 1][y] - w;   /* score is sum of his influence on central */
  5957.   b = iNil;                      /*  point and my influence on this neighbor */
  5958.   if (y > 0)
  5959.     if (claim[x][y - 1] > -1)
  5960.       b = claim[x][y - 1] - w;
  5961.   c = iNil;
  5962.   if (x < maxPoint)
  5963.     if (claim[x + 1][y] > -1)
  5964.       c = claim[x + 1][y] - w;
  5965.   d = iNil;
  5966.   if (y < maxPoint)
  5967.     if (claim[x][y + 1] > -1)
  5968.       d = claim[x][y + 1] - w;
  5969.   z = a;             /* z = max(a, b, c, d) */
  5970.   if (z != iNil)
  5971.     {
  5972.       if ((b != iNil) &&
  5973.          (b > z))
  5974.         z = b;
  5975.     }
  5976.   else
  5977.     z = b; 
  5978.   if (z != iNil)
  5979.     {
  5980.       if ((c != iNil) &&
  5981.          (c > z))
  5982.         z = c;
  5983.     }
  5984.   else
  5985.     z = c; 
  5986.   if (z != iNil)
  5987.     {
  5988.       if ((d != iNil) &&
  5989.          (d > z))
  5990.         z = d;
  5991.     }
  5992.   else
  5993.     z = d; 
  5994.   if ((z != iNil) &&
  5995.      ((x == 0) ||
  5996.       (y == 0) ||
  5997.       (x == maxPoint) ||
  5998.       (y == maxPoint)))
  5999.     z = z * 2;     /* double z if (on the edge of the board ?? */
  6000.   if (z != iNil)
  6001.     return z;
  6002.   else
  6003.     return 50;
  6004. } /* tencen */
  6005.  
  6006. initGPUtils()
  6007. { /* initGPUtils */
  6008. #ifdef DEBUG
  6009.   printf( "initGPUtils\n" );
  6010. #endif
  6011.   initArray(markBoard);
  6012.   initState();
  6013.   marker = 0;
  6014.   playMark = 0;
  6015.       gList[0].isLive = FALSE;
  6016.       gList[0].isDead = FALSE;
  6017.       gList[0].libC = 0;
  6018.       gList[0].size = 0;
  6019.       gList[0].numEyes = 0;
  6020.       gList[0].lx = -1;
  6021.       gList[0].ly = -1;
  6022.   gMap[0] = 0;
  6023.   dbStop = FALSE;
  6024.   inGenState = FALSE;
  6025. } /* initGPUtils */
  6026.  
  6027. SHAR_EOF
  6028. fi
  6029. if test -f 'goplayutils.h'
  6030. then
  6031.     echo shar: "will not over-write existing file 'goplayutils.h'"
  6032. else
  6033. cat << \SHAR_EOF > 'goplayutils.h'
  6034. #define iNil 32767 /* a distinguished value like nil */
  6035. #define  maxGroup 512
  6036. #define  maxSPoint 16
  6037. #define tryLimit 300
  6038.  
  6039. typedef short intBoard[19][19];  /* these were -2 to maxPoint + 2 */
  6040.  
  6041. typedef short boolBoard[19][19];
  6042.  
  6043. typedef struct
  6044. {
  6045.    short px, py;
  6046. } point;
  6047.  
  6048. typedef struct
  6049. {
  6050.    point p[401];
  6051.    short indx;
  6052. } pointList;
  6053.  
  6054. typedef struct
  6055. {
  6056.   point p[maxSPoint+1];
  6057.   short indx;
  6058. } sPointList;
  6059.  
  6060. typedef struct
  6061. {
  6062.    short indx,
  6063.    v[401];
  6064. } intList;
  6065.    
  6066. typedef struct { short w, s, sm; } sgRec;
  6067.  
  6068. typedef struct
  6069. {
  6070.    short groupMark,
  6071.          atLevel,
  6072.      isLive,
  6073.      isDead,
  6074.      libC,
  6075.      numEyes,
  6076.      size,
  6077.      lx, ly;
  6078. } groupRec;
  6079.  
  6080. typedef enum {rem, add, chLib, reMap} playType;
  6081.  
  6082. typedef struct { short who, xl, yl, nextGID, sNumber; } remAddRec;
  6083. typedef struct { short oldLC, oldLevel; } chLibRec;
  6084. typedef struct { short oldGID; } reMapRec;
  6085. typedef struct
  6086. {
  6087.    short gID;
  6088.    playType kind;
  6089.    union {
  6090.       remAddRec rem, add;
  6091.       chLibRec chLib;
  6092.       reMapRec reMap;
  6093.    } uval;
  6094. } playRec;
  6095.  
  6096. SHAR_EOF
  6097. fi
  6098. if test -f 'graystone.bm'
  6099. then
  6100.     echo shar: "will not over-write existing file 'graystone.bm'"
  6101. else
  6102. cat << \SHAR_EOF > 'graystone.bm'
  6103. #define graystone_width 16
  6104. #define graystone_height 16
  6105. #define graystone_x_hot 7
  6106. #define graystone_y_hot 8
  6107. static char graystone_bits[] = {
  6108.    0xc0, 0x03, 0xb0, 0x0e, 0x58, 0x15, 0xac, 0x2a, 0x56, 0x55, 0xaa, 0x6a,
  6109.    0x55, 0xd5, 0xab, 0xaa, 0x55, 0xd5, 0xab, 0xba, 0x56, 0x5d, 0xaa, 0x6e,
  6110.    0x54, 0x37, 0xa8, 0x1a, 0x70, 0x0d, 0xc0, 0x03};
  6111. SHAR_EOF
  6112. fi
  6113. if test -f 'killable.c'
  6114. then
  6115.     echo shar: "will not over-write existing file 'killable.c'"
  6116. else
  6117. cat << \SHAR_EOF > 'killable.c'
  6118. /* By Stoney Ballard */
  6119. /* Ported from Pascal to C by Todd R. Johnson */
  6120.  
  6121. #include "go.h"
  6122. #include "amigo.h"
  6123. #include "goplayutils.h"
  6124.  
  6125. extern intBoard bord, groupIDs;
  6126. extern boolBoard legal;
  6127. extern groupRec gList[maxGroup];
  6128. extern short gMap[maxGroup], adjInAtari, adj2Libs, playMark, treeLibLim,
  6129.              utilPlayLevel, killFlag, depthLimit, dbStop, showTrees;
  6130. extern pointList plist2;
  6131.  
  6132. /*
  6133.   returns true if the group (at x, y) is killable.
  6134.   if so, returns the point to play at in killx, killy.
  6135. */
  6136.  
  6137.   short me, him, depth, i, j, tryCount, tl, topMark, tkMark, mark2;
  6138.   char sChar;
  6139.   sPointList lList, dList;
  6140.   point tp;
  6141.   short libList[maxSPoint+1];
  6142.   short esc;
  6143.  
  6144. short mtNbrs(x, y)
  6145. short x, y;
  6146.   { /* mtNbrs */
  6147.     short n = 0;
  6148.     if ((x > 0) && (bord[x - 1][y] == 0))
  6149.       n = n + 1;
  6150.     if ((x < maxPoint) && (bord[x + 1][y] == 0))
  6151.       n = n + 1;
  6152.     if ((y > 0) && (bord[x][y - 1] == 0))
  6153.       n = n + 1;
  6154.     if ((y < maxPoint) && (bord[x][y + 1] == 0))
  6155.       n = n + 1;
  6156.     return n;
  6157.   } /* mtNbrs */
  6158.  
  6159. short killTree(tx, ty, gx, gy, escape, tkMark)
  6160. short tx, ty, gx, gy, *escape, tkMark;
  6161.     { /* killTree */
  6162.       short curMark, mark2, mark3, i, j, k, tl, dStart, result;
  6163.       sPointList lList1, lList2;
  6164.       short libList[maxSPoint+1];
  6165.       point tp;
  6166.       short esc = FALSE;
  6167.       tryCount = tryCount + 1;
  6168.       if (tryCount > tryLimit)
  6169.         {
  6170.           undoTo(tkMark);
  6171. /*          for (i = 1; i <= depth - 1; i++)
  6172.             {
  6173.               sClearChar(sChar, rXor); 
  6174.             } */
  6175.           depth = 1;
  6176.       return FALSE;
  6177.         }
  6178. /*      write(sChar); */
  6179.       depth = depth + 1;
  6180.       curMark = playMark;
  6181.       tryPlay(tx, ty, me); /* try my move */
  6182.       pause();
  6183.       if (gList[gMap[groupIDs[tx][ty]]].libC == 0) /* I'm dead */
  6184.     {
  6185.     result = FALSE;
  6186.     goto one;
  6187.     }
  6188.       else if (killFlag) /* I killed something of his */
  6189.     {
  6190.     result = TRUE;
  6191.     goto one;
  6192.     }
  6193.       else if (gList[gMap[groupIDs[gx][gy]]].libC > treeLibLim) /* safe */
  6194.     {
  6195.     result = FALSE;
  6196.     goto one;
  6197.     }
  6198.       else
  6199.         {
  6200.           sSpanGroup(gx, gy, &lList1); /* find his liberties */
  6201.           if (gList[gMap[groupIDs[tx][ty]]].libC == 1) /* he can kill me */
  6202.             {
  6203.               if (lList1.indx < maxSPoint) /* add that option to his list */
  6204.                 {
  6205.                   lList1.indx = lList1.indx + 1;
  6206.                   spanGroup(tx, ty, &plist2); /* find my liberty */
  6207.                       lList1.p[lList1.indx].px = plist2.p[1].px;
  6208.                       lList1.p[lList1.indx].py = plist2.p[1].py;
  6209.                 }
  6210.               else
  6211.         {
  6212.         result = FALSE;
  6213.         goto one;
  6214.         }
  6215.             }
  6216.           for (i = 1; i <= maxSPoint; i++)    /* init liblist so diags can be marked */
  6217.             libList[i] = -1;
  6218.           if ((utilPlayLevel > 4) &&
  6219.              (lList1.indx > 1) &&
  6220.              (gList[gMap[groupIDs[gx][gy]]].libC > 1)) /* try diags */
  6221.             {
  6222.               listDiags(gx, gy, &dList);
  6223.               j = 0;
  6224.               i = lList1.indx;
  6225.               while ((j < dList.indx) &&
  6226.                     (i < maxSPoint))
  6227.                 {
  6228.                   j = j + 1;
  6229.                   i = i + 1;
  6230.                   libList[i] = 0;     /* mark this as a diag */
  6231.                       lList1.p[i].px = dList.p[j].px;
  6232.                       lList1.p[i].py = dList.p[j].py;
  6233.                 }
  6234.               lList1.indx = i;
  6235.             }
  6236.           if (lList1.indx > 1) /* sort by decreasing lib count */
  6237.             {
  6238.               for (i = 1; i <= lList1.indx; i++)
  6239.                 if (libList[i] != 0)       /* diags are tried last */
  6240.                     {
  6241.                       mark2 = playMark;
  6242.                       tryPlay(lList1.p[i].px, lList1.p[i].py, him);
  6243.                       libList[i] = gList[gMap[groupIDs[gx][gy]]].libC;
  6244.                       if ((libList[i] > treeLibLim) ||
  6245.                          ((libList[i] > (depthLimit - depth)) &&
  6246.                           (libList[i] > 2)))
  6247.             {
  6248.             *escape = TRUE;
  6249.             result = FALSE;
  6250.             goto one;
  6251.             }
  6252.                       undoTo(mark2);
  6253.                     }
  6254.               for (i = 1; i <= lList1.indx - 1; i++)
  6255.                 for (j = i + 1; j <= lList1.indx; j++)
  6256.                   if (libList[i] < libList[j])
  6257.                     {
  6258.                       tl = libList[i];
  6259.                       libList[i] = libList[j];
  6260.                       libList[j] = tl;
  6261.                       tp = lList1.p[i];
  6262.                       lList1.p[i] = lList1.p[j];
  6263.                       lList1.p[j] = tp;
  6264.                     }
  6265.             }
  6266.           for (i = 1; i <= lList1.indx + 1; i++) /* try his responses */
  6267.             {
  6268.               mark2 = playMark;
  6269.               if (i <= lList1.indx) /* try his move */
  6270.                   {
  6271.                     tryPlay(lList1.p[i].px, lList1.p[i].py, him); /* play his response */
  6272.                     pause();
  6273.                     if (gList[gMap[groupIDs[lList1.p[i].px]
  6274.                                    [lList1.p[i].py]]].libC < 2)
  6275.                       goto two; /* a bogus move */
  6276.                   }
  6277.               else if (gList[gMap[groupIDs[gx][gy]]].libC <= 1)
  6278.             {
  6279.             result = TRUE;
  6280.             goto one;
  6281.             }
  6282.               if (gList[gMap[groupIDs[gx][gy]]].libC > treeLibLim)
  6283.                 {
  6284.                   *escape = TRUE;
  6285.           result = FALSE;
  6286.           goto one;
  6287.                 }
  6288.               if (gList[gMap[groupIDs[gx][gy]]].libC > 1)
  6289.                 {  /* look at my responses */
  6290.                   sSpanGroup(gx, gy, &lList2); /* list his liberties */
  6291.                   dStart = lList2.indx + 1;
  6292.                   if (adjInAtari) /* he wins */
  6293.                      {
  6294.                        result = FALSE;
  6295.                        goto one;
  6296.                      }
  6297.                   if ((lList2.indx > 2) && adj2Libs) /* he wins */
  6298.                      {
  6299.                        result = FALSE;
  6300.                        goto one;
  6301.                      }
  6302.                   for (k = 1; k <= maxSPoint; k++)
  6303.                     libList[k] = -1;
  6304.                   if (utilPlayLevel > 4) /* account for diagonal moves */
  6305.                     {
  6306.                       listDiags(gx, gy, &dList);
  6307.                       j = 0;
  6308.                       k = lList2.indx;
  6309.                       while ((j < dList.indx) &&
  6310.                             (k < maxSPoint))
  6311.                         {
  6312.                           j = j + 1;
  6313.                           k = k + 1;
  6314.                           libList[k] = 100;
  6315.                               lList2.p[k].px = dList.p[j].px;
  6316.                               lList2.p[k].py = dList.p[j].py;
  6317.                         }
  6318.                       lList2.indx = k;
  6319.                     }
  6320.                   if (lList2.indx > 1) /* sort by increasing lib count */
  6321.                     {
  6322.                       for (k = 1; k <= lList2.indx; k++)
  6323.                         if (libList[k] != 100)     /* diags go last */
  6324.                             {
  6325.                               mark3 = playMark;
  6326.                               tryPlay(lList2.p[k].px, lList2.p[k].py, me);
  6327.                               libList[k] = gList[gMap[groupIDs[gx][gy]]].libC;
  6328.                               undoTo(mark3);
  6329.                             }
  6330.                       for (k = 1; k <= lList2.indx - 1; k++)
  6331.                         for (j = k + 1; j <= lList2.indx; j++)
  6332.                           if (libList[k] > libList[j])
  6333.                             {
  6334.                               tl = libList[k];
  6335.                               libList[k] = libList[j];
  6336.                               libList[j] = tl;
  6337.                               tp = lList2.p[k];
  6338.                               lList2.p[k] = lList2.p[j];
  6339.                               lList2.p[j] = tp;
  6340.                             }
  6341.                           else if ((libList[k] == libList[j]) &&
  6342.                                   (libList[k] == 1))
  6343.                             if (mtNbrs(lList2.p[k].px, lList2.p[k].py) <
  6344.                                mtNbrs(lList2.p[j].px, lList2.p[j].py))
  6345.                               {
  6346.                                 tl = libList[k];
  6347.                                 libList[k] = libList[j];
  6348.                                 libList[j] = tl;
  6349.                                 tp = lList2.p[k];
  6350.                                 lList2.p[k] = lList2.p[j];
  6351.                                 lList2.p[j] = tp;
  6352.                               }
  6353.                     }
  6354.                   for (j = 1; j <= lList2.indx; j++)
  6355.                     {
  6356.                       if (killTree(lList2.p[j].px, lList2.p[j].py, gx,
  6357.                 gy, &esc, tkMark))
  6358.                         goto two; /* this kills him */
  6359.                       if (esc && (j >= dStart))
  6360.                         {
  6361.                           result = FALSE;
  6362.                           goto one; /* don't bother with more diags if escapes */
  6363.                         }
  6364.                     }
  6365.                   result = FALSE;  /* none of my responses kills him */
  6366.                   goto one;
  6367.                 }
  6368.     two:
  6369.              undoTo(mark2);
  6370.            }
  6371.           result = TRUE; /* none of his responses saves him */
  6372.         }
  6373.     one:
  6374.       undoTo(curMark);
  6375. /*      sClearChar(sChar, rXor); */
  6376.       depth = depth - 1;
  6377.       return result;
  6378.     } /* killTree */
  6379.  
  6380. short tKillTree(tx, ty, gx, gy)
  6381. short tx, ty, gx, gy;
  6382.   { /* tKillTree */
  6383.     short tkMark, escape;
  6384.     tryCount = 0;
  6385.     tkMark = playMark;
  6386.     return killTree(tx, ty, gx, gy, &escape, tkMark);
  6387.   } /* tKillTree */
  6388.  
  6389. short killable(gx, gy, killx, killy)
  6390. short gx, gy, *killx, *killy;
  6391. { /* killable */
  6392. #ifdef DEBUG
  6393.   printf( "killable\n" );
  6394.   showTrees = TRUE;
  6395. #endif
  6396.   dbStop = TRUE;
  6397.   him = bord[gx][gy]; /* find out who I am */
  6398.   me = -him;
  6399. /*  if (me == 1)
  6400.     sChar = '>';
  6401.   else
  6402.     sChar = '|'; */
  6403. /*  write(sChar); */
  6404.   depth = 1;
  6405.   topMark = playMark;
  6406.   sSpanGroup(gx, gy, &lList); /* find his liberties */
  6407.   if (lList.indx == 1)
  6408.     {
  6409.       *killx = lList.p[1].px;
  6410.       *killy = lList.p[1].py;
  6411.       return TRUE;
  6412.     }
  6413.   else if (lList.indx > treeLibLim)
  6414.     return FALSE;
  6415.   else if (adjInAtari)
  6416.     return FALSE;
  6417.   else if ((lList.indx > 2) && adj2Libs)
  6418.     return FALSE;
  6419.   else
  6420.     {
  6421.       for (i = 1; i <= maxSPoint; i++)
  6422.         libList[i] = -1;
  6423.       if (utilPlayLevel > 4) /* account for diagonal moves */
  6424.         {
  6425.           listDiags(gx, gy, &dList);
  6426.           j = 0;
  6427.           i = lList.indx;
  6428.           while ((j < dList.indx) &&
  6429.                 (i < maxSPoint))
  6430.             {
  6431.               j = j + 1;
  6432.               i = i + 1;
  6433.               libList[i] = 100;
  6434.                   lList.p[i].px = dList.p[j].px;
  6435.                   lList.p[i].py = dList.p[j].py;
  6436.             }
  6437.           lList.indx = i;
  6438.         }
  6439.       if (lList.indx > 1) /* sort by increasing lib count */
  6440.         {
  6441.           for (i = 1; i <= lList.indx; i++)
  6442.             if (libList[i] != 100)  /* diags go last */
  6443.                 {
  6444.                   mark2 = playMark;
  6445.                   tryPlay(lList.p[i].px, lList.p[i].py, me);
  6446.                   libList[i] = gList[gMap[groupIDs[gx][gy]]].libC;
  6447.                   undoTo(mark2);
  6448.                 }
  6449.           for (i = 1; i <= lList.indx - 1; i++)
  6450.             for (j = i + 1; j <= lList.indx; j++)
  6451.               if (libList[i] > libList[j])
  6452.                 {
  6453.                   tl = libList[i];
  6454.                   libList[i] = libList[j];
  6455.                   libList[j] = tl;
  6456.                   tp = lList.p[i];
  6457.                   lList.p[i] = lList.p[j];
  6458.                   lList.p[j] = tp;
  6459.                 }
  6460.               else if ((libList[i] == libList[j]) &&
  6461.                       (libList[i] == 1))
  6462.                 if (mtNbrs(lList.p[i].px, lList.p[i].py) <
  6463.                    mtNbrs(lList.p[j].px, lList.p[j].py))
  6464.                   {
  6465.                     tl = libList[i];
  6466.                     libList[i] = libList[j];
  6467.                     libList[j] = tl;
  6468.                     tp = lList.p[i];
  6469.                     lList.p[i] = lList.p[j];
  6470.                     lList.p[j] = tp;
  6471.                   }
  6472.         }
  6473.       for (i = 1; i <= lList.indx; i++)
  6474.         {
  6475.           if (legal[lList.p[i].px, lList.p[i].py])
  6476.             {
  6477.               *killx = lList.p[i].px;
  6478.               *killy = lList.p[i].py;
  6479.               if (tKillTree(*killx, *killy, gx, gy))
  6480.                 {
  6481. /*                  sClearChar(sChar, rXor); */
  6482.                   return TRUE;
  6483.                 }
  6484.             }
  6485.         }
  6486.       return FALSE;
  6487.     }
  6488. /*   sClearChar(sChar, rXor); */
  6489. } /* killable */
  6490.  
  6491. SHAR_EOF
  6492. fi
  6493. if test -f 'main.c'
  6494. then
  6495.     echo shar: "will not over-write existing file 'main.c'"
  6496. else
  6497. cat << \SHAR_EOF > 'main.c'
  6498. /*=========================================================================
  6499. ===                                    ===
  6500. === FILE    main.c                            ===
  6501. ===                                    ===
  6502. === CONTENTS    Main file for xamigo.                    ===
  6503. ===                                    ===
  6504. === PART OF    xamigo                            ===
  6505. ===                                    ===
  6506. === COPYRIGHT    Copyright (C) 1992 by Neil Bowers            ===
  6507. ===                                    ===
  6508. =========================================================================*/
  6509.  
  6510. #include <stdio.h>
  6511. #include <X11/Intrinsic.h>
  6512. #include <X11/StringDefs.h>
  6513. #include <X11/Xaw/Form.h>
  6514. #include <X11/Xaw/Command.h>
  6515. #include <X11/Xaw/AsciiText.h>
  6516. #include <X11/Xaw/Box.h>
  6517. #include <X11/Shell.h>
  6518. #include "check16.xbm"
  6519. #include "Goban.h"
  6520. #include "xamigo.h"
  6521. #include "amigo.h"
  6522.  
  6523. Pixmap    checkmark;
  6524.  
  6525.  
  6526. char    *stat_widget_names[] =
  6527. {
  6528.     "playerLabel","scoreLabel","playerScore","lastMoveLabel","lastMove"
  6529. };
  6530.  
  6531. Widget        black_stat_widgets[5];
  6532. Widget        white_stat_widgets[5];
  6533. Widget        toplevel,form,box;
  6534. Widget        goban,stats_popup,message;
  6535. int        current_handicap, new_handicap;
  6536. int        current_level, new_level;
  6537. int        ingame,counting;
  6538. short        humanColor, amigoColor;
  6539. short        new_color;
  6540. short        human_passed,amigo_passed;
  6541. short        amigo_last_x,amigo_last_y,
  6542.         human_last_x,human_last_y;
  6543.  
  6544. extern short    playLevel;
  6545. extern short    showTrees,showMoveReason,groupInfo;
  6546. extern char    *playReason;
  6547.  
  6548. extern MenuItem    game_items[],level_items[],handicap_items[],level_items[];
  6549.  
  6550.  
  6551. XtActionsRec actions[] =
  6552. {
  6553.     {"inputStone",    InputStone},
  6554.     {"pass",    PassMove}
  6555. };
  6556.  
  6557.  
  6558. /*--------------------------------------------------------
  6559. -- main()                        --
  6560. --------------------------------------------------------*/
  6561. void
  6562. main(argc, argv)
  6563.     unsigned int    argc;
  6564.     char        *argv[];
  6565. {
  6566.     XtAppContext    app_con;
  6567.     int        i;
  6568.  
  6569.  
  6570.     toplevel = XtAppInitialize(&app_con, "Xamigo", NULL, 0,
  6571.                     &argc, argv, NULL, NULL, 0);
  6572.  
  6573.     form = XtCreateManagedWidget("form", formWidgetClass, toplevel,
  6574.                             NULL,0);
  6575.  
  6576.     box = XtCreateManagedWidget("buttonBox", boxWidgetClass, form,
  6577.                             NULL,0);
  6578.  
  6579.  
  6580.     /*-- create the menus --*/
  6581.  
  6582.     CreateAmigoMenus(box);
  6583.  
  6584.     goban = XtVaCreateManagedWidget("goban",gobanWidgetClass,form,
  6585.             XtNsensitive,    TRUE,
  6586.             XtNcursor,    GbCGrayStone,
  6587.             0);
  6588.  
  6589.     checkmark = XCreateBitmapFromData(XtDisplay(toplevel),
  6590.             RootWindowOfScreen(XtScreen(toplevel)),
  6591.             check16_bits, check16_width, check16_height);
  6592.  
  6593.     XtAppAddActions(app_con, actions, XtNumber(actions));
  6594.  
  6595.     ingame = counting = 0;
  6596.     new_handicap = current_handicap = 0;
  6597.     new_level = playLevel = 7;
  6598.     humanColor = WHITE;
  6599.     new_color = amigoColor = BLACK;
  6600.     XtVaSetValues(game_items[4].widget,XtNleftBitmap,checkmark,0);
  6601.     XtVaSetValues(level_items[6].widget,XtNleftBitmap,checkmark,0);
  6602.     XtVaSetValues(handicap_items[0].widget,XtNleftBitmap,checkmark,0);
  6603.  
  6604.     CreateStatsPopup();
  6605.  
  6606.     XtRealizeWidget(toplevel);
  6607.     XtAppMainLoop(app_con);
  6608. }
  6609.  
  6610.  
  6611. /*----------------------------------------------------------------
  6612. -- NewGameProc()                        --
  6613. --    Handler routine for New Game entry on "Game" menu.    --
  6614. --    Clear board, initialise AmiGo, and start a new game.    --
  6615. ----------------------------------------------------------------*/
  6616. void
  6617. NewGameProc(widget,call_data,closure)
  6618.     Widget        widget;
  6619.     XtPointer    closure;
  6620.     XtPointer    call_data;
  6621. {
  6622.     ingame = 0;
  6623.     current_handicap = new_handicap;
  6624.     playLevel = new_level;
  6625.     human_passed = amigo_passed = FALSE;
  6626.  
  6627.     amigo_last_x = amigo_last_y = human_last_x = human_last_y = 0;
  6628.     amigoColor = new_color;
  6629.     humanColor = (amigoColor==BLACK?WHITE:BLACK);
  6630.     XtVaSetValues(goban,
  6631.         XtNcursor,(humanColor==BLACK ? GbCBlackStone: GbCWhiteStone),
  6632.         NULL);
  6633.  
  6634.     /*-- clear goban *before* calling goRestart() --*/
  6635.     GbClearBoard(goban);
  6636.     goRestart(current_handicap);
  6637.  
  6638.     XtVaSetValues(black_stat_widgets[4],XtNlabel,"      ",0);
  6639.     XtVaSetValues(white_stat_widgets[4],XtNlabel,"      ",0);
  6640.     XtVaSetValues(message,XtNstring,"",0);
  6641.  
  6642.     ingame = 1;
  6643.  
  6644.     if ((amigoColor == BLACK && current_handicap == 0) ||
  6645.                 (amigoColor == WHITE && current_handicap > 0))
  6646.         AmigoMove();
  6647. }
  6648.  
  6649. /*----------------------------------------------------------------
  6650. -- QuitProc()                            --
  6651. --    Handler routine for the Quit item of the Game menu.    --
  6652. --    This should perhaps do a bit more.  Eg, if there is a    --
  6653. --    game in progress, request confirmation.            --
  6654. ----------------------------------------------------------------*/
  6655. void
  6656. QuitProc(widget,call_data,closure)
  6657.     Widget        widget;
  6658.     XtPointer    closure;
  6659.     XtPointer    call_data;
  6660. {
  6661.     exit(0);
  6662. }
  6663.  
  6664. /*----------------------------------------------------------------
  6665. -- LevelProc()                            --
  6666. --    Handler routine for "Level" menu.            --
  6667. ----------------------------------------------------------------*/
  6668. void
  6669. LevelProc(widget,call_data,closure)
  6670.     Widget        widget;
  6671.     XtPointer    closure;
  6672.     XtPointer    call_data;
  6673. {
  6674.     Widget        old;
  6675.     int        item_num = (int) call_data;
  6676.  
  6677.     if (item_num == new_level - 1)
  6678.         return;
  6679.  
  6680.     old = level_items[new_level-1].widget;
  6681.     XtVaSetValues(old,XtNleftBitmap,None,0);
  6682.  
  6683.     new_level = item_num + 1;
  6684.     XtVaSetValues(widget,XtNleftBitmap,checkmark,0);
  6685. }
  6686.  
  6687. /*----------------------------------------------------------------
  6688. -- OptionProc()                            --
  6689. --    Handler routine for `option' entries on the "Game" menu    --
  6690. ----------------------------------------------------------------*/
  6691. void
  6692. OptionProc(widget,call_data,closure)
  6693.     Widget        widget;
  6694.     XtPointer    closure;
  6695.     XtPointer    call_data;
  6696. {
  6697.     int        item_num = (int) call_data;
  6698.     short        setting;
  6699.  
  6700.     if (item_num < 5)
  6701.     {
  6702.         XtVaSetValues(game_items[3].widget,XtNleftBitmap,None,0);
  6703.         XtVaSetValues(game_items[4].widget,XtNleftBitmap,None,0);
  6704.         new_color = (item_num==3?WHITE:BLACK);
  6705.         XtVaSetValues(widget,XtNleftBitmap,checkmark,0);
  6706.         return;
  6707.     }
  6708.     switch (item_num)
  6709.     {
  6710.         case 6:        /* Move Reason */
  6711.             setting = (showMoveReason = ! showMoveReason);
  6712.             break;
  6713.  
  6714.         case 7:        /* show lookahead */
  6715.             setting = (showTrees = ! showTrees);
  6716.     }
  6717.     XtVaSetValues(widget,XtNleftBitmap,(setting?checkmark:None),0);
  6718. }
  6719.  
  6720. /*----------------------------------------------------------------
  6721. -- HandicapProc()                        --
  6722. --    Handler routine for the "Move" menu.            --
  6723. ----------------------------------------------------------------*/
  6724. void
  6725. MoveProc(widget,call_data,closure)
  6726.     Widget        widget;
  6727.     XtPointer    closure;
  6728.     XtPointer    call_data;
  6729. {
  6730.     short        x,y;
  6731.     char        mv[8];
  6732.  
  6733.     if (!ingame && !counting)
  6734.     {
  6735.         XtVaSetValues(message,XtNstring,"Game not in progess.",0);
  6736.         XBell(XtDisplay(goban),0);
  6737.         return;
  6738.     }
  6739.     switch((int)call_data)
  6740.     {
  6741.         case 0:        /* pass */
  6742.             HumanPassMove();
  6743.             break;
  6744.  
  6745.         case 1:        /* resign */
  6746.             intrMoveReport(humanColor,"resign","");
  6747.             XtVaSetValues(message,XtNstring,"Game over.",0);
  6748.             XtVaSetValues(goban,XtNcursor,GbCGrayStone,NULL);
  6749.             counting = 0;
  6750.             ingame = 0;
  6751.             break;
  6752.     }
  6753. }
  6754.  
  6755. /*----------------------------------------------------------------
  6756. -- HandicapProc()                        --
  6757. --    Handler routine for the "Handicap" menu.        --
  6758. ----------------------------------------------------------------*/
  6759. void
  6760. HandicapProc(widget,call_data,closure)
  6761.     Widget        widget;
  6762.     XtPointer    closure;
  6763.     XtPointer    call_data;
  6764. {
  6765.     Widget        old;
  6766.     int        item_num = (int) call_data;
  6767.     int        newh;
  6768.  
  6769.     newh = (item_num==0?0:item_num + 1);
  6770.     if (newh == new_handicap)
  6771.         return;
  6772.  
  6773.     old = handicap_items[(new_handicap?new_handicap-1:0)].widget;
  6774.     XtVaSetValues(old,XtNleftBitmap,None,0);
  6775.  
  6776.     new_handicap = newh;
  6777.     XtVaSetValues(widget,XtNleftBitmap,checkmark,0);
  6778. }
  6779.  
  6780. /*----------------------------------------------------------------
  6781. -- PopupStatsProc()                        --
  6782. --    Popup the stats window.  Simple bit of code which tries    --
  6783. --    to put the popup in a sensible position.  Only handles    --
  6784. --    one case right now.                    --
  6785. ----------------------------------------------------------------*/
  6786. void
  6787. PopupStatsProc(widget,call_data,closure)
  6788.     Widget        widget;
  6789.     XtPointer    closure;
  6790.     XtPointer    call_data;
  6791. {
  6792.     Dimension    width,height,twidth,theight;
  6793.     Position    x,y,tx,ty;
  6794.  
  6795.  
  6796.     XtVaGetValues(stats_popup,
  6797.         XtNx,&x,
  6798.         XtNy,&y,
  6799.         XtNwidth,&width,
  6800.         XtNheight,&height,
  6801.         0);
  6802.     XtVaGetValues(toplevel,
  6803.         XtNx,&tx,
  6804.         XtNy,&ty,
  6805.         XtNwidth,&twidth,
  6806.         XtNheight,&theight,
  6807.         0);
  6808.     if (ty > height+40)
  6809.         XtVaSetValues(stats_popup,
  6810.             XtNx,tx,
  6811.             XtNy,ty-height-40,
  6812.             0);
  6813.     XtPopup(stats_popup,XtGrabNone);
  6814. }
  6815.  
  6816. /*----------------------------------------------------------------
  6817. -- StatDoneProc()                        --
  6818. --    Callback routine for the "Done" button on the Stats    --
  6819. --    popup window.  Pop down the stats window.        --
  6820. ----------------------------------------------------------------*/
  6821. void
  6822. StatDoneProc(widget,call_data,closure)
  6823.     Widget        widget;
  6824.     XtPointer    closure;
  6825.     XtPointer    call_data;
  6826. {
  6827.     XtPopdown(stats_popup);
  6828. }
  6829.  
  6830. /*----------------------------------------------------------------
  6831. -- CreateStatsPopup()                        --
  6832. --    Create the stats popup window, which displays captured    --
  6833. --    stone count, last move, any messages from AmiGo, and    --
  6834. --    the final score.                    --
  6835. ----------------------------------------------------------------*/
  6836. CreateStatsPopup()
  6837. {
  6838.     Widget        statform,form,done;
  6839.     char        *getenv(), *username;
  6840.     Dimension    width;
  6841.     int        i;
  6842.  
  6843.     stats_popup = XtCreatePopupShell("statsPopup",
  6844.                 transientShellWidgetClass,toplevel,NULL,0);
  6845.  
  6846.     username = getenv("USER");
  6847.     statform = XtCreateManagedWidget("statForm", formWidgetClass,
  6848.                 stats_popup, NULL,0);
  6849.  
  6850.     form = XtCreateManagedWidget("blackStatForm",formWidgetClass,statform,
  6851.                 NULL,0);
  6852.  
  6853.     for (i=0;i<5;i++)
  6854.         black_stat_widgets[i] = XtCreateManagedWidget(
  6855.                 stat_widget_names[i],labelWidgetClass,
  6856.                 form,NULL,0);
  6857.  
  6858.     form = XtCreateManagedWidget("whiteStatForm",formWidgetClass,statform,
  6859.                 NULL,0);
  6860.  
  6861.     for (i=0;i<5;i++)
  6862.         white_stat_widgets[i] = XtCreateManagedWidget(
  6863.                 stat_widget_names[i],labelWidgetClass,
  6864.                 form,NULL,0);
  6865.  
  6866.     message = XtCreateManagedWidget("messageWindow",asciiTextWidgetClass,
  6867.                 statform,NULL,0);
  6868.  
  6869.     done = XtCreateManagedWidget("statDone",commandWidgetClass,statform,
  6870.                 NULL,0);
  6871.  
  6872.     XtAddCallback(done,XtNcallback,StatDoneProc,NULL);
  6873.  
  6874.     XtRealizeWidget(stats_popup);
  6875. }
  6876.  
  6877. /*----------------------------------------------------------------
  6878. -- HumanPassMove()                        --
  6879. --    Called when (human) player passes: check for end of    --
  6880. --    game.  Should we pass a stone to the opponent?        --
  6881. --    Generate a move for computer player.            --
  6882. ----------------------------------------------------------------*/
  6883. void
  6884. HumanPassMove()
  6885. {
  6886.     if (!ingame)
  6887.     {
  6888.         if (counting)
  6889.         {
  6890.             CountUp();
  6891.             counting=0;
  6892.         }
  6893.         return;
  6894.     }
  6895.     intrMoveReport(humanColor,"pass  ","");
  6896.     human_passed = TRUE;
  6897.     CheckBothPassed();
  6898.     if (ingame)
  6899.         AmigoMove();
  6900. }
  6901.  
  6902. /*----------------------------------------------------------------
  6903. -- AmigoMove()                            --
  6904. --    Generate a move for the computer player.  Update    --
  6905. --    message window, mark stone placed.  If we passed, check    --
  6906. --    to see if game is over.                    --
  6907. ----------------------------------------------------------------*/
  6908. AmigoMove()
  6909. {
  6910.     short    x,y;
  6911.     char    mv[8];
  6912.  
  6913.  
  6914.     XtVaSetValues(message,XtNstring,"I'm thinking...",0);
  6915.     UpdateWidget(message);
  6916.     if (genMove(amigoColor,&x,&y))
  6917.     {
  6918.         sprintf(mv,"%c%d%s",(x<8?x+'A':x+'B'),y+1,(y<9?"    ":"   "));
  6919.         GoPlaceStone(amigoColor,x,y);
  6920.         if (amigo_last_x != 0)
  6921.             GbSetMark(goban,amigo_last_x,amigo_last_y,0,0);
  6922.         amigo_last_x = x+1;
  6923.         amigo_last_y = y+1;
  6924.         GbSetMark(goban,amigo_last_x,amigo_last_y,0,GbMDiamondMark);
  6925.         intrMoveReport(amigoColor,mv,playReason);
  6926.         amigo_passed = FALSE;
  6927.     }
  6928.     else
  6929.     {
  6930.         intrMoveReport(amigoColor,"pass  ","");
  6931.         amigo_passed = TRUE;
  6932.         CheckBothPassed();
  6933.     }
  6934. }
  6935.  
  6936. /*----------------------------------------------------------------
  6937. -- CheckBothPassed()                        --
  6938. --    Check to see whether the last two moves were both PASS.    --
  6939. --    If so, go into `remove dead stone' mode.        --
  6940. ----------------------------------------------------------------*/
  6941. CheckBothPassed()
  6942. {
  6943.     if (human_passed && amigo_passed)
  6944.     {
  6945.         XtVaSetValues(message,XtNstring,
  6946.             "Click on dead groups.  When all dead groups are removed, select \"pass\" from the Move menu.",0);
  6947.         XtVaSetValues(goban,XtNcursor,GbCGrayStone,NULL);
  6948.         ingame = 0;
  6949.         counting = 1;
  6950.     }
  6951. }
  6952.  
  6953.  
  6954. /*----------------------------------------------------------------
  6955. -- PassMove()                            --
  6956. --    Action proc for the 'p' keyboard command (pass).    --
  6957. ----------------------------------------------------------------*/
  6958. void
  6959. PassMove(widget,event)
  6960.     Widget        widget;
  6961.     XKeyEvent    *event;
  6962. {
  6963.     HumanPassMove();
  6964. }
  6965.  
  6966. /*----------------------------------------------------------------
  6967. -- InputStone()                            --
  6968. --    Mouse button press handler for Goban widget.        --
  6969. ----------------------------------------------------------------*/
  6970. void
  6971. InputStone(widget,event)
  6972.     Widget        widget;
  6973.     XButtonEvent    *event;
  6974. {
  6975.     char        mv[8];
  6976.     Position    x    = event->x;
  6977.     Position    y    = event->y;
  6978.  
  6979.  
  6980.     if (GbGetStoneFromPosition(widget, &x, &y) != TRUE)
  6981.         return;
  6982.  
  6983.     x--;
  6984.     y--;
  6985.     sprintf(mv,"%c%d%s",(x<8?x+'A':x+'B'),y+1,(y<9?"    ":"   "));
  6986.  
  6987.     if (!ingame && counting)
  6988.     {
  6989.         DeleteGroupFromStone(x,y);
  6990.         return;
  6991.     }
  6992.  
  6993.     if (!ingame && !counting)
  6994.         return;
  6995.  
  6996.     if (!GoPlaceStone(humanColor,x,y))
  6997.         return;
  6998.  
  6999.     if (human_last_x != 0)
  7000.         GbSetMark(goban,human_last_x,human_last_y,0,0);
  7001.     human_last_x = x+1;
  7002.     human_last_y = y+1;
  7003.     GbSetMark(goban,human_last_x,human_last_y,0,GbMDiamondMark);
  7004.  
  7005.     intrMoveReport(humanColor,mv,"");
  7006.     human_passed = FALSE;
  7007.  
  7008.     AmigoMove();
  7009. }
  7010. SHAR_EOF
  7011. fi
  7012. if test -f 'menus.c'
  7013. then
  7014.     echo shar: "will not over-write existing file 'menus.c'"
  7015. else
  7016. cat << \SHAR_EOF > 'menus.c'
  7017. /*=========================================================================
  7018. ===                                    ===
  7019. === FILE    menus.c                            ===
  7020. ===                                    ===
  7021. === CONTENTS    Definitions and routines for creating menus.        ===
  7022. ===                                    ===
  7023. === PART OF    xamigo                            ===
  7024. ===                                    ===
  7025. === COPYRIGHT    Copyright (C) 1992 by Neil Bowers            ===
  7026. ===                                    ===
  7027. =========================================================================*/
  7028.  
  7029. #include <stdio.h>
  7030. #include <X11/Intrinsic.h>
  7031. #include <X11/StringDefs.h>
  7032. #include <X11/Xaw/MenuButton.h>
  7033. #include <X11/Xaw/SimpleMenu.h>
  7034. #include <X11/Xaw/Sme.h>
  7035. #include <X11/Xaw/SmeBSB.h>
  7036. #include <X11/Xaw/SmeLine.h>
  7037. #include "xamigo.h"
  7038.  
  7039.  
  7040. MenuItem    game_items[] =
  7041. {
  7042.     {"newGame",    NewGameProc,    NULL},
  7043.     {"stats",    PopupStatsProc,    NULL},
  7044.     {"line",    NULL,        NULL},
  7045.     {"aWhite",    OptionProc,    NULL},
  7046.     {"aBlack",    OptionProc,    NULL},
  7047.     {"line",    NULL,        NULL},
  7048.     {"reason",    OptionProc,    NULL},
  7049.     {"lookahead",    OptionProc,    NULL},
  7050.     {"line",    NULL,        NULL},
  7051.     {"quit",    QuitProc,    NULL}
  7052. };
  7053.  
  7054. MenuItem    move_items[] =
  7055. {
  7056.     {"pass",    MoveProc,    NULL},
  7057.     {"resign",    MoveProc,    NULL}
  7058. };
  7059.  
  7060. MenuItem    level_items[] =
  7061. {
  7062.     {"level1",    LevelProc,    NULL},
  7063.     {"level2",    LevelProc,    NULL},
  7064.     {"level3",    LevelProc,    NULL},
  7065.     {"level4",    LevelProc,    NULL},
  7066.     {"level5",    LevelProc,    NULL},
  7067.     {"level6",    LevelProc,    NULL},
  7068.     {"level7",    LevelProc,    NULL}
  7069. };
  7070.  
  7071. MenuItem    handicap_items[] =
  7072. {
  7073.     {"handicap0",    HandicapProc,    NULL},
  7074.     {"handicap2",    HandicapProc,    NULL},
  7075.     {"handicap3",    HandicapProc,    NULL},
  7076.     {"handicap4",    HandicapProc,    NULL},
  7077.     {"handicap5",    HandicapProc,    NULL},
  7078.     {"handicap6",    HandicapProc,    NULL},
  7079.     {"handicap7",    HandicapProc,    NULL},
  7080.     {"handicap8",    HandicapProc,    NULL},
  7081.     {"handicap9",    HandicapProc,    NULL}
  7082. };
  7083.  
  7084.  
  7085. Menu    menus[] =
  7086. {
  7087.     {"gameMenu", "gameButton",
  7088.         game_items, XtNumber(game_items), NULL},
  7089.  
  7090.     {"moveMenu", "moveButton",
  7091.         move_items, XtNumber(move_items), NULL},
  7092.  
  7093.     {"levelMenu", "levelButton",
  7094.         level_items, XtNumber(level_items), NULL},
  7095.  
  7096.     {"handicapMenu", "handicapButton",
  7097.         handicap_items, XtNumber(handicap_items), NULL}
  7098. };
  7099.  
  7100.  
  7101. void
  7102. CreateAmigoMenus(widget)
  7103.     Widget    widget;
  7104. {
  7105.     CreateMenuStrip(widget,menus,XtNumber(menus));
  7106. }
  7107.  
  7108.  
  7109. void
  7110. CreateMenuStrip(container,mdef,num)
  7111.     Widget    container;
  7112.     Menu    *mdef;
  7113.     int    num;
  7114. {
  7115.     while (num--)
  7116.     {
  7117.         mdef->menu_button = CreateMenu(container,
  7118.             mdef->menu_name,
  7119.             mdef->button_name,
  7120.             mdef->items,
  7121.             mdef->num_items);
  7122.         mdef++;
  7123.     }
  7124. }
  7125.  
  7126.  
  7127. Widget
  7128. CreateMenu(parent,menu_name,button_name,menu_items,nitems)
  7129.     Widget        parent;
  7130.     char        *menu_name;
  7131.     char        *button_name;
  7132.     MenuItem    menu_items[];
  7133.     int        nitems;
  7134. {
  7135.     Widget        button, menu, item;
  7136.     int        i;
  7137.  
  7138.  
  7139.     button = XtVaCreateManagedWidget(button_name,
  7140.             menuButtonWidgetClass, parent,
  7141.             XtNmenuName, menu_name,
  7142.             0);
  7143.  
  7144.     menu = XtCreatePopupShell(menu_name, simpleMenuWidgetClass, button,
  7145.                             NULL, 0);
  7146.  
  7147.     for (i=0;i<nitems;i++)
  7148.     {
  7149.         if (!strcmp(menu_items[i].item_name,"line"))
  7150.             menu_items[i].widget = XtVaCreateManagedWidget(
  7151.                         menu_items[i].item_name,
  7152.                         smeLineObjectClass,menu, 0);
  7153.         else
  7154.         {
  7155.             menu_items[i].widget = XtVaCreateManagedWidget(
  7156.                         menu_items[i].item_name,
  7157.                         smeBSBObjectClass,menu,
  7158.                         0);
  7159.  
  7160.             XtAddCallback(menu_items[i].widget,
  7161.                 XtNcallback, menu_items[i].callback,
  7162.                 (XtPointer)i);
  7163.         }
  7164.     }
  7165.  
  7166.     return button;
  7167. }
  7168. SHAR_EOF
  7169. fi
  7170. if test -f 'stonemask.bm'
  7171. then
  7172.     echo shar: "will not over-write existing file 'stonemask.bm'"
  7173. else
  7174. cat << \SHAR_EOF > 'stonemask.bm'
  7175. #define stonemask_width 16
  7176. #define stonemask_height 16
  7177. #define stonemask_x_hot 7
  7178. #define stonemask_y_hot 8
  7179. static char stonemask_bits[] = {
  7180.    0xc0, 0x03, 0xf0, 0x0f, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xfe, 0x7f,
  7181.    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe, 0x7f,
  7182.    0xfc, 0x3f, 0xf8, 0x1f, 0xf0, 0x0f, 0xc0, 0x03};
  7183. SHAR_EOF
  7184. fi
  7185. if test -f 'whitestone.bm'
  7186. then
  7187.     echo shar: "will not over-write existing file 'whitestone.bm'"
  7188. else
  7189. cat << \SHAR_EOF > 'whitestone.bm'
  7190. #define whitestone_width 16
  7191. #define whitestone_height 16
  7192. #define whitestone_x_hot 7
  7193. #define whitestone_y_hot 8
  7194. static char whitestone_bits[] = {
  7195.    0xc0, 0x03, 0x30, 0x0c, 0x08, 0x10, 0x04, 0x20, 0x02, 0x40, 0x02, 0x40,
  7196.    0x01, 0x80, 0x01, 0x80, 0x01, 0x90, 0x01, 0x90, 0x02, 0x48, 0x02, 0x44,
  7197.    0x04, 0x23, 0x08, 0x10, 0x30, 0x0c, 0xc0, 0x03};
  7198. SHAR_EOF
  7199. fi
  7200. if test -f 'xamigo.h'
  7201. then
  7202.     echo shar: "will not over-write existing file 'xamigo.h'"
  7203. else
  7204. cat << \SHAR_EOF > 'xamigo.h'
  7205. /*=========================================================================
  7206. ===                                    ===
  7207. === FILE    xamigo.h                        ===
  7208. ===                                    ===
  7209. === CONTENTS    Definitions for xamigo.                    ===
  7210. ===                                    ===
  7211. === PART OF    xamigo                            ===
  7212. ===                                    ===
  7213. === AUTHOR    Neil Bowers, University of Leeds            ===
  7214. ===                                    ===
  7215. === DATE    12th July 1992                        ===
  7216. ===                                    ===
  7217. =========================================================================*/
  7218.  
  7219. #ifndef __xamigo_h
  7220. #define __xamigo_h
  7221.  
  7222. #include <X11/Intrinsic.h>
  7223. #include <X11/StringDefs.h>
  7224.  
  7225. #ifdef __STDC__
  7226. #define PROTO(fp)    fp
  7227. #else
  7228. #define PROTO(fp)    ()
  7229. #endif
  7230.  
  7231.  
  7232. typedef struct _MenuItem
  7233. {
  7234.     char        *item_name;
  7235.     void        (*callback)();
  7236.     Widget        widget;
  7237. } MenuItem;
  7238.  
  7239.  
  7240. typedef struct _Menu
  7241. {
  7242.     char        *menu_name;
  7243.     char        *button_name;
  7244.     MenuItem    *items;
  7245.     int        num_items;
  7246.     Widget        menu_button;
  7247. } Menu;
  7248.  
  7249.  
  7250. /*----------------------------------------------------------------
  7251. --            Function Prototypes            --
  7252. ----------------------------------------------------------------*/
  7253.  
  7254. void    NewGameProc    PROTO((Widget,XtPointer,XtPointer));
  7255. void    QuitProc    PROTO((Widget,XtPointer,XtPointer));
  7256. void    LevelProc    PROTO((Widget,XtPointer,XtPointer));
  7257. void    OptionProc    PROTO((Widget,XtPointer,XtPointer));
  7258. void    MoveProc    PROTO((Widget,XtPointer,XtPointer));
  7259. void    HandicapProc    PROTO((Widget,XtPointer,XtPointer));
  7260. void    PopupStatsProc    PROTO((Widget,XtPointer,XtPointer));
  7261. void    StatDoneProc    PROTO((Widget,XtPointer,XtPointer));
  7262. Widget    CreateMenu    PROTO((Widget,char *,char *,MenuItem,int));
  7263. void    CreateMenuStrip    PROTO((Widget,Menu *,int));
  7264. void    CreateAmigoMenus PROTO((Widget));
  7265. void    InputStone    PROTO((Widget,XButtonEvent));
  7266. void    PassMove    PROTO((Widget,XKeyEvent));
  7267. void    HumanPassMove    PROTO(());
  7268.  
  7269.  
  7270. #endif
  7271. SHAR_EOF
  7272. fi
  7273. if test -f 'xamigo.man'
  7274. then
  7275.     echo shar: "will not over-write existing file 'xamigo.man'"
  7276. else
  7277. cat << \SHAR_EOF > 'xamigo.man'
  7278. .\" Man page for xamigo, by Neil Bowers
  7279. .TH Xamigo 1.0 "August 12 1992"
  7280. .SH NAME
  7281. \fIXamigo\fR \- An X interface to "AmiGo" --- A Go playing program
  7282. .SH SYNOPSIS
  7283. .B xamigo
  7284. [-\fItoolkit_options\fP]
  7285. .SH DESCRIPTION
  7286. .I Xamigo
  7287. is a simple interface to the
  7288. .I AmiGo
  7289. Go playing program,
  7290. originally written for the Amiga computer.
  7291. The Go player was written by Stoney Ballard,
  7292. with additional code by Todd R. Johnson.
  7293. Xamigo is at best a beta release,
  7294. please send any suggestions for improvements to the author (see below).
  7295.  
  7296. When you invoke xamigo,
  7297. a window will appear which contains a goban with a row
  7298. of menu buttons across the top.
  7299. There are four menus, which are described in the following sections.
  7300.  
  7301. .SH "GAME MENU"
  7302.  
  7303. The Project menu contains entries which give control over xamigo,
  7304. rather than the wally code, or the goban.
  7305. The menu items are as follows:
  7306. .TP 8
  7307. .BI "New Game"
  7308. clears the goban and starts a new game,
  7309. using the level and handicap selected on the appropriate menus.
  7310. .TP 8
  7311. .BI "Game Stats"
  7312. pops up a window which presents game details for the players ---
  7313. last move and stones captured --- and a text window used to display
  7314. messages from xamigo, such as the final score when the game is over.
  7315. The Game Stats window has a
  7316. .BI Done
  7317. button which will pop down the window.
  7318. .TP 8
  7319. .BI "Amigo Plays White"
  7320. .TP 8
  7321. .BI "Amigo Plays Black"
  7322. hopefully obvious.  One (and only one) of these items should be checked,
  7323. signifying which color the computer will take in the next game.
  7324. .TP 8
  7325. .BI "Move Reason"
  7326. if this item is checked, then whenever the computer player makes a move,
  7327. the reasoning behind the move will be displayed in the message area
  7328. of the stats window.
  7329. .TP 8
  7330. .BI "Show Lookahead"
  7331. If checked, then xamigo will display each move which it is considering.
  7332. Fun to look at the first time,
  7333. but slows down the play.
  7334. .TP 8
  7335. .BI "Quit"
  7336. guess what this does.
  7337.  
  7338. .SH "MOVES MENU"
  7339. The Moves menu contains items related to moves once the game is in play.
  7340. .TP 8
  7341. .BI "Pass"
  7342. pass this move.
  7343. When both players pass, you can then remove dead groups by clicking on stones.
  7344. Once all dead groups have been removed, selecting Pass again will
  7345. result in the final score being displayed in the message window
  7346. (which is part of the Game Stats popup window).
  7347. The `p' key can be used as a short-cut for pass.
  7348. .TP 8
  7349. .BI "Resign"
  7350. resign the current game.
  7351. .LP
  7352. Other commands which could be added in the future include `undo',
  7353. `make my move for me', etc.
  7354.  
  7355. .SH "LEVEL MENU"
  7356. Select the level at which xamigo should play, between 1 and 7,
  7357. with 7 the highest.
  7358.  
  7359. .SH "HANDICAP MENU"
  7360.  
  7361. The Handicap
  7362. menu is used to set the handicap for the next game.
  7363.  
  7364. .SH OPTIONS
  7365. \fIXamigo\fP accepts the standard X Toolkit command line options.
  7366. One day there might be some xamigo options, who knows?
  7367.  
  7368. .SH RESOURCES
  7369. \fIXamigo\fP accepts the standard X Toolkit resource names and classes.
  7370. See OPTIONS above.
  7371.  
  7372. .SH BUGS
  7373. Plenty no doubt.  Please let me know if you find any.
  7374.  
  7375. .SH COPYRIGHT
  7376. The Goban widget is copyright (c) 1992 by Antoine Dumesnil de Maricourt.
  7377.  
  7378. The xamigo specific code is copyright (c) 1992 by Neil Bowers.
  7379. Feel free to distribute xamigo and use any code,
  7380. provided you give due credit to the respective authors.
  7381.  
  7382. .SH AUTHOR
  7383. .nf
  7384. Go player: Stoney Ballard
  7385. .fi
  7386.  
  7387. .nf
  7388. Goban Widget: Antoine Dumesnil de Maricourt
  7389. Email: dumesnil@etca.fr
  7390. .fi
  7391.  
  7392. .nf
  7393. Xamigo: Neil Bowers
  7394.         School of Computer Studies
  7395.         University of Leeds.
  7396. Email: neilb@scs.leeds.ac.uk
  7397. .fi
  7398.  
  7399. SHAR_EOF
  7400. fi
  7401. if test -f 'xinterface.c'
  7402. then
  7403.     echo shar: "will not over-write existing file 'xinterface.c'"
  7404. else
  7405. cat << \SHAR_EOF > 'xinterface.c'
  7406. /* AmiGo Interface.  Started 4/7/88 by Todd R. Johnson */
  7407. /* 8/8/89 Cleaned up for first release */
  7408. /* Version 1.0 */
  7409. /* Public Domain */
  7410.  
  7411. #include <X11/Intrinsic.h>
  7412. #include <X11/StringDefs.h>
  7413. #include "Goban.h"
  7414. #include <stdio.h>
  7415.  
  7416. #include "amigo.h"
  7417.  
  7418. extern Widget    goban;
  7419. extern Widget    black_stat_widgets[5];
  7420. extern Widget    white_stat_widgets[5];
  7421. extern Widget    message;
  7422.  
  7423.  
  7424. extern short    showTrees, playLevel, showMoveReason, groupInfo;
  7425.          
  7426.  
  7427. /* Print a stone of color at x, y intersection */
  7428. void
  7429. placestone(color, x, y)
  7430.     enum bVal    color;
  7431.     short        x, y;
  7432. {
  7433.     GbSetPoint(goban,++x,++y,(color==BLACK ? GbBlackStone : GbWhiteStone));
  7434.     UpdateWidget(goban);
  7435. }
  7436.  
  7437. /* Remove a stone from an intersection */
  7438. void
  7439. removestone(x, y)
  7440.     short        x, y;
  7441. {
  7442.     GbSetPoint(goban,++x,++y,GbEmptyPoint);
  7443.     UpdateWidget(goban);
  7444. }
  7445.  
  7446. /* Report on a move */
  7447. void
  7448. intrMoveReport(color, coord, reason)
  7449.     enum bVal    color;
  7450.     char        *coord;
  7451.     char        *reason;
  7452. {
  7453.     XtVaSetValues(message, XtNstring,"", NULL);
  7454.  
  7455.     XtVaSetValues((color == BLACK ? black_stat_widgets[4] :
  7456.                 white_stat_widgets[4]),XtNlabel,coord,0);
  7457.  
  7458.     XtVaSetValues(message,XtNstring, (showMoveReason ? reason : ""), NULL);
  7459. }
  7460.  
  7461. void
  7462. intrPrisonerReport(blackcnt, whitecnt)
  7463.     short    blackcnt;
  7464.     short    whitecnt;
  7465. {
  7466.     char    val[5];
  7467.  
  7468.     sprintf(val,"%d",blackcnt);
  7469.     XtVaSetValues(white_stat_widgets[2],XtNlabel,val,0);
  7470.     sprintf(val,"%d",whitecnt);
  7471.     XtVaSetValues(black_stat_widgets[2],XtNlabel,val,0);
  7472. }
  7473.  
  7474. #if 0
  7475. void intrCredits()
  7476. {
  7477.     intrPuts( "Player by Stoney Ballard" ); intrPutLn();
  7478.     intrPuts( "C port and interface"); intrPutLn();
  7479.     intrPuts( "by Todd R. Johnson"); intrPutLn();
  7480.     intrPutLn();
  7481.     intrPuts( "Use menus to set options." ); intrPutLn();
  7482.     intrPuts( "Select the Play menu" ); intrPutLn();
  7483.     intrPuts( "item to begin play." );
  7484. }
  7485. #endif
  7486.  
  7487. UpdateWidget(widget)
  7488.     Widget    widget;
  7489. {
  7490.     XEvent    event;
  7491.  
  7492.  
  7493.     while (XCheckTypedWindowEvent(XtDisplay(widget),XtWindow(widget),
  7494.                         Expose,&event))
  7495.         XtDispatchEvent(&event);
  7496. }
  7497. SHAR_EOF
  7498. fi
  7499. exit 0
  7500. #    End of shell archive
  7501.