home *** CD-ROM | disk | FTP | other *** search
/ Giga Games 1 / Giga Games.iso / net / go / prog / standard.sh < prev    next >
Encoding:
Linux/UNIX/POSIX Shell Script  |  1993-06-20  |  77.2 KB  |  3,454 lines

  1. #! /bin/sh
  2. # This is a shell archive, meaning:
  3. # 1. Remove everything above the #! /bin/sh line.
  4. # 2. Save the resulting text in a file.
  5. # 3. Execute the file with /bin/sh (not csh) to create:
  6. #    example.go
  7. #    formspec.txt
  8. #    makefile
  9. #    readme
  10. #    sf.c
  11. #    sf.lnk
  12. #    sfread.c
  13. #    sfrecord.c
  14. #    stdform.h
  15. #    testbad.go
  16. # This archive created: Wed Nov 28 00:32:16 1990
  17. export PATH; PATH=/bin:/usr/bin:$PATH
  18. if test -f 'example.go'
  19. then
  20.     echo shar: "will not over-write existing file 'example.go'"
  21. else
  22. cat << \SHAR_EOF > 'example.go'
  23. Remark     testspec.go
  24. Remark     Three-event Standard-Format file for illustration and testing
  25.  
  26. EVENT
  27. B 1 R16
  28. W 2 D17
  29. B 3 Q3
  30. W 4 P17
  31. B 5 C4
  32. W 6 E3
  33. B 7 Q5
  34. W 8 C6
  35. B 9 D6
  36. W 10 D7
  37. B 11 E6
  38. W 12 E7
  39. B 13 E4
  40. W 14 D3
  41. B 15 C7
  42. W 16 C8
  43. B 17 B7
  44. W 18 F7
  45. B 19 B8
  46. W 20 F4
  47. B 21 F6
  48. W 22 C9
  49. B 23 G7
  50. W 24 G8
  51. B 25 H6
  52. W 26 J3
  53. B 27 E9
  54. W 28 B9
  55. B 29 F8
  56. W 30 D8
  57. B 31 G9
  58. W 32 H8
  59. B 33 H9
  60. W 34 J8
  61. B 35 J9
  62. W 36 K8
  63. B 37 D11
  64. W 38 C12
  65. B 39 C11
  66. W 40 B11
  67. B 41 B12
  68. W 42 B13
  69. B 43 D12
  70. W 44 A12
  71. PRISONER  B12
  72. B 45 C13
  73. W 46 C14
  74. B 47 B12
  75. PRISONER C12
  76. W 48 F10
  77. B 49 F9
  78. W 50 C12
  79. PRISONER  B12
  80. B 51 D13
  81. W 52 B6
  82. B 53 B5
  83. W 54 A8
  84. B 55 C5
  85. W 56 A7
  86. PRISONER  B8  #17  C7
  87. B 57 B12
  88. PRISONER  C12
  89. W 58 G5
  90.  
  91.  
  92. Event Yose Problem 7
  93. Source Page 164 of "Basic Techniques of Go"
  94. Source By Haruyama and Nagahara
  95. Source Ishi Press, Berkeley-Tokyo, 1969
  96. Black Haruyama 6-dan
  97. White Nagahara 4-dan
  98. Komi   0
  99. Boardsize 10
  100. Timelimit 30 minutes each
  101. Handicap 1
  102. Result Black wins by 1
  103. Rules Japanese
  104. Analysis The authors
  105. Recorder W. Lobb
  106. Date 8 March 1990
  107. Place Concord MA
  108. Setup w e10 f9 j9 k9 b8 f8 g8 h8 k8 b7 c6 h6 k6
  109. Setup b B9 C9 D9 E9 A8 C8 E8 J8 D7 E7 F7 G7 H7 J7 K7 D6 J6
  110. Setup w C5 G5 H5 J5 K5 B4 C4 F4 G4 a3 b3 e3 f3 a2 c2 d2 e2 b2
  111. Setup b d5 f5 d4 e4 h4 j4 k4 c3 d3 g3 j3 f2 g2 h2
  112. Com Yose Problem 7.
  113. How should Black play so as to win by one point?
  114. Endcom
  115. B 1 h9
  116. W 2 h10
  117. b 3 f10
  118. Mark #1-2
  119. com
  120. Black 1 and 3 are kiri (cut) and horikomi tesuji. The meaning of these
  121. moves will become clear in a moment.
  122. endcom
  123. w 4 g10
  124. PRISONER #3
  125. b 5 b6
  126. COM \d
  127. Black 5 is the atekomi tesuji and is worth 1 point
  128. with sente for Black.
  129. ENDCOM
  130. w 6 a6
  131. b 7 c7
  132. w 8 b5
  133. PRISONER b6
  134. b 9 f1
  135. w 10 f6
  136. b 11 E5
  137. w 12 G6
  138. b 13 E1
  139. w 14 D1
  140. b 15 D10
  141. w 16   g9
  142. Prisoner h9
  143. b 17   a9
  144. w 18   a7
  145. b 19   f10
  146. prisoner E10
  147. w 20   j2
  148. b 21   k2
  149. w 22   E10
  150. prisoner #19
  151. b 23   A5
  152. w 24   A4
  153. prisoner #23
  154. b 25   F10
  155. PRISONer E10
  156. User Print-Diagram 1 of 10
  157.    MARK All
  158.    numbase -22
  159.    partial c1 k8
  160.    show 12 28
  161.    Ko information goes here
  162. Enduser
  163. w 26   J1
  164. b 27   H1
  165. w 28   E10
  166. Prisoner #25
  167. b 29   j10
  168. w 30 k10
  169. prisoner #29
  170. b 31 f10
  171. PRISONER e10
  172. COM
  173. After Black takes ko at 31, White has no more ko threats. Black wins
  174. by 1 point, having 15 points against White's 14.
  175. ENDCOM
  176.  
  177.  
  178. EVENT    Problem 1 from Ishigure
  179. COM
  180. Adapted from page 111 of "In the Beginning"
  181. By Ikuro Ishigure, Ishi Press 1973
  182. ENDCOM
  183. BOARDSIZE 19
  184. SETUP B R16 C4 R5 P17 O5  W E17 Q3 E3 Q8 P5 P4
  185. SETUP W O6 N6 Q10  B P6 Q6 O7  W O4 N4 L3  B P8 O3 N5 M5
  186. COM Problem 1
  187. Black to play.
  188. ENDCOM
  189. B 1 Q12
  190. MARK 10@R12 8@Q13 8@R13 8@C17 8@C16 8@D15 \S@q10
  191. MARK \t@Q8 8@L5 7@P9 7@J17 7@J16 7@K16
  192. COM \D \c
  193. Black 1 is the best move and scores 10.
  194.  
  195. The focal point of the game as it now stands is the unsettled position
  196. on the right side. Black should make a pincer play either at 1 or at
  197. '10', attacking the white stones marked \T and \s while forming territory
  198. in front of his shimari.
  199.  
  200. If you chose to play one line higher, at one of the points
  201. marked 8 in the upper right, you can take credit for finding the right
  202. direction of play, but you are being too timid.
  203. ENDCOM
  204.    VAR 8
  205.    B 1 M7
  206.    COM     Score: 8
  207.    ENDCOM
  208.    W 2 R13
  209.    MARK m7
  210.    COM
  211.    Black 1, capturing two stones and tying Black's forces
  212.    together, is an important point, but White 2 makes White's
  213.    position safe, too, and robs Black of territory on the right
  214.    side.
  215.    ENDCOM
  216.       VAR
  217.       W 2 p7
  218.       MARK M7
  219.       COM
  220.       This is not good for White.
  221.       ENDCOM
  222.       USER Some user data here.
  223.       More user data.
  224.       Last line of user data.
  225.       ENDUSER
  226.       ENDVAR
  227.    ENDVAR
  228.  
  229.    VAR 8
  230.    B 1 D5
  231.    COM Score: 8
  232.    ENDCOM
  233.    W 2 M6
  234.    B 3 L5
  235.    W 4 L6
  236.    B 5 K5
  237.    W 6 L8
  238.    MARK ALL
  239.    UNMARK #6
  240.    MARK \t@L8
  241.    COM
  242.    If Black plays on the left side, 1 looks best, but then White
  243.    will play 2, 4 and \t, and be one move ahead on the right side
  244.    of where he comes out in the main sequence.
  245.    ENDCOM
  246.    ENDVAR
  247.  
  248.    VAR 7
  249.    B 1 Q9
  250.    COM Score: 7
  251.    ENDCOM
  252.    W 2 R9
  253.    B 3 P9
  254.    W 4 r13
  255.    MARK #1 r9 p9 X@r10
  256.    COM
  257.    If Black plays at 1 and 3, White will extend to 4, with
  258.    nothing to fear from Black's cutting at X.
  259.    ENDCOM
  260.    ENDVAR
  261.  
  262. W 2 M6
  263.    VAR
  264.    W 2 P9
  265.    B 3 L5
  266.    MARK p9
  267.    COM
  268.    If White answers Black 1 directly by playing, say, 2, Black
  269.    will capture at 3. White, his three stones on the right side
  270.    sandwiched between two strong black positions, faces a dreary
  271.    prospect. White cannot play this way; the fight in the main
  272.    sequence is inevitable.
  273.    ENDCOM
  274.    ENDVAR
  275. B 3 L5
  276. W 4 L6
  277. B 5 K5
  278. W 6 L8
  279. MARK all a@k6
  280. COM
  281. After Black 1, White should push out into the center with 2 and 4,
  282. then jump to 6 (or, if he prefers, keep pushing at 'a'). This starts
  283. a four-way fight between two weak black groups and two weak white ones.
  284. It will be difficult, but Black has already staked out his claim on
  285. the best ground by playing 1.
  286. ENDCOM
  287.   VAR
  288.   DIAGRAM
  289.   HIDE q12 r16 p17 e17 c4 e3 l5 k5 l6 m6
  290.   MARK 1@q8 2@o5 3@p5 4@p6 5@p4 6@q6 7@o6 8@o7 9@n6 10@p8
  291.   MARK 11@q10 12@o3 13@o4 14@n5 15@n4 16@m5 17@l3
  292.   COM
  293.   For your reference, the position in the lower right corner arose from this
  294.   pincer joseki.
  295.   ENDCOM
  296.   ENDVAR
  297. SHAR_EOF
  298. fi
  299. if test -f 'formspec.txt'
  300. then
  301.     echo shar: "will not over-write existing file 'formspec.txt'"
  302. else
  303. cat << \SHAR_EOF > 'formspec.txt'
  304. Standard Format for Go Data Files
  305.  
  306. Specification
  307. 17 March 1990
  308.  
  309. Contents
  310.  
  311.      1. Standard Format ......................... 1
  312.      2. Definitions ............................. 1
  313.      3. General Discussion ...................... 2
  314.      4. Detailed File Structure     ................ 3
  315.     4.1  Files .............................. 3
  316.     4.2  Events ............................. 3
  317.     4.3  Moves .............................. 4
  318.     4.4  Diagrams ........................... 5
  319.      5. Keywords ................................ 5
  320.     5.1  List of Keywords ................... 5
  321.     5.2  Header Keywords .................... 6
  322.     5.3  Notation for Keyword Specs ......... 7
  323.     5.4  Keyword Specifications ............. 8
  324.      6. General Error Conditions ................ 13
  325.      7. Sample Valid-Format Data ................ 13
  326.  
  327.  
  328.  
  329. 1. Standard Format
  330.    ===============
  331.  
  332. The Standard Format for Go data provides a means for storing and
  333. transferring data that represents Go games, Go problems, joseki
  334. dictionaries, diagrams, and other Go-related information, in a
  335. way that is reasonably independent of machines, operating systems
  336. and application programs.
  337.  
  338. To support the Standard fully, an application program must be
  339. able to recognize and interpret correctly all data signalled by
  340. the keywords listed and described in Section 5.
  341.  
  342. An application that only reads Standard Format files, and does
  343. not also write such files, must be able only to recognize and
  344. interpret the keywords of interest to it. An application that
  345. only writes Standard Format files can write a minimum subset of
  346. keywords, sufficient to capture the information it generates.
  347.  
  348. An application that both fully reads and fully writes Standard
  349. Format files must be able to recognize and store all data
  350. signalled by the keywords described in Section 5, and write all
  351. that data into an output file without adding to, losing, or
  352. modifying data in the file in any significant way. Not
  353. significant are white space, case outside of commentary and board
  354. marks associated with commentary, and order except where obvious
  355. or where specifically required.
  356.  
  357.  
  358. 2. Definitions
  359.    ===========
  360.  
  361.      current event  the event most recently defined in the data
  362.             file
  363.  
  364.      current move   the most recent Black or White move in the
  365.             current sequence within the current event
  366.  
  367.      event        a game, or problem, or joseki, or other
  368.             similar block of conceptually-related G0 data
  369.  
  370.      keyword        a string of valid characters with no blanks;
  371.             signals that data of some particular type
  372.             follows
  373.  
  374.      sequence        a series of consecutive moves NOT including
  375.             any variations on those moves; can be in the
  376.             main game/problem or follow a variation on
  377.             some other move; every sequence is terminated
  378.             either by an EVENT, or by an ENDVAR, or by
  379.             the end of the data file
  380.  
  381.      setup        non-indexed moves/stones including handicap
  382.             stones, problem-situation stones, and stones
  383.             associated directly only to diagrams
  384.  
  385.      SF            Standard Format for Go data
  386.  
  387.      valid        characters in the ASCII decimal range 32 to
  388.       characters    126 inclusive, plus tab (ASCII 9) and the
  389.             carriage-return-line-feed pair (ASCII 13 and
  390.             10 consecutively)
  391.  
  392.      white space    blank spaces and tabs (ASCII decimal 32 and 9
  393.             resp.)
  394.  
  395.  
  396.  
  397. 3. General Discussion
  398.    ==================
  399.  
  400. Data files in Standard Format (SF) are line-oriented, keyword-
  401. driven, and white-space-delimited. That is:
  402.  
  403.      1. The main unit of reading/writing in an SF file is the
  404.     line: a series of valid characters terminated by the
  405.     ASCII carriage-return-line-feed pair.
  406.  
  407.      2. Each line in an SF file either begins after white space
  408.     with a keyword, or is part of a block of lines set off by
  409.     the keyword pair COM/ENDCOM (commentary) or by the pair
  410.     USER/ENDUSER (user-defined data).
  411.  
  412.      3. Any pair of data fields - keywords, plus other fields
  413.     that are required to follow them or can optionally follow
  414.     them - can be separated from each other by any amount of
  415.     white space (spaces and/or tabs) but by at least one
  416.     space or tab. A keyword can have any number of spaces or
  417.     tabs before it on its file line.
  418.  
  419.  
  420. Empty lines can appear anywhere in an SF file. They have no
  421. bearing on the data in the file except within commentary blocks,
  422. wherein the application decides how to handle them.
  423.  
  424. An SF file is not required to have any data in it: a completely
  425. empty file is a valid-format file.
  426.  
  427. Valid characters in an SF file are those in the ASCII range 32 to
  428. 126 inclusive, plus the tab character (ASCII 9) and the carriage-
  429. return-line-feed pair (ASCII 13 and 10 consecutively). All other
  430. characters can be ignored by applications.
  431.  
  432. Case is irrelevant in SF files except within commentary blocks
  433. and for explicit characters that represent board marks (see the
  434. section on Notation). Outside of board marks and commentary, all
  435. of upper case, lower case, and mixed case are accepted and
  436. treated as equivalent for keywords, move locations, special-
  437. character designations, etc.
  438.  
  439. No assumptions are made in SF files about evenness or oddness for
  440. move numbers in relation to player's color. Black's moves can be
  441. even-numbered and White's can be odd-numbered, or vice-versa for
  442. both colors. No assumptions are made about alternation of play
  443. between Black and White.
  444.  
  445.  
  446.  
  447. 4. Detailed File Structure
  448.    ========================
  449.  
  450. 4.1  Files
  451.      -----
  452.  
  453. Each Standard Format (SF) file contains one or more events. An
  454. event can be a game, a problem, a joseki, a special diagram, or
  455. some other block of Go-related data. Each event occupies a
  456. distinct, contiguous block of lines in the file.
  457.  
  458. An empty SF file consists only of the default implicit event with
  459. no attached data. A file with no events specifically defined via
  460. the EVENT keyword, but with moves or other data, has an implicit
  461. first event to which the data is associated.
  462.  
  463. An SF file looks like this:
  464.  
  465.            Event 1
  466.            Event 2
  467.          .
  468.          .
  469.          .
  470.            Event n
  471.  
  472.  
  473. 4.2  Events
  474.      ------
  475.  
  476. Each event has a single, square board size between 2x2 and 19x19
  477. inclusive, with default 19x19 unless otherwise specified. Each
  478. event contains zero or more of the following (but no more than
  479. one tree of moves and diagrams):
  480.  
  481.      - remarks in the file that apply to the event and are
  482.        typically seen only by a person viewing the file directly;
  483.  
  484.      - header records such as player names and ranks, date,
  485.        source, place, handicap, komi, result, etc.;
  486.  
  487.      - unnumbered Black and White setup stones, for example
  488.        handicap stones or problem-situation stones;
  489.  
  490.      - commentary that applies to the event as a whole;
  491.  
  492.      - blocks of user-defined data that apply to the event as
  493.        a whole;
  494.  
  495.      - board marks - letters or special characters or shapes that
  496.        will be displayed on the empty board at the start of the
  497.        event, before any setup stones or moves, and only then;
  498.  
  499.      - a "tree" of numbered Black and White moves that represent
  500.        the flow of play in the event, plus any number of diagrams
  501.        interspersed with the moves; the moves and move-related
  502.        diagrams in an event follow all other data that applies to
  503.        the event as a whole.
  504.  
  505.  
  506. An event's structure in a file looks like this:
  507.  
  508.       Remarks
  509.       Event definition (EVENT keyword)
  510.       Event header data
  511.       Event commentary and marks
  512.       Event setup stones
  513.       Event user data
  514.       Tree of moves and diagrams
  515.  
  516.  
  517. The remarks if any precede the event definition in the file. The
  518. event definition line precedes all the remaining lines in the
  519. event. All header lines, commentary blocks, marks, setup stones,
  520. and blocks of user data may occur in any order among themselves,
  521. subject to those keywords' own rules, but all must precede the
  522. tree of moves and diagrams if any.
  523.  
  524.  
  525. 4.3  Moves
  526.      -----
  527.  
  528. Each move in an event is defined by a player color, a move number
  529. that is greater than zero, and the board position for the move or
  530. an indication that the move was a pass or tenuki. Each move is
  531. either a move in the main flow of play, or a variation on such a
  532. move, or a move within a sequence that follows a variation upon
  533. another move. Variations may be nested to any "depth": moves
  534. within variation sequences may have "deeper" variations on them.
  535.  
  536. A move is defined either as a setup stone (SETUP keyword) or as a
  537. regularly-played Black or White play on the board (B or W keyword
  538. respectively).
  539.  
  540. A move has associated with it zero or more of the following:
  541.  
  542.      - remarks in the file that apply to the move and are
  543.        typically seen only by a person viewing the file directly;
  544.  
  545.      - a list of the prisoners taken when this move is played;
  546.  
  547.      - commentary that applies to the move;
  548.  
  549.      - board marks - letters or special characters or shapes that
  550.        normally relate to the commentary and will be displayed on
  551.        the board when the move itself becomes displayed as the
  552.        last of the current sequence, and only then;
  553.  
  554.      - blocks of user-defined data that apply to the move.
  555.  
  556.  
  557. A move's structure in a file looks like this:
  558.  
  559.       Remarks
  560.       Move definition (SETUP or B or W keyword)
  561.       Prisoners
  562.       Marks
  563.       Commentary
  564.       User data
  565.       Variations on the move
  566.  
  567.  
  568. Remarks if any precede the move's definition. Prisoner lines,
  569. commentary blocks, marks and user data all follow the move
  570. definition line and may occur in any order among themselves.
  571. Variations on the move must follow all other move data.
  572.  
  573.  
  574. 4.4  Diagrams
  575.      --------
  576.  
  577. Each diagram occupies a specific place in the tree of moves,
  578. variations and diagrams associated with an event.
  579.  
  580. A diagram is defined by a board region to be displayed when the
  581. diagram is shown. Unless otherwise specified, the region is the
  582. same as the parent event's board size. The region can be any
  583. rectangular subarea of any board between 2x2 and 19x19 in size;
  584.  
  585. Each diagram contains zero or more of the following:
  586.  
  587.      - remarks in the file that apply to the diagram and are
  588.        typically seen only by a person viewing the file directly;
  589.  
  590.      - a list of Black and/or White setup stones that will be
  591.        displayed only when the diagram is displayed; these stones
  592.        have no bearing on the flow of play that precedes or
  593.        follows the diagram;
  594.  
  595.      - a list of stones/moves to hide when the diagram is
  596.        displayed; i.e., to remove temporarily from the display
  597.        when the diagram is shown and to restore to view when the
  598.        diagram is taken down;
  599.  
  600.      - commentary that applies to the diagram;
  601.  
  602.      - board marks - letters or special characters or shapes that
  603.        normally relate to the commentary and will be displayed on
  604.        the board when the diagram itself becomes displayed, and
  605.        only then; these marks can apply to regular moves in the
  606.        sequence and/or to the diagram's setup stones;
  607.  
  608.      - blocks of user-defined data that apply to the diagram.
  609.  
  610.  
  611. A diagram's structure in a file looks like this:
  612.  
  613.       Remarks
  614.       Diagram definition (DIAGRAM keyword)
  615.       Setup stones
  616.       Hide moves/stones
  617.       Marks
  618.       Commentary
  619.       User data
  620.  
  621.  
  622. Remarks if any precede the diagram's definition. Setup lines,
  623. hide-stone lines, commentary blocks, marks and user data all
  624. follow the diagram definition line and may occur in any order
  625. among themselves.
  626.  
  627.  
  628.  
  629. 5. Keywords
  630.    ========
  631.  
  632. 5.1  List of Keywords
  633.      ----------------
  634.  
  635.   Event keyword
  636.  
  637.      EVENT        begin next event: game, problem, joseki, etc.
  638.  
  639.  
  640.   Header keywords per EVENT
  641.  
  642.      ANALYSIS        person(s) who provided the commentary
  643.      BLACK        Black player's name, rank etc.
  644.      DATE        date(s) on which game was played
  645.      HANDICAP        handicap count (informational only)
  646.      KOMI        komi
  647.      PLACE        location(s) where game was played
  648.      RECORDER        person(s) who recorded the data
  649.      RESULT        result of the game
  650.      RULES        Japanese (the default) or Chinese
  651.      SOURCE        source for data: book, journal, etc.
  652.      TIMELIMIT        time limits for one or both players
  653.      WHITE        White player's name, rank etc.
  654.  
  655.  
  656.   Data keywords per EVENT
  657.  
  658.      B            next Black move(s)
  659.      BOARDSIZE        size of square board for event
  660.      COM        begin a commentary block
  661.      DIAGRAM        begin definition of a diagram
  662.      ENDCOM        end a commentary block
  663.      ENDUSER        end a user-defined block
  664.      ENDVAR        end a variation sequence
  665.      HIDE        stones/moves to hide in a diagram
  666.      MARK        board markers related to commentary
  667.      PRISONER        prisoners taken by current move
  668.      REMARK        file-writer's remark on event, move, diagram
  669.      SETUP        setup B/W stones for an event or diagram
  670.      UNMARK        remove some previously-defined MARKs
  671.      USER        begin a user-defined block
  672.      VAR        begin a variation sequence
  673.      W            next White move(s)
  674.  
  675.  
  676. 5.2  Header Keywords
  677.      ---------------
  678.  
  679. Header keywords represent informational data about the current
  680. event. Each header line consists of a keyword optionally followed
  681. by free-form text that represents the header data. This text may
  682. contain any amount of white space.
  683.  
  684. Each header keyword can be repeated within an event. In the case
  685. of generally textual data such as source, place, analysis, etc.,
  686. the total data is the sum from all the repeated lines. In the
  687. case of normally once-only data such as Black player, komi, etc.,
  688. the last line encountered should be taken as the correct data. An
  689. application may treat multiple occurences of once-only data lines
  690. as an error condition but is not required to do so.
  691.  
  692. A note on handicaps: Exact board locations for a given number of
  693. handicap stones are usually ambiguous. For this reason, handicap
  694. stones are placed in specific locations using the SETUP keyword.
  695. HANDICAP keyword data is informational and does not necessarily
  696. have to match the actual setup.
  697.  
  698. Below are valid examples of header keywords.
  699.  
  700.      Analysis Jim Kerwin, professional 1-dan
  701.      ANALYSIS    Kato 9 Dan
  702.      BLACK   Honinbo Shusaku
  703.      black     Alan Chen (9 years old)
  704.      Black
  705.      Date 8 March 1990
  706.      Date      3-21-48
  707.      date November 21-24, 1847
  708.      DATE  Dec 9, 1938 and Mar 3-4, 1939
  709.      Date    June 3 and 7, 1958
  710.      HANDICAP 0
  711.      Handicap 7
  712.      komi 5
  713.      Komi  3 1/2
  714.      KOMI 4.5
  715.      Place
  716.      PLACE  Kyoto (April) and Tokyo (May)
  717.      place    US Go Congress, Denver
  718.      Recorder Ishi Press
  719.      RECORDER    Phil Straus (playing Black)
  720.      RESULT White wins by resignation
  721.      result  Black by 3
  722.      Result Black resigns at move 186
  723.      RULES Japanese
  724.      Rules CHINESE
  725.      Rules
  726.      SOURCE  "Invincible: The Games of Shusaku"
  727.      SOURCE  John Powers, Kiseido Publishing Co., Tokyo 1982
  728.      Timelimit    1 hour
  729.      WHITE James Redmond 5-dan (made 6-dan after this game)
  730.  
  731.  
  732. 5.3. Notation for Keyword Specifications
  733.      -----------------------------------
  734.  
  735.      <>           nonrepeatable required data field with no
  736.            embedded white space
  737.  
  738.      <>*       repeatable required data field, each occurence of
  739.            which contains no embedded white space
  740.  
  741.      []           nonrepeatable optional data field that may have
  742.            embedded white space if so indicated
  743.  
  744.      []*       repeatable optional data field, each occurence of
  745.            which may contain white space if so indicated
  746.  
  747.      n           positive integer
  748.  
  749.      n-n       sequence of positive integers increasing from the
  750.            first number n to second, inclusive: e.g., 21-29
  751.  
  752.      loc       board location of form cn, where the character c,
  753.            in the (case-insensitive) set a b c ... not
  754.            including i, represents the column starting from
  755.            the left, and the number n represents the row
  756.            starting from the bottom; e.g. A3 r17 F6
  757.  
  758.      cc           one or two characters in the standard ASCII range
  759.            33 decimal to 126 decimal inclusive; the blank
  760.            character ASCII 32 is not included; if the first
  761.            character is \ then c, d, s or t as the second
  762.            character indicates a special character (see next
  763.            notation)
  764.  
  765.      \C           special marker character, under DOS outside the
  766.            ASCII range 32-126; case-insensitive; one of
  767.  
  768.             \d     diamond    ASCII 4
  769.             \t     triangle    ASCII 30
  770.             \c     check mark    ASCII 251
  771.             \s     square        ASCII 9
  772.  
  773.  
  774.      |           "or"; precedes next in a series of alternate
  775.            entries in a data field; e.g. <#n | loc>
  776.  
  777.  
  778.  
  779. 5.4  Specifications for Non-Header Keywords
  780.      --------------------------------------
  781.  
  782. _________________________________________________________________
  783.  
  784. B <n> <loc | PASS>
  785.  
  786.      Next move by Black.
  787.  
  788.      The move number <n> must be greater than 0.
  789.  
  790.      Consecutive B lines in a file are not required to have
  791.      consecutive move numbers, though applications may choose to
  792.      treat nonconsecutive numbers as an error condition.
  793.  
  794.      Examples
  795.       B 17 q3
  796.       B 21 pass
  797. _________________________________________________________________
  798.  
  799. BOARDSIZE <n>
  800.  
  801.      Size of current event's square board, between 2 and 19
  802.      inclusive. If no boardsize is indicated for an event, 19x19
  803.      is assumed.
  804.  
  805.      Examples
  806.       BOARDSIZE 2
  807.       BOARDSIZE 9
  808.       BOARDSIZE 13
  809. _________________________________________________________________
  810.  
  811. COM [title data]
  812.  
  813.      Begin block of commentary on current event, move or diagram.
  814.  
  815.      If there is no current move or previously-defined setup
  816.      stones in the current event, apply commentary to the event
  817.      as a whole.
  818.  
  819.      All other data after the COM keyword on the line is treated
  820.      as "title" data for the comment that follows. Title data may
  821.      contain white space.
  822.  
  823.      The next keyword line in an SF file after a COM line must be
  824.      an ENDCOM line. COM blocks cannot be nested. All lines
  825.      between a COM and an ENDCOM are treated as commentary text.
  826.  
  827.      Examples
  828.  
  829.       COM
  830.       COM  JK's notes \c + !
  831.       COM The famous "ear-reddening" move
  832. _________________________________________________________________
  833.  
  834. ENDCOM
  835.  
  836.      End block of commentary.
  837.  
  838.      A line starting with ENDCOM must follow each COM line. All
  839.      lines between the COM and ENDCOM are treated as commentary
  840.      text.
  841.  
  842.      Example
  843.  
  844.       ENDCOM
  845. _________________________________________________________________
  846.  
  847. DIAGRAM [<nXn> | <loc loc>]
  848.  
  849.      Begin definition of a diagram and specify its board region.
  850.  
  851.      The region of a diagram is any rectangular subarea of any
  852.      board of size 2x2 through 19x19. If no region is indicated,
  853.      a diagram occupies the full BOARDSIZE of the current event.
  854.      A full-board diagram of a certain size is given by nXn where
  855.      n is in the range 2 to 19.
  856.  
  857.      If a diagram's size is different from the current event's
  858.      BOARDSIZE, it is up to the application to decide whether or
  859.      not to clear the board's display, or to put up a separate
  860.      window with the diagram, or whatever.
  861.  
  862.      Diagram title and commentary data is contained in COM/ENDCOM
  863.      blocks as with regular B and W moves.
  864.  
  865.      See also the HIDE keyword discussion.
  866.  
  867.      Examples
  868.       DIAGRAM       (use current event boardsize)
  869.       DIAGRAM 19x19       (full 19x19 board)
  870.       DIAGRAM a19 t1   (full 19x19 board)
  871.       DIAGRAM 9X9       (full 9x9 board)
  872.       DIAGRAM a1 j9       (9x9 lower-left corner of board)
  873.       DIAGRAM b5 j12
  874.       DIAGRAM b12 j5   (same region as previous example)
  875. _________________________________________________________________
  876.  
  877. ENDUSER
  878.  
  879.      End a block of user-defined data.
  880.  
  881.      Must be preceded in the file by a USER line.
  882.  
  883.      Example
  884.  
  885.       ENDUSER
  886. _________________________________________________________________
  887.  
  888. ENDVAR
  889.  
  890.      End a variation sequence.
  891.  
  892.      Must be preceded in the file by a VAR line.
  893.  
  894.      Example
  895.  
  896.       ENDVAR
  897. _________________________________________________________________
  898.  
  899. EVENT [event title]
  900.  
  901.      Start the next game/problem/joseki/diagram/etc.
  902.  
  903.      An EVENT line terminates the current sequence if any and
  904.      terminates the current event if any.
  905.  
  906.      All other data on the line after the EVENT keyword is
  907.      treated as title commentary on the event. Such title data
  908.      may contain white space.
  909.  
  910.      Examples
  911.  
  912.       EVENT Problem 6
  913.       EVENT Joseki for 3-4 point attacked from 5-4 point
  914.       EVENT Honinbo 1989 Final
  915. _________________________________________________________________
  916.  
  917. HIDE [loc | #n | #n-n]*
  918.  
  919.      For a DIAGRAM, temporarily remove from display the indicated
  920.      stones, which are specified either by board location or by
  921.      move numbers in order to support removal of regularly played
  922.      moves as well as handicap/setup stones.
  923.  
  924.      See the syntax discussion under MARK.
  925.  
  926.      Examples
  927.       HIDE #21
  928.       HIDE #3-9 q9 R11 #17
  929. _________________________________________________________________
  930.  
  931. MARK [ALL | loc | #n | #n-n | \C@loc | \C@#n | \C@#n-n |
  932.                    cc@loc | cc@#n | cc@#n-n]*
  933.  
  934.  
  935.      Board marks (highlights) attached to the current event,
  936.      move or diagram. If no move or diagram exists in the current
  937.      event then the marks apply to the empty board.
  938.      Both kinds of indicator for move locations - move number or
  939.      stone location - are supported because handicap/setup stones
  940.      can be marked and because move numbers can be ambiguous
  941.      within a variation sequence: does the number apply to the
  942.      move within the variation, or to a move with the same number
  943.      in a higher-level variation or in the main game?
  944.  
  945.      Board marks are instructions to a program to display or
  946.      undisplay special letters or shapes on the board, usually in
  947.      conjunction with commentary. The sequence of mark keylines
  948.      is important: a read-write application must preserve the
  949.      sequence in which MARKs and UNMARKs are defined. For
  950.      example, the below lines in the order presented cause moves
  951.      1-5, 11, and 21-33 to have their move numbers displayed:
  952.  
  953.            MARK #1-33
  954.            UNMARK #6-20
  955.            MARK #11
  956.  
  957.      A different order would result in a different display.
  958.  
  959.  
  960.   Data fields:
  961.  
  962.      ALL
  963.       show move numbers on all visible numbered stones (does
  964.           not show numbers on setup or handicap stones)
  965.       example  MARK All
  966.  
  967.      loc
  968.       show move number on stone at this location
  969.       example  MARK Q8
  970.  
  971.      #n
  972.       show number on most recent move with this number
  973.       example  MARK #21 #233
  974.  
  975.      #n-n
  976.       show move numbers on a range of moves
  977.       example  MARK #21-28    #221-233
  978.  
  979.      \C@#n
  980.       special character on specified move number
  981.       example  MARK \s@#221 \t@#18
  982.  
  983.      \C@#n-n
  984.       special character on all of specified range of moves
  985.       example  MARK \t@#21-30
  986.  
  987.      \C@loc
  988.       special character at board location; can be at a stone
  989.       example  MARK \t@Q5 \S@R1 \T@m3
  990.  
  991.      cc@loc
  992.       one or two characters at a location; case is retained;
  993.          can be at a stone
  994.       example  MARK a@R3 B0@o9 +@A6 X@r7
  995.  
  996.      cc@#n
  997.       place one or two characters on a numbered move
  998.       example  MARK     aa@#33     X@#102
  999.  
  1000.      cc@#n-n
  1001.  
  1002.       place one or two characters on a range of moves
  1003.       example  MARK     x@#81-90  ..@#320-323
  1004. _________________________________________________________________
  1005.  
  1006. PRISONER [#n | loc]*
  1007.  
  1008.      Prisoner(s) taken by current move.
  1009.  
  1010.      Both forms of move/stone indicator are supported - move
  1011.      index and board location - because handicap and setup stones
  1012.      can be captured.
  1013.  
  1014.      Examples
  1015.       PRISONER #22 Q9 F3 #28
  1016.       PRISONER #25 #3 #11 #33
  1017. _________________________________________________________________
  1018.  
  1019. REMARK [free-form text]
  1020.  
  1021.      A remark in a file is normally meant for view only by a
  1022.      person who is directly reading or editing the file.
  1023.  
  1024.      Each remark applies to the next EVENT, SETUP, B or W move,
  1025.      or DIAGRAM in the file. Each of these keyword types can have
  1026.      any number of remarks preceding it in a file.
  1027.  
  1028.      Examples
  1029.       REMARK file test.go
  1030.       REMARK Jack - are the next 3 lines OK?
  1031.       REMARK Diagram 3 of 9
  1032. _________________________________________________________________
  1033.  
  1034. SETUP [<B | W> [loc]*]*
  1035.  
  1036.      Place unnumbered setup stones for an event or diagram,
  1037.      including handicap stones for a game. In general, all setup
  1038.      stones in an event or diagram are considered one generalized
  1039.      "move": they are all displayed or undisplayed as a unit in a
  1040.      single step.
  1041.  
  1042.      An event or diagram can have any number of SETUP lines.
  1043.      Either B or W must precede any list of setup stones to
  1044.      indicate their color. Multiple sets of different-colored
  1045.      setup stones can follow the SETUP keyword on a line.
  1046.  
  1047.      Only the first SETUP line in a series of setup lines can
  1048.      have an associated REMARK. Only the last of a series of
  1049.      SETUP lines can have MARKs, UNMARKs, commentary or user-
  1050.      defined data.
  1051.  
  1052.      Examples
  1053.       SETUP B d4 q4 d16 q16
  1054.       SETUP W a6 B a7 R11 J9 W b5 B M4
  1055. _________________________________________________________________
  1056.  
  1057. UNMARK [ALL | loc | #n | #n-n]*
  1058.  
  1059.  
  1060.      Board marks attached to the current event, move or diagram.
  1061.      If no move or diagram exists in the current event then the
  1062.      unmarks apply to the empty board. An UNMARK removes a MARK
  1063.      previously specified. A series of MARK and UNMARK keywords
  1064.      can be used to build Boolean operations on the marks to be
  1065.      displayed.
  1066.  
  1067.      See the discussion under MARK for details.
  1068.  
  1069.      Examples
  1070.       UNMARK All
  1071.       UNMARK Q8 #21 r3 #39-43
  1072.  
  1073. _________________________________________________________________
  1074.  
  1075. USER [user-defined data of any format whatsoever]
  1076.  
  1077.      Begin a block of user-defined data.
  1078.  
  1079.      This line, and all lines after it and up to and including
  1080.      the next ENDUSER line, define a block of user data.
  1081.  
  1082.      USER/ENDUSER blocks may not be nested
  1083.  
  1084.      Examples
  1085.       USER
  1086.       USER    Ishi inventory
  1087.       USER    Printed diagram #4 of 8
  1088. _________________________________________________________________
  1089.  
  1090. VAR [cc]
  1091.  
  1092.      Begin a variation sequence.
  1093.  
  1094.      The variation in question applies to the current move, which
  1095.      must be a B or W keyword-prefixed move.
  1096.  
  1097.      The optional one- or two-character marker may be placed by a
  1098.      display application at the variation's board location as a
  1099.      visual cue, or the character(s) may represent sequencing
  1100.      numbers or letters with no special display significance.
  1101.  
  1102.      Example
  1103.       VAR
  1104.       VAR b
  1105.       VAR 10
  1106. _________________________________________________________________
  1107.  
  1108. W <n> <loc | PASS>
  1109.  
  1110.      Next move by White.
  1111.  
  1112.      The move number <n> must be greater than 0.
  1113.  
  1114.      See the discussion under keyword B for more details.
  1115.  
  1116.      Examples
  1117.       W 38 R19
  1118.       w  99     pass
  1119.  
  1120.  
  1121.  
  1122. 6. General Error Conditions
  1123.    ========================
  1124.  
  1125. A keyword line that is missing required data is in error.
  1126.  
  1127. Duplicate or out-of-sequence move numbers within a sequence
  1128. usually implies an error condition. For example, "B 12 Q3"
  1129. followed by "B 11 R5" or "B 12 R8" probably implies an error. In
  1130. certain cases an application may choose to accept out-of-sequence
  1131. moves. In all cases, however, duplicate moves indicate errors.
  1132.  
  1133. In general, a missing move index implies an error condition. For
  1134. example, if Black 19 is followed by B 21, a White move is
  1135. probably missing. This may be an acceptable condition for certain
  1136. application; it is up to the application to decide.
  1137.  
  1138. Certain keyword fields may have, after their required and/or
  1139. optional data, further data on the line. Most applications will
  1140. ignore such extra data. It is NOT necessarily an error condition
  1141. for extra data to be present. For example, the ENDVAR keyword has
  1142. no further required or optional data; a line such as "ENDVAR back
  1143. to main game" should not generate an error, but a program that
  1144. reads a file with such a line is not expected to write the extra
  1145. data to an output file. If the specification for a keyword would
  1146. cause extra data to be parsed, and if that data has incorrect
  1147. format, than an error condition would however be indicated. For
  1148. example, the line "B 22 Q3 R7" should be seen as an error.
  1149.  
  1150.  
  1151.  
  1152. 7. Sample Valid-Format Data
  1153.    ========================
  1154.  
  1155. The below data is valid-format with respect to the Standard.
  1156. Nearly all of the keywords are represented in this data, and most
  1157. data-field variations for the keywords are represented.
  1158.  
  1159. Remark       testspec.go
  1160. Remark       Three-event SF file for illustration and testing
  1161. event
  1162. B 1 R16
  1163. W 2 D17
  1164. B 3 Q3
  1165. W 4 P17
  1166. B 5 C4
  1167. W 6 E3
  1168. B 7 Q5
  1169. W 8 C6
  1170. B 9 D6
  1171. W 10 D7
  1172. B 11 E6
  1173. W 12 E7
  1174. B 13 E4
  1175. W 14 D3
  1176. B 15 C7
  1177. W 16 C8
  1178. B 17 B7
  1179. W 18 F7
  1180. B 19 B8
  1181. W 20 F4
  1182. B 21 F6
  1183. W 22 C9
  1184. B 23 G7
  1185. W 24 G8
  1186. B 25 H6
  1187. W 26 J3
  1188. B 27 E9
  1189. W 28 B9
  1190. B 29 F8
  1191. W 30 D8
  1192. B 31 G9
  1193. W 32 H8
  1194. B 33 H9
  1195. W 34 J8
  1196. B 35 J9
  1197. W 36 K8
  1198. B 37 D11
  1199. W 38 C12
  1200. B 39 C11
  1201. W 40 B11
  1202. B 41 B12
  1203. W 42 B13
  1204. B 43 D12
  1205. W 44 A12
  1206. PRISONER  B12
  1207. B 45 C13
  1208. W 46 C14
  1209. B 47 B12
  1210. PRISONER C12
  1211. W 48 F10
  1212. B 49 F9
  1213. W 50 C12
  1214. PRISONER  B12
  1215. B 51 D13
  1216. W 52 B6
  1217. B 53 B5
  1218. W 54 A8
  1219. B 55 C5
  1220. W 56 A7
  1221. PRISONER  B8  #17  C7
  1222. B 57 B12
  1223. PRISONER  C12
  1224. W 58 G5
  1225.  
  1226.  
  1227. Event Yose Problem 7
  1228. Source Page 164 of "Basic Techniques of Go"
  1229. Source By Haruyama and Nagahara
  1230. Source Ishi Press, Berkeley-Tokyo, 1969
  1231. Black Haruyama 6-dan
  1232. White Nagahara 4-dan
  1233. Komi   0
  1234. Boardsize 10
  1235. Timelimit 30 minutes each
  1236. Handicap 1
  1237. Result Black wins by 1
  1238. Rules Japanese
  1239. Analysis The authors
  1240. Recorder W. Lobb
  1241. Date 8 March 1990
  1242. Place Concord MA
  1243. Setup w e10 f9 j9 k9 b8 f8 g8 h8 k8 b7 c6 h6 k6
  1244. Setup b B9 C9 D9 E9 A8 C8 E8 J8 D7 E7 F7 G7 H7 J7 K7 D6 J6
  1245. Setup w C5 G5 H5 J5 K5 B4 C4 F4 G4 a3 b3 e3 f3 a2 c2 d2 e2 b2
  1246. Setup b d5 f5 d4 e4 h4 j4 k4 c3 d3 g3 j3 f2 g2 h2
  1247. Com Yose Problem 7.
  1248. How should Black play so as to win by one point?
  1249. Endcom
  1250. B 1 h9
  1251. W 2 h10
  1252. b 3 f10
  1253. Mark #1-2
  1254. com
  1255. Black 1 and 3 are kiri (cut) and horikomi tesuji. The meaning of
  1256. these moves will become clear in a moment.
  1257. endcom
  1258. w 4 g10
  1259. PRISONER #3
  1260. b 5 b6
  1261. COM \d
  1262. Black 5 is the atekomi tesuji and is worth 1 point with
  1263. sente for Black.
  1264. ENDCOM
  1265. w 6 a6
  1266. b 7 c7
  1267. w 8 b5
  1268. PRISONER b6
  1269. b 9 f1
  1270. w 10 f6
  1271. b 11 E5
  1272. w 12 G6
  1273. b 13 E1
  1274. w 14 D1
  1275. b 15 D10
  1276. w 16   g9
  1277. Prisoner h9
  1278. b 17   a9
  1279. w 18   a7
  1280. b 19   f10
  1281. prisoner E10
  1282. w 20   j2
  1283. b 21   k2
  1284. w 22   E10
  1285. prisoner #19
  1286. b 23   A5
  1287. w 24   A4
  1288. prisoner #23
  1289. b 25   F10
  1290. PRISONer E10
  1291. User Print-Diagram 1 of 10
  1292.    MARK All
  1293.    numbase -22
  1294.    partial c1 k8
  1295.    show 12 28
  1296.    Ko information goes here
  1297. Enduser
  1298. w 26   J1
  1299. b 27   H1
  1300. w 28   E10
  1301. Prisoner #25
  1302. b 29   j10
  1303. w 30 k10
  1304. prisoner #29
  1305. b 31 f10
  1306. PRISONER e10
  1307. COM
  1308. After Black takes ko at 31, White has no more ko threats. Black
  1309. wins by 1 point, having 15 points against White's 14.
  1310. ENDCOM
  1311.  
  1312.  
  1313. EVENT      Problem 1 from Ishigure
  1314. COM
  1315. Adapted from page 111 of "In the Beginning"
  1316. By Ikuro Ishigure, Ishi Press 1973
  1317. ENDCOM
  1318. BOARDSIZE 19
  1319. SETUP B R16 C4 R5 P17 O5  W E17 Q3 E3 Q8 P5 P4
  1320. SETUP W O6 N6 Q10  B P6 Q6 O7  W O4 N4 L3  B P8 O3 N5 M5
  1321. COM Problem 1
  1322. Black to play.
  1323. ENDCOM
  1324. B 1 Q12
  1325. MARK 10@R12 8@Q13 8@R13 8@C17 8@C16 8@D15 \S@q10
  1326. MARK \t@Q8 8@L5 7@P9 7@J17 7@J16 7@K16
  1327. COM \D \c
  1328. Black 1 is the best move and scores 10.
  1329.  
  1330. The focal point of the game as it now stands is the unsettled
  1331. position on the right side. Black should make a pincer play
  1332. either at 1 or at '10', attacking the white stones marked \T and
  1333. \s while forming territory in front of his shimari.
  1334.  
  1335. If you chose to play one line higher, at one of the points
  1336. marked 8 in the upper right, you can take credit for finding the
  1337. right direction of play, but you are being too timid.
  1338. ENDCOM
  1339.    VAR 8
  1340.    B 1 M7
  1341.    COM       Score: 8
  1342.    ENDCOM
  1343.    W 2 R13
  1344.    MARK m7
  1345.    COM
  1346.    Black 1, capturing two stones and tying Black's forces
  1347.    together, is an important point, but White 2 makes White's
  1348.    position safe, too, and robs Black of territory on the right
  1349.    side.
  1350.    ENDCOM
  1351.       VAR
  1352.       W 2 p7
  1353.       MARK M7
  1354.       COM
  1355.       This is not good for White.
  1356.       ENDCOM
  1357.       USER Some user data here.
  1358.       More user data.
  1359.       Last line of user data.
  1360.       ENDUSER
  1361.       ENDVAR
  1362.    ENDVAR
  1363.  
  1364.    VAR 8
  1365.    B 1 D5
  1366.    COM Score: 8
  1367.    ENDCOM
  1368.    W 2 M6
  1369.    B 3 L5
  1370.    W 4 L6
  1371.    B 5 K5
  1372.    W 6 L8
  1373.    MARK ALL
  1374.    UNMARK #6
  1375.    MARK \t@L8
  1376.    COM
  1377.    If Black plays on the left side, 1 looks best, but then White
  1378.    will play 2, 4 and \t, and be one move ahead on the right side
  1379.    of where he comes out in the main sequence.
  1380.    ENDCOM
  1381.    ENDVAR
  1382.  
  1383.    VAR 7
  1384.    B 1 Q9
  1385.    COM Score: 7
  1386.    ENDCOM
  1387.    W 2 R9
  1388.    B 3 P9
  1389.    W 4 r13
  1390.    MARK #1 r9 p9 X@r10
  1391.    COM
  1392.    If Black plays at 1 and 3, White will extend to 4, with
  1393.    nothing to fear from Black's cutting at X.
  1394.    ENDCOM
  1395.    ENDVAR
  1396.  
  1397. W 2 M6
  1398.    VAR
  1399.    W 2 P9
  1400.    B 3 L5
  1401.    MARK p9
  1402.    COM
  1403.    If White answers Black 1 directly by playing, say, 2, Black
  1404.    will capture at 3. White, his three stones on the right side
  1405.    sandwiched between two strong black positions, faces a dreary
  1406.    prospect. White cannot play this way; the fight in the main
  1407.    sequence is inevitable.
  1408.    ENDCOM
  1409.    ENDVAR
  1410. B 3 L5
  1411. W 4 L6
  1412. B 5 K5
  1413. W 6 L8
  1414. MARK all a@k6
  1415. COM
  1416. After Black 1, White should push out into the center with 2 and
  1417. 4, then jump to 6 (or, if he prefers, keep pushing at 'a'). This
  1418. starts a four-way fight between two weak black groups and two
  1419. weak white ones. It will be difficult, but Black has already
  1420. staked out his claim on the best ground by playing 1.
  1421. ENDCOM
  1422.   VAR
  1423.   DIAGRAM
  1424.   HIDE q12 r16 p17 e17 c4 e3 l5 k5 l6 m6
  1425.   MARK 1@q8 2@o5 3@p5 4@p6 5@p4 6@q6 7@o6 8@o7 9@n6 10@p8
  1426.   MARK 11@q10 12@o3 13@o4 14@n5 15@n4 16@m5 17@l3
  1427.   COM
  1428.   For your reference, the position in the lower right
  1429.   corner arose from this pincer joseki.
  1430.   ENDCOM
  1431.   ENDVAR
  1432. SHAR_EOF
  1433. fi
  1434. if test -f 'makefile'
  1435. then
  1436.     echo shar: "will not over-write existing file 'makefile'"
  1437. else
  1438. cat << \SHAR_EOF > 'makefile'
  1439. #
  1440. #   filename: makefile
  1441. #
  1442. #   Turbo C 2.0 make file for SF - Standard Format parser
  1443.  
  1444. OBJS = sf.obj sfread.obj sfrecord.obj
  1445.  
  1446. CC=tcc
  1447. OPTS=-c -mm -O.
  1448.  
  1449. #
  1450. #   RULES
  1451. #
  1452.  
  1453. .c.obj:
  1454.     $(CC) $(OPTS) $*.c
  1455.  
  1456. .asm.obj:
  1457.     tasm $*,$*,,/MX;
  1458.  
  1459. #
  1460. #   DEPENDENCIES
  1461. #
  1462.  
  1463. sf.exe: $(OBJS)
  1464.     tlink /e /c @sf.lnk
  1465. SHAR_EOF
  1466. fi
  1467. if test -f 'readme'
  1468. then
  1469.     echo shar: "will not over-write existing file 'readme'"
  1470. else
  1471. cat << \SHAR_EOF > 'readme'
  1472. file: readme
  1473. date: 31 May  90
  1474.  
  1475.  
  1476. Parser SF for Standard-Format Go Files
  1477.  
  1478.  
  1479. Enclosed is a program, SF, that reads Standard Format files and
  1480. echoes to the screen their input plus any errors found. If SF is
  1481. run without arguments it explains itself and exits.
  1482.  
  1483. Complete source code for the program is included. This code
  1484. builds under Turbo C 2.0 and runs under DOS 3.0+. Graphics are
  1485. not required or used.
  1486.  
  1487. SF as a file-reader conforms in nearly all respects to the Format
  1488. spec dated 17 March 1990. Both GoScribe 2.0 and this program
  1489. deviate from that spec in the following significant ways:
  1490.  
  1491.      1. EVENT title data is pushed into a commentary block
  1492.         attached to the event.
  1493.  
  1494.      2. Commentary title data is pushed into the body of the
  1495.         commentary and loses its identity as a distinct title.
  1496.  
  1497.      3. All data associated with header keywords - Analysis,
  1498.         Date, Recorder, Handicap, etc. - is pushed into a
  1499.         commentary block associated with the current event.
  1500.  
  1501.      4. Diagrams are full-board only. I.e., diagrams that occupy
  1502.         only a region of the board are not supported.
  1503.  
  1504.  
  1505. In addition, GoScribe 2.0 does not read or remember "variation
  1506. marks": optional 1- or 2-character strings associated with each
  1507. variation move.
  1508. SHAR_EOF
  1509. fi
  1510. if test -f 'sf.c'
  1511. then
  1512.     echo shar: "will not over-write existing file 'sf.c'"
  1513. else
  1514. cat << \SHAR_EOF > 'sf.c'
  1515. /********  Copyright (C) 1990    Oxbow Research Inc.  ************************
  1516.  
  1517.     Filename: sf.c
  1518.  
  1519.     Main module for standalone reading of Standard Format Go files
  1520.     Includes general utility routines, both Go-related and not
  1521.  
  1522.     Development begun:    8 March 1990        Wayne A. Lobb
  1523.  
  1524. ****************************************************************************/
  1525.  
  1526. #include <stdio.h>
  1527. #include <stdlib.h>
  1528. #include <string.h>
  1529. #include <ctype.h>
  1530.  
  1531. #include "stdform.h"
  1532.  
  1533. /*
  1534.  *  sfread.c
  1535.  */
  1536. extern long int fileline;
  1537. extern int movenum;
  1538.  
  1539. static char *read_err_strings[] =
  1540.     {
  1541.     "Not enough memory",
  1542.     "Unable to use data",
  1543.     "Unusable board size",
  1544.     "Size changed after move",
  1545.     "Unusable board location",
  1546.     "Out of sequence?",
  1547.     "Unopened comment",
  1548.     "Unclosed comment",
  1549.     "Comment too long",
  1550.     "Unopened user data",
  1551.     "Unclosed user data",
  1552.     "User data too long",
  1553.     "Unopened variation",
  1554.     "Unclosed variation",
  1555.     "Incomplete move data",
  1556.     "Unusable move number",
  1557.     "Unusable move range",
  1558.     "Unusable prisoner",
  1559.     "Unusable variation",
  1560.     "Unusable board mark",
  1561.     "Setup after B/W move",
  1562.     "Setup comment deleted",
  1563.     "Setup un/mark deleted",
  1564.     };
  1565.  
  1566.  
  1567.  
  1568. /**************************************************************************\
  1569.  
  1570.               EXECUTION STARTS HERE
  1571.  
  1572. \**************************************************************************/
  1573.  
  1574. main (argc, argv)
  1575. int argc;
  1576. char *argv[];        /* program name and game-file name */
  1577. {
  1578.     FILE *fopen();
  1579.     FILE *infile;
  1580.  
  1581.     if ( argc < 2 )
  1582.     {
  1583.     printf("\nParser for Standard-Format Go Data Files\n");
  1584.     printf(     "Echoes input data and errors to screen\n\n");
  1585.     printf(     "Usage:    sf  <game-file name>\n");
  1586.     printf(     "Example:  sf  example.go\n\n");
  1587.     exit(0);
  1588.     }
  1589.  
  1590.     if ( (infile = fopen(argv[1], "r")) == (FILE *)NULL )
  1591.     {
  1592.     printf("\nUnable to find or to open file %s\n", argv[1]);
  1593.     exit(-1);
  1594.     }
  1595.  
  1596.     printf("\n");
  1597.     read_std_file(infile);
  1598.  
  1599.     fclose(infile);
  1600.     exit(0);
  1601. }
  1602.  
  1603.  
  1604.  
  1605. /*
  1606.  *    ECHO_READ_ERROR
  1607.  *
  1608.  */
  1609. echo_read_error (index, str)
  1610. int index;            /* in read_err_strings[] */
  1611. char *str;            /* supplementary string */
  1612. {
  1613.     int ch;
  1614.  
  1615.     printf("\n*** Line %-6ld  move %-3d ", fileline, movenum);
  1616.  
  1617.     if ( index < 0  ||    index >= MAXREADERRS )
  1618.     printf(" Unknown read error %s\n", str);
  1619.     else
  1620.     printf("%s %s\n", read_err_strings[index], str);
  1621.  
  1622.     printf("*** Press Y or y to continue, any other key to quit.\n");
  1623.  
  1624.     while ( !kbhit() )
  1625.     ;
  1626.  
  1627.     if ( (ch = getch()) == 0 )
  1628.     ch = BIT7 | getch();
  1629.  
  1630.     if ( tolower(ch) == 'y' )
  1631.     return(S_OK);
  1632.  
  1633.     return(S_QUIT);
  1634. }
  1635.  
  1636.  
  1637. /*--------------------------------------------------------------------------*\
  1638.               General Go-related utilities
  1639. \*--------------------------------------------------------------------------*/
  1640.  
  1641. static char *column_letters = "abcdefghjklmnopqrst";
  1642.  
  1643. /*
  1644.  *    COLUMN_FROM_INDEX
  1645.  *
  1646.  */
  1647. column_from_index (boardsize, index, cptr)
  1648. int boardsize;
  1649. int index;            /* 1...boardsize */
  1650. int *cptr;            /* column letter */
  1651. {
  1652.     *cptr = NODATA;
  1653.  
  1654.     if ( index < 1  ||    index > boardsize )
  1655.     return(FALSE);
  1656.  
  1657.     *cptr = (int)(column_letters[index-1]);
  1658.     return(TRUE);
  1659. }
  1660.  
  1661.  
  1662. /*
  1663.  *    INDEX_FROM_COLUMN
  1664.  *
  1665.  */
  1666. index_from_column (ch, index)
  1667. int ch;                /* column letter */
  1668. int *index;            /* 1...eventsize */
  1669. {
  1670.     int i, count, lch;
  1671.  
  1672.     *index = NODATA;
  1673.     lch = tolower(ch);
  1674.     count = strlen(column_letters);
  1675.  
  1676.     for ( i = 0; i < count; ++i )
  1677.     {
  1678.     if ( lch == column_letters[i] )
  1679.         {
  1680.         *index = i+1;
  1681.         return(TRUE);
  1682.         }
  1683.     }
  1684.  
  1685.     return(FALSE);
  1686. }
  1687.  
  1688.  
  1689.  
  1690. /*--------------------------------------------------------------------------*\
  1691.               General non-Go-related utilities
  1692. \*--------------------------------------------------------------------------*/
  1693.  
  1694. /*
  1695.  *    SHAVE_STRING
  1696.  *
  1697.  */
  1698. shave_string (str)
  1699. char str[];
  1700. {
  1701.     int i, j, len;
  1702.  
  1703.     len = strlen(str);
  1704.  
  1705.     i = 0;
  1706.     while ( i < len  &&     isspace(str[i]) )
  1707.     ++i;
  1708.  
  1709.     j = 0;
  1710.     while ( i < len )
  1711.     str[j++] = str[i++];
  1712.  
  1713.     while ( j < len )
  1714.     str[j++] = '\0';
  1715.  
  1716.     i = strlen(str) - 1;
  1717.     while ( i >= 0  &&    isspace(str[i]) )
  1718.     str[i--] = '\0';
  1719.  
  1720. }
  1721.  
  1722.  
  1723. /*
  1724.  *    NEXT_WORD
  1725.  *
  1726.  *    Returns number of characters placed in 'wordbuf'.
  1727.  *    Passed buffer is assumed to be null-terminated.
  1728.  *    Passed 'wordbuf' is assumed to have room for null terminator at end.
  1729.  */
  1730. next_word (buf, offset, wordbuf, maxword)
  1731. char *buf;
  1732. int *offset;        /* starting offset in buf */
  1733. char wordbuf[];        /* filled by this routine */
  1734. int maxword;        /* max chars allowable in worbuf[] */
  1735. {
  1736.     int i;
  1737.  
  1738.     memset(wordbuf, 0, maxword+1);
  1739.  
  1740.     /*
  1741.      *    skip white space
  1742.      */
  1743.     while ( isspace(buf[*offset]) )
  1744.     ++(*offset);
  1745.  
  1746.     /*
  1747.      *    advance to end or to next white char, copying up to allowable chars
  1748.      */
  1749.     i = 0;
  1750.     while ( buf[*offset] != '\0'  &&  !isspace(buf[*offset]) )
  1751.     {
  1752.     if ( i < maxword )
  1753.         wordbuf[i++] = buf[*offset];
  1754.  
  1755.     ++(*offset);
  1756.     }
  1757.  
  1758.     return(i);
  1759. }
  1760.  
  1761. SHAR_EOF
  1762. fi
  1763. if test -f 'sf.lnk'
  1764. then
  1765.     echo shar: "will not over-write existing file 'sf.lnk'"
  1766. else
  1767. cat << \SHAR_EOF > 'sf.lnk'
  1768. d:\tc2\lib\c0m sf sfread sfrecord
  1769. sf
  1770. sf
  1771. d:\tc2\lib\mathm d:\tc2\lib\cm
  1772. SHAR_EOF
  1773. fi
  1774. if test -f 'sfread.c'
  1775. then
  1776.     echo shar: "will not over-write existing file 'sfread.c'"
  1777. else
  1778. cat << \SHAR_EOF > 'sfread.c'
  1779. /********  Copyright (C) 1990    Oxbow Research Inc.  ************************
  1780.  
  1781.     Filename: sfread.c
  1782.  
  1783.     Reads Standard Format Go files (to the extent that GoScribe 2.0 does)
  1784.  
  1785.     Development begun:    8 March 1990        Wayne A. Lobb
  1786.  
  1787.     Builds under Turbo C 2.0 and runs under DOS 3.0+ without graphics.
  1788.  
  1789.     No warranties are made or implied. No claims are made about
  1790.     beauty, rigor or portability of this code. It does work, however.
  1791.  
  1792.     Motivated by and based on work done in late 1989 by Bob High of AGA.
  1793.  
  1794.     May be used for any and all purposes whatever EXCEPT sale.
  1795.  
  1796. ****************************************************************************/
  1797.  
  1798. #include <stdio.h>
  1799. #include <stdlib.h>
  1800. #include <string.h>
  1801. #include <ctype.h>
  1802.  
  1803. #include "stdform.h"
  1804.  
  1805. /*------------------------------------------------------------------------*\
  1806.          Global constants and structures
  1807. \*------------------------------------------------------------------------*/
  1808. int echo = FALSE;    /* TRUE = echo each input line to screen */
  1809.  
  1810. long int fileline;
  1811. int movenum;        /* move number in current event, for echoing errors */
  1812.  
  1813.  
  1814. /*------------------------------------------------------------------------*\
  1815.         Standard Format keywords and their handlers
  1816. \*------------------------------------------------------------------------*/
  1817. static int read_remark();
  1818. static int read_event(), read_boardsize(), record_head_data(), read_setup();
  1819. static int read_bmove(), read_wmove(), read_prisoners();
  1820. static int read_mark(), read_unmark(), read_com(), read_endcom();
  1821. static int read_user(), read_enduser();
  1822. static int read_var(), read_endvar();
  1823. static int read_diagram(), read_hide();
  1824.  
  1825. static FILE_KEY keys[MAXFILEKEY] =
  1826.     {
  1827.     { "Analysis",    record_head_data    },
  1828.     { "B",        read_bmove        },
  1829.     { "Black",    record_head_data    },
  1830.     { "BOARDSIZE",    read_boardsize        },
  1831.     { "COM",    read_com        },
  1832.     { "Date",    record_head_data    },
  1833.     { "DIAGRAM",    read_diagram        },
  1834.     { "ENDCOM",    read_endcom        },
  1835.     { "ENDUSER",    read_enduser        },
  1836.     { "ENDVAR",    read_endvar        },
  1837.     { "EVENT",    read_event        },
  1838.     { "Handicap",    record_head_data    },
  1839.     { "HIDE",    read_hide        },
  1840.     { "Komi",    record_head_data    },
  1841.     { "MARK",    read_mark        },
  1842.     { "Place",    record_head_data    },
  1843.     { "PRISONER",    read_prisoners        },
  1844.     { "Recorder",    record_head_data    },
  1845.     { "REMARK",    read_remark        },
  1846.     { "Result",    record_head_data    },
  1847.     { "Rules",    record_head_data    },
  1848.     { "SETUP",    read_setup        },
  1849.     { "Source",    record_head_data    },
  1850.     { "Timelimit",    record_head_data    },
  1851.     { "UNMARK",    read_unmark        },
  1852.     { "USER",    read_user        },
  1853.     { "VAR",    read_var        },
  1854.     { "W",        read_wmove        },
  1855.     { "White",    record_head_data    }
  1856.     };
  1857.  
  1858.  
  1859. /*------------------------------------------------------------------------*\
  1860.           Local constants and structures
  1861. \*------------------------------------------------------------------------*/
  1862.  
  1863. static char *empty_string = "";
  1864.  
  1865. /*
  1866.  *    buffers
  1867.  */
  1868. static char remarkbuf[MAXREMLEN];  /* remark(s) prefixed to current move */
  1869. static char cbuf[MAXCOMLEN];       /* commentary postfixed to current move */
  1870. static char userbuf[MAXUSERLEN];   /* user-data postfixed to current move */
  1871.  
  1872. /*
  1873.  *    events
  1874.  */
  1875. static int eventcount;        /* number of distinct EVENTs so far in the file */
  1876. static int eventsize;        /* current event's board size, default MAXBOARD */
  1877. static int movecount;        /* moves in current event NOT counting setups */
  1878. static int setupcount;        /* setup stones in current event */
  1879.  
  1880. /*
  1881.  *    moves etc. within events
  1882.  */
  1883. static int indiagram;        /* TRUE if current data applies to a diagram */
  1884. static int incomment;        /* TRUE if currently within commentary block */
  1885. static int comment_status;  /* S_OK or S_ERR, latter if overflow found */
  1886. static int inuser;        /* TRUE if currently within user block */
  1887. static int user_status;        /* S_OK or S_ERR, latter if overflow found */
  1888. static int read_vardepth;   /* stacked depth of variations */
  1889.  
  1890.  
  1891. /**************************************************************************\
  1892.  
  1893.               EXECUTION STARTS HERE
  1894.  
  1895. \**************************************************************************/
  1896.  
  1897.  
  1898. /*
  1899.  *    READ_STD_FILE
  1900.  *
  1901.  *    Read Standard-Format game file
  1902.  */
  1903. read_std_file (infile)
  1904. FILE *infile;
  1905. {
  1906.     char *fgets();
  1907.     char linebuf[MAXLINELEN];
  1908.  
  1909.     init_reading(infile);
  1910.     memset(linebuf, 0, sizeof(linebuf));
  1911.  
  1912.     while ( fgets(linebuf, MAXLINELEN, infile) != (char *)NULL )
  1913.     {
  1914.     ++fileline;
  1915.  
  1916.     if ( parse_file_line(linebuf) == S_QUIT )
  1917.         return(S_ERR);
  1918.  
  1919.     memset(linebuf, 0, sizeof(linebuf));
  1920.     }
  1921.  
  1922.     if ( incomment )
  1923.     echo_read_error(RE_COM_UNCLOSED, empty_string);
  1924.  
  1925.     if ( inuser )
  1926.     echo_read_error(RE_USER_UNCLOSED, empty_string);
  1927.  
  1928.     if ( read_vardepth > 0 )
  1929.     echo_read_error(RE_VAR_UNCLOSED, empty_string);
  1930.  
  1931.     return( record_reset_movetext() );
  1932. }
  1933.  
  1934.  
  1935. /*
  1936.  *    parse_file_line
  1937.  *
  1938.  */
  1939. static parse_file_line (buf)
  1940. char *buf;
  1941. {
  1942.     int i, offset, parsed, status;
  1943.     char nextword[MAXLINELEN];
  1944.  
  1945.     shave_string(buf);
  1946.  
  1947.     /*
  1948.      *    get keyword
  1949.      */
  1950.     offset = 0;
  1951.     next_word(buf, &offset, nextword, MAXLINELEN-1);
  1952.  
  1953.     /*
  1954.      *    add a line to current move's commentary?
  1955.      */
  1956.     if ( incomment  &&    strcmpi(nextword, keys[K_ENDCOM].keyword) != 0 )
  1957.     return( add_comment_line(buf) );
  1958.  
  1959.     /*
  1960.      *    add a line to current move's user-defined data?
  1961.      */
  1962.     if ( inuser     &&  strcmpi(nextword, keys[K_ENDUSER].keyword) != 0 )
  1963.     return( add_user_line(buf) );
  1964.  
  1965.     /*
  1966.      *    parse some other nonempty line
  1967.      */
  1968.     status = S_OK;
  1969.     parsed = FALSE;
  1970.  
  1971.     if ( strlen(nextword) > 0 )
  1972.     {
  1973.     for ( i = 0; !parsed  &&  i < MAXFILEKEY; ++i )
  1974.         {
  1975.         if ( keys[i].handler != NULL  &&
  1976.                 strcmpi(nextword, keys[i].keyword) == 0 )
  1977.         {
  1978.         parsed = TRUE;
  1979.         status = (*keys[i].handler)(i, buf+offset);
  1980.         }
  1981.         }
  1982.  
  1983.     if ( parsed )
  1984.         return(status);
  1985.     else
  1986.         return( echo_read_error(RE_UNPARSED, buf) );
  1987.     }
  1988.  
  1989.     return(S_OK);
  1990. }
  1991.  
  1992.  
  1993. /*
  1994.  *    init_reading
  1995.  *
  1996.  */
  1997. static init_reading (infile)
  1998. FILE *infile;
  1999. {
  2000.     movenum = 0;
  2001.     movecount = 0;
  2002.     fileline = 0L;
  2003.     eventcount = 0;
  2004.     setupcount = 0;
  2005.  
  2006.     inuser = FALSE;
  2007.     incomment = FALSE;
  2008.     indiagram = FALSE;
  2009.     read_vardepth = 0;
  2010.     eventsize = MAXBOARD;
  2011.  
  2012.     fseek(infile, 0L, SEEK_SET);
  2013.     clear_buffers();
  2014. }
  2015.  
  2016.  
  2017. /*
  2018.  *    clear_buffers
  2019.  *
  2020.  */
  2021. static clear_buffers ()
  2022. {
  2023.     memset(cbuf, 0, sizeof(cbuf));
  2024.     memset(userbuf, 0, sizeof(userbuf));
  2025.     memset(remarkbuf, 0, sizeof(remarkbuf));
  2026. }
  2027.  
  2028.  
  2029.  
  2030. /*------------------------------------------------------------------------*\
  2031.         Keyword handler routines in alphabetical order
  2032. \*------------------------------------------------------------------------*/
  2033.  
  2034. /*
  2035.  *    read_bmove
  2036.  *
  2037.  */
  2038. static read_bmove (keyindex, buf)
  2039. int keyindex;
  2040. char *buf;
  2041. {
  2042.     int col, row, index, offset;
  2043.     char nextword[MAXLINELEN];
  2044.  
  2045.     if ( echo )
  2046.     printf("%s %s\n", keys[keyindex].keyword, buf);
  2047.  
  2048.     indiagram = FALSE;
  2049.  
  2050.     if ( record_reset_movetext() == S_QUIT )
  2051.     return(S_QUIT);
  2052.  
  2053.     /*
  2054.      *    get move number
  2055.      */
  2056.     offset = 0;
  2057.     if ( next_word(buf, &offset, nextword, MAXLINELEN-1) == 0 )
  2058.     return( echo_read_error(RE_PARTIALMOVE, empty_string) );
  2059.  
  2060.     if ( (index = atoi(nextword)) < 1 )
  2061.     return( echo_read_error(RE_MOVENUMBER, nextword) );
  2062.  
  2063.     movenum = index;
  2064.  
  2065.     /*
  2066.      *    get board location
  2067.      */
  2068.     if ( next_word(buf, &offset, nextword, MAXLINELEN-1) == 0 )
  2069.     return( echo_read_error(RE_PARTIALMOVE, empty_string) );
  2070.  
  2071.     col = row = 0;
  2072.     if ( strcmpi(nextword, "Pass") != 0     &&
  2073.                 strcmpi(nextword, "Tenuki") != 0 )
  2074.     {
  2075.     if ( !decode_location(eventsize, nextword, &col, &row) )
  2076.         return( echo_read_error(RE_LOCATION, nextword) );
  2077.     }
  2078.  
  2079.     /*
  2080.      *    record move
  2081.      */
  2082.     ++movecount;
  2083.     return( record_move(indiagram, BLACKPC, index, col, row) );
  2084. }
  2085.  
  2086.  
  2087. /*
  2088.  *    read_boardsize
  2089.  *
  2090.  */
  2091. static read_boardsize (keyindex, buf)
  2092. int keyindex;
  2093. char *buf;
  2094. {
  2095.     int size;
  2096.  
  2097.     if ( echo )
  2098.     printf("%s %s\n", keys[keyindex].keyword, buf);
  2099.  
  2100.     indiagram = FALSE;
  2101.  
  2102.     if ( (size = atoi(buf)) > MAXBOARD    ||  size < MINBOARD )
  2103.     return( echo_read_error(RE_BOARDSIZE, buf) );
  2104.  
  2105.     if ( size != eventsize )
  2106.     {
  2107.     if ( setupcount > 0  ||     movecount > 0 )
  2108.         return( echo_read_error(RE_SIZE_TWICE, buf) );
  2109.  
  2110.     eventsize = size;
  2111.     }
  2112.  
  2113.     return( record_boardsize(eventsize) );
  2114. }
  2115.  
  2116.  
  2117. /*
  2118.  *    read_com
  2119.  *
  2120.  */
  2121. static read_com (keyindex, buf)
  2122. int keyindex;
  2123. char *buf;
  2124. {
  2125.     if ( echo )
  2126.     printf("%s %s\n", keys[keyindex].keyword, buf);
  2127.  
  2128.     if ( incomment )
  2129.     return( echo_read_error(RE_COM_UNCLOSED, empty_string) );
  2130.  
  2131.     incomment = TRUE;
  2132.     comment_status = S_OK;
  2133.  
  2134.     shave_string(buf);
  2135.  
  2136.     if ( strlen(buf) > 0 )
  2137.     {
  2138.     strcat(buf, "\n\n");
  2139.     return( add_comment_line(buf) );
  2140.     }
  2141.  
  2142.     return(S_OK);
  2143. }
  2144.  
  2145.  
  2146. /*
  2147.  *    read_diagram
  2148.  *
  2149.  */
  2150. static read_diagram (keyindex, buf)
  2151. int keyindex;
  2152. char *buf;
  2153. {
  2154.     if ( echo )
  2155.     printf("%s %s\n", keys[keyindex].keyword, buf);
  2156.  
  2157.     indiagram = TRUE;
  2158.  
  2159.     if ( record_reset_movetext() == S_QUIT )
  2160.     return(S_QUIT);
  2161.  
  2162.     ++movecount;
  2163.  
  2164.     return( record_move(indiagram, BLACKPC, (-1), 0, 0) );
  2165. }
  2166.  
  2167.  
  2168. /*
  2169.  *    read_endcom
  2170.  *
  2171.  */
  2172. static read_endcom (keyindex, buf)
  2173. int keyindex;
  2174. char *buf;
  2175. {
  2176.     if ( echo )
  2177.     printf("%s %s\n", keys[keyindex].keyword, buf);
  2178.  
  2179.     if ( !incomment )
  2180.     return( echo_read_error(RE_COM_UNOPENED, empty_string) );
  2181.  
  2182.     incomment = FALSE;
  2183.     comment_status = S_OK;
  2184.  
  2185.     return(S_OK);
  2186. }
  2187.  
  2188.  
  2189. /*
  2190.  *    read_enduser
  2191.  *
  2192.  */
  2193. static read_enduser (keyindex, buf)
  2194. int keyindex;
  2195. char *buf;
  2196. {
  2197.     if ( echo )
  2198.     printf("%s %s\n", keys[keyindex].keyword, buf);
  2199.  
  2200.     if ( !inuser )
  2201.     return( echo_read_error(RE_USER_UNOPENED, empty_string) );
  2202.  
  2203.     inuser = FALSE;
  2204.     user_status = S_OK;
  2205.  
  2206.     return(S_OK);
  2207. }
  2208.  
  2209.  
  2210. /*
  2211.  *    read_endvar
  2212.  *
  2213.  */
  2214. static read_endvar (keyindex, buf)
  2215. int keyindex;
  2216. char *buf;
  2217. {
  2218.     if ( echo )
  2219.     printf("%s %s\n", keys[keyindex].keyword, buf);
  2220.  
  2221.     indiagram = FALSE;
  2222.  
  2223.     if ( record_reset_movetext() == S_QUIT )
  2224.     return(S_QUIT);
  2225.  
  2226.     if ( movecount < 1 )
  2227.     {
  2228.     if ( echo_read_error(RE_VAR_NOMOVE, empty_string) == S_QUIT )
  2229.         return(S_QUIT);
  2230.     }
  2231.  
  2232.     if ( read_vardepth < 1 )
  2233.     return( echo_read_error(RE_VAR_UNOPENED, empty_string) );
  2234.  
  2235.     --read_vardepth;
  2236.     return( record_endvar() );
  2237. }
  2238.  
  2239.  
  2240. /*
  2241.  *    read_event
  2242.  *
  2243.  */
  2244. static read_event (keyindex, buf)
  2245. int keyindex;
  2246. char *buf;
  2247. {
  2248.     if ( echo )
  2249.     printf("%s %s\n", keys[keyindex].keyword, buf);
  2250.  
  2251.     indiagram = FALSE;
  2252.  
  2253.     if ( record_reset_movetext() == S_QUIT )
  2254.     return(S_QUIT);
  2255.  
  2256.     if ( movecount > 0     &&  eventcount == 0 )
  2257.     eventcount = 2;
  2258.     else
  2259.     ++eventcount;
  2260.  
  2261.     movenum = 0;
  2262.     movecount = 0;
  2263.     setupcount = 0;
  2264.     eventsize = MAXBOARD;
  2265.  
  2266.     shave_string(buf);
  2267.  
  2268.     if ( strlen(buf) > 0 )
  2269.     {
  2270.     strcat(buf, "\n\n");
  2271.     add_comment_line(buf);
  2272.     }
  2273.  
  2274.     return( record_event() );
  2275. }
  2276.  
  2277.  
  2278.  
  2279. /*
  2280.  *    read_hide
  2281.  *
  2282.  */
  2283. static read_hide (keyindex, buf)
  2284. int keyindex;
  2285. char *buf;
  2286. {
  2287.     int col, row, offset;
  2288.     char nextword[MAXLINELEN];
  2289.  
  2290.     if ( echo )
  2291.     printf("%s %s\n", keys[keyindex].keyword, buf);
  2292.  
  2293.     if ( !indiagram )
  2294.     return( echo_read_error(RE_MARK, keys[keyindex].keyword) );
  2295.  
  2296.     offset = 0;
  2297.  
  2298.     while ( next_word(buf, &offset, nextword, MAXLINELEN-1) > 0 )
  2299.     {
  2300.     if ( decode_location(eventsize, nextword, &col, &row) )
  2301.         {
  2302.         if ( record_hide(col, row) == S_QUIT )
  2303.          return(S_QUIT);
  2304.         }
  2305.     }
  2306.  
  2307.     return(S_OK);
  2308. }
  2309.  
  2310.  
  2311. /*
  2312.  *    read_mark
  2313.  *
  2314.  */
  2315. static read_mark (keyindex, buf)
  2316. int keyindex;
  2317. char *buf;
  2318. {
  2319.     char *strrchr();
  2320.  
  2321.     int i, j, from, to, col, row, offset, atoffset;
  2322.     char nextword[MAXLINELEN], parseword[MAXLINELEN], letters[MAXLINELEN];
  2323.  
  2324.     if ( echo )
  2325.     printf("%s %s\n", keys[keyindex].keyword, buf);
  2326.  
  2327.     /*
  2328.      *    formats for marks:
  2329.      *        ALL            show all move numbers
  2330.      *        <location>        move number at location:    q8 A5
  2331.      *        #<number>        move number            #211
  2332.      *        #<num>-<num>    range of move numbers        #31-42
  2333.      *        <cc>@<loc>        1 or 2 letters at loc        a@r14 10@d17
  2334.      *                (special chars: \t \c \d \s)
  2335.      *        <cc>@#<num>        1 or 2 chars on move        zz@#59
  2336.      *        <cc>@#<num>-<num>    1 or 2 chars on move range  x@#3-7 21@#9-12
  2337.      */
  2338.  
  2339.     offset = 0;
  2340.  
  2341.     while ( next_word(buf, &offset, nextword, MAXLINELEN-1) > 0 )
  2342.     {
  2343.     memset(letters, 0, sizeof(letters));
  2344.  
  2345.     if ( strcmpi(nextword, "all") == 0 )
  2346.         {
  2347.         if ( record_mark(TRUE, 0, 0, letters, 0, 0) == S_QUIT )
  2348.         return(S_QUIT);
  2349.         }
  2350.     else
  2351.         {
  2352.         atoffset = (-1);
  2353.         row = col = from = to = NODATA;
  2354.  
  2355.         j = strlen(nextword);
  2356.  
  2357.         for ( i = j-1; i >= 0; --i )
  2358.         {
  2359.         if ( nextword[i] == '@' )
  2360.             {
  2361.             atoffset = i;
  2362.             strncpy(letters, nextword, i);
  2363.             break;
  2364.             }
  2365.         }
  2366.  
  2367.         if ( atoffset >= 0 )
  2368.         strcpy(parseword, nextword + atoffset + 1);
  2369.         else
  2370.         strcpy(parseword, nextword);
  2371.  
  2372.         if ( strlen(letters) > 2 )
  2373.         {
  2374.         if ( echo_read_error(RE_MARK, nextword) == S_QUIT )
  2375.             return(S_QUIT);
  2376.         }
  2377.         else if ( decode_location(eventsize, parseword, &col, &row) )
  2378.         {
  2379.         if ( record_mark(FALSE, 0, 0, letters, col, row) == S_QUIT )
  2380.             return(S_QUIT);
  2381.         }
  2382.         else if ( decode_move_range(parseword, &from, &to) )
  2383.         {
  2384.         if ( record_mark(FALSE, from, to, letters, 0, 0) == S_QUIT )
  2385.             return(S_QUIT);
  2386.         }
  2387.         else if ( echo_read_error(RE_MARK, nextword) == S_QUIT )
  2388.         return(S_QUIT);
  2389.         }
  2390.     }
  2391.  
  2392.     return(S_OK);
  2393. }
  2394.  
  2395.  
  2396. /*
  2397.  *    read_prisoners
  2398.  *
  2399.  */
  2400. static read_prisoners (keyindex, buf)
  2401. int keyindex;
  2402. char *buf;
  2403. {
  2404.     int col, row, from, to, offset;
  2405.     char nextword[MAXLINELEN];
  2406.  
  2407.     if ( echo )
  2408.     printf("%s %s\n", keys[keyindex].keyword, buf);
  2409.  
  2410.     if ( movecount < 1    ||  indiagram )
  2411.     return( echo_read_error(RE_PRISONER, buf) );
  2412.  
  2413.     /*
  2414.      *    formats for prisoner records:
  2415.      *        <location>        capture stone at location:        q8 A5
  2416.      *        #<number>        capture numbered move        #211 #31
  2417.      */
  2418.  
  2419.     offset = 0;
  2420.  
  2421.     while ( next_word(buf, &offset, nextword, MAXLINELEN-1) > 0 )
  2422.     {
  2423.     from = to = row = col = 0;
  2424.  
  2425.     if ( decode_location(eventsize, nextword, &col, &row) )
  2426.         {
  2427.         if ( record_prisoner(0, col, row) == S_QUIT )
  2428.         return(S_QUIT);
  2429.         }
  2430.     else if ( decode_move_range(nextword, &from, &to) )
  2431.         {
  2432.         if ( from != to )
  2433.         {
  2434.         if ( echo_read_error(RE_MOVERANGE, nextword) == S_QUIT )
  2435.             return(S_QUIT);
  2436.         }
  2437.         else
  2438.         {
  2439.         if ( record_prisoner(from, 0, 0) == S_QUIT )
  2440.             return(S_QUIT);
  2441.         }
  2442.         }
  2443.  
  2444.     else if ( echo_read_error(RE_PRISONER, nextword) == S_QUIT )
  2445.         return(S_QUIT);
  2446.     }
  2447.  
  2448.     return(S_OK);
  2449. }
  2450.  
  2451.  
  2452. /*
  2453.  *    read_remark
  2454.  *
  2455.  */
  2456. static read_remark (keyindex, buf)
  2457. int keyindex;
  2458. char *buf;
  2459. {
  2460.     if ( echo )
  2461.     printf("%s %s\n", keys[keyindex].keyword, buf);
  2462.  
  2463.     shave_string(buf);
  2464.  
  2465.     if ( strlen(buf) == 0 )
  2466.     return(S_OK);
  2467.  
  2468.     if ( strlen(remarkbuf) + strlen(buf) > MAXREMLEN-1 )
  2469.     return(S_OK);
  2470.  
  2471.     strcat(remarkbuf, buf);
  2472.     strcat(remarkbuf, "\n");
  2473.     return(S_OK);
  2474. }
  2475.  
  2476.  
  2477. /*
  2478.  *    read_setup
  2479.  *
  2480.  */
  2481. static read_setup (keyindex, buf)
  2482. int keyindex;
  2483. char *buf;
  2484. {
  2485.     int col, row, color, newcolor, offset;
  2486.     char nextword[MAXLINELEN];
  2487.  
  2488.     if ( echo )
  2489.     printf("%s %s\n", keys[keyindex].keyword, buf);
  2490.  
  2491.     if ( record_reset_movetext() == S_QUIT )
  2492.     return(S_QUIT);
  2493.  
  2494.     if ( movecount > 0    &&  !indiagram )
  2495.     return( echo_read_error(RE_SETUP_LATE, buf) );
  2496.  
  2497.     color = NODATA;
  2498.     newcolor = NODATA;
  2499.  
  2500.     /*
  2501.      *    each data field must be one of <blackmove>, <whitemove> or <location>
  2502.      */
  2503.     offset = 0;
  2504.  
  2505.     while ( next_word(buf, &offset, nextword, MAXLINELEN-1) > 0 )
  2506.     {
  2507.     if ( decode_color(nextword, &newcolor) )
  2508.         {
  2509.         color = newcolor;
  2510.         }
  2511.     else
  2512.         {
  2513.         if ( !decode_location(eventsize, nextword, &col, &row) )
  2514.         {
  2515.         if ( echo_read_error(RE_LOCATION, nextword) == S_QUIT )
  2516.             return(S_QUIT);
  2517.         }
  2518.         else if ( color == NODATA )
  2519.         {
  2520.         if ( echo_read_error(RE_PARTIALMOVE, empty_string) == S_QUIT )
  2521.             return(S_QUIT);
  2522.         }
  2523.         else
  2524.         {
  2525.         if ( record_move(indiagram, color, 0, col, row) == S_QUIT )
  2526.             return(S_QUIT);
  2527.  
  2528.         ++setupcount;
  2529.         }
  2530.         }
  2531.     }
  2532.  
  2533.     return(S_OK);
  2534. }
  2535.  
  2536.  
  2537. /*
  2538.  *    read_unmark
  2539.  *
  2540.  */
  2541. static read_unmark (keyindex, buf)
  2542. int keyindex;
  2543. char *buf;
  2544. {
  2545.     int from, to, col, row, offset;
  2546.     char nextword[MAXLINELEN];
  2547.  
  2548.     if ( echo )
  2549.     printf("%s %s\n", keys[keyindex].keyword, buf);
  2550.  
  2551.     /*
  2552.      *    formats for unmarks:
  2553.      *        ALL            hide all marks
  2554.      *        <location>        hide mark at location:        q8 A5
  2555.      *        #<number>        hide mark on move        #211
  2556.      *        #<num>-<num>    hide on range of moves        #31-42
  2557.      */
  2558.  
  2559.     offset = 0;
  2560.  
  2561.     while ( next_word(buf, &offset, nextword, MAXLINELEN-1) > 0 )
  2562.     {
  2563.     if ( strcmpi(nextword, "all") == 0 )
  2564.         {
  2565.         if ( record_unmark(TRUE, 0, 0, 0, 0) == S_QUIT )
  2566.         return(S_QUIT);
  2567.         }
  2568.     else
  2569.         {
  2570.         row = col = from = to = 0;
  2571.  
  2572.         if ( decode_location(eventsize, nextword, &col, &row) )
  2573.         {
  2574.         if ( record_unmark(FALSE, 0, 0, col, row) == S_QUIT )
  2575.             return(S_QUIT);
  2576.         }
  2577.         else if ( decode_move_range(nextword, &from, &to) )
  2578.         {
  2579.         if ( record_unmark(FALSE, from, to, 0, 0) == S_QUIT )
  2580.             return(S_QUIT);
  2581.         }
  2582.         else if ( echo_read_error(RE_MARK, nextword) == S_QUIT )
  2583.         return(S_QUIT);
  2584.         }
  2585.     }
  2586.  
  2587.     return(S_OK);
  2588. }
  2589.  
  2590.  
  2591. /*
  2592.  *    read_user
  2593.  *
  2594.  */
  2595. static read_user (keyindex, buf)
  2596. int keyindex;
  2597. char *buf;
  2598. {
  2599.     if ( echo )
  2600.     printf("%s %s\n", keys[keyindex].keyword, buf);
  2601.  
  2602.     if ( inuser )
  2603.     return( echo_read_error(RE_USER_UNCLOSED, empty_string) );
  2604.  
  2605.     inuser = TRUE;
  2606.     user_status = S_OK;
  2607.  
  2608.     shave_string(buf);
  2609.     return( add_user_line(buf) );
  2610. }
  2611.  
  2612.  
  2613. /*
  2614.  *    read_var
  2615.  *
  2616.  */
  2617. static read_var (keyindex, buf)
  2618. int keyindex;
  2619. char *buf;        /* optional variation 1- or 2-letter mark */
  2620. {
  2621.     if ( echo )
  2622.     printf("%s %s\n", keys[keyindex].keyword, buf);
  2623.  
  2624.     indiagram = FALSE;
  2625.  
  2626.     if ( record_reset_movetext() == S_QUIT )
  2627.     return(S_QUIT);
  2628.  
  2629.     if ( movecount < 1 )
  2630.     return( echo_read_error(RE_VAR_NOMOVE, empty_string) );
  2631.  
  2632.     ++read_vardepth;
  2633.     return( record_var(buf) );
  2634. }
  2635.  
  2636.  
  2637. /*
  2638.  *    read_wmove
  2639.  *
  2640.  */
  2641. static read_wmove (keyindex, buf)
  2642. int keyindex;
  2643. char *buf;
  2644. {
  2645.     int col, row, index, offset;
  2646.     char nextword[MAXLINELEN];
  2647.  
  2648.     if ( echo )
  2649.     printf("%s %s\n", keys[keyindex].keyword, buf);
  2650.  
  2651.     indiagram = FALSE;
  2652.  
  2653.     if ( record_reset_movetext() == S_QUIT )
  2654.     return(S_QUIT);
  2655.  
  2656.     /*
  2657.      *    get move number
  2658.      */
  2659.     offset = 0;
  2660.     if ( next_word(buf, &offset, nextword, MAXLINELEN-1) == 0 )
  2661.     return( echo_read_error(RE_PARTIALMOVE, empty_string) );
  2662.  
  2663.     if ( (index = atoi(nextword)) < 1 )
  2664.     return( echo_read_error(RE_MOVENUMBER, nextword) );
  2665.  
  2666.     movenum = index;
  2667.  
  2668.     /*
  2669.      *    get board location
  2670.      */
  2671.     if ( next_word(buf, &offset, nextword, MAXLINELEN-1) == 0 )
  2672.     return( echo_read_error(RE_PARTIALMOVE, empty_string) );
  2673.  
  2674.     col = row = 0;
  2675.     if ( strcmpi(nextword, "Pass") != 0     &&
  2676.                 strcmpi(nextword, "Tenuki") != 0 )
  2677.     {
  2678.     if ( !decode_location(eventsize, nextword, &col, &row) )
  2679.         return( echo_read_error(RE_LOCATION, nextword) );
  2680.     }
  2681.  
  2682.     ++movecount;
  2683.     return( record_move(indiagram, WHITEPC, index, col, row) );
  2684. }
  2685.  
  2686.  
  2687. /*
  2688.  *    record_head_data
  2689.  *
  2690.  */
  2691. static record_head_data (keyindex, buf)
  2692. int keyindex;
  2693. char *buf;
  2694. {
  2695.     char fulldata[MAXLINELEN];
  2696.  
  2697.     if ( echo )
  2698.     printf("%s %s\n", keys[keyindex].keyword, buf);
  2699.  
  2700.     shave_string(buf);
  2701.  
  2702.     if ( strlen(buf) == 0 )
  2703.     return(S_OK);
  2704.  
  2705.     memset(fulldata, 0, sizeof(fulldata));
  2706.     sprintf(fulldata, "%s: ", keys[keyindex].keyword);
  2707.     strcat(fulldata, buf);
  2708.     strcat(fulldata, "\n\n");
  2709.     return( add_comment_line(fulldata) );
  2710. }
  2711.  
  2712.  
  2713. /*
  2714.  *    record_reset_movetext
  2715.  *
  2716.  */
  2717. static record_reset_movetext ()
  2718. {
  2719.     if ( strlen(remarkbuf) > 0 )
  2720.     {
  2721.     if ( record_remark(remarkbuf) == S_QUIT )
  2722.         return(S_QUIT);
  2723.     }
  2724.  
  2725.     if ( strlen(cbuf) > 0 )
  2726.     {
  2727.     add_comment_line(" ");        /* pad end of commentary a tad */
  2728.  
  2729.     if ( record_commentary(cbuf) == S_QUIT )
  2730.         return(S_QUIT);
  2731.     }
  2732.  
  2733.     if ( strlen(userbuf) > 0 )
  2734.     {
  2735.     if ( record_userdata(userbuf) == S_QUIT )
  2736.         return(S_QUIT);
  2737.     }
  2738.  
  2739.     clear_buffers();
  2740.     return(S_OK);
  2741. }
  2742.  
  2743.  
  2744. /*------------------------------------------------------------------------*\
  2745.             Parsing-specific utilities
  2746. \*------------------------------------------------------------------------*/
  2747.  
  2748. /*
  2749.  *    add_comment_line
  2750.  *
  2751.  */
  2752. static add_comment_line (buf)
  2753. char *buf;
  2754. {
  2755.     int buflen, cbuflen;
  2756.  
  2757.     if ( comment_status != S_OK )
  2758.     return(S_OK);
  2759.  
  2760.     /*
  2761.      *    if nonempty comment, install paragraph or pad end with a space
  2762.      */
  2763.     if ( (cbuflen = strlen(cbuf)) > 0  &&  cbuflen < MAXCOMLEN-2 )
  2764.     {
  2765.     if ( (buflen = strlen(buf)) == 0 )
  2766.         {
  2767.         strcpy(buf, "\n\n");
  2768.         }
  2769.     else if ( !isspace(buf[buflen-1])  &&  !isspace(cbuf[cbuflen-1]) )
  2770.         {
  2771.         strcat(cbuf, " ");
  2772.         cbuflen += 1;
  2773.         }
  2774.     }
  2775.  
  2776.     /*
  2777.      *    append new text only if it's nonempty and won't cause overflow;
  2778.      *    allow an extra character for next pad-space
  2779.      */
  2780.     if ( (buflen = strlen(buf)) == 0 )
  2781.     return(S_OK);
  2782.  
  2783.     if ( buflen + cbuflen + 1 > MAXCOMLEN )
  2784.     return( echo_read_error(RE_COM_TOO_LONG, buf) );
  2785.  
  2786.     strcat(cbuf, buf);
  2787.     return(S_OK);
  2788. }
  2789.  
  2790.  
  2791. /*
  2792.  *    add_user_line
  2793.  *
  2794.  */
  2795. static add_user_line (buf)
  2796. char *buf;
  2797. {
  2798.     int ubuflen;
  2799.  
  2800.     if ( user_status != S_OK )
  2801.     return(S_OK);
  2802.  
  2803.     /*
  2804.      *    add to user buffer if room; allow 1 char for CRLF
  2805.      */
  2806.     if ( (ubuflen = strlen(userbuf)) + strlen(buf) + 1 > MAXUSERLEN-1 )
  2807.     {
  2808.     user_status = S_ERR;
  2809.     return( echo_read_error(RE_USER_TOO_LONG, buf) );
  2810.     }
  2811.  
  2812.     /*
  2813.      *    prefix this line with CRLF. then append it
  2814.      */
  2815.     if ( ubuflen > 0 )
  2816.     strcat(userbuf, "\n");
  2817.  
  2818.     strcat(userbuf, buf);
  2819.  
  2820.     return(S_OK);
  2821. }
  2822.  
  2823.  
  2824. /*
  2825.  *    DECODE_LOCATION
  2826.  *
  2827.  *    Returns TRUE if passed buf consists exactly of a valid location;
  2828.  *    if so, fills column and row indexes in range 1...boardsize.
  2829.  *    Otherwise, returns FALSE.
  2830.  */
  2831. decode_location (boardsize, buf, colptr, rowptr)
  2832. int boardsize;
  2833. char *buf;
  2834. int *colptr, *rowptr;
  2835. {
  2836.     int buflen;
  2837.  
  2838.     *colptr = *rowptr = NODATA;
  2839.  
  2840.     if ( (buflen = strlen(buf)) < 2  ||     buflen > 3 )
  2841.     return(FALSE);
  2842.  
  2843.     if ( !index_from_column((int)(buf[0]), colptr)  ||    *colptr > boardsize )
  2844.     return(FALSE);
  2845.  
  2846.     if ( (*rowptr = atoi(buf+1)) < 1  ||  *rowptr > boardsize )
  2847.     {
  2848.     *rowptr = NODATA;
  2849.     return(FALSE);
  2850.     }
  2851.  
  2852.     return(TRUE);
  2853. }
  2854.  
  2855.  
  2856. /*
  2857.  *    ENCODE_LOCATION
  2858.  *
  2859.  */
  2860. encode_location (board_size, col, row, str)
  2861. int board_size;
  2862. int col, row;        /* 1...board_size */
  2863. char str[];        /* place 2- or 3-letter composed string here */
  2864. {
  2865.     int colname;
  2866.  
  2867.     strcpy(str, "???");
  2868.  
  2869.     if ( !column_from_index(board_size, col, &colname)    ||
  2870.                     row < 1     ||  row > board_size )
  2871.     {
  2872.     return;
  2873.     }
  2874.  
  2875.     sprintf(str, "%c%d", (char)(colname), row);
  2876. }
  2877.  
  2878.  
  2879. /*
  2880.  *    DECODE_COLOR
  2881.  *
  2882.  *    Returns TRUE if passed buf consists exactly of a
  2883.  *    valid stone-color keyword; if so, fills in the color index.
  2884.  *    Otherwise, returns FALSE.
  2885.  */
  2886. decode_color (buf, colorptr)
  2887. char *buf;
  2888. int *colorptr;
  2889. {
  2890.     *colorptr = NODATA;
  2891.  
  2892.     if ( strcmpi(buf, keys[K_BLACKMOVE].keyword) == 0 )
  2893.     *colorptr = BLACKPC;
  2894.     else if ( strcmpi(buf, keys[K_WHITEMOVE].keyword) == 0 )
  2895.     *colorptr = WHITEPC;
  2896.     else
  2897.     return(FALSE);
  2898.  
  2899.     return(TRUE);
  2900. }
  2901.  
  2902.  
  2903. /*
  2904.  *    DECODE_MOVE_RANGE
  2905.  *
  2906.  *    Returns TRUE if passed buffer consists exactly of a move number or
  2907.  *    a range of move numbers; if so, fills start and end numbers.
  2908.  *    Otherwise, returns FALSE.
  2909.  */
  2910. decode_move_range (buf, fromptr, toptr)
  2911. char *buf;
  2912. int *fromptr, *toptr;
  2913. {
  2914.     int i, j;
  2915.     char numstr[5];
  2916.  
  2917.     *fromptr = *toptr = 0;
  2918.  
  2919.     if ( buf[0] != '#' )
  2920.     return(FALSE);
  2921.  
  2922.     /*
  2923.      *    get starting number
  2924.      */
  2925.     i = 1;
  2926.     j = 0;
  2927.     memset(numstr, 0, sizeof(numstr));
  2928.     while ( j < 4  &&  isdigit(buf[i]) )
  2929.     numstr[j++] = buf[i++];
  2930.     if ( (*fromptr = atoi(numstr)) < 1 )
  2931.     {
  2932.     *fromptr = 0;
  2933.     return(FALSE);
  2934.     }
  2935.  
  2936.     /*
  2937.      *    get ending number if any
  2938.      */
  2939.     *toptr = *fromptr;
  2940.     if ( buf[i++] != '-' )
  2941.     return(TRUE);
  2942.  
  2943.     j = 0;
  2944.     memset(numstr, 0, sizeof(numstr));
  2945.     while ( j < 4  &&  isdigit(buf[i]) )
  2946.     numstr[j++] = buf[i++];
  2947.     if ( (*toptr = atoi(numstr)) < 1 )
  2948.     {
  2949.     *fromptr = *toptr = 0;
  2950.     return(FALSE);
  2951.     }
  2952.  
  2953.     return(TRUE);
  2954. }
  2955. SHAR_EOF
  2956. fi
  2957. if test -f 'sfrecord.c'
  2958. then
  2959.     echo shar: "will not over-write existing file 'sfrecord.c'"
  2960. else
  2961. cat << \SHAR_EOF > 'sfrecord.c'
  2962. /********  Copyright (C) 1990    Oxbow Research Inc.  ************************
  2963.  
  2964.     Filename: sfrecord.c
  2965.  
  2966.     Echoes data read from Standard Format Go files
  2967.  
  2968.     Development begun:    8 March 1990        Wayne A. Lobb
  2969.  
  2970. ****************************************************************************/
  2971.  
  2972. #include <stdio.h>
  2973. #include <stdlib.h>
  2974. #include <string.h>
  2975. #include <ctype.h>
  2976.  
  2977. #include "stdform.h"
  2978.  
  2979. static FILE *outfile = stdout;
  2980. static int boardsize = MAXBOARD;
  2981. static int at_variation = FALSE;
  2982. static int variation_depth = 0;
  2983. static char var_indent[31];
  2984.  
  2985.  
  2986. /*
  2987.  *    INIT_RECORDING
  2988.  *
  2989.  */
  2990. init_recording ()
  2991. {
  2992.     memset(var_indent, 0, sizeof(var_indent));
  2993. }
  2994.  
  2995.  
  2996. /*
  2997.  *    RECORD_BOARDSIZE
  2998.  *
  2999.  */
  3000. record_boardsize (size)
  3001. int size;
  3002. {
  3003.     at_variation = FALSE;
  3004.     fprintf(outfile, "Board size: %d\n", size);
  3005.     boardsize = size;
  3006.     return(S_OK);
  3007. }
  3008.  
  3009.  
  3010. /*
  3011.  *    RECORD_COMMENTARY
  3012.  *
  3013.  */
  3014. record_commentary (buf)
  3015. char *buf;
  3016. {
  3017.     at_variation = FALSE;
  3018.     echo_text("Commentary", buf);
  3019.     return(S_OK);
  3020. }
  3021.  
  3022.  
  3023. /*
  3024.  *    echo_text
  3025.  *
  3026.  */
  3027. static echo_text (type_str, data_str)
  3028. char *type_str, *data_str;
  3029. {
  3030.     int i, indentlen;
  3031.     char partial_data[61];
  3032.  
  3033.     memset(partial_data, 0, sizeof(partial_data));
  3034.  
  3035.     indentlen = strlen(var_indent);
  3036.     strncpy(partial_data, data_str, 56-indentlen);
  3037.  
  3038.     if ( strlen(data_str) > 56-indentlen )
  3039.     strcat(partial_data, " ...");
  3040.  
  3041.     for ( i = 0; i < 61; ++i )
  3042.     if ( partial_data[i] == '\n' )
  3043.         partial_data[i] = ' ';
  3044.  
  3045.     fprintf(outfile, "%s%s: %s\n", var_indent, type_str, partial_data);
  3046. }
  3047.  
  3048.  
  3049. /*
  3050.  *    RECORD_ENDVAR
  3051.  *
  3052.  */
  3053. record_endvar ()
  3054. {
  3055.     at_variation = FALSE;
  3056.     fprintf(outfile, "%sEnd var\n\n", var_indent);
  3057.  
  3058.     if ( --variation_depth < 10 )
  3059.     memset(var_indent + 3*variation_depth, '\0', 3);
  3060.  
  3061.     return(S_OK);
  3062. }
  3063.  
  3064.  
  3065. /*
  3066.  *    RECORD_EVENT
  3067.  *
  3068.  */
  3069. record_event ()
  3070. {
  3071.     at_variation = FALSE;
  3072.     fprintf(outfile, "\n\n---------- Event ----------\n");
  3073.     return(S_OK);
  3074. }
  3075.  
  3076.  
  3077. /*
  3078.  *    RECORD_HIDE
  3079.  *
  3080.  */
  3081. record_hide (col, row)
  3082. int col, row;            /* board location */
  3083. {
  3084.     char hide_loc[5];
  3085.  
  3086.     at_variation = FALSE;
  3087.     encode_location(boardsize, col, row, hide_loc);
  3088.     fprintf(outfile, "%sHide %s\n", var_indent, hide_loc);
  3089.     return(S_OK);
  3090. }
  3091.  
  3092.  
  3093. /*
  3094.  *    RECORD_MARK
  3095.  *
  3096.  */
  3097. record_mark (all, from, to, letters, col, row)
  3098. int all;            /* TRUE = show all move numbers */
  3099. int from, to;            /* range of move numbers if applicable */
  3100. char *letters;            /* 1 or 2 letters at location or on stone */
  3101. int col, row;            /* board location if applicable */
  3102. {
  3103.     char mark_loc[5];
  3104.  
  3105.     at_variation = FALSE;
  3106.  
  3107.     fprintf(outfile, "%sMark", var_indent);
  3108.  
  3109.     if ( all )
  3110.     {
  3111.     fprintf(outfile, " all move numbers\n");
  3112.     return(S_OK);
  3113.     }
  3114.  
  3115.     if ( strlen(letters) > 0 )
  3116.     fprintf(outfile, " \"%s\"", letters);
  3117.     else
  3118.     fprintf(outfile, " number");
  3119.  
  3120.     if ( from > 0  &&  to > 0 )
  3121.     {
  3122.     if ( from != to )
  3123.         fprintf(outfile, " on moves %d to %d\n", from, to);
  3124.     else
  3125.         fprintf(outfile, " on move %d\n", from);
  3126.     }
  3127.     else
  3128.     {
  3129.     encode_location(boardsize, col, row, mark_loc);
  3130.     fprintf(outfile, " at point %s\n", mark_loc);
  3131.     }
  3132.  
  3133.     return(S_OK);
  3134. }
  3135.  
  3136.  
  3137. /*
  3138.  *    RECORD_MOVE
  3139.  *
  3140.  */
  3141. record_move (indiagram, color, index, col, row)
  3142. int indiagram;        /* TRUE or FALSE */
  3143. int color;        /* BLACKPC or WHITEPC */
  3144. int index;        /* 0 = setup move, else assumed > 0 */
  3145. int col, row;
  3146. {
  3147.     char move_color[2], move_loc[5];
  3148.  
  3149.     move_color[0] = 'W';
  3150.     move_color[1] = '\0';
  3151.     if ( color == BLACKPC )
  3152.     move_color[0] = 'B';
  3153.  
  3154.     encode_location(boardsize, col, row, move_loc);
  3155.  
  3156.     if ( indiagram )
  3157.     {
  3158.     fprintf(outfile, "%sDiagram", var_indent);
  3159.  
  3160.     if ( col > 0  &&  row > 0 )
  3161.         fprintf(outfile, " setup %s %s", move_color, move_loc);
  3162.  
  3163.     fprintf(outfile, "\n");
  3164.     }
  3165.     else if ( at_variation )
  3166.     {
  3167.     fprintf(outfile,
  3168.         "%sVariation %s %s\n", var_indent, move_color, move_loc);
  3169.     }
  3170.     else
  3171.     {
  3172.     if ( index != 0 )
  3173.         fprintf(outfile,
  3174.         "%sMove %s %d %s\n", var_indent, move_color, index, move_loc);
  3175.     else
  3176.         fprintf(outfile,
  3177.             "%sSetup %s %s\n", var_indent, move_color, move_loc);
  3178.     }
  3179.  
  3180.     at_variation = FALSE;
  3181.     return(S_OK);
  3182. }
  3183.  
  3184.  
  3185. /*
  3186.  *    RECORD_PRISONER
  3187.  *
  3188.  */
  3189. record_prisoner (number, col, row)
  3190. int number;            /* move number if appropriate */
  3191. int col, row;            /* board location if appropriate */
  3192. {
  3193.     char pris_loc[5];
  3194.  
  3195.     fprintf(outfile, "%sKill move", var_indent);
  3196.  
  3197.     if ( number > 0 )
  3198.     fprintf(outfile, " %d\n", number);
  3199.     else
  3200.     {
  3201.     encode_location(boardsize, col, row, pris_loc);
  3202.     fprintf(outfile, " at %s\n", pris_loc);
  3203.     }
  3204.  
  3205.     return(S_OK);
  3206. }
  3207.  
  3208.  
  3209. /*
  3210.  *    RECORD_REMARK
  3211.  *
  3212.  */
  3213. record_remark (buf)
  3214. char *buf;
  3215. {
  3216.     at_variation = FALSE;
  3217.     echo_text("Remark", buf);
  3218.     return(S_OK);
  3219. }
  3220.  
  3221.  
  3222. /*
  3223.  *    RECORD_UNMARK
  3224.  *
  3225.  */
  3226. record_unmark (all, from, to, col, row)
  3227. int all;            /* TRUE = hide all marks */
  3228. int from, to;            /* range of move numbers if applicable */
  3229. int col, row;            /* board location if applicable */
  3230. {
  3231.     char mark_loc[5];
  3232.  
  3233.     fprintf(outfile, "%sUnmark", var_indent);
  3234.  
  3235.     if ( all )
  3236.     {
  3237.     fprintf(outfile, " all marks\n");
  3238.     }
  3239.     else if ( from > 0    &&  to > 0 )
  3240.     {
  3241.     if ( from != to )
  3242.         fprintf(outfile, " numbers on moves %d to %d\n", from, to);
  3243.     else
  3244.         fprintf(outfile, " number on move %d\n");
  3245.     }
  3246.     else
  3247.     {
  3248.     encode_location(boardsize, col, row, mark_loc);
  3249.     fprintf(outfile, " mark on point or stone at %s\n", mark_loc);
  3250.     }
  3251.  
  3252.     at_variation = FALSE;
  3253.     return(S_OK);
  3254. }
  3255.  
  3256.  
  3257. /*
  3258.  *    RECORD_USERDATA
  3259.  *
  3260.  */
  3261. record_userdata (buf)
  3262. char *buf;
  3263. {
  3264.     at_variation = FALSE;
  3265.     echo_text("User data", buf);
  3266.     return(S_OK);
  3267. }
  3268.  
  3269.  
  3270. /*
  3271.  *    RECORD_VAR
  3272.  *
  3273.  */
  3274. record_var (buf)
  3275. char *buf;            /* optional 1- or 2-letter variation mark */
  3276. {
  3277.     at_variation = TRUE;
  3278.  
  3279.     if ( ++variation_depth <= 10 )
  3280.     strcat(var_indent, "   ");
  3281.  
  3282.     return(S_OK);
  3283. }
  3284. SHAR_EOF
  3285. fi
  3286. if test -f 'stdform.h'
  3287. then
  3288.     echo shar: "will not over-write existing file 'stdform.h'"
  3289. else
  3290. cat << \SHAR_EOF > 'stdform.h'
  3291. /********  Copyright (C) 1990    Oxbow Research Inc.  ************************
  3292.  
  3293.     Filename: stdform.h
  3294.  
  3295.     Header for parsing Standard Format Go files
  3296.  
  3297.     Development begun:    8 March 1990        Wayne A. Lobb
  3298.  
  3299. ****************************************************************************/
  3300.  
  3301. /*------------------------------------------------------------------------*\
  3302.                General constants
  3303. \*------------------------------------------------------------------------*/
  3304. #define TRUE        1
  3305. #define FALSE        0
  3306.  
  3307. #define BIT7        128        /* for extended characters */
  3308.  
  3309. #define S_OK        0        /* everything's A-OK */
  3310. #define S_ERR        1        /* error(s) found */
  3311. #define S_QUIT        2        /* terminate process */
  3312.  
  3313. typedef int (*PROC_PTR)();    /* pointer to function that returns integer */
  3314.  
  3315. /*------------------------------------------------------------------------*\
  3316.               Go-related constants
  3317. \*------------------------------------------------------------------------*/
  3318. #define NODATA        (-1)
  3319.  
  3320. #define MINBOARD    2
  3321. #define MAXBOARD    19
  3322.  
  3323. #define BLACKPC        0
  3324. #define WHITEPC        1
  3325.  
  3326. /*
  3327.  *  move types
  3328.  */
  3329. #define EVENTMOVE    0
  3330. #define SETUPMOVE    1
  3331. #define GAMEMOVE    2
  3332. #define VARIATION    3
  3333. #define DIAGRAM        4
  3334.  
  3335. /*------------------------------------------------------------------------*\
  3336.               File-i/o-related constants
  3337. \*------------------------------------------------------------------------*/
  3338. #define MAXLINELEN    81    /* 1 + max acceptable input line */
  3339. #define MAXKEYWORDLEN    15    /* max length of a file-line keyword */
  3340. #define MAXREMLEN    300    /* max length of one event/move's remarks */
  3341. #define MAXCOMLEN    5000    /* max length of one move's commentary */
  3342. #define MAXUSERLEN    5000    /* max length of one move's user data */
  3343.  
  3344. /*------------------------------------------------------------------------*\
  3345.              Standard Format keywords
  3346. \*------------------------------------------------------------------------*/
  3347. /*
  3348.  *    keyword indexes
  3349.  */
  3350. #define MAXFILEKEY    29
  3351.  
  3352. #define K_ANALYSIS    0
  3353. #define K_BLACKMOVE    1
  3354. #define K_BLACKPLAYER    2
  3355. #define K_BOARDSIZE    3
  3356. #define K_COM        4
  3357. #define K_DATE        5
  3358. #define K_DIAGRAM    6
  3359. #define K_ENDCOM    7
  3360. #define K_ENDUSER    8
  3361. #define K_ENDVAR    9
  3362. #define K_EVENT        10
  3363. #define K_HANDICAP    11
  3364. #define K_HIDE        12
  3365. #define K_KOMI        13
  3366. #define K_MARK        14
  3367. #define K_PLACE        15
  3368. #define K_PRISONER    16
  3369. #define K_RECORDER    17
  3370. #define K_REMARK    18
  3371. #define K_RESULT    19
  3372. #define K_RULES        20
  3373. #define K_SETUP        21
  3374. #define K_SOURCE    22
  3375. #define K_TIMELIMIT    23
  3376. #define K_UNMARK    24
  3377. #define K_USER        25
  3378. #define K_VAR        26
  3379. #define K_WHITEMOVE    27
  3380. #define K_WHITEPLAYER    28
  3381.  
  3382. /*
  3383.  *    keyword-handler data structure
  3384.  */
  3385. typedef struct file_key_data
  3386.     {
  3387.     char keyword[MAXKEYWORDLEN];
  3388.     PROC_PTR handler;
  3389.     }
  3390. FILE_KEY;
  3391.  
  3392. /*------------------------------------------------------------------------*\
  3393.        Parsing-related error strings ("RE" = Read Error)
  3394. \*------------------------------------------------------------------------*/
  3395. #define MAXREADERRS        23
  3396.  
  3397. #define RE_NOMEMORY        0
  3398. #define RE_UNPARSED        1
  3399. #define RE_BOARDSIZE        2
  3400. #define RE_SIZE_TWICE        3
  3401. #define RE_LOCATION        4
  3402. #define RE_SEQUENCE        5
  3403. #define RE_COM_UNOPENED        6
  3404. #define RE_COM_UNCLOSED        7
  3405. #define RE_COM_TOO_LONG        8
  3406. #define RE_USER_UNOPENED    9
  3407. #define RE_USER_UNCLOSED    10
  3408. #define RE_USER_TOO_LONG    11
  3409. #define RE_VAR_UNOPENED        12
  3410. #define RE_VAR_UNCLOSED        13
  3411. #define RE_PARTIALMOVE        14
  3412. #define RE_MOVENUMBER        15
  3413. #define RE_MOVERANGE        16
  3414. #define RE_PRISONER        17
  3415. #define RE_VAR_NOMOVE        18
  3416. #define RE_MARK            19
  3417. #define RE_SETUP_LATE        20
  3418. #define RE_SETUP_COM        21
  3419. #define RE_SETUP_MARK        22
  3420. SHAR_EOF
  3421. fi
  3422. if test -f 'testbad.go'
  3423. then
  3424.     echo shar: "will not over-write existing file 'testbad.go'"
  3425. else
  3426. cat << \SHAR_EOF > 'testbad.go'
  3427. remark testbad.go - test Standard Format parsing problems
  3428.  
  3429. B 1 A8
  3430. B R16
  3431. W 2
  3432. boardsize 13
  3433. B 0 Q3
  3434. W 1 t20
  3435. b 10 a 4
  3436. PRISONER  B 12 #0 #1-5
  3437.  
  3438. EVENT
  3439. BOARDSIZE 0
  3440. BOARDSIZE 19
  3441. B 20 A4
  3442. SETUP R16
  3443. SETUP B A 4
  3444. MARK 10R12 8 @Q13 abc@R13 \s@a20
  3445. ENDCOM
  3446. ENDUSER
  3447. ENDVAR
  3448. VAR
  3449. USER
  3450. SHAR_EOF
  3451. fi
  3452. exit 0
  3453. #    End of shell archive
  3454.