home *** CD-ROM | disk | FTP | other *** search
/ Carousel / CAROUSEL.cdr / mactosh / code / cshar_go.sit < prev    next >
Text File  |  1988-06-20  |  91KB  |  2,408 lines

  1. 18-Jun-88 14:51:33-MDT,93237;000000000000
  2. Return-Path: <u-lchoqu%sunset@cs.utah.edu>
  3. Received: from cs.utah.edu by SIMTEL20.ARPA with TCP; Sat, 18 Jun 88 14:49:36 MDT
  4. Received: by cs.utah.edu (5.54/utah-2.0-cs)
  5.     id AA22730; Sat, 18 Jun 88 14:49:32 MDT
  6. Received: by sunset.utah.edu (5.54/utah-2.0-leaf)
  7.     id AA24857; Sat, 18 Jun 88 14:49:25 MDT
  8. Date: Sat, 18 Jun 88 14:49:25 MDT
  9. From: u-lchoqu%sunset@cs.utah.edu (Lee Choquette)
  10. Message-Id: <8806182049.AA24857@sunset.utah.edu>
  11. To: rthum@simtel20.arpa
  12. Subject: go.c.shar
  13.  
  14. #! /bin/sh
  15. #
  16. # This is a shell archive.  Save this into a file, edit it
  17. # and delete all lines above this comment.  Then give this
  18. # file to sh by executing the command "sh file".  The files
  19. # will be extracted into the current directory owned by
  20. # you with default permissions.
  21. #
  22. # The files contained herein are:
  23. #
  24. #   17 README
  25. #   12 go.c
  26. #    5 gofile.c
  27. #   10 gomain.c
  28. #   11 gomoves.c
  29. #    1 gomoves.h
  30. #   28 goprocs.c
  31. #    3 goprocs.h
  32. #
  33. echo 'Extracting README'
  34. if test -f README; then echo 'shar: will not overwrite README'; else
  35. sed 's/^X//' << '________This_Is_The_END________' > README
  36. XThis directory contains 1 document file and 7 files of source code for
  37. Xthe Go program posted 24 Feb 86, as promised.  The programs were written
  38. Xfor Megamax C.
  39. X
  40. XThe core programs (in goprocs.c) have been through extensive testing,
  41. Xeverything else is in the process of conceptualization and development.
  42. X
  43. XThese programs are provided as a simple skeleton go program.  Some code was
  44. Xremoved from the 'bestmoves' routine for this posting, to keep it simple.
  45. XSince code was removed, the following programs will not play as well as the
  46. Xexecutable version that was posted 24 Feb 1986.
  47. X
  48. XThis is not to be taken as an example of great coding technique - this is a
  49. Xfirst effort.
  50. X
  51. XKnown problems:  The last time that I adjusted the weights in the
  52. Xmove selection routine (bestmoves) to play a better game against Nemesis I
  53. Xmade a mistake, so presently the executable version of the program will
  54. Xattempt an illegal move in some situations.
  55. X
  56. XAlso, I do not have access to a Mac XL, so I can not insure that the
  57. Xprogram runs properly there.  As far as I know, the code follows the
  58. Xtoolbox interface conventions - nothing tricky there.
  59. X
  60. XWill this kind posting create more interest in Programs that play go?
  61. XOr will it set the programming of go back ten years by undermining support
  62. Xfor more professional efforts?  Other?
  63. X
  64. XThanks to those of you who have responded with problems and suggestions!
  65. XCorrespondence and gratuities of any kind (verbal, code, financial, ...)
  66. Xcan be sent to:
  67. X
  68. XLynn Beus & Jim Logan
  69. XBYU Computer Science
  70. X232 TMCB
  71. XProvo, Utah  84602
  72. X
  73. Xor email:  loganj@byuvax.bitnet
  74. X
  75. XPhone: (801) 378-3617
  76. X___________________________________________________________________________
  77. X
  78. X26 February 1986
  79. X
  80. XGo Utility Programs Description
  81. X
  82. XDeveloper:  James R. Logan Jr. (BYU)
  83. XAdvisor:  Dr. Lynn H. Beus (BYU)
  84. XBYU Computer Science
  85. X232 TMCB
  86. XProvo, Utah  84602
  87. Xemail address:  loganj@byuvax.bitnet
  88. Xphone:  (801) 378-3617
  89. X
  90. XThis document describes procedures, variables, arrays, and structures
  91. Xthat maintain a 1-dimensional representation of the Oriental game of Go.
  92. XThe present implementation of the programs, for lack of development
  93. Xtime, has the following arbitrary limitations:
  94. X
  95. X  -  No count is maintained of the number of eyes that each army has
  96. X     (an easy thing to implement?),  but only the number of individual
  97. X     liberties that each army has.
  98. X
  99. X  -  No count is maintained of the number of neighboring armies to an
  100. X     army.
  101. X
  102. X  -  The maximum allowable board size is 19 by 19 lines, or 361 positions.
  103. X
  104. X  -  The maximum allowable number of armies is 362 (compile time
  105. X     parameter).
  106. X
  107. X  -  The game board must be square.
  108. X
  109. XThe 'who' variable in the game structure (game.who) designates black's
  110. Xor white's turn to play, and is an input parameter to some of these
  111. Xprocedures.  The user is required to set this variable to White or Black
  112. Xbefore each procedure call.
  113. X
  114. XAll 1-dimensional representations of the Go board are defined in C as
  115. Xchar [361].  The Go Programs consist of twelve main procedures.  The
  116. Xcalling conventions and purpose of these twelve procedures is described
  117. Xas follows:
  118. X
  119. X-initialize
  120. XInitializes the specified game structure by clearing all stones from the
  121. Xvarious arrays and building the initial blank army.  Initialize must be
  122. Xcalled for a newly allocated game structure.  For example, to initialize
  123. Xa 5 by 5 game board the initialize routine should be called as follows:
  124. X
  125. X  g->width = 5;
  126. X  initialize(g);
  127. X  where g is a game structure pointer previously allocated by the user.
  128. X
  129. X-addastone
  130. XAdds a stone of color g.who to the specified 1-dimensional position and
  131. Xupdates the specified game structure.  If the specified position is
  132. Xalready occupied then no update occurs.  For example, to add a stone to
  133. Xposition 9 the addastone routine should be called as follows:
  134. X
  135. X  addastone(g,9);
  136. X  where g is an initialized game structure pointer.
  137. X
  138. X-removeastone
  139. XRemoves the specified stone and updates the specified game structure.
  140. XIf the specified stone represents an unoccupied position then no update
  141. Xoccurs.  For example, to remove a stone at position 9 the removeastone
  142. Xroutine should be called as follows:
  143. X
  144. X  removeastone(g,9,status);
  145. X  where g is a game structure pointer,
  146. X  and status is a movestatus (mstatus) structure.
  147. X
  148. X-getneighbors
  149. XReturns the number of immediate non-blank neighbors to a position, and
  150. Xreturns the 1 dimensional board position of each non-blank neighbor in a
  151. Xstone[1..4] array sorted by army number.  For example, to get all
  152. Xneighboring positions (white, black, and blank) to position 9 the
  153. Xgetneighbors routine should be called as follows:
  154. X
  155. X  getneighbors(g,n,9);
  156. X  where g is a game structure pointer,
  157. X  and n is a nabor structure pointer.
  158. X
  159. XThe next two procedures will not normally be needed by the users program,
  160. Xbut they are included for completeness.
  161. X
  162. X-capture
  163. XRemoves the army represented by the specified stone and updates the
  164. Xappropriate data structures.  If the specified stone represents a blank
  165. Xarmy then no update occurs.  For example, to remove an army that
  166. Xcontains a stone at position 9 the capture routine should be called as
  167. Xfollows:
  168. X
  169. X  capture(g,9);
  170. X  where g is a game structure pointer.
  171. X
  172. X-uncapture
  173. XUncaptures the army represented by the specified position and updates
  174. Xthe appropriate data structures.  If the specified postion is occupied
  175. Xthen no update occurs.  For example, to uncapture an army that contains
  176. Xa stone at position 9 the uncapture routine should be called as follows:
  177. X
  178. X  uncapture(g,9,color);
  179. X  where g is a game structure pointer,
  180. X  and color is the color of the army (White or Black) being uncaptured.
  181. X_________________________________________________________________________
  182. X
  183. XThe following routines print the values of game structures upside down
  184. Xfrom the game board displayed on the screen.
  185. X
  186. X-moveboard
  187. XThis procedure prints the game.board array on the screen, for debugging.
  188. XFor example, to display game.board call moveboard as follows:
  189. X
  190. X  moveboard(g);
  191. X  where g is a game structure pointer.
  192. X
  193. X-armyboard
  194. XThis procedure prints the game.armymen array on the screen, for debugging.
  195. XFor example, to display game.armymen call armyboard as follows:
  196. X
  197. X  armyboard(g);
  198. X  where g is a game structure pointer.
  199. X
  200. X-armyinfo
  201. XThis procedure prints the game.army structure on the screen, for debugging.
  202. XFor example, to display game.army call armyinfo as follows:
  203. X
  204. X  armyinfo(g);
  205. X  where g is a game structure pointer.
  206. X
  207. Xlinkinfo
  208. XThis procedure prints the game.armylnk array on the screen, for debugging.
  209. XFor example, to display game.armylnk call linkinfo as follows:
  210. X
  211. X  linkinfo(g);
  212. X  where g is a game structure pointer.
  213. X
  214. X-pictinfo
  215. XThis procedure prints the game.cpict and game.opict arrays on the screen
  216. Xin hex, for debugging.  For example, to display game.cpict and
  217. Xgame.opict call pictinfo as follows:
  218. X
  219. X  pictinfo(g);
  220. X  where g is a game structure pointer.
  221. X
  222. X-neighborinfo
  223. XThis procedure prints the game.neibrd array on the screen in hex, for
  224. Xdebugging.  For example, to display game.neibrd call neighborinfo as
  225. Xfollows:
  226. X
  227. X  neighborinfo(g);
  228. X  where g is a game structure pointer.
  229. X________________________________________________________________________
  230. X
  231. XThese Go Programs use one main data structure to represent a game of Go,
  232. Xas follows:
  233. X
  234. Xgame - This structure contains some basic structures for the analysis of
  235. Xa single board position.
  236. X
  237. XThe Game structure contains the following variables, arrays, and
  238. Xstructures:
  239. X
  240. Xwho - This variable represents the color of the player making the
  241. Xcurrent move, and is set to White for one player, and Black for the
  242. Xother player.  This variable must be set before a call to the addastone
  243. Xprocedure, because the addastone procedure uses this variable to set the
  244. Xboard array value (stone color).
  245. X
  246. Xavail - This variable is the next available army number in a linked list
  247. Xof army numbers. Do not change this variable.
  248. X
  249. Xmaxstone - This variable indicates the 1-dimensional size of the game
  250. Xboard being used.  It is computed by the initialize procedure.  Do not
  251. Xchange this variable.
  252. X
  253. Xwidth - This variable indicates the width of the game board.  The
  254. Xinitialize procedure sets this variable to the maximum column number.
  255. XDo not change this variable.
  256. X
  257. Xmovecount - This variable indicates the number of stones played in the
  258. Xgame structure.  This variable is cleared by the initialize procedure,
  259. Xincremented by calls to the addastone procedure, and decremented by
  260. Xcalls to the removeastone and capture procedures. Do not change this
  261. Xvariable.
  262. X
  263. Xmovestatus - This structure contains ko information and capture
  264. Xinformation based on the last stone played on the board.  This structure
  265. Xshould be pushed on the stack during tree searches, because it is used
  266. Xto remove a play and restore the previous game position.  Do not change
  267. Xthe variables in this structure.
  268. X
  269. XThe ko position (movestatus.kospot) is set by the capture procedure to
  270. Xthe 1-dimensional position of a 1-man army that was just captured.  If
  271. Xno army was captured by the last move then this variable is set to -1.
  272. XAlso if the size of the captured army is greater than one then this
  273. Xvariable is set to -1.  The addastone procedure sets this variable to
  274. X-1, but the addastone procedure calls the capture procedure if a capture
  275. Xis made by a move.
  276. X
  277. XThe capture information (movestatus.captures) is set by the addastone
  278. Xprocedure to reflect which of the four possible armies surrounding the
  279. Xnew stone was captured.  This variable type (movestatus.captures) is bit
  280. Xencoded, where the least significant 4 bits determine which direction an
  281. Xarmy was captured in (so that the army can be restored if the capturing
  282. Xstone is removed).
  283. X
  284. Xdebug - This BITSET variable represents various debug states.  Bits 0-5
  285. Xare used in these programs, and bits 6-15 are available for any use.
  286. X
  287. Xboard - This 1-dimensional array contains the position of black and
  288. Xwhite stones on the Go Board.  One player's stones are represented by a
  289. Xvalue of White, and opponent stones are represented by a value of Black.
  290. XDo not change this array.
  291. X
  292. Xrowbrd - This 1-dimensional array corresponds exactly to the board array
  293. Xabove and indicates the 2-dimensional row number of each position.  Do
  294. Xnot change this array.
  295. X
  296. Xcolbrd - This 1-dimensional array corresponds exactly to the board array
  297. Xabove and indicates the 2-dimensional column number of each position.
  298. XDo not change this array.
  299. X
  300. Xarmymen - This 1-dimensional array corresponds exactly to the Board
  301. Xstructure (above). Each board position in this array contains the army
  302. Xnumber of the army that occupies this position.  The army number is used
  303. Xto access information about the army.
  304. X
  305. Xarmylnk - This 1-dimensional array corresponds exactly to the Board
  306. Xstructure (above). Each position in this array contains the number of
  307. Xthe next man in the army.  This array is used for processing every man
  308. Xin an army, which occurs when an army is being built, when an army is
  309. Xcaptured, and when army neighbors need to be counted.
  310. X
  311. Xwhitepats - This 1-dimensional array corresponds exactly to the Board
  312. Xstructure (above). Each position in this array contains a binary
  313. Xrepresentation of the white stones in a 5 by 5 diamond shape around the
  314. Xposition.  This binary picture can be used to test for a specific
  315. Xgeometic arrangement of the white player's stones around a given
  316. Xposition.  See the diagram below.
  317. X
  318. Xblackpats - This 1-dimensional array corresponds exactly to the Board
  319. Xstructure (above). Each position in this array contains a binary
  320. Xrepresentation of the black stones in a 5 by 5 diamond shape around the
  321. Xposition.  This binary picture can be used to test for a specific
  322. Xgeometic arrangement of the black player's stones around a given
  323. Xposition.  See the diagram below.
  324. X
  325. XWhitepats and blackpats (above) contain 32 bit values that represent
  326. Xstone patterns in a 5 by 5 diamond shape, centered around a given board
  327. Xposition (S).  Only 29 bits are actually used, 25 bits for a 5 by 5
  328. Xsquare and 4 bits at the center of each outside edge.  The area covered
  329. Xand bits represented are as follows:
  330. X
  331. X    Shape              Bit numbers
  332. X
  333. X      *                    28
  334. X  * * * * *           5  4  3  2  1
  335. X  * * * * *          10  9  8  7  6
  336. X* * * S * * *     27 15 14 13 12 11 26
  337. X  * * * * *          20 19 18 17 16
  338. X  * * * * *          25 24 23 22 21
  339. X      *                    29
  340. X
  341. Xneibrd - This 1-dimensional array corresponds exactly to the Board
  342. Xstructure (above).  The purpose of this array is to test a 1-dimensional
  343. Xposition and determine if the position is on one edge or corner of the
  344. Xboard.  This array can also be used to test for a position on row 1, 2,
  345. X3, or 4 from any side of the board.
  346. X
  347. Xarmy - This structure is indexed by army number, and contains
  348. Xinformation about each army such as size, color, first (first army man's
  349. Xboard position), last (last army man's board position), fp (forward
  350. Xpointer to the next army), bp (backward pointer to the previous army),
  351. Xlib (liberties), friend (number of bordering friendly stones), enemy
  352. X(number of bordering enemy stones), armies (number of neighboring
  353. Xnon-blank armies -- not implemented yet), and rollcall (scratchpad
  354. Xvariable).  For blank armies the number of liberties is not used, the
  355. Xnumber of friendly stones is the number of neighboring white stones, and
  356. Xthe number of enemy stones is the number of neighboring black stones.
  357. XFor non-blank armies the number of friendly stones is not used.
  358. X________________________________________________________________________
  359. X
  360. XThe following additional data structures are used by these programs and
  361. Xalso made available for convenience, as follows:
  362. X
  363. Xneighbors - This structure contains the output of the getneighbors
  364. Xprocedure:  the number and position of non-blank neighbors to a
  365. Xspecified 1-dimensional position, sorted by army number (which makes it
  366. Xeasier to tell if different neighbors are in the same army).
  367. X
  368. Xneighborcount - This array is used with the game.neibrd array to quickly
  369. Xdetermine how many valid neighboring positions there are to a given
  370. Xstone position.  This array, neighborcount[0..15], merely translates a
  371. Xbinary number from 0 to 15 into the number of bits that are set in that
  372. Xbinary number.
  373. X
  374. Xmstatus - This structure contains ko information and capture information
  375. Xbased on the last stone played on the board.
  376. X
  377. XThe ko position (movestatus.kospot) is set by the capture procedure to
  378. Xthe 1-dimensional position of a 1-man army that was just captured.  If
  379. Xno army was captured by the last move then this variable is set to -1.
  380. XAlso if the size of the captured army is greater than one then this
  381. Xvariable is set to -1.  The addastone procedure sets this variable to
  382. X-1, but the addastone procedure calls the capture procedure if a capture
  383. Xis made by a move.
  384. X
  385. XThe capture information (movestatus.captures) is set by the addastone
  386. Xprocedure to reflect which of the four possible armies surrounding the
  387. Xnew stone was captured.  This variable is bit encoded.
  388. X_________________________________________________________________________
  389. X
  390. XTo use all of the above utility programs and data structures the
  391. Xfollowing C code is necessary:
  392. X
  393. X#include <goprocs.h>
  394. X#include <gomoves.h>
  395. X
  396. XThe following C code creates/allocates a game structure called g at
  397. Xcompile time (this is the responsibility of the user):
  398. X
  399. X  game g;
  400. X
  401. XBlack, White, and Blank are C parameters that define the only valid
  402. Xstates of a board position.  Black and White define the only valid
  403. Xstone colors and player designations.  The following C code changes
  404. Xthe designated player in the game structure pointed to by g:
  405. X
  406. X  g->who = otherside[g->who];
  407. X
  408. XThe following C code will walk through all armies (black,white, and blank),
  409. Xgiven a game structure pointer (g):
  410. X
  411. X  int armynumber;
  412. X  armynumber = mygame.army[mygame.avail].bp; /* back pointer is first army */
  413. X  while (armynumber > 0) {
  414. X    if (mygame.army[armynumber].size > 0) {
  415. X      (* code to process each army goes here *)
  416. X    }
  417. X    armynumber = mygame.army[armynumber].bp;
  418. X  }
  419. X
  420. XThe following C code will walk through an army, given a game structure
  421. Xpointer (g) and the position of any stone in the army (s):
  422. X
  423. X  int stone;
  424. X  stone = g->army[g->armymen[s]].first; /* first man in army */
  425. X  while (stone >= 0) {
  426. X    (* code to process each army man goes here *)
  427. X    stone = g->armylnk[stone]; /* next man in army */
  428. X  }
  429. X
  430. XThe following C code will obtain the positions of the neighbors to a
  431. Xgiven stone position (s), given a game structure pointer (g) and visit
  432. Xeach of the non-blank neighboring positions in order of their army number:
  433. X
  434. X  neighbors nabor; int n;
  435. X  getneighbors(g,&nabor,s);     /* get the neighbors */
  436. X  for (n = 0; n < nabor.neis; n++) {  /* go through neighbors */
  437. X    if (g->board[s] != Blank) {
  438. X      (* code to process non-blank neighbors to stone s goes here *)
  439. X  } }
  440. ________This_Is_The_END________
  441. if test `wc -l < README` -ne 404; then
  442.     echo 'shar: README was damaged during transit'
  443.   echo '      (should have been 404 bytes)'
  444. fi
  445. fi        ; : end of overwriting check
  446. echo 'Extracting go.c'
  447. if test -f go.c; then echo 'shar: will not overwrite go.c'; else
  448. sed 's/^X//' << '________This_Is_The_END________' > go.c
  449. X/* File go.c
  450. X   Developer:  James R. Logan Jr. (BYU), Advisor:  Dr. Lynn H. Beus (BYU)
  451. X   email address:  loganj@byuvax.bitnet
  452. X   (801) 378-3617
  453. X
  454. X   These routines and the routines in gomoves.c determine the strategy of
  455. X   the go program.  This code is not machine dependent.
  456. X*/
  457. X
  458. X#include <qd.h>
  459. X#include <pack.h>
  460. X#include <win.h>
  461. X#include <dialog.h>
  462. X#include <stdio.h>
  463. X#include <goprocs.h>
  464. X#include <gomoves.h>
  465. X
  466. Xextern char coltable[19];
  467. Xextern int activeplayer,blinkstone,looking,play,otherside[2];
  468. Xextern game mygame;
  469. Xextern int addastone();
  470. Xextern initialize(),removeastone(),capture(),uncapture(),
  471. X  getneighbors(),allarmies(),linkarmies(),buildarmies(),
  472. X  armymerge(),topicture(),frompicture(),moveboard(),
  473. X  armyboard(),linkinfo(),armyinfo(),pictinfo(),neighborinfo();
  474. X
  475. Xoverlay "gamestuff"
  476. X
  477. X#define allyweight 4
  478. X#define blankweight 1
  479. X#define enemyweight 2
  480. X#define libertiesweight 1
  481. X#define squareweight 4
  482. X
  483. X#define edgevalue 1
  484. X#define openvalue 2  /* ordinary unoccupied square, not on edge */
  485. X#define cornervalue 10
  486. X#define connectvalue 3
  487. X#define midneivalue 6
  488. X#define midrowvalue 8
  489. X#define row3value 4
  490. X#define row5value 3
  491. X
  492. Xpattern greypat = {0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92};
  493. X
  494. Xrect screenrect;
  495. Xwindowrecord merecord,myrecord,drecord;
  496. Xwindowptr mewindow,mywindow = {0L},dummywindow;
  497. X
  498. Xsons root[maxlevs];
  499. X
  500. Xmstatus status;
  501. X
  502. Xint
  503. X  init[maxstones],value[maxstones],  /* initial position values */
  504. X  color,stone,nextmove,passcount,
  505. X  searchdepth = {1},searchwidth = {1},work;
  506. X
  507. Xinitgame(g) game *g; {
  508. Xint i,j,brdsze;
  509. Xchar dummyscreen[20000];
  510. X  if (mywindow == 0L) {
  511. X/* calculate the size of the window for the game board, and display */
  512. X    brdsze = 16 + 8 * (g->width - 1);
  513. X    setrect(&screenrect,351-brdsze,181-brdsze,351+brdsze,181+brdsze);
  514. X    mywindow = newwindow(&myrecord, &screenrect, "", 1, 2,
  515. X      (long)-1, 0, (long)0);
  516. X    dummywindow = newwindow(&drecord, &screenrect, "", 0, 2,
  517. X      (long)-1, 1, (long)0);
  518. X    drecord.port.portbits.baseaddr = &dummyscreen;
  519. X    setrect(&screenrect, 0, 21, 188, 340);
  520. X    mewindow = newwindow(&merecord, &screenrect, "", 1, 2,
  521. X      (long)-1, 0, (long)0);
  522. X  } else {
  523. X    disposewindow(mywindow);
  524. X    brdsze = 16 + 8 * (g->width - 1);
  525. X    setrect(&screenrect,351-brdsze,181-brdsze,351+brdsze,181+brdsze);
  526. X    mywindow = newwindow(&myrecord, &screenrect, "Go", 1, 3,
  527. X                     (long)-1, 0, (long)0);
  528. X  }
  529. X  if ((g->debug & 1) != 0) { printf("Initgame: \n"); }
  530. X  setport(mywindow);
  531. X  textmode(srcxor);
  532. X  backpat(&greypat);
  533. X  setorigin(-12,0);
  534. X  brdsze = 4 + 16 * g->width;
  535. X  setrect(&screenrect,0,0,400,brdsze);
  536. X  eraserect(&screenrect);
  537. X  setport(mewindow);
  538. X  textsize(9);
  539. X  initialize(g);  /* initialize the game structure for the go procs */
  540. X  g->who = Black; /* first move is black's */
  541. X  passcount = 0;  /* number of consecutive passes in the game */
  542. X  blinkstone = -1; /* indicate no stone to blink yet */
  543. X/* set the initial value of each position, first the whole board */
  544. X  for (i = firstelement; i < g->maxstone; i++) { init[i] = openvalue; }
  545. X/* set the initial value of the edges of the board */
  546. X  j = firstelement;
  547. X  for (i = firstelement; i < g->width; i++) {
  548. X    init[j] = edgevalue; init[j+g->width-1] = edgevalue;
  549. X    init[i] = edgevalue; init[g->maxstone-g->width+i] = edgevalue;
  550. X    j = j + g->width;
  551. X  }
  552. X/* Set the initial value for row 3 all around the board */
  553. X  if (g->width >= 7) {
  554. X    j = 2*g->width+3;
  555. X    for (i = firstelement; i < g->width-6; i++) {
  556. X      init[j] = row3value; init[g->maxstone-j-1] = row3value;
  557. X      j = j + 1; }
  558. X    j = 3*g->width+2;
  559. X    for (i = firstelement; i < g->width-6; i++) {
  560. X      init[j] = row3value; init[j+g->width-5] = row3value;
  561. X      j = j + g->width; }
  562. X  }
  563. X/* Set the value for the middle of row 3 around the edge of the board */
  564. X  if (g->width >= 9) {
  565. X    j = (2*g->width)+(g->width/2);
  566. X    init[j] = midrowvalue;
  567. X    init[g->maxstone-1-j] = midrowvalue;
  568. X    j = ((g->width / 2) * g->width) + 2;
  569. X    init[j] = midrowvalue;
  570. X    init[g->maxstone-1-j] = midrowvalue;
  571. X  }
  572. X/* Set the initial value for row 5 all around the board, but not in 5 corner */
  573. X  if (g->width >= 11) {
  574. X    j = 4*g->width+5;
  575. X    for (i = firstelement; i < g->width-10; i++) {
  576. X      init[j] = row5value; init[g->maxstone-j-1] = row5value;
  577. X      j = j + 1; }
  578. X    j = 5*g->width+4;
  579. X    for (i = firstelement; i < g->width-10; i++) {
  580. X      init[j] = row5value; init[j+g->width-9] = row5value;
  581. X      j = j + g->width; }
  582. X  }
  583. X/* Set the initial value for 3 rows in from each corner */
  584. X  if (g->width >= 5) {
  585. X    init[2*g->width+2] = cornervalue;
  586. X    init[3*g->width-3] = cornervalue;
  587. X    init[g->maxstone-2*g->width-3] = cornervalue;
  588. X    init[g->maxstone-3*g->width+2] = cornervalue;
  589. X  }
  590. X/* Set the initial value for 2 jump neighbors from mid row 3 */
  591. X  if (g->width == 19) {
  592. X    init[44] = midneivalue; init[50] = midneivalue;
  593. X    init[116] = midneivalue; init[130] = midneivalue;
  594. X    init[230] = midneivalue; init[244] = midneivalue;
  595. X    init[310] = midneivalue; init[316] = midneivalue;
  596. X  }
  597. X  init[0] = 0; init[g->width-1] = 0;
  598. X  init[g->maxstone-g->width] = 0; init[g->maxstone-1] = 0;
  599. X  if ((g->debug & 1) != 0) { printf("Initgame end.\n"); }
  600. X}
  601. X
  602. Xint moves(g) game *g; {
  603. X/* This procedure receives control when the computer needs to make a move,
  604. X   and returns the 1-dimensional position selected by the computer.
  605. X   If g->who == White a move is computed for the computer, else a move is
  606. X   computed for the opponent.  A legal move is always added to the board */
  607. Xint s; sons *sonsp;
  608. X  alphabeta(); /* look ahead for the best move */
  609. X  if (nextmove >= 0) {
  610. X    s = addastone(g,nextmove); /* add this move to the game board */
  611. X    if (s >= 0) {
  612. X      if (g->who == White) printf(" White to %c,%d\n",
  613. X          coltable[g->colbrd[s]],g->rowbrd[s]);
  614. X      else printf(" Black to %c,%d\n",
  615. X          coltable[g->colbrd[s]],g->rowbrd[s]);
  616. X    }
  617. X    passcount = 0;
  618. X  } else {
  619. X    s = -1;
  620. X    if (activeplayer == 1) passcount = passcount + 1;
  621. X    if (g->who == White) printf(" White passes\n");
  622. X    else printf(" Black passes\n");
  623. X  }
  624. X  g->who = otherside[g->who];
  625. X  if ((activeplayer == 1) && (passcount >= 2)) {
  626. X    play = 0;
  627. X    printf(" Play stopped after two passes!\n");
  628. X  }
  629. X  return s;
  630. X}
  631. X
  632. Xalphabeta() {
  633. X/* This procedure is the top level of the alpha-beta cutoff look ahead
  634. X   procedure.  Alpha and beta are initialized here. */
  635. Xint a,b,dummy; int sonsp;
  636. X  looking = 1;   /* indicate look ahead in progress */
  637. X  nextmove = -1; /* default next move is a pass */
  638. X  sonsp = 0;     /* point to root of tree */
  639. X  a = -9999; b = 9999; /* alpha-beta initialization */
  640. X  dummy = abcontrol (sonsp,a,b,mygame.who);
  641. X  looking = 0;
  642. X}
  643. X
  644. Xint abcontrol (tr,a,b,wh) int tr,a,b,wh; {
  645. X/* This procedure performs the actual alpha-beta search.  Inputs are
  646. X   tree level, Alpha, Beta, and who's move it is.  The present
  647. X   implementation does not dynamically allocate the tree. */
  648. Xint ta,tb,ev,junk,r,c,v;
  649. X  if (tr >= searchdepth) {   /* last level of tree? */
  650. X    ev = eval(searchdepth);    /* yes, compute the position value */
  651. X    if ((mygame.debug & 0xF) != 0) {
  652. X      printf("\nabcontrol - level, node, value: %d %d %d\n",
  653. X        searchdepth-1,root[searchdepth-1].nodepnt-1,ev);
  654. X    }
  655. X    return (ev);        /* return the best position value */
  656. X  } else if (wh == mygame.who) {    /* for maximizing level */
  657. X    bestmoves(&mygame,tr);   /* fill in the best moves */
  658. X    while ((root[tr].nodepnt < root[tr].nodecnt) && (a < b)) {
  659. X      junk = addastone(&mygame,root[tr].nodes[root[tr].nodepnt].s);
  660. X      root[tr].status = mygame.movestatus;
  661. X      root[tr].nodepnt = root[tr].nodepnt + 1;
  662. X      ta = abcontrol (tr + 1, a, b, otherside[wh]);
  663. X      if (ta > a) {
  664. X        a = ta; /* new alpha value */
  665. X        if (tr <= 0) { nextmove = root[tr].nodes[root[tr].nodepnt-1].s; }
  666. X      }
  667. X      removeastone(&mygame,root[tr].nodes[root[tr].nodepnt-1].s,root[tr].status)
  668. X;
  669. X    }
  670. X    return (a);
  671. X  } else {   /* for minimizing level */
  672. X    bestmoves(&mygame,tr);   /* fill in the best moves */
  673. X    while ((root[tr].nodepnt < root[tr].nodecnt) && (a < b)) {
  674. X      mygame.who = wh;                      /* change sides */
  675. X      junk = addastone(&mygame,root[tr].nodes[root[tr].nodepnt].s);
  676. X      root[tr].status = mygame.movestatus;
  677. X      mygame.who = otherside[mygame.who];   /* change sides back */
  678. X      root[tr].nodepnt = root[tr].nodepnt + 1;
  679. X      tb = abcontrol (tr + 1, a, b, otherside[wh]);
  680. X      if (tb < b) { b = tb; } /* new beta value */
  681. X      removeastone(&mygame,root[tr].nodes[root[tr].nodepnt-1].s,root[tr].status)
  682. X;
  683. X    }
  684. X    return (b);
  685. X  }
  686. X}
  687. X
  688. Xint eval(sonsp) int sonsp; {
  689. X/* This procedure evaluates the worth of look ahead moves during the alpha
  690. X   beta search - not a well defined process.  Need a lot of work here!
  691. X   The game structure fields don't seem to represent enough higher level
  692. X   (human) abstractions to play a good game yet.  The evaluation here
  693. X   is based on the number of armies, eyes, and total number of liberties
  694. X   for both sides.  Variables beginning with an 'a' are ally values, 'e' are
  695. X   enemy values. */
  696. Xint n,v,pv,allies,enemies,alibs,elibs,wh,tb;
  697. X  if ((mygame.debug & 1) != 0) { printf("eval: \n"); }
  698. X  pv = 0; allies = 0; enemies = 0; alibs = 0; elibs = 0;
  699. X  wh = 1;
  700. X  for (tb = 0; tb < sonsp; tb++) {    /* traverse the tree */
  701. X    pv = pv + root[tb].nodes[root[tb].nodepnt-1].pv * wh;
  702. X    tb = tb + 1;
  703. X    wh = -wh;     /* switch players at each level of the tree */
  704. X  }
  705. X  n = mygame.army[mygame.avail].bp;   /* visit each army */
  706. X  while (n > 0) {
  707. X    if (mygame.army[n].size > 0) {
  708. X      if (mygame.army[n].color == Blank) {   /* blank army is an eye? */
  709. X        if (mygame.army[n].enemy <= 0) {
  710. X          if (mygame.who == White) allies = allies + 1; /* ally eyes */
  711. X          else enemies = enemies + 1;                   /* enemy eyes */
  712. X        } else if (mygame.army[n].friend <= 0) {
  713. X          if (mygame.who == White) enemies = enemies + 1;/* ally eyes */
  714. X          else allies = allies + 1;                     /* enemy eyes */
  715. X        }
  716. X      } else if (mygame.army[n].color == mygame.who) {
  717. X        alibs = alibs + mygame.army[n].lib;
  718. X      } else {
  719. X        elibs = elibs + mygame.army[n].lib;
  720. X      }
  721. X    }
  722. X    n = mygame.army[n].bp;
  723. X  }
  724. X  v = allies * allyweight - enemies * enemyweight +
  725. X       libertiesweight * alibs - libertiesweight * elibs +
  726. X       pv * squareweight;
  727. X  if ((mygame.debug & 1) != 0) { printf("eval.\n"); }
  728. X  return (v);
  729. X}
  730. X
  731. Xboardsize(g) game *g; {
  732. X/* This procedure handles the game initialization dialog */
  733. Xint the_item,item_type,value;
  734. Xhandle item_handle;
  735. Xrect drect,item_box;
  736. Xchar item_text[64];
  737. Xdialogptr mydialog;
  738. X  setrect(&drect,-16,28,440,200);
  739. X  copybits(&mywindow->portbits,&dummywindow->portbits,
  740. X        &drect,&drect,srccopy,(long)0);
  741. X  mydialog = getnewdialog(9507,(long) 0,(long)-1);
  742. X  getditem(mydialog,3,&item_type,&item_handle,&item_box);
  743. X  sprintf(item_text,"%d",g->width);
  744. X  setitext(item_handle,item_text);
  745. X  getditem(mydialog,4,&item_type,&item_handle,&item_box);
  746. X  sprintf(item_text,"%d",searchwidth);
  747. X  setitext(item_handle,item_text);
  748. X  getditem(mydialog,5,&item_type,&item_handle,&item_box);
  749. X  sprintf(item_text,"%d",searchdepth);
  750. X  setitext(item_handle,item_text);
  751. X  do {
  752. X    modaldialog((long) 0,&the_item);
  753. X    if (the_item == 1) {
  754. X      getditem(mydialog,3,&item_type,&item_handle,&item_box);
  755. X      getitext(item_handle,&item_text);
  756. X      sscanf(item_text,"%d",&value);
  757. X      if ((value > 2) && (value < 20)) g->width = value;
  758. X      getditem(mydialog,4,&item_type,&item_handle,&item_box);
  759. X      getitext(item_handle,&item_text);
  760. X      sscanf(item_text,"%d",&value);
  761. X      if ((value > 0) && (value <= maxsons)) searchwidth = value;
  762. X      getditem(mydialog,5,&item_type,&item_handle,&item_box);
  763. X      getitext(item_handle,&item_text);
  764. X      sscanf(item_text,"%d",&value);
  765. X      if ((value > 0) && (value <= maxlevs)) searchdepth = value;
  766. X    }
  767. X  } while ((the_item != 1) && (the_item != 2));
  768. X  closedialog(mydialog);
  769. X  copybits(&dummywindow->portbits,&mywindow->portbits,
  770. X        &drect,&drect,srccopy,(long)0);
  771. X  if (the_item == 1) initgame(g);
  772. X}
  773. X
  774. Xvalueboard(g) game *g; {
  775. Xint i,s;
  776. X  s = 0;
  777. X  while (s < g->maxstone) {
  778. X    for (i = firstelement; i < g->width; i++) { printf("%3d",value[s]); s = s +
  779. X1; }
  780. X    printf("\n");
  781. X} }
  782. ________This_Is_The_END________
  783. if test `wc -l < go.c` -ne 333; then
  784.     echo 'shar: go.c was damaged during transit'
  785.   echo '      (should have been 333 bytes)'
  786. fi
  787. fi        ; : end of overwriting check
  788. echo 'Extracting gofile.c'
  789. if test -f gofile.c; then echo 'shar: will not overwrite gofile.c'; else
  790. sed 's/^X//' << '________This_Is_The_END________' > gofile.c
  791. X/* File gofile.c
  792. X   Developer:  James R. Logan Jr. (BYU), Advisor:  Dr. Lynn H. Beus (BYU)
  793. X   email address:  loganj@byuvax.bitnet
  794. X   (801) 378-3617
  795. X
  796. X   These routines handle the disk I/O for the go program's log file and
  797. X   replay feature.  This code is not machine dependent.
  798. X*/
  799. X
  800. X#include <qd.h>
  801. X#include <pack.h>
  802. X#include <win.h>
  803. X#include <dialog.h>
  804. X#include <stdio.h>
  805. X#include <goprocs.h>
  806. X
  807. Xoverlay "filestuff"
  808. X
  809. Xchar prompt[2] = {' ','\0'},origname[2] = {' ','\0'},filename[32];
  810. Xrect drect;
  811. X
  812. Xextern FILE *fp,*gp;
  813. Xextern char coltable[19];
  814. Xextern int play;
  815. Xextern game mygame;
  816. Xextern windowptr mywindow, dummywindow;
  817. Xextern int addastone(),moves();
  818. X
  819. Xcreatefile() {
  820. X/* This procedure opens a log file for the game in progess */
  821. Xsfreply reply; point pt; char volname[30]; int i,j,tint; long tlong;
  822. X  setrect(&drect,-16,28,440,200);
  823. X  copybits(&mywindow->portbits,&dummywindow->portbits,&drect,&drect,srccopy,(lon
  824. Xg)0);
  825. X  setpt(&pt, 190, 75);
  826. X  sfputfile(&pt, &prompt[0], &origname[0], NULL, &reply);
  827. X  copybits(&dummywindow->portbits,&mywindow->portbits,&drect,&drect,srccopy,(lon
  828. Xg)0);
  829. X  if (reply.good) {
  830. X    getvinfo(reply.vrefnum, volname, &tint, &tlong);
  831. X    strcpy(filename, volname); strcat(filename, ":"); strcat(filename, reply.fna
  832. Xme);
  833. X    if (fp != NULL) fclose(fp);
  834. X    fp = fopen(filename,"w");
  835. X} }
  836. X
  837. Xreplay() {
  838. X/* This procedure opens a saved game and replays the game.  The game file
  839. X   can be modified by an editor to change the sequence of play.  The first
  840. X   letter of each line determines the function.  Using log files is the
  841. X   fastest way to set up a specific board position.  */
  842. Xchar col,color,tline[128];
  843. Xint c,i,row,s,size,tint; long tlong;
  844. Xsfreply reply; point pt; char volname[30];
  845. X  if (gp == 0) {
  846. X    setrect(&drect,-16,28,440,200);
  847. X    copybits(&mywindow->portbits,&dummywindow->portbits,
  848. X          &drect,&drect,srccopy,(long)0);
  849. X    setpt(&pt, 186, 75);
  850. X    sfgetfile(&pt, NULL, NULL, 1, "TEXT", NULL, &reply);
  851. X    copybits(&dummywindow->portbits,&mywindow->portbits,
  852. X          &drect,&drect,srccopy,(long)0);
  853. X    if (reply.good) {
  854. X      getvinfo(reply.vrefnum, volname, &tint, &tlong);
  855. X      strcpy(filename, volname); strcat(filename, ":"); strcat(filename, reply.f
  856. Xname);
  857. X      gp = fopen(filename,"r");
  858. X    }
  859. X  } else {
  860. X    c = NULL;
  861. X    for (i=0; (i<128) && ((c = getc(gp)) != EOF) && (c != 10); i++) tline[i] = c
  862. X;
  863. X    tline[i] = 0;
  864. X    switch (tline[0]) {
  865. X      case 'a': case 'A':
  866. X        sscanf(tline,"%*s %c %c,%d",&color,&col,&row);
  867. X        s = position(col,row);
  868. X        if ((color == 'w') || (color == 'W')) mygame.who = White;
  869. X        else if ((color == 'b') || (color == 'B')) mygame.who = Black;
  870. X        if (s >= 0) s = addastone(&mygame,s);
  871. X        break;
  872. X      case 'b': case 'B': mygame.who = Black; break;
  873. X      case 'c': case 'C':
  874. X        sscanf(tline,"%*s %c,%d",&col,&row);
  875. X        s = position(col,row);
  876. X        if (s >= 0) capture(&mygame,s);
  877. X        break;
  878. X      case 'i': case 'I':
  879. X        sscanf(tline,"%*s %d",&size);
  880. X        if ((size > 2) && (size < 20)) {
  881. X          mygame.width = size;
  882. X          initgame(&mygame);
  883. X        }
  884. X        break;
  885. X      case 'm': case 'M': s = moves(&mygame); break;
  886. X      case 'r': case 'R':
  887. X        sscanf(tline,"%*s %c,%d",&col,&row);
  888. X        s = position(col,row);
  889. X        if (s >= 0) removeastone(&mygame,s,mygame.movestatus);
  890. X        break;
  891. X      case 'u': case 'U':
  892. X        sscanf(tline,"%*s %c,%d,%c",&col,&row,&color);
  893. X        s = position(col,row);
  894. X        if (s >= 0) {
  895. X          if ((color == 'w') || (color == 'W')) uncapture(&mygame,s,White);
  896. X          else if ((color == 'b') || (color == 'B')) uncapture(&mygame,s,Black);
  897. X
  898. X        }
  899. X        break;
  900. X      case 'w': case 'W': mygame.who = White; break;
  901. X      default:
  902. X    }
  903. X    if (c == EOF) { fclose(gp); gp = NULL; play = 0; }
  904. X} }
  905. X
  906. Xint position(col,row) char col; int row; {
  907. X/* This procedure converts from a 2-dimensional position used by the world,
  908. X   to the 1-dimensional position used in the game structures */
  909. Xint i,s;
  910. X  s = -1;
  911. X  if ((row > 0) && (row <= mygame.width)) {
  912. X    for (i = 0; i < mygame.width; i++) if (col == coltable[i]) s = i;
  913. X    if ((s >= 0) && (s < mygame.width)) s = (row - 1) * mygame.width + s;
  914. X  }
  915. X  return(s);
  916. X}
  917. ________This_Is_The_END________
  918. if test `wc -l < gofile.c` -ne 126; then
  919.     echo 'shar: gofile.c was damaged during transit'
  920.   echo '      (should have been 126 bytes)'
  921. fi
  922. fi        ; : end of overwriting check
  923. echo 'Extracting gomain.c'
  924. if test -f gomain.c; then echo 'shar: will not overwrite gomain.c'; else
  925. sed 's/^X//' << '________This_Is_The_END________' > gomain.c
  926. X/* File gomain.c
  927. X   Developer:  James R. Logan Jr. (BYU), Advisor:  Dr. Lynn H. Beus (BYU)
  928. X   email address:  loganj@byuvax.bitnet
  929. X   (801) 378-3617
  930. X
  931. X   This procedure provides the interface between the Mac and the operator.
  932. X   This code is machine dependent.
  933. X*/
  934. X
  935. X#include <qd.h>
  936. X#include <win.h>
  937. X#include <menu.h>
  938. X#include <event.h>
  939. X#include <te.h>
  940. X#include <stdio.h>
  941. X#include <goprocs.h>
  942. X
  943. X#define lastmenu 5
  944. X#define applemenu 1
  945. X#define filemenu 256
  946. X#define gamemenu 257
  947. X#define playermenu 258
  948. X#define displaymenu 259
  949. X
  950. XFILE *fp,*gp;
  951. Xwindowptr whichwindow;
  952. Xmenuhandle mymenus[lastmenu+1];
  953. Xboolean doneflag,temp;
  954. Xeventrecord myevent;
  955. Xlong blinktime;
  956. Xint code,refnum;
  957. Xint themenu,theitem,
  958. X  activeplayer,blinkstate,blinkcolor,blinkstone,drawnumber,
  959. X  lookahead,play,playfile,stonestate;
  960. X
  961. Xgame mygame;
  962. X
  963. Xextern initgame();
  964. Xextern int addastone(),moves();
  965. Xextern char coltable[19];
  966. Xextern int otherside[2];
  967. Xextern windowptr mewindow,mywindow;
  968. X
  969. Xsetupmenus() {
  970. Xint i;
  971. Xchar appletitle[2];
  972. X  initmenus();
  973. X  appletitle[0] = applemark; appletitle[1] = 0;
  974. X  mymenus[1] = newmenu(applemenu, appletitle);
  975. X  addresmenu(mymenus[1], "DRVR");
  976. X  mymenus[2] = newmenu(filemenu, "Directives");
  977. X  appendmenu(mymenus[2], "Pass;Change Sides;Log to File;Play Log File;Quit");
  978. X  mymenus[3] = newmenu(gamemenu, "Game");
  979. X  appendmenu(mymenus[3], "Initialize;Begin or Resume;Pause");
  980. X  mymenus[4] = newmenu(playermenu, "Players");
  981. X  appendmenu(mymenus[4], "Computer Vs Computer;Computer Vs Human;Human Vs Human"
  982. X);
  983. X  mymenus[5] = newmenu(displaymenu, "Display");
  984. X  appendmenu(mymenus[5],
  985. X    "Look Ahead Moves;Stone Numbers;Procedures;Stones;Stone Armies;Stone Links;S
  986. Xtone Patterns;Position Values;Army Info");
  987. X  for (i=1; i<=lastmenu; i++) insertmenu(mymenus[i], 0);
  988. X  drawmenubar();
  989. X  drawnumber = 1;
  990. X  checkitem(mymenus[5],2,1);
  991. X  lookahead = 0;
  992. X  activeplayer = 1;
  993. X  checkitem(mymenus[4],activeplayer,1);
  994. X}
  995. X
  996. Xdocommand(themenu, theitem) int themenu, theitem; {
  997. Xchar name[256];
  998. Xint i;
  999. X  switch (themenu) {
  1000. X  case applemenu:
  1001. X    getitem(mymenus[1], theitem, name);
  1002. X    refnum = opendeskacc(name);
  1003. X    break;
  1004. X  case filemenu:
  1005. X    switch (theitem) {
  1006. X    case 1: /* pass */
  1007. X      if (play == 0) {
  1008. X        if ((activeplayer == 2) || (activeplayer == 3)) {
  1009. X          mygame.who = otherside[mygame.who];
  1010. X          if (activeplayer == 2) {
  1011. X            play = 1;
  1012. X          } else {
  1013. X            if (mygame.who == White) printf(" White's turn ...\n");
  1014. X            else printf(" Black's turn ...\n");
  1015. X          }
  1016. X        }
  1017. X      }
  1018. X      break;
  1019. X    case 2: /* change sides */
  1020. X      mygame.who = otherside[mygame.who];
  1021. X      if (mygame.who == White) printf(" White's turn ...\n");
  1022. X      else printf(" Black's turn ...\n");
  1023. X      break;
  1024. X    case 3:
  1025. X      if (fp == NULL) {
  1026. X        checkitem(mymenus[2],3,1);
  1027. X        createfile();
  1028. X      } else {
  1029. X        checkitem(mymenus[2],3,0);
  1030. X        fclose(fp); fp = NULL;
  1031. X      }
  1032. X      break;
  1033. X    case 4:
  1034. X      if (gp == 0) {
  1035. X        if (activeplayer == 2) blinkoff();
  1036. X        replay();
  1037. X        if (gp != 0) {
  1038. X          checkitem(mymenus[2],4,1);
  1039. X          play = 1;
  1040. X          playfile = 1;
  1041. X        }
  1042. X      } else {
  1043. X        checkitem(mymenus[2],4,0);
  1044. X        if (gp != NULL) fclose(gp); gp = NULL;
  1045. X        play = 0;
  1046. X        playfile = 0;
  1047. X        mygame.who = otherside[mygame.who];
  1048. X        if (mygame.who == White) printf(" White's turn ...\n");
  1049. X        else printf(" Black's turn ...\n");
  1050. X        if (activeplayer == 2) blinkon();
  1051. X      }
  1052. X      break;
  1053. X    case 5:
  1054. X      if (fp != NULL) { fclose(fp); fp = NULL; }
  1055. X      if (gp != NULL) { fclose(gp); gp = NULL; }
  1056. X      doneflag = 1;
  1057. X      break;
  1058. X    }
  1059. X    break;
  1060. X  case gamemenu:
  1061. X    switch (theitem) {
  1062. X    case  1:
  1063. X      play = 0;
  1064. X      if (playfile != 0) {
  1065. X        checkitem(mymenus[2],4,0);
  1066. X        if (gp != NULL) fclose(gp); gp = NULL;
  1067. X        playfile = 0;
  1068. X      }
  1069. X      blinkoff();
  1070. X      boardsize(&mygame);
  1071. X      if (activeplayer == 1) {
  1072. X        if (mygame.who == White) printf(" White's turn ...\n");
  1073. X        else printf(" Black's turn ...\n");
  1074. X      } else if (activeplayer == 2) {
  1075. X        blinkon();
  1076. X        printf(" Your turn ...\n");
  1077. X      } else if (activeplayer == 3) printf(" Black's turn ...\n");
  1078. X      break;
  1079. X    case  2:
  1080. X      if ((playfile != 0) || (activeplayer == 1)) play = 1;
  1081. X      else if (activeplayer == 2) printf(" Your turn ...\n");
  1082. X      else if (mygame.who == White) printf(" White's turn ...\n");
  1083. X      else printf(" Black's turn ...\n");
  1084. X      break;
  1085. X    case  3: play = 0; break;
  1086. X    }
  1087. X    break;
  1088. X  case playermenu:
  1089. X    switch (theitem) {
  1090. X    case  1:
  1091. X      if (activeplayer == 2) blinkoff();
  1092. X      checkitem(mymenus[4],activeplayer,0);
  1093. X      activeplayer = 1;
  1094. X      checkitem(mymenus[4],activeplayer,1);
  1095. X      break;
  1096. X    case  2:
  1097. X      play = 0;
  1098. X      blinkstone = -1;
  1099. X      checkitem(mymenus[4],activeplayer,0);
  1100. X      activeplayer = 2;
  1101. X      checkitem(mymenus[4],activeplayer,1);
  1102. X      break;
  1103. X    case  3:
  1104. X      play = 0;
  1105. X      if (activeplayer == 2) blinkoff();
  1106. X      checkitem(mymenus[4],activeplayer,0);
  1107. X      activeplayer = 3;
  1108. X      checkitem(mymenus[4],activeplayer,1);
  1109. X      break;
  1110. X    }
  1111. X    break;
  1112. X  case displaymenu:
  1113. X    switch (theitem) {
  1114. X    case  1:
  1115. X      lookahead = 1 - lookahead;
  1116. X      checkitem(mymenus[5],1,lookahead);
  1117. X      break;
  1118. X    case  2:
  1119. X      drawnumber = 1 - drawnumber;
  1120. X      checkitem(mymenus[5],2,drawnumber);
  1121. X      break;
  1122. X    case  3:
  1123. X      if ((mygame.debug & 1) == 0) {
  1124. X        mygame.debug |= 1;
  1125. X        checkitem(mymenus[5],3,1);
  1126. X      } else {
  1127. X        mygame.debug &= ~1;
  1128. X        checkitem(mymenus[5],3,0);
  1129. X      }
  1130. X      break;
  1131. X    case  4: moveboard(&mygame); break;
  1132. X    case  5: armyboard(&mygame); break;
  1133. X    case  6: linkinfo(&mygame); break;
  1134. X    case  7: pictinfo(&mygame); break;
  1135. X    case  8: valueboard(&mygame); break;
  1136. X    case  9: armyinfo(&mygame); break;
  1137. X  } }
  1138. X  hilitemenu(0);
  1139. X}
  1140. X
  1141. Xstoneon() {
  1142. X  if ((stonestate == 0) && (blinkstone >= 0))
  1143. X    drawstone(&mygame,blinkstone,blinkcolor);
  1144. X  stonestate = 1;
  1145. X}
  1146. X
  1147. Xstoneoff() {
  1148. X  if ((stonestate != 0) && (blinkstone >= 0))
  1149. X    undrawstone(&mygame,blinkstone);
  1150. X  stonestate = 0;
  1151. X}
  1152. X
  1153. Xblinkon() {
  1154. X/* Turn on the blink'n blinker if no look ahead in progress. */
  1155. X  if (lookahead == 0) {
  1156. X    blinkstate = 1;
  1157. X    blinktime = tickcount();
  1158. X} }
  1159. X
  1160. Xblinkoff() { blinkstate = 0; stoneon(); }
  1161. X
  1162. Xblink() {
  1163. X/* This procedure does the actual blinking of the last stone played */
  1164. Xlong now;
  1165. X  if (blinkstate != 0) {
  1166. X    now = tickcount();
  1167. X    if (now > blinktime + 20) {
  1168. X      if (stonestate != 0) stoneoff(); else stoneon();
  1169. X      blinktime = now;
  1170. X} } }
  1171. X
  1172. Xmain() {
  1173. X/* This procedure provides the interface between the Mac and the
  1174. X   operator */
  1175. Xint i,s;
  1176. Xextern struct qdvar { char dummy[202]; grafptr qdtheport;} qdvars;
  1177. X#define theport (qdvars.qdtheport)
  1178. X
  1179. X  openresfile("clock");
  1180. X  initgraf(&theport);
  1181. X  initfonts();
  1182. X  flushevents(everyevent, 0);
  1183. X  initwindows();
  1184. X  setupmenus();
  1185. X  initdialogs(0L);
  1186. X  initcursor();
  1187. X
  1188. X  doneflag = 0; play = 0; playfile = 0; blinkstone = -1;
  1189. X  mygame.debug = 0;
  1190. X  mygame.width = 19;
  1191. X  fp = NULL; gp = NULL;
  1192. X  initgame(&mygame);
  1193. X
  1194. X  do {
  1195. X    systemtask();
  1196. X    blink();
  1197. X    temp = getnextevent(everyevent, &myevent);
  1198. X    switch (myevent.what) {
  1199. X    case mousedown:
  1200. X      code = findwindow(&myevent.where, &whichwindow);
  1201. X      switch (code) {
  1202. X      case inmenubar:
  1203. X        docommand(menuselect(&myevent.where)); break;
  1204. X      case insyswindow:
  1205. X        systemclick(&myevent, whichwindow); break;
  1206. X      case indrag:
  1207. X        break;
  1208. X      case ingrow:
  1209. X      case incontent:
  1210. X        if ((play == 0) &&
  1211. X          ((playfile != 0) || (activeplayer == 2) || (activeplayer == 3))) {
  1212. X          if (whichwindow == mywindow) {
  1213. X            blinkoff();
  1214. X            setport(mywindow);
  1215. X            globaltolocal(&myevent.where);
  1216. X            setport(mewindow);
  1217. X/* place a stone on the board */
  1218. X            s = (mygame.width - 1 - ((myevent.where.a.v - 2) / 16));
  1219. X            if (s < 0) s = 0;
  1220. X            if (s >= mygame.width) s = mygame.width - 1;
  1221. X            s = s * mygame.width;
  1222. X            i = (myevent.where.a.h - 2) / 16;
  1223. X            if (i < 0) i = 0;
  1224. X            if (i >= mygame.width) i = mygame.width - 1;
  1225. X            s = s + i;
  1226. X            s = addastone(&mygame,s);
  1227. X            if (s >= 0) {
  1228. X              if (mygame.who == White) printf(" White to %c,%d\n",
  1229. X                coltable[mygame.colbrd[s]],mygame.rowbrd[s]);
  1230. X              else printf(" Black to %c,%d\n",
  1231. X                coltable[mygame.colbrd[s]],mygame.rowbrd[s]);
  1232. X              if (activeplayer == 2) play = 1;
  1233. X              mygame.who = otherside[mygame.who];
  1234. X              if (mygame.who == White) printf(" White's turn ...\n");
  1235. X              else printf(" Black's turn ...\n");
  1236. X            } else {
  1237. X              if (mygame.who == White) printf(" Still White's turn ...\n");
  1238. X              else printf(" Still Black's turn ...\n");
  1239. X            }
  1240. X          }
  1241. X        }
  1242. X        break;
  1243. X/* goaway box is on the modify window only, so save the changes to the
  1244. X   letter being modified and take down the modify window */
  1245. X      case ingoaway: break;
  1246. X      }
  1247. X      break;
  1248. X    case mouseup: break;
  1249. X    case keydown:
  1250. X    case autokey:
  1251. X/*      draw_text((char) (255 & myevent.message)); */
  1252. X      break;
  1253. X    case activateevt: break;
  1254. X    case updateevt:
  1255. X/*      setport(mywindow);
  1256. X      beginupdate(mywindow);
  1257. X      endupdate(mywindow);*/
  1258. X      break;
  1259. X    }
  1260. X    if (doneflag == 0) {
  1261. X      if (gp == NULL) {
  1262. X        if (playfile != 0) {
  1263. X          playfile = 0;
  1264. X          checkitem(mymenus[2],4,0);
  1265. X        }
  1266. X        if (((activeplayer == 1) || (activeplayer == 2)) && (play != 0)) {
  1267. X          blinkcolor = mygame.who;
  1268. X          blinkstone = moves(&mygame);
  1269. X          if (mygame.who == White) printf(" White's turn ...\n");
  1270. X          else printf(" Black's turn ...\n");
  1271. X          if (activeplayer == 2) {
  1272. X            play = 0;
  1273. X            blinkon();
  1274. X        } }
  1275. X      } else if (play != 0) replay();
  1276. X    }
  1277. X  } while (doneflag == 0);
  1278. X}
  1279. ________This_Is_The_END________
  1280. if test `wc -l < gomain.c` -ne 353; then
  1281.     echo 'shar: gomain.c was damaged during transit'
  1282.   echo '      (should have been 353 bytes)'
  1283. fi
  1284. fi        ; : end of overwriting check
  1285. echo 'Extracting gomoves.c'
  1286. if test -f gomoves.c; then echo 'shar: will not overwrite gomoves.c'; else
  1287. sed 's/^X//' << '________This_Is_The_END________' > gomoves.c
  1288. X/* File gomoves.c
  1289. X   Developer:  James R. Logan Jr. (BYU), Advisor:  Dr. Lynn H. Beus (BYU)
  1290. X   email address:  loganj@byuvax.bitnet
  1291. X   (801) 378-3617
  1292. X
  1293. X   This routine determines the best n moves available when a move is
  1294. X   being selected by the computer.  This code is not machine dependent.
  1295. X*/
  1296. X
  1297. X#include <goprocs.h>
  1298. X#include <gomoves.h>
  1299. X
  1300. X#define maxsons 5
  1301. X#define maxlevs 5     /* must be odd, maximizing level for best odds */
  1302. X
  1303. X#define allyweight 4
  1304. X#define blankweight 1
  1305. X#define enemyweight 2
  1306. X#define libertiesweight 1
  1307. X#define squareweight 4
  1308. X
  1309. X/* The following 32 bit values represent patterns in a 5 by 5 diamond shape,
  1310. X   centered around a given board position (s).  Only 29 bits are actually
  1311. X   used, 25 bits for a 5 by 5 square and 4 bits at the center of each
  1312. X   outside edge.  The area covered and bits represented are as follows:
  1313. X
  1314. X      *                    28
  1315. X  * * * * *           5  4  3  2  1
  1316. X  * * * * *          10  9  8  7  6
  1317. X* * * S * * *     27 15 14 13 12 11 26
  1318. X  * * * * *          20 19 18 17 16
  1319. X  * * * * *          25 24 23 22 21
  1320. X      *                    29
  1321. X*/
  1322. X#define square3 0x739C0L
  1323. X#define square5 0x0E8C62EL
  1324. X#define diamond5 0x477DC4L
  1325. X#define circle7 0x1F100011L
  1326. X
  1327. X#define firstmoves 17 /* number of moves before middle game */
  1328. X
  1329. X#define attackvalue 14
  1330. X#define circle7value 2
  1331. X#define edgevalue 1
  1332. X#define edgecutvalue 10
  1333. X#define edgejoinvalue 16
  1334. X#define openvalue 2  /* ordinary unoccupied square, not on edge */
  1335. X#define capturevalue 24
  1336. X#define cornervalue 10
  1337. X#define connectvalue 3
  1338. X#define cutvalue 3
  1339. X#define hitarivalue 18
  1340. X#define invadevalue 20 /* must be 4 less than capture value */
  1341. X#define midneivalue 6
  1342. X
  1343. X#define midrowvalue 8
  1344. X#define protvalue 24
  1345. X#define retreatsize 18
  1346. X#define row3value 4
  1347. X#define row5value 3
  1348. X#define square5value 1
  1349. X#define runtoedgevalue 12
  1350. X#define territoryvalue 4
  1351. X
  1352. Xextern sons root[maxlevs];
  1353. Xextern int
  1354. X  otherside[2],
  1355. X  init[maxstones],value[maxstones],  /* initial position values */
  1356. X  searchdepth,searchwidth;
  1357. X
  1358. Xbestmoves(g,sonsp) game *g; int sonsp; {
  1359. X/* This procedure determines the best n moves available using a point
  1360. X   scheme with weights for different patterns and situations.  This
  1361. X   routine does not explicitly check the validity of each move (bad
  1362. X   moves are possible if the weights are not properly set. */
  1363. Xchar *enmcount,*fricount;
  1364. Xint a1,a2,blankfris,blankenms,frilibs,lastus,lastthem,
  1365. X  ha,pa,snapstone,snaplibs,i,n,s,s1,us,them,
  1366. X  captsize,protsize,totallibs,hitarisize,hitarisave,neiarms,neienms,node;
  1367. Xlong fripats,enmpats,neipats;
  1368. Xneighbors nabor,nextnabor;
  1369. X/* First initialize all the best moves to pass */
  1370. X  if ((g->debug & 1) != 0) { printf("bestmoves: \n"); }
  1371. X  root[sonsp].nodecnt = 0; root[sonsp].nodepnt = 0;
  1372. X  for (node = firstelement; node < searchwidth; node++) {
  1373. X    root[sonsp].nodes[node].pv = 0;
  1374. X    root[sonsp].nodes[node].s = -1;   /* default is to pass */
  1375. X  }
  1376. X/* Evaluate each square of the board and assign a value to it */
  1377. X  for (i = firstelement; i < g->maxstone; i++) {
  1378. X    value[i] = 0;          /* default is not blank, so no value */
  1379. X    if ((g->board[i] == Blank) && (i != g->movestatus.kospot)) {
  1380. X      neipats = g->neibrd[i];
  1381. X      a1 = g->armymen[i];    /* blank army number */
  1382. X      if (g->who == White) {
  1383. X        fricount = &g->whitecount[0]; enmcount = &g->blackcount[0];
  1384. X        fripats = g->whitepats[i]; enmpats = g->blackpats[i];
  1385. X        blankfris = g->army[a1].friend; blankenms = g->army[a1].enemy;
  1386. X      } else {
  1387. X        fricount = &g->blackcount[0]; enmcount = &g->whitecount[0];
  1388. X        fripats = g->blackpats[i]; enmpats = g->whitepats[i];
  1389. X        blankfris = g->army[a1].enemy; blankenms = g->army[a1].friend;
  1390. X      }
  1391. X      getneighbors(g,&nabor,i);  /* get the neighbors */
  1392. X      if ((g->army[a1].size > g->maxstone-4) ||
  1393. X         ((blankfris > 0) && (blankenms > 0))) {
  1394. X        if ((init[i] > openvalue) &&
  1395. X          (((fripats & square3) != 0) || ((enmpats & square3) != 0)) ) {
  1396. X          value[i] = openvalue;
  1397. X        } else {
  1398. X          value[i] = init[i];      /* default value */
  1399. X        }
  1400. X      }
  1401. X/* territory value, more territory value for empty diamonds
  1402. X   some code was removed here too */
  1403. X      if (((fripats & diamond5) == 0) &&
  1404. X          ((enmpats & diamond5) == 0) &&
  1405. X          ((neipats & 0x0F0) == 0x0F0)) {
  1406. X            value[i] = value[i] + territoryvalue;
  1407. X      } else {
  1408. X        us = 0; them = 0; captsize = 0; protsize = 0;
  1409. X        lastus = -1; lastthem = -1; totallibs = g->army[a1].size - 1;
  1410. X        frilibs = 0; hitarisize = 0; hitarisave = 0;
  1411. X        neiarms = 0; neienms = 0; ha = -1; pa = -1;
  1412. X        for (n = firstelement; n < nabor.neis; n++) { /* count new army neighbor
  1413. Xs */
  1414. X          s = nabor.stone[n];              /* neighbors row & column */
  1415. X          a2 = g->armymen[s];              /* neighbor army number */
  1416. X          if (g->board[s] == Blank) {
  1417. X            frilibs = frilibs + 1;
  1418. X          } else {
  1419. X            if (g->army[a2].color == g->who) {
  1420. X              frilibs = frilibs + g->army[a2].lib - 1;
  1421. X              totallibs = totallibs + g->army[a2].lib - 1;
  1422. X            }
  1423. X            if (g->army[a2].lib == 1) {
  1424. X              if (g->army[a2].color == g->who) {
  1425. X                protsize = protsize + g->army[a2].size;
  1426. X                pa = a2;
  1427. X              } else {
  1428. X                captsize = captsize + g->army[a2].size;
  1429. X              }
  1430. X/* Check for hitari ...
  1431. X   If the enemy can be hitari'd add in the points, if we can be hitari'd
  1432. X   add in the points if we can protect against hitari without using up
  1433. X   our eyes and if the blank army has more of our stones as neighbors */
  1434. X            } else if (g->army[a2].lib == 2) {
  1435. X              if (g->army[a2].color == otherside[g->who]) {
  1436. X                hitarisize = hitarisize + g->army[a2].size;
  1437. X              } else if ((g->army[a2].color == g->who) &&
  1438. X                (g->army[a1].enemy > 0) && (blankfris > 1)) {
  1439. X                hitarisave = hitarisave + g->army[a2].size;
  1440. X                ha = a2;
  1441. X              }
  1442. X            }
  1443. X/* Don't count neighbors in the same amry more than once in neiarms,
  1444. X   and don't count armies in trouble */
  1445. X            if (g->board[s] == g->who) {
  1446. X              us = us + 1;
  1447. X              if (((lastus < 0) || (a2 != lastus)) &&
  1448. X                   (a2 != ha)) {
  1449. X                neiarms = neiarms + 1;
  1450. X                lastus = a2;
  1451. X              }
  1452. X            } else {
  1453. X              them = them + 1;
  1454. X              if ((lastthem < 0) || (a2 != lastthem)) {
  1455. X                neienms = neienms + 1;
  1456. X                lastthem = a2;
  1457. X              }
  1458. X            }
  1459. X          }
  1460. X        }
  1461. X/* This is the place!  I cut lots of strategic code from here.  If you want
  1462. X   to improve the ability of this program to play go, this is the place to
  1463. X   do it. */
  1464. X
  1465. X
  1466. X/* lower the value of a square controlled */
  1467. X        if (((neipats & 0xF00) != 0xF00) &&    /* row 3 test */
  1468. X            ((neipats & 0x0F0) == 0x0F0) &&
  1469. X            (them > 0) && ((fripats & diamond5) == 0)) value[i] = 0;
  1470. X        if ((us > 2) && (them <= 0)) { value[i] = 0; }
  1471. X        if ((us > 1) && (neiarms < us)) { value[i] = 0; }
  1472. X        if ((them > 2) && (us <= 0)) { value[i] = 0; }
  1473. X/* lower the value of a square that can be hitari'd on the next move */
  1474. X        if ((us <= 0) && (them >= nabor.neis-2)) {
  1475. X          value[i] = (value[i] / 2) - 1;
  1476. X        }
  1477. X/* increase the value of a position that protects us from hitari, unless
  1478. X   that position is already controlled by us */
  1479. X        if ((hitarisave > 0) && (nabor.neis > 3) && (frilibs > 1) &&
  1480. X            ((us < 3) || (them > 0))) {
  1481. X          value[i] = value[i] + hitarisave + retreatsize + neiarms - us;
  1482. X        }
  1483. X/* increase the value of a square that hitari's the enemy */
  1484. X        if (hitarisize > 0) {
  1485. X          if (frilibs > 1) {
  1486. X            value[i] = value[i] + hitarisize - us;
  1487. X            if (nabor.neis > 3) {
  1488. X              value[i] = value[i] + hitarivalue;
  1489. X            }
  1490. X          } else if ((snaplibs > 0) && (snaplibs < 3)) {
  1491. X              value[i] = value[i] + hitarisize + capturevalue +
  1492. X                hitarivalue + neiarms + snaplibs;
  1493. X        } }
  1494. X/* protect if we pick up at least 3 liberties, or 2 liberties without
  1495. X   having to move on the edge of the board and without having to move
  1496. X   into our eyes */
  1497. X        if ((protsize > 0) && (blankfris > 1) &&
  1498. X            ((frilibs > 2) || ((frilibs > 1) && (nabor.neis > 3)))) {
  1499. X          value[i] = value[i] + protsize + protvalue - us;
  1500. X        }
  1501. X/* don't move to the edge unless someone else is there */
  1502. X        if (((fripats & square3) == 0) && (nabor.neis < 4)) { value[i] = 0; }
  1503. X/* lower the value of a square we are next to if the enemy is not near */
  1504. X        if (((enmpats & square3) == 0) && ((fripats & square3) != 0)) {
  1505. X          if (nabor.neis > 3) value[i] = value[i] / 2; else value[i] = 0;
  1506. X        }
  1507. X/* Increase the value of moves that extend influence into unoccupied territory *
  1508. X/
  1509. X        if ((g->movecount >= firstmoves) &&
  1510. X            ((fripats & square3) == 0) && ((enmpats & square3) == 0)) {
  1511. X          if (((fripats & square5) != 0) && ((enmpats & square5) != 0)) {
  1512. X            value[i] = value[i] + square5value;
  1513. X          } else if (((fripats & square5) == 0) && ((enmpats & square5) == 0)) {
  1514. X            if (((fripats & circle7) != 0) && ((enmpats & circle7) != 0))
  1515. X              value[i] = value[i] + circle7value;
  1516. X          } }
  1517. X/* don't move to a square surrounded by enemy unless we have a capture */
  1518. X        if (captsize > 0) {
  1519. X          value[i] = value[i] + capturevalue + captsize;
  1520. X        } else if (them >= nabor.neis) {
  1521. X          value[i] = 0;
  1522. X        }
  1523. X      }
  1524. X/* There are three situations we move into:  1 is during the first
  1525. X   moves of the game when a large blank army occupies most of the
  1526. X   board; 2 is into a blank army that borders on computer and enemy
  1527. X   stones; 3 is into an eye if the value high enough to indicate a
  1528. X   capture or protection required, if not a KO situation. */
  1529. X      if (value[i] > 0) {
  1530. X        if ((i != g->movestatus.kospot) &&
  1531. X            ((g->army[a1].size > g->maxstone-4) ||
  1532. X            ((blankfris > 0) && (blankenms > 0)) ||
  1533. X            (value[i] > invadevalue))) {
  1534. X          s = i; node = firstelement;
  1535. X          while ((node < searchwidth) && (s >= 0)) {
  1536. X            if (value[s] > root[sonsp].nodes[node].pv) {
  1537. X              root[sonsp].nodes[node].pv = value[s];
  1538. X              s1 = root[sonsp].nodes[node].s;   /* save the old value */
  1539. X              root[sonsp].nodes[node].s = s;    /* use the better value */
  1540. X              s = s1;                      /* continue with old value */
  1541. X            }
  1542. X            node = node + 1;
  1543. X          }
  1544. X          root[sonsp].nodecnt = root[sonsp].nodecnt + 1;
  1545. X        }
  1546. X      }
  1547. X    }
  1548. X  }
  1549. X  if (root[sonsp].nodecnt > searchwidth) { root[sonsp].nodecnt = searchwidth; }
  1550. X  if ((g->debug & 1) != 0) { printf("bestmoves end.\n"); }
  1551. X}
  1552. ________This_Is_The_END________
  1553. if test `wc -l < gomoves.c` -ne 264; then
  1554.     echo 'shar: gomoves.c was damaged during transit'
  1555.   echo '      (should have been 264 bytes)'
  1556. fi
  1557. fi        ; : end of overwriting check
  1558. echo 'Extracting gomoves.h'
  1559. if test -f gomoves.h; then echo 'shar: will not overwrite gomoves.h'; else
  1560. sed 's/^X//' << '________This_Is_The_END________' > gomoves.h
  1561. X/* File gomoves.h
  1562. X   Developer:  James R. Logan Jr. (BYU), Advisor:  Dr. Lynn H. Beus (BYU)
  1563. X   email address:  loganj@byuvax.bitnet
  1564. X   (801) 378-3617
  1565. X*/
  1566. X
  1567. X#define maxsons 5  /* maximum depth of alpha-beta tree */
  1568. X#define maxlevs 5  /* must be odd, maximizing level for best odds? */
  1569. X
  1570. Xtypedef struct {
  1571. X  int s,pv;       /* alpha beta stone position and board value */
  1572. X} nodestruct;
  1573. X
  1574. Xtypedef struct {  /* children of node in alpha-beta tree */
  1575. X  int nodepnt,nodecnt;
  1576. X  mstatus status; /* board status resulting from stone */
  1577. X  nodestruct nodes[maxsons];
  1578. X} sons;
  1579. ________This_Is_The_END________
  1580. if test `wc -l < gomoves.h` -ne 18; then
  1581.     echo 'shar: gomoves.h was damaged during transit'
  1582.   echo '      (should have been 18 bytes)'
  1583. fi
  1584. fi        ; : end of overwriting check
  1585. echo 'Extracting goprocs.c'
  1586. if test -f goprocs.c; then echo 'shar: will not overwrite goprocs.c'; else
  1587. sed 's/^X//' << '________This_Is_The_END________' > goprocs.c
  1588. X/* File goprocs.c
  1589. X   Developer:  James R. Logan Jr. (BYU), Advisor:  Dr. Lynn H. Beus (BYU)
  1590. X   BYU Computer Science
  1591. X   232 TMCB
  1592. X   Provo, Utah  84602
  1593. X   email address:  loganj@byuvax.bitnet
  1594. X   (801) 378-3617
  1595. X
  1596. X   These procedures are go playing utility procedures that can be used by
  1597. X   a go playing progam to do all the house keeping during a game of go.
  1598. X   These procedures a based on a 1-dimensional representation of the game.
  1599. X   This code is not machine dependent, except for the drawing routines at
  1600. X   the end.
  1601. X*/
  1602. X
  1603. X#include <qd.h>
  1604. X#include <win.h>
  1605. X#include <stdio.h>
  1606. X#include <goprocs.h>
  1607. X
  1608. X#define patwidth 5
  1609. X
  1610. Xextern FILE *fp;
  1611. Xextern int drawnumber,lookahead,otherside[2];
  1612. Xextern windowptr mewindow,mywindow;
  1613. X
  1614. Xoverlay "gostuff"
  1615. X
  1616. Xchar coltable[19] = {'A','B','C','D','E','F','G','H','J','K','L','M','N','O','P'
  1617. X,'Q','R','S','T'};
  1618. Xint picset[29] =
  1619. X  {0x50,0x41,0x40,0x42,0x60,
  1620. X   0x14,0x05,0x04,0x06,0x24,
  1621. X   0x10,0x01,0x00,0x02,0x20,
  1622. X   0x18,0x09,0x08,0x0A,0x28,
  1623. X   0x90,0x81,0x80,0x82,0xA0,
  1624. X   0x100,0x200,0x400,0x800};
  1625. Xpattern whitepat = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
  1626. Xpattern blackpat = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
  1627. X
  1628. Xint looking,stonenumber,otherside[2],
  1629. X  wrkbrd[maxstones];
  1630. X
  1631. Xinitialize (g) game *g; {
  1632. X/* This procedure initializes the game structure supplied by the caller */
  1633. Xint i,j,r1,c1,w1,w2,w3,w4,w5,w6,w7,w8;
  1634. X  if ((g->debug & 1) != 0) printf("initializing, board size %d.\n",g->width);
  1635. X/* initialize other side table */
  1636. X  otherside[White] = Black; otherside[Black] = White;
  1637. X/* initialize game parameters */
  1638. X  g->movecount = 0;
  1639. X  g->deadwhite = 0; g->deadblack = 0;
  1640. X  w1 = g->width; w2 = w1 + w1; w3 = w2 + w1; w4 = w3 + w1;
  1641. X  w5 = w4 + w1; w6 = w5 + w1; w7 = w6 + 1; w8 = w7 + 1;
  1642. X  g->maxstone = w1 * w1; g->movestatus.kospot = -1;
  1643. X/* initialize the neighbor board */
  1644. X  for (i = firstelement; i < g->maxstone; i++) g->neibrd[i] = 0x0FFFFFFFFL;
  1645. X  j = firstelement;
  1646. X  for (i = firstelement; i < g->width; i++) {
  1647. X    g->neibrd[j] = g->neibrd[j] & 0x0EEEEEEEEL;
  1648. X    g->neibrd[j+w1-1] = g->neibrd[j+w1-1] & 0x0DDDDDDDDL;
  1649. X    g->neibrd[i] = g->neibrd[i] & 0x0BBBBBBBBL;
  1650. X    g->neibrd[g->maxstone-w1+i] = g->neibrd[g->maxstone-w1+i] & 0x077777777L;
  1651. X    if (w1 > 1) {
  1652. X      g->neibrd[j+1] = g->neibrd[j+1] & 0x0EEEEEEEFL;
  1653. X      g->neibrd[j+w1-2] = g->neibrd[j+w1-2] & 0x0DDDDDDDFL;
  1654. X      g->neibrd[i+w1] = g->neibrd[i+w1] & 0x0BBBBBBBFL;
  1655. X      g->neibrd[g->maxstone-w2+i] = g->neibrd[g->maxstone-w2+i] & 0x07777777FL;
  1656. X    }
  1657. X    if (w1 > 2) {
  1658. X      g->neibrd[j+2] = g->neibrd[j+2] & 0x0EEEEEEFFL;
  1659. X      g->neibrd[j+w1-3] = g->neibrd[j+w1-3] & 0x0DDDDDDFFL;
  1660. X      g->neibrd[i+w2] = g->neibrd[i+w2] & 0x0BBBBBBFFL;
  1661. X      g->neibrd[g->maxstone-w3+i] = g->neibrd[g->maxstone-w3+i] & 0x0777777FFL;
  1662. X    }
  1663. X    if (w1 > 3) {
  1664. X      g->neibrd[j+3] = g->neibrd[j+3] & 0x0EEEEEFFFL;
  1665. X      g->neibrd[j+w1-4] = g->neibrd[j+w1-4] & 0x0DDDDDFFFL;
  1666. X      g->neibrd[i+w3] = g->neibrd[i+w3] & 0x0BBBBBFFFL;
  1667. X      g->neibrd[g->maxstone-w4+i] = g->neibrd[g->maxstone-w4+i] & 0x077777FFFL;
  1668. X    }
  1669. X    if (w1 > 4) {
  1670. X      g->neibrd[j+4] = g->neibrd[j+4] & 0x0EEEEFFFFL;
  1671. X      g->neibrd[j+w1-5] = g->neibrd[j+w1-5] & 0x0DDDDFFFFL;
  1672. X      g->neibrd[i+w4] = g->neibrd[i+w4] & 0x0BBBBFFFFL;
  1673. X      g->neibrd[g->maxstone-w5+i] = g->neibrd[g->maxstone-w5+i] & 0x07777FFFFL;
  1674. X    }
  1675. X    if (w1 > 5) {
  1676. X      g->neibrd[j+5] = g->neibrd[j+5] & 0x0EEEFFFFFL;
  1677. X      g->neibrd[j+w1-6] = g->neibrd[j+w1-6] & 0x0DDDFFFFFL;
  1678. X      g->neibrd[i+w5] = g->neibrd[i+w5] & 0x0BBBFFFFFL;
  1679. X      g->neibrd[g->maxstone-w6+i] = g->neibrd[g->maxstone-w6+i] & 0x0777FFFFFL;
  1680. X    }
  1681. X    if (w1 > 6) {
  1682. X      g->neibrd[j+6] = g->neibrd[j+6] & 0x0EEFFFFFFL;
  1683. X      g->neibrd[j+w1-7] = g->neibrd[j+w1-7] & 0x0DDFFFFFFL;
  1684. X      g->neibrd[i+w6] = g->neibrd[i+w6] & 0x0BBFFFFFFL;
  1685. X      g->neibrd[g->maxstone-w7+i] = g->neibrd[g->maxstone-w7+i] & 0x077FFFFFFL;
  1686. X    }
  1687. X    if (w1 > 7) {
  1688. X      g->neibrd[j+7] = g->neibrd[j+7] & 0x0EFFFFFFFL;
  1689. X      g->neibrd[j+w1-8] = g->neibrd[j+w1-8] & 0x0DFFFFFFFL;
  1690. X      g->neibrd[i+w7] = g->neibrd[i+w7] & 0x0BFFFFFFFL;
  1691. X      g->neibrd[g->maxstone-w8+i] = g->neibrd[g->maxstone-w8+i] & 0x07FFFFFFFL;
  1692. X    }
  1693. X    j = j + g->width;
  1694. X  }
  1695. X/* initialize the row and column arrays */
  1696. X  i = 0;
  1697. X  r1 = 1;
  1698. X  while (i < g->maxstone) {
  1699. X    for (c1 = 0; c1 < g->width; c1++)
  1700. X      { g->rowbrd[i] = r1; g->colbrd[i] = c1; i = i + 1; }
  1701. X    r1 = r1 + 1;
  1702. X  }
  1703. X  for (i = firstelement; i < g->maxstone; i++) {
  1704. X    g->board[i] = Blank; g->whitepats[i] = 0; g->blackpats[i] = 0;
  1705. X    g->whitecount[i] = 0; g->blackcount[i] = 0;
  1706. X  }
  1707. X  allarmies(g);  /* Create the armies */
  1708. X  drawboard(g);  /* display the game board */
  1709. X  looking = 0;   /* indicate not in look ahead now */
  1710. X  stonenumber = 0;
  1711. X  if ((g->debug & 1) != 0) printf("initialize end.\n");
  1712. X}
  1713. X
  1714. Xint addastone(g,newstone) game *g; int newstone; {
  1715. X/* Clear the blank army for rebuilding, update any neighboring enemy
  1716. X   armies directly, and do nothing for neighboring friendly armies.
  1717. X   Friendly armies are merged and updated by linkarmies at the end. */
  1718. Xint a1,a2,first,playedstone,n,s; neighbors nabor; mstatus oldstatus;
  1719. X  playedstone = -1;
  1720. X  a2 = -1;
  1721. X  if ((newstone >= 0) && (newstone < g->maxstone) &&
  1722. X      (newstone != g->movestatus.kospot) && (g->board[newstone] == Blank)) {
  1723. X    g->movecount = g->movecount + 1;
  1724. X    if (looking == 0) stonenumber = stonenumber + 1;
  1725. X    oldstatus = g->movestatus;  /* save the old status */
  1726. X    g->board[newstone] = g->who;
  1727. X    drawstone(g,newstone,g->who);
  1728. X    g->movestatus.kospot = -1;  /* clear the ko position */
  1729. X    g->movestatus.captures = 0; /* clear captures */
  1730. X    topicture(g,newstone);
  1731. X    a1 = g->armymen[newstone]; /* old blank army number */
  1732. X    first = g->army[a1].first; /* create link list of armies to relink */
  1733. X    getneighbors(g,&nabor,newstone);
  1734. X    a2 = -1;
  1735. X    for (n = firstelement; n < nabor.neis; n++) {
  1736. X      s = nabor.stone[n];
  1737. X      if (g->board[s] != Blank) {
  1738. X        a1 = g->armymen[s];
  1739. X        if ((a1 != a2) && (g->army[a1].color == otherside[g->who])) {
  1740. X          g->army[a1].enemy = g->army[a1].enemy + 1;
  1741. X          g->army[a1].lib = g->army[a1].lib - 1;
  1742. X          if (g->army[a1].lib <= 0) {
  1743. X            capture(g,g->army[a1].first);
  1744. X            g->movestatus.captures = g->movestatus.captures | nabor.direction[n]
  1745. X;
  1746. X          }
  1747. X        }
  1748. X        a2 = a1;
  1749. X    } }
  1750. X    linkarmies(g,first);
  1751. X/* If the added stone was illegal for lack of liberties then remove it */
  1752. X    if (g->army[g->armymen[newstone]].lib <= 0) {
  1753. X      if (g->who == White) printf(" Bad add by white at %c,%d\n",
  1754. X          coltable[g->colbrd[newstone]],g->rowbrd[newstone]);
  1755. X      else printf(" Bad add by black at %c,%d\n",
  1756. X          coltable[g->colbrd[newstone]],g->rowbrd[newstone]);
  1757. X      removeastone(g,newstone,g->movestatus);
  1758. X      g->movestatus = oldstatus;
  1759. X      if (looking == 0) stonenumber = stonenumber - 1;
  1760. X    } else {
  1761. X/* If the added stone merged into another army then there is no ko spot */
  1762. X      a1 = g->armymen[newstone]; /* old blank army number */
  1763. X      if (g->army[a1].size > 1) g->movestatus.kospot = -1;
  1764. X      if (looking == 0) {
  1765. X        playedstone = newstone;
  1766. X        if (fp != NULL) {
  1767. X          if (g->who == White) fprintf(fp,"add w %c,%d\n",
  1768. X            coltable[g->colbrd[newstone]],g->rowbrd[newstone]);
  1769. X          else fprintf(fp,"add b %c,%d\n",
  1770. X            coltable[g->colbrd[newstone]],g->rowbrd[newstone]);
  1771. X    } } }
  1772. X  } else {
  1773. X    if (g->who == White) printf(" Bad add by white at %c,%d\n",
  1774. X          coltable[g->colbrd[newstone]],g->rowbrd[newstone]);
  1775. X    else printf(" Bad add by black at %c,%d\n",
  1776. X          coltable[g->colbrd[newstone]],g->rowbrd[newstone]);
  1777. X  }
  1778. X  return playedstone;
  1779. X}
  1780. X
  1781. Xremoveastone(g,newstone,status) game *g; int newstone; mstatus status; {
  1782. X/* Clear the blank army for rebuilding, update any neighboring enemy
  1783. X   armies directly, and do nothing for neighboring friendly armies.
  1784. X   Friendly armies are merged and updated by linkarmies at the end. */
  1785. Xint a1,a2,first,n,s,color,wh; neighbors nabor;
  1786. X  if ((g->debug & 1) != 0) printf("removeastone at: %d\n",newstone);
  1787. X  if ((newstone >= 0) && (newstone < g->maxstone) &&
  1788. X      (g->board[newstone] != Blank)) {
  1789. X    g->movecount = g->movecount - 1;
  1790. X    g->movestatus = status;    /* set the new board status */
  1791. X    wh = g->board[newstone];   /* save the old color */
  1792. X    color = otherside[wh];
  1793. X    frompicture(g,newstone);   /* remove stone from picture */
  1794. X    g->board[newstone] = Blank;/* remove the stone */
  1795. X    if (wh == White) g->deadwhite = g->deadwhite + 1;
  1796. X    else g->deadblack = g->deadblack + 1;
  1797. X    undrawstone(g,newstone);
  1798. X    a1 = g->armymen[newstone]; /* old army number */
  1799. X    first = g->army[a1].first; /* first man in army to be relinked */
  1800. X    getneighbors(g,&nabor,newstone);
  1801. X    a2 = 0;
  1802. X    for (n = firstelement; n < nabor.neis; n++) { /* for neighbors */
  1803. X      a1 = g->armymen[nabor.stone[n]];
  1804. X      if ((g->army[a1].color == Blank) &&
  1805. X          ((nabor.direction[n] & g->movestatus.captures) != 0)) {
  1806. X        uncapture(g,nabor.stone[n],color);
  1807. X        g->army[a1].lib = 1;   /* set 1 liberty for the removed stone */
  1808. X      } else if ((a1 != a2) && (g->army[a1].color == otherside[wh])) {
  1809. X        g->army[a1].enemy = g->army[a1].enemy - 1;
  1810. X        g->army[a1].lib = g->army[a1].lib + 1;
  1811. X      }
  1812. X      a2 = a1;
  1813. X    }
  1814. X    linkarmies(g,first);
  1815. X  } else {
  1816. X    if (g->who == White) printf(" Bad remove by white at %c,%d\n",
  1817. X          coltable[g->colbrd[newstone]],g->rowbrd[newstone]);
  1818. X    else printf(" Bad remove by black at %c,%d\n",
  1819. X          coltable[g->colbrd[newstone]],g->rowbrd[newstone]);
  1820. X  }
  1821. X  if ((g->debug & 1) != 0) printf("removeastone, end.\n");
  1822. X}
  1823. X
  1824. Xcapture(g,s) game *g; int s; {
  1825. X/* Call this routine to remove an army that has been captured.  The
  1826. X   army remains intact, just changes to a blank army.  Neighboring
  1827. X   enemy armies have their liberties updated by buildarmies. */
  1828. Xint a1,a2,s1,n,wh; neighbors nabor;
  1829. X  if ((g->debug & 1) != 0) printf("capture:\n");
  1830. X  if ((s >= 0) && (s < g->maxstone)) {
  1831. X    a1 = g->armymen[s];       /* get the army number */
  1832. X    if (g->army[a1].color != Blank) {
  1833. X      if (g->army[a1].size == 1) {
  1834. X        g->movestatus.kospot = g->army[a1].first;
  1835. X      } else {
  1836. X        g->movestatus.kospot = -1;
  1837. X      }
  1838. X      g->movecount = g->movecount - g->army[a1].size;
  1839. X      wh = g->army[a1].color;     /* save the army color */
  1840. X      if (wh == White) g->deadwhite = g->deadwhite + g->army[a1].size;
  1841. X      else g->deadblack = g->deadblack + g->army[a1].size;
  1842. X      g->army[a1].color = Blank;  /* change army color to blank */
  1843. X      g->army[a1].size = 0;   /* causes army to be rebuilt by buildarmies */
  1844. X      s1 = g->army[a1].first; /* first man in army */
  1845. X      while (s1 >= 0) {
  1846. X        frompicture(g,s1);    /* take out of picture */
  1847. X        undrawstone(g,s1);
  1848. X        g->board[s1] = Blank;     /* change stone color to blank */
  1849. X/* clear the size in neighboring enemy armies so they will be rebuilt */
  1850. X        getneighbors(g,&nabor,s1);
  1851. X        for (n = firstelement; n < nabor.neis; n++) {   /* for neighbors */
  1852. X          a2 = g->armymen[nabor.stone[n]];
  1853. X          if (a2 > 0) {
  1854. X            if (g->army[a2].color == otherside[wh]) {
  1855. X              g->army[a2].size = 0; }
  1856. X          }
  1857. X        }
  1858. X/* get the next man in the army */
  1859. X        s1 = g->armylnk[s1];  /* row link to next army man   */
  1860. X      }
  1861. X      buildarmies(g);
  1862. X    } else {
  1863. X      printf(" Bad capture at: %c,%d\n",coltable[g->colbrd[s]],g->rowbrd[s]);
  1864. X    }
  1865. X  } else {
  1866. X    printf(" Bad capture at: %c,%d\n",coltable[g->colbrd[s]],g->rowbrd[s]);
  1867. X  }
  1868. X  if ((g->debug & 1) != 0) printf("capture, end.\n");
  1869. X}
  1870. X
  1871. Xuncapture(g,s,wh) game *g; int s,wh; {
  1872. X/* Call this routine to uncapture an army that had been captured.  The
  1873. X   army remains intact, just changes to a non-blank army.  Neighboring
  1874. X   enemy armies have their liberties updated by buildarmies. */
  1875. Xint a1,a2,s1,n; neighbors nabor;
  1876. X  if ((g->debug & 1) != 0) printf("uncapture:\n");
  1877. X  if ((s >= 0) && (s < g->maxstone)) {
  1878. X    a1 = g->armymen[s];     /* get the army number */
  1879. X    if (g->army[a1].color == Blank) {
  1880. X      g->movecount = g->movecount + g->army[a1].size;
  1881. X      if (wh == White) g->deadwhite = g->deadwhite - g->army[a1].size;
  1882. X      else g->deadblack = g->deadblack - g->army[a1].size;
  1883. X      g->army[a1].color = wh; /* change army color to non-blank */
  1884. X      g->army[a1].size = 0;   /* causes army to be rebuilt by buildarmies */
  1885. X      s1 = g->army[a1].first; /* first man in army */
  1886. X      while (s1 >= 0) {
  1887. X        g->board[s1] = wh;  /* change stone color to non-blank */
  1888. X        drawstone(g,s1,wh);
  1889. X        topicture(g,s1);    /* add to picture */
  1890. X/* clear the size in neighboring enemy armies so they will be rebuilt */
  1891. X        getneighbors(g,&nabor,s1);
  1892. X        for (n = firstelement; n < nabor.neis; n++) {   /* for neighbors */
  1893. X          a2 = g->armymen[nabor.stone[n]];
  1894. X          if (g->army[a2].color != wh) g->army[a2].size = 0;
  1895. X        }
  1896. X/* get the next man in the army */
  1897. X        s1 = g->armylnk[s1];  /* row link to next army man */
  1898. X      }
  1899. X      buildarmies(g);
  1900. X    }
  1901. X  } else {
  1902. X    printf("Bad uncapture an army at: %c,%d\n",
  1903. X      coltable[g->colbrd[s]],g->rowbrd[s]);
  1904. X  }
  1905. X  if ((g->debug & 1) != 0) printf(" uncapture, end.\n");
  1906. X}
  1907. X
  1908. Xgetneighbors(g,nabor,stone) game *g; neighbors *nabor; int stone; {
  1909. Xint b,i,j,s;
  1910. X/* Establish the number and position of neighbors to a stone.  Gather
  1911. X   the stone numbers of neighboring positions into the nabor.stone
  1912. X   array sorted by army number.  The purpose of the sort is
  1913. X   to group neighbors belonging to the same army together. */
  1914. X  nabor->neis = firstelement;
  1915. X  if ((g->neibrd[stone] & 1) != 0) {
  1916. X    nabor->stone[firstelement] = stone - 1;
  1917. X    nabor->direction[firstelement] = 1;
  1918. X    nabor->neis = nabor->neis + 1; }
  1919. X  if ((g->neibrd[stone] & 2) != 0) {
  1920. X    nabor->stone[nabor->neis] = stone + 1;
  1921. X    nabor->direction[nabor->neis] = 2;
  1922. X    nabor->neis = nabor->neis + 1; }
  1923. X  if ((g->neibrd[stone] & 4) != 0) {
  1924. X    nabor->stone[nabor->neis] = stone - g->width;
  1925. X    nabor->direction[nabor->neis] = 4;
  1926. X    nabor->neis = nabor->neis + 1; }
  1927. X  if ((g->neibrd[stone] & 8) != 0) {
  1928. X    nabor->stone[nabor->neis] = stone + g->width;
  1929. X    nabor->direction[nabor->neis] = 8;
  1930. X    nabor->neis = nabor->neis + 1; }
  1931. X  for (i = firstelement; i < nabor->neis-1; i++) {
  1932. X    for (j = i+1; j < nabor->neis; j++) {
  1933. X      if (g->armymen[nabor->stone[j]] < g->armymen[nabor->stone[i]]) {
  1934. X        s = nabor->stone[j];
  1935. X        nabor->stone[j] = nabor->stone[i]; nabor->stone[i] = s;
  1936. X        b = nabor->direction[j];
  1937. X        nabor->direction[j] = nabor->direction[i]; nabor->direction[i] = b;
  1938. X} } } }
  1939. X
  1940. Xallarmies(g) game *g; {
  1941. X/* Clear all army numbers in the army array, and call build armies */
  1942. Xint n,s;
  1943. X  if ((g->debug & 1) != 0) printf("allarmies:\n");
  1944. X  g->avail = 1;      /* next available army number */
  1945. X  g->army[1].bp = 0;
  1946. X  for (n = firstelement; n < maxarmies; n++) {
  1947. X    g->army[n].first = -1;
  1948. X    g->army[n].fp = n + 1;  /* initialize armies forward links */
  1949. X  }
  1950. X  for (s = firstelement; s < g->maxstone; s++) {
  1951. X    g->armymen[s] = 0; g->armylnk[s] = s - 1;
  1952. X  }
  1953. X  linkarmies(g,g->maxstone-1);
  1954. X  if ((g->debug & 1) != 0) printf(" allarmies.\n");
  1955. X}
  1956. X
  1957. Xlinkarmies(g,first) game *g; int first; {
  1958. X/* Create a 1 man army for each square.  Then look at neighboring squares,
  1959. X   and if any are the same color army then merge the new army into the
  1960. X   neighboring army */
  1961. Xint n,s,s1,s2,new,old; neighbors nabor;
  1962. X  if ((g->debug & 1) != 0) printf("linkarmies:\n");
  1963. X  s = first;
  1964. X  old = g->armymen[s];      /* save old army number */
  1965. X  while (s >= 0) {
  1966. X    s1 = g->armylnk[s];     /* save link to next old army man */
  1967. X    new = g->avail;         /* get next available army number */
  1968. X    g->avail = g->army[g->avail].fp;
  1969. X    g->army[g->avail].bp = new;
  1970. X    g->armymen[s] = new;    /* set new army number */
  1971. X    g->armylnk[s] = -1;
  1972. X    g->army[new].size = 0;  /* size is done by buildarmies */
  1973. X    g->army[new].color = g->board[s];
  1974. X    g->army[new].first = s; g->army[new].last = s;
  1975. X    getneighbors(g,&nabor,s);     /* get the neighbors */
  1976. X    for (n = firstelement; n < nabor.neis; n++) {  /* go through the neighbors *
  1977. X/
  1978. X      s2 = nabor.stone[n];
  1979. X      if (g->armymen[s2] != old) { armymerge(g,s2,s); }
  1980. X    }
  1981. X    s = s1;  /* next man to be linked */
  1982. X  }
  1983. X/* make old army number available */
  1984. X  if (old > 0) {
  1985. X    if (g->army[old].fp != g->avail) {
  1986. X      if (g->army[old].bp > 0) {
  1987. X        g->army[g->army[old].bp].fp = g->army[old].fp; }
  1988. X      g->army[g->army[old].fp].bp = g->army[old].bp;
  1989. X      g->army[g->army[g->avail].bp].fp = old;
  1990. X      g->army[old].fp = g->avail;
  1991. X      g->army[old].bp = g->army[g->avail].bp;
  1992. X      g->army[g->avail].bp = old;
  1993. X    }
  1994. X    g->army[old].first = -1; g->avail = old;
  1995. X  }
  1996. X  buildarmies(g);
  1997. X  if ((g->debug & 1) != 0) printf("  linkarmies.\n");
  1998. X}
  1999. X
  2000. Xbuildarmies(g) game *g; {
  2001. X/* Add up the number of computer and opponent stones that border on
  2002. X   each army */
  2003. Xint a1,a2,n,s,s1; neighbors nabor;
  2004. X  if ((g->debug & 1) != 0) printf("buildarmies:\n");
  2005. X  for (s = firstelement; s < g->maxstone; s++) wrkbrd[s] = 0;
  2006. X  a1 = g->army[g->avail].bp;
  2007. X  while (a1 > 0) {                  /* go through each active army */
  2008. X    if ((g->army[a1].size <= 0) && (g->army[a1].first >= 0)) {
  2009. X      g->army[a1].lib = 0;
  2010. X      g->army[a1].friend = 0;
  2011. X      g->army[a1].enemy = 0;
  2012. X      g->army[a1].armies = 0;
  2013. X      s = g->army[a1].first;          /* first man in army */
  2014. X      while (s >= 0) {
  2015. X        g->army[a1].size = g->army[a1].size + 1;
  2016. X        getneighbors(g,&nabor,s);     /* get the neighbors */
  2017. X        for (n = firstelement; n < nabor.neis; n++) {  /* go through neighbors *
  2018. X/
  2019. X          s1 = nabor.stone[n];
  2020. X          if (wrkbrd[s1] != a1) {
  2021. X            wrkbrd[s1] = a1;        /* mark this neighbor counted */
  2022. X            if (g->board[s] != Blank) {
  2023. X              if (g->board[s1] == Blank) {
  2024. X                g->army[a1].lib = g->army[a1].lib + 1;
  2025. X              } else if (g->board[s1] != g->board[s]) {
  2026. X                g->army[a1].enemy = g->army[a1].enemy + 1;
  2027. X              }
  2028. X            } else {
  2029. X              if (g->board[s1] != Blank) {
  2030. X                if (g->board[s1] == White) {
  2031. X                  g->army[a1].friend = g->army[a1].friend + 1;
  2032. X                } else {
  2033. X                  g->army[a1].enemy = g->army[a1].enemy + 1;
  2034. X                }
  2035. X              }
  2036. X            }
  2037. X          }
  2038. X        }
  2039. X        s = g->armylnk[s]; /* link to next man */
  2040. X      }
  2041. X    }
  2042. X    a1 = g->army[a1].bp;
  2043. X  }
  2044. X  if ((g->debug & 1) != 0) printf("  buildarmies.\n");
  2045. X}
  2046. X
  2047. Xarmymerge(g,s1,s2) game *g; int s1,s2; {
  2048. X/* Merge two armies by merging the linked lists */
  2049. Xint a1,a2,i,s,s3;
  2050. X  a1 = g->armymen[s1]; a2 = g->armymen[s2];
  2051. X  if ((a1 > 0) && (a1 != a2) && (g->board[s1] == g->board[s2])) {
  2052. X/* Change a2 number to a1 for all the a2 armymen */
  2053. X    s = g->army[a2].first;  /* first man in army */
  2054. X    while (s >= 0) { g->armymen[s] = a1; s = g->armylnk[s]; }
  2055. X/* Link army a2 into army a1 */
  2056. X    g->armylnk[g->army[a2].last] = g->army[a1].first;
  2057. X    g->army[a1].first = g->army[a2].first;
  2058. X    g->army[a2].first = -1; /* delete army a2 */
  2059. X    g->army[a2].size = 0;
  2060. X    g->army[a1].size = 0;   /* required for buildarmies */
  2061. X    if (g->army[a2].fp != g->avail) {
  2062. X      if (g->army[a2].bp > 0) {
  2063. X        g->army[g->army[a2].bp].fp = g->army[a2].fp; }
  2064. X      g->army[g->army[a2].fp].bp = g->army[a2].bp;
  2065. X      g->army[g->army[g->avail].bp].fp = a2;
  2066. X      g->army[a2].fp = g->avail;
  2067. X      g->army[a2].bp = g->army[g->avail].bp;
  2068. X      g->army[g->avail].bp = a2;
  2069. X    }
  2070. X    g->avail = a2;
  2071. X} }
  2072. X
  2073. Xtopicture(g,s) game *g; int s; {
  2074. X/* Add the specified stone to the bitmap of the stones in the 5 by 5
  2075. X   diamond centered about the specified stone */
  2076. Xint i,s1,s2,s3,w3; long bit,*p; char *c;
  2077. X  i = - g->width - g->width - 2; bit = 1L; s1 = -1;
  2078. X  if (g->who == White) { p = &g->whitepats[s]; c = &g->whitecount[s]; }
  2079. X  else { p = &g->blackpats[s]; c = &g->blackcount[s]; }
  2080. X  for (s2 = 0; s2 < patwidth; s2++) {
  2081. X    for (s3 = 0; s3 < patwidth; s3++) {
  2082. X      s1 = s1 + 1;
  2083. X      if ((picset[s1] & g->neibrd[s]) == picset[s1])
  2084. X        { *(p+i) = *(p+i) | bit; *(c+i) = *(c+i) + 1; }
  2085. X      bit = bit + bit; i = i + 1;
  2086. X    } i = i + g->width - patwidth;
  2087. X  }
  2088. X  w3 = g->width + g->width + g->width;
  2089. X  if ((picset[25] & g->neibrd[s]) == picset[25])
  2090. X    { *(p-3) = *(p-3) | 0x2000000L; *(c-3) = *(c-3) + 1; }
  2091. X  if ((picset[26] & g->neibrd[s]) == picset[26])
  2092. X    { *(p+3) = *(p+3) | 0x4000000L; *(c+3) = *(c+3) + 1; }
  2093. X  if ((picset[27] & g->neibrd[s]) == picset[27])
  2094. X    { *(p-w3) = *(p-w3) | 0x8000000L; *(c-w3) = *(c-w3) + 1; }
  2095. X  if ((picset[28] & g->neibrd[s]) == picset[28])
  2096. X    { *(p+w3) = *(p+w3) | 0x10000000L; *(c+w3) = *(c+w3) + 1; }
  2097. X}
  2098. X
  2099. Xfrompicture(g,s) game *g; int s; {
  2100. X/* Remove the specified stone from the bitmap of the stones in the 5 by 5
  2101. X   diamond centered about the specified stone. */
  2102. Xint i,s1,s2,s3,w3; long bit,*p; char *c;
  2103. X  i = - g->width - g->width - 2; bit = 1; s1 = -1;
  2104. X  if (g->who == White) { p = &g->whitepats[s]; c = &g->whitecount[s]; }
  2105. X  else { p = &g->blackpats[s]; c = &g->blackcount[s]; }
  2106. X  for (s2 = 0; s2 < patwidth; s2++) {
  2107. X    for (s3 = 0; s3 < patwidth; s3++) {
  2108. X      s1 = s1 + 1;
  2109. X      if ((picset[s1] & g->neibrd[s]) == picset[s1])
  2110. X        { *(p+i) = *(p+i) & ~bit; *(c+i) = *(c+i) - 1; }
  2111. X      bit = bit + bit; i = i + 1;
  2112. X    } i = i + g->width - patwidth;
  2113. X  }
  2114. X  w3 = g->width + g->width + g->width;
  2115. X  if ((picset[25] & g->neibrd[s]) == picset[25])
  2116. X    { *(p-3) = *(p-3) & ~0x2000000L; *(c-3) = *(c-3) - 1; }
  2117. X  if ((picset[26] & g->neibrd[s]) == picset[26])
  2118. X    { *(p+3) = *(p+3) & ~0x4000000L; *(c+3) = *(c+3) - 1; }
  2119. X  if ((picset[27] & g->neibrd[s]) == picset[27])
  2120. X    { *(p-w3) = *(p-w3) & ~0x8000000L; *(c-w3) = *(c-w3) - 1; }
  2121. X  if ((picset[28] & g->neibrd[s]) == picset[28])
  2122. X    { *(p+w3) = *(p+w3) & ~0x10000000L; *(c+w3) = *(c+w3) - 1; }
  2123. X}
  2124. X
  2125. X/* The following routines provide output for debugging */
  2126. X
  2127. Xmoveboard(g) game *g; {
  2128. Xint i,s;
  2129. X  s = 0;
  2130. X  while (s < g->maxstone) {
  2131. X    for (i = firstelement; i < g->width; i++) {
  2132. X      if (g->board[s] == White) printf(" 1");
  2133. X      else if (g->board[s] == Black) printf(" 2");
  2134. X      else printf(" 0");
  2135. X      s = s + 1;
  2136. X    }
  2137. X    printf("\n");
  2138. X} }
  2139. X
  2140. Xarmyboard(g) game *g; {
  2141. Xint i,s;
  2142. X  s = 0;
  2143. X  while (s < g->maxstone) {
  2144. X    for (i = firstelement; i < g->width; i++) { printf("%3d",g->armymen[s]); s =
  2145. X s + 1; }
  2146. X    printf("\n");
  2147. X} }
  2148. X
  2149. Xarmyinfo(g) game *g; {
  2150. Xint i,n; char qkey;
  2151. X  qkey = 'g';
  2152. X  printf("Total stones: %d\nAvail: %d\n",g->movecount,g->avail);
  2153. X  n = 0;
  2154. X  i = g->army[g->avail].bp;
  2155. X  while (i > 0) { if (i > n) n = i; i = g->army[i].bp; }
  2156. X  printf("Highest army number: %d\n",n);
  2157. X  i = g->army[g->avail].bp;
  2158. X  while ((qkey != 'q') && (i > 0)) {
  2159. X    printf("Army %d\n",i);
  2160. X    if (g->army[i].first >= 0) {
  2161. X      printf("Color %d\nSize %d\nFirst %d\nLast %d\n",
  2162. X        g->army[i].color,g->army[i].size,g->army[i].first,g->army[i].last);
  2163. X      printf("FP %d\nBP %d\nLiberties %d\nFriends %d\nEnemies %d\n",
  2164. X        g->army[i].fp,g->army[i].bp,g->army[i].lib,g->army[i].friend,g->army[i].
  2165. Xenemy);
  2166. X    }
  2167. X    i = g->army[i].bp;
  2168. X    printf("q return to quit, space to continue\n"); qkey = getchar();
  2169. X  }
  2170. X}
  2171. X
  2172. Xlinkinfo(g) game *g; {
  2173. Xint i,s;
  2174. X  s = firstelement;
  2175. X  while (s < g->maxstone) {
  2176. X    for (i = firstelement; i < g->width; i++) { printf("%d ",g->armylnk[s]); s =
  2177. X s + 1; }
  2178. X    printf("\n");
  2179. X  }
  2180. X}
  2181. X
  2182. Xpictinfo(g) game *g; {
  2183. Xint i,s; char qkey;
  2184. X  s = 0; qkey = 'g';
  2185. X  printf("White stone patterns:\n");
  2186. X  while ((s < g->maxstone) && (qkey != 'q') && (qkey != 'n')) {
  2187. X    for (i = firstelement; i < g->width; i++)
  2188. X      { printf(" %lx\n",g->whitepats[s]); s = s + 1; }
  2189. X    printf("q return to quit, space to continue\n"); qkey = getchar();
  2190. X  } printf("Black stone patterns:\n");
  2191. X  s = 0;
  2192. X  while ((s < g->maxstone) && (qkey != 'q')) {
  2193. X    for (i = firstelement; i < g->width; i++)
  2194. X      { printf(" %lx\n",g->blackpats[s]); s = s + 1; }
  2195. X    printf("q return to quit, space to continue\n"); qkey = getchar();
  2196. X  }
  2197. X}
  2198. X
  2199. Xneighborinfo(g) game *g; {
  2200. Xint i,s;
  2201. X  s = 0;
  2202. X  while (s < g->maxstone) {
  2203. X    for (i = firstelement; i < g->width; i++)
  2204. X      { printf("%4x ",g->neibrd[s]); s = s + 1; }
  2205. X    printf("\n");
  2206. X  }
  2207. X}
  2208. X
  2209. Xdrawboard(g) game *g; {
  2210. Xint i,linelength; rect srect; char num[4];
  2211. X  setport(mywindow);
  2212. X/* Draw the position letters and numbers */
  2213. X  textsize(9);
  2214. X  for (i = g->width; i > 0; i--) {
  2215. X    moveto(-12,14 + 16 * (g->width - i));
  2216. X    sprintf(num,"%2d", i);
  2217. X    drawstring(num);
  2218. X  }
  2219. X  for (i = 0; i < g->width; i++) {
  2220. X    moveto(7 + 16 * i,13 + 16 * g->width);
  2221. X    drawchar(coltable[i]);
  2222. X  }
  2223. X/* Draw the board */
  2224. X  textsize(7);
  2225. X  linelength = 16 * (g->width - 1);
  2226. X  moveto(10,10);
  2227. X  for (i = 0; i < g->width; i++) {
  2228. X    line(linelength,0);
  2229. X    move(-linelength,16);
  2230. X  }
  2231. X  moveto(10,10);
  2232. X  for (i = 0; i < g->width; i++) {
  2233. X    line(0,linelength);
  2234. X    move(16,-linelength);
  2235. X  }
  2236. X/* draw the handicap positions on a 19 X 19 board */
  2237. X  if (g->width == 19) {
  2238. X/* first draw the corner handicap positions */
  2239. X    setrect(&srect,  55,  55,  61,  61); filloval(&srect,&blackpat);
  2240. X    setrect(&srect,  55, 247,  61, 253); filloval(&srect,&blackpat);
  2241. X    setrect(&srect, 247,  55, 253,  61); filloval(&srect,&blackpat);
  2242. X    setrect(&srect, 247, 247, 253, 253); filloval(&srect,&blackpat);
  2243. X/* now draw the other row 3 handicap positions */
  2244. X    setrect(&srect,  55, 151,  61, 157); filloval(&srect,&blackpat);
  2245. X    setrect(&srect, 151,  55, 157,  61); filloval(&srect,&blackpat);
  2246. X    setrect(&srect, 247, 151, 253, 157); filloval(&srect,&blackpat);
  2247. X    setrect(&srect, 151, 247, 157, 253); filloval(&srect,&blackpat);
  2248. X/* finally draw the center handicap position */
  2249. X    setrect(&srect, 151, 151, 157, 157); filloval(&srect,&blackpat);
  2250. X  }
  2251. X  setport(mewindow);
  2252. X}
  2253. X
  2254. Xdrawstone(g,s,wh) game *g; int s,wh; {
  2255. Xint w,x,y; rect srect; char num[8];
  2256. X  if ((looking == 0) || (lookahead != 0)) {
  2257. X    setport(mywindow);
  2258. X    x = 10 + 16 * (s % g->width);
  2259. X    y = 10 + 16 * ((g->maxstone - 1 - s) / g->width);
  2260. X    setrect(&srect, x-8, y-8, x+8, y+8);
  2261. X    if (wh == White) {
  2262. X      filloval(&srect,&whitepat);
  2263. X    } else {
  2264. X      filloval(&srect,&blackpat);
  2265. X    }
  2266. X    if ((drawnumber != 0) && (looking == 0)) {
  2267. X      sprintf(num,"%d",stonenumber);
  2268. X      w = stringwidth(num) >> 1;
  2269. X      moveto(x-w,y+3);
  2270. X      drawstring(num);
  2271. X    }
  2272. X    setport(mewindow);
  2273. X  }
  2274. X}
  2275. X
  2276. Xundrawstone(g,s) game *g; int s; {
  2277. Xint x,y; rect srect;
  2278. X  if ((looking == 0) || (lookahead != 0)) {
  2279. X    setport(mywindow);
  2280. X    x = 10 + 16 * (s % g->width);
  2281. X    y = 10 + 16 * ((g->maxstone - 1 - s) / g->width);
  2282. X    setrect(&srect, x-8, y-8, x+8, y+8);
  2283. X    eraseoval(&srect);
  2284. X    if ((g->neibrd[s] & 1) != 0) { moveto(x,y); line(-8,0); }
  2285. X    if ((g->neibrd[s] & 2) != 0) { moveto(x,y); line(8,0); }
  2286. X    if ((g->neibrd[s] & 4) != 0) { moveto(x,y); line(0,8); }
  2287. X    if ((g->neibrd[s] & 8) != 0) { moveto(x,y); line(0,-8); }
  2288. X/* draw the handicap positions on a 19 X 19 board */
  2289. X    if (g->width == 19) {
  2290. X/* first draw the corner handicap positions */
  2291. X      if (s == 60) {
  2292. X        setrect(&srect,  55, 247,  61, 253); filloval(&srect,&blackpat); }
  2293. X      if (s == 72) {
  2294. X        setrect(&srect, 247, 247, 253, 253); filloval(&srect,&blackpat); }
  2295. X      if (s == 288) {
  2296. X        setrect(&srect,  55,  55,  61,  61); filloval(&srect,&blackpat); }
  2297. X      if (s == 300) {
  2298. X        setrect(&srect, 247,  55, 253,  61); filloval(&srect,&blackpat); }
  2299. X/* now draw the other row 3 handicap positions */
  2300. X      if (s == 174) {
  2301. X        setrect(&srect,  55, 151,  61, 157); filloval(&srect,&blackpat); }
  2302. X      if (s == 294) {
  2303. X        setrect(&srect, 151,  55, 157,  61); filloval(&srect,&blackpat); }
  2304. X      if (s == 186) {
  2305. X        setrect(&srect, 247, 151, 253, 157); filloval(&srect,&blackpat); }
  2306. X      if (s == 66) {
  2307. X        setrect(&srect, 151, 247, 157, 253); filloval(&srect,&blackpat); }
  2308. X/* finally draw the center handicap position */
  2309. X      if (s == 180) {
  2310. X        setrect(&srect, 151, 151, 157, 157); filloval(&srect,&blackpat); }
  2311. X    }
  2312. X    setport(mewindow);
  2313. X  }
  2314. X}
  2315. ________This_Is_The_END________
  2316. if test `wc -l < goprocs.c` -ne 727; then
  2317.     echo 'shar: goprocs.c was damaged during transit'
  2318.   echo '      (should have been 727 bytes)'
  2319. fi
  2320. fi        ; : end of overwriting check
  2321. echo 'Extracting goprocs.h'
  2322. if test -f goprocs.h; then echo 'shar: will not overwrite goprocs.h'; else
  2323. sed 's/^X//' << '________This_Is_The_END________' > goprocs.h
  2324. X/* File goprocs.h
  2325. X   Developer:  James R. Logan Jr. (BYU), Advisor:  Dr. Lynn H. Beus (BYU)
  2326. X   email address:  loganj@byuvax.bitnet
  2327. X   (801) 378-3617
  2328. X
  2329. X   Structures required by the go program utilities.
  2330. X   This code is not machine dependent.
  2331. X*/
  2332. X
  2333. X#define firstelement 0
  2334. X#define brdsize 19
  2335. X#define maxstones 362
  2336. X#define maxarmies 362
  2337. X#define White 0
  2338. X#define Black 1
  2339. X#define Blank 2
  2340. X
  2341. Xtypedef struct {
  2342. X  int
  2343. X  color,   /* army color */
  2344. X  size,    /* army size  */
  2345. X  first,   /* first armyman's position */
  2346. X  last,    /* last armyman's position */
  2347. X  fp,      /* forward pointer to next army */
  2348. X  bp,      /* backward pointer to last army */
  2349. X  lib,     /* number of liberties, for nonblank armies only */
  2350. X  friend,  /* number of neighboring White stones, for blank armies only */
  2351. X  enemy,   /* number of enemy stones for nonblank armies, or Black stones */
  2352. X  armies,  /* number of neighboring armies */
  2353. X  rollcall;/* scratch pad variable */
  2354. X} armystruct;
  2355. X
  2356. Xtypedef struct {
  2357. X  int kospot;    /* valid ko position, or -1, result of last move */
  2358. X  long captures; /* bit 1 is capture on the west (left)
  2359. X                    bit 2 is capture on the east (right)
  2360. X                    bit 3 is capture on the south (down)
  2361. X                    bit 4 is capture on the north (up) */
  2362. X} mstatus;
  2363. X
  2364. Xtypedef struct {
  2365. X  int
  2366. X  who,      /* White for computer's level, Black for opponent */
  2367. X  avail,    /* next available army number */
  2368. X  maxstone, /* size of 1-dimensional board */
  2369. X  width,    /* width of 1-dimensional board */
  2370. X  movecount,/* number of stones played on the board */
  2371. X  deadwhite,/* number of captured white stones */
  2372. X  deadblack,/* number of captured black stones */
  2373. X  debug;    /* debug flags */
  2374. X  char
  2375. X  board[maxstones],    /* computer = White, opponent = Black */
  2376. X  rowbrd[maxstones],   /* translates 1-dimension row to 2-dimension */
  2377. X  colbrd[maxstones],   /* translates 1-dimension col to 2-dimension */
  2378. X  whitecount[maxstones],/* count of white stones in whitepats */
  2379. X  blackcount[maxstones];/* count of black stones in blackpats */
  2380. X  int
  2381. X  armymen[maxstones],  /* men of same army have same num */
  2382. X  armylnk[maxstones];  /* link to next army member */
  2383. X  long
  2384. X  whitepats[maxstones],/* bit pattern of white stones in 5 by 5 square */
  2385. X  blackpats[maxstones],/* bit pattern of black stones in 5 by 5 square */
  2386. X  neibrd[maxstones];   /* n by n bit encoded valid neighbors array */
  2387. X  mstatus movestatus;  /* ko position and capture info */
  2388. X  armystruct army[maxarmies];
  2389. X} game;
  2390. X
  2391. Xtypedef struct {
  2392. X  int
  2393. X  neis,
  2394. X  stone[4],
  2395. X  direction[4];
  2396. X        /* bit 1 is neighbor on the west (left)
  2397. X           bit 2 is capture on the east (right)
  2398. X           bit 3 is capture on the south (down)
  2399. X           bit 4 is capture on the north (up) */
  2400. X} neighbors;
  2401. ________This_Is_The_END________
  2402. if test `wc -l < goprocs.h` -ne 77; then
  2403.     echo 'shar: goprocs.h was damaged during transit'
  2404.   echo '      (should have been 77 bytes)'
  2405. fi
  2406. fi        ; : end of overwriting check
  2407. exit 0
  2408.