home *** CD-ROM | disk | FTP | other *** search
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create:
- # example.go
- # formspec.txt
- # makefile
- # readme
- # sf.c
- # sf.lnk
- # sfread.c
- # sfrecord.c
- # stdform.h
- # testbad.go
- # This archive created: Wed Nov 28 00:32:16 1990
- export PATH; PATH=/bin:/usr/bin:$PATH
- if test -f 'example.go'
- then
- echo shar: "will not over-write existing file 'example.go'"
- else
- cat << \SHAR_EOF > 'example.go'
- Remark testspec.go
- Remark Three-event Standard-Format file for illustration and testing
-
- EVENT
- B 1 R16
- W 2 D17
- B 3 Q3
- W 4 P17
- B 5 C4
- W 6 E3
- B 7 Q5
- W 8 C6
- B 9 D6
- W 10 D7
- B 11 E6
- W 12 E7
- B 13 E4
- W 14 D3
- B 15 C7
- W 16 C8
- B 17 B7
- W 18 F7
- B 19 B8
- W 20 F4
- B 21 F6
- W 22 C9
- B 23 G7
- W 24 G8
- B 25 H6
- W 26 J3
- B 27 E9
- W 28 B9
- B 29 F8
- W 30 D8
- B 31 G9
- W 32 H8
- B 33 H9
- W 34 J8
- B 35 J9
- W 36 K8
- B 37 D11
- W 38 C12
- B 39 C11
- W 40 B11
- B 41 B12
- W 42 B13
- B 43 D12
- W 44 A12
- PRISONER B12
- B 45 C13
- W 46 C14
- B 47 B12
- PRISONER C12
- W 48 F10
- B 49 F9
- W 50 C12
- PRISONER B12
- B 51 D13
- W 52 B6
- B 53 B5
- W 54 A8
- B 55 C5
- W 56 A7
- PRISONER B8 #17 C7
- B 57 B12
- PRISONER C12
- W 58 G5
-
-
- Event Yose Problem 7
- Source Page 164 of "Basic Techniques of Go"
- Source By Haruyama and Nagahara
- Source Ishi Press, Berkeley-Tokyo, 1969
- Black Haruyama 6-dan
- White Nagahara 4-dan
- Komi 0
- Boardsize 10
- Timelimit 30 minutes each
- Handicap 1
- Result Black wins by 1
- Rules Japanese
- Analysis The authors
- Recorder W. Lobb
- Date 8 March 1990
- Place Concord MA
- Setup w e10 f9 j9 k9 b8 f8 g8 h8 k8 b7 c6 h6 k6
- Setup b B9 C9 D9 E9 A8 C8 E8 J8 D7 E7 F7 G7 H7 J7 K7 D6 J6
- Setup w C5 G5 H5 J5 K5 B4 C4 F4 G4 a3 b3 e3 f3 a2 c2 d2 e2 b2
- Setup b d5 f5 d4 e4 h4 j4 k4 c3 d3 g3 j3 f2 g2 h2
- Com Yose Problem 7.
- How should Black play so as to win by one point?
- Endcom
- B 1 h9
- W 2 h10
- b 3 f10
- Mark #1-2
- com
- Black 1 and 3 are kiri (cut) and horikomi tesuji. The meaning of these
- moves will become clear in a moment.
- endcom
- w 4 g10
- PRISONER #3
- b 5 b6
- COM \d
- Black 5 is the atekomi tesuji and is worth 1 point
- with sente for Black.
- ENDCOM
- w 6 a6
- b 7 c7
- w 8 b5
- PRISONER b6
- b 9 f1
- w 10 f6
- b 11 E5
- w 12 G6
- b 13 E1
- w 14 D1
- b 15 D10
- w 16 g9
- Prisoner h9
- b 17 a9
- w 18 a7
- b 19 f10
- prisoner E10
- w 20 j2
- b 21 k2
- w 22 E10
- prisoner #19
- b 23 A5
- w 24 A4
- prisoner #23
- b 25 F10
- PRISONer E10
- User Print-Diagram 1 of 10
- MARK All
- numbase -22
- partial c1 k8
- show 12 28
- Ko information goes here
- Enduser
- w 26 J1
- b 27 H1
- w 28 E10
- Prisoner #25
- b 29 j10
- w 30 k10
- prisoner #29
- b 31 f10
- PRISONER e10
- COM
- After Black takes ko at 31, White has no more ko threats. Black wins
- by 1 point, having 15 points against White's 14.
- ENDCOM
-
-
- EVENT Problem 1 from Ishigure
- COM
- Adapted from page 111 of "In the Beginning"
- By Ikuro Ishigure, Ishi Press 1973
- ENDCOM
- BOARDSIZE 19
- SETUP B R16 C4 R5 P17 O5 W E17 Q3 E3 Q8 P5 P4
- SETUP W O6 N6 Q10 B P6 Q6 O7 W O4 N4 L3 B P8 O3 N5 M5
- COM Problem 1
- Black to play.
- ENDCOM
- B 1 Q12
- MARK 10@R12 8@Q13 8@R13 8@C17 8@C16 8@D15 \S@q10
- MARK \t@Q8 8@L5 7@P9 7@J17 7@J16 7@K16
- COM \D \c
- Black 1 is the best move and scores 10.
-
- The focal point of the game as it now stands is the unsettled position
- on the right side. Black should make a pincer play either at 1 or at
- '10', attacking the white stones marked \T and \s while forming territory
- in front of his shimari.
-
- If you chose to play one line higher, at one of the points
- marked 8 in the upper right, you can take credit for finding the right
- direction of play, but you are being too timid.
- ENDCOM
- VAR 8
- B 1 M7
- COM Score: 8
- ENDCOM
- W 2 R13
- MARK m7
- COM
- Black 1, capturing two stones and tying Black's forces
- together, is an important point, but White 2 makes White's
- position safe, too, and robs Black of territory on the right
- side.
- ENDCOM
- VAR
- W 2 p7
- MARK M7
- COM
- This is not good for White.
- ENDCOM
- USER Some user data here.
- More user data.
- Last line of user data.
- ENDUSER
- ENDVAR
- ENDVAR
-
- VAR 8
- B 1 D5
- COM Score: 8
- ENDCOM
- W 2 M6
- B 3 L5
- W 4 L6
- B 5 K5
- W 6 L8
- MARK ALL
- UNMARK #6
- MARK \t@L8
- COM
- If Black plays on the left side, 1 looks best, but then White
- will play 2, 4 and \t, and be one move ahead on the right side
- of where he comes out in the main sequence.
- ENDCOM
- ENDVAR
-
- VAR 7
- B 1 Q9
- COM Score: 7
- ENDCOM
- W 2 R9
- B 3 P9
- W 4 r13
- MARK #1 r9 p9 X@r10
- COM
- If Black plays at 1 and 3, White will extend to 4, with
- nothing to fear from Black's cutting at X.
- ENDCOM
- ENDVAR
-
- W 2 M6
- VAR
- W 2 P9
- B 3 L5
- MARK p9
- COM
- If White answers Black 1 directly by playing, say, 2, Black
- will capture at 3. White, his three stones on the right side
- sandwiched between two strong black positions, faces a dreary
- prospect. White cannot play this way; the fight in the main
- sequence is inevitable.
- ENDCOM
- ENDVAR
- B 3 L5
- W 4 L6
- B 5 K5
- W 6 L8
- MARK all a@k6
- COM
- After Black 1, White should push out into the center with 2 and 4,
- then jump to 6 (or, if he prefers, keep pushing at 'a'). This starts
- a four-way fight between two weak black groups and two weak white ones.
- It will be difficult, but Black has already staked out his claim on
- the best ground by playing 1.
- ENDCOM
- VAR
- DIAGRAM
- HIDE q12 r16 p17 e17 c4 e3 l5 k5 l6 m6
- MARK 1@q8 2@o5 3@p5 4@p6 5@p4 6@q6 7@o6 8@o7 9@n6 10@p8
- MARK 11@q10 12@o3 13@o4 14@n5 15@n4 16@m5 17@l3
- COM
- For your reference, the position in the lower right corner arose from this
- pincer joseki.
- ENDCOM
- ENDVAR
- SHAR_EOF
- fi
- if test -f 'formspec.txt'
- then
- echo shar: "will not over-write existing file 'formspec.txt'"
- else
- cat << \SHAR_EOF > 'formspec.txt'
- Standard Format for Go Data Files
-
- Specification
- 17 March 1990
-
- Contents
-
- 1. Standard Format ......................... 1
- 2. Definitions ............................. 1
- 3. General Discussion ...................... 2
- 4. Detailed File Structure ................ 3
- 4.1 Files .............................. 3
- 4.2 Events ............................. 3
- 4.3 Moves .............................. 4
- 4.4 Diagrams ........................... 5
- 5. Keywords ................................ 5
- 5.1 List of Keywords ................... 5
- 5.2 Header Keywords .................... 6
- 5.3 Notation for Keyword Specs ......... 7
- 5.4 Keyword Specifications ............. 8
- 6. General Error Conditions ................ 13
- 7. Sample Valid-Format Data ................ 13
-
-
-
- 1. Standard Format
- ===============
-
- The Standard Format for Go data provides a means for storing and
- transferring data that represents Go games, Go problems, joseki
- dictionaries, diagrams, and other Go-related information, in a
- way that is reasonably independent of machines, operating systems
- and application programs.
-
- To support the Standard fully, an application program must be
- able to recognize and interpret correctly all data signalled by
- the keywords listed and described in Section 5.
-
- An application that only reads Standard Format files, and does
- not also write such files, must be able only to recognize and
- interpret the keywords of interest to it. An application that
- only writes Standard Format files can write a minimum subset of
- keywords, sufficient to capture the information it generates.
-
- An application that both fully reads and fully writes Standard
- Format files must be able to recognize and store all data
- signalled by the keywords described in Section 5, and write all
- that data into an output file without adding to, losing, or
- modifying data in the file in any significant way. Not
- significant are white space, case outside of commentary and board
- marks associated with commentary, and order except where obvious
- or where specifically required.
-
-
- 2. Definitions
- ===========
-
- current event the event most recently defined in the data
- file
-
- current move the most recent Black or White move in the
- current sequence within the current event
-
- event a game, or problem, or joseki, or other
- similar block of conceptually-related G0 data
-
- keyword a string of valid characters with no blanks;
- signals that data of some particular type
- follows
-
- sequence a series of consecutive moves NOT including
- any variations on those moves; can be in the
- main game/problem or follow a variation on
- some other move; every sequence is terminated
- either by an EVENT, or by an ENDVAR, or by
- the end of the data file
-
- setup non-indexed moves/stones including handicap
- stones, problem-situation stones, and stones
- associated directly only to diagrams
-
- SF Standard Format for Go data
-
- valid characters in the ASCII decimal range 32 to
- characters 126 inclusive, plus tab (ASCII 9) and the
- carriage-return-line-feed pair (ASCII 13 and
- 10 consecutively)
-
- white space blank spaces and tabs (ASCII decimal 32 and 9
- resp.)
-
-
-
- 3. General Discussion
- ==================
-
- Data files in Standard Format (SF) are line-oriented, keyword-
- driven, and white-space-delimited. That is:
-
- 1. The main unit of reading/writing in an SF file is the
- line: a series of valid characters terminated by the
- ASCII carriage-return-line-feed pair.
-
- 2. Each line in an SF file either begins after white space
- with a keyword, or is part of a block of lines set off by
- the keyword pair COM/ENDCOM (commentary) or by the pair
- USER/ENDUSER (user-defined data).
-
- 3. Any pair of data fields - keywords, plus other fields
- that are required to follow them or can optionally follow
- them - can be separated from each other by any amount of
- white space (spaces and/or tabs) but by at least one
- space or tab. A keyword can have any number of spaces or
- tabs before it on its file line.
-
-
- Empty lines can appear anywhere in an SF file. They have no
- bearing on the data in the file except within commentary blocks,
- wherein the application decides how to handle them.
-
- An SF file is not required to have any data in it: a completely
- empty file is a valid-format file.
-
- Valid characters in an SF file are those in the ASCII range 32 to
- 126 inclusive, plus the tab character (ASCII 9) and the carriage-
- return-line-feed pair (ASCII 13 and 10 consecutively). All other
- characters can be ignored by applications.
-
- Case is irrelevant in SF files except within commentary blocks
- and for explicit characters that represent board marks (see the
- section on Notation). Outside of board marks and commentary, all
- of upper case, lower case, and mixed case are accepted and
- treated as equivalent for keywords, move locations, special-
- character designations, etc.
-
- No assumptions are made in SF files about evenness or oddness for
- move numbers in relation to player's color. Black's moves can be
- even-numbered and White's can be odd-numbered, or vice-versa for
- both colors. No assumptions are made about alternation of play
- between Black and White.
-
-
-
- 4. Detailed File Structure
- ========================
-
- 4.1 Files
- -----
-
- Each Standard Format (SF) file contains one or more events. An
- event can be a game, a problem, a joseki, a special diagram, or
- some other block of Go-related data. Each event occupies a
- distinct, contiguous block of lines in the file.
-
- An empty SF file consists only of the default implicit event with
- no attached data. A file with no events specifically defined via
- the EVENT keyword, but with moves or other data, has an implicit
- first event to which the data is associated.
-
- An SF file looks like this:
-
- Event 1
- Event 2
- .
- .
- .
- Event n
-
-
- 4.2 Events
- ------
-
- Each event has a single, square board size between 2x2 and 19x19
- inclusive, with default 19x19 unless otherwise specified. Each
- event contains zero or more of the following (but no more than
- one tree of moves and diagrams):
-
- - remarks in the file that apply to the event and are
- typically seen only by a person viewing the file directly;
-
- - header records such as player names and ranks, date,
- source, place, handicap, komi, result, etc.;
-
- - unnumbered Black and White setup stones, for example
- handicap stones or problem-situation stones;
-
- - commentary that applies to the event as a whole;
-
- - blocks of user-defined data that apply to the event as
- a whole;
-
- - board marks - letters or special characters or shapes that
- will be displayed on the empty board at the start of the
- event, before any setup stones or moves, and only then;
-
- - a "tree" of numbered Black and White moves that represent
- the flow of play in the event, plus any number of diagrams
- interspersed with the moves; the moves and move-related
- diagrams in an event follow all other data that applies to
- the event as a whole.
-
-
- An event's structure in a file looks like this:
-
- Remarks
- Event definition (EVENT keyword)
- Event header data
- Event commentary and marks
- Event setup stones
- Event user data
- Tree of moves and diagrams
-
-
- The remarks if any precede the event definition in the file. The
- event definition line precedes all the remaining lines in the
- event. All header lines, commentary blocks, marks, setup stones,
- and blocks of user data may occur in any order among themselves,
- subject to those keywords' own rules, but all must precede the
- tree of moves and diagrams if any.
-
-
- 4.3 Moves
- -----
-
- Each move in an event is defined by a player color, a move number
- that is greater than zero, and the board position for the move or
- an indication that the move was a pass or tenuki. Each move is
- either a move in the main flow of play, or a variation on such a
- move, or a move within a sequence that follows a variation upon
- another move. Variations may be nested to any "depth": moves
- within variation sequences may have "deeper" variations on them.
-
- A move is defined either as a setup stone (SETUP keyword) or as a
- regularly-played Black or White play on the board (B or W keyword
- respectively).
-
- A move has associated with it zero or more of the following:
-
- - remarks in the file that apply to the move and are
- typically seen only by a person viewing the file directly;
-
- - a list of the prisoners taken when this move is played;
-
- - commentary that applies to the move;
-
- - board marks - letters or special characters or shapes that
- normally relate to the commentary and will be displayed on
- the board when the move itself becomes displayed as the
- last of the current sequence, and only then;
-
- - blocks of user-defined data that apply to the move.
-
-
- A move's structure in a file looks like this:
-
- Remarks
- Move definition (SETUP or B or W keyword)
- Prisoners
- Marks
- Commentary
- User data
- Variations on the move
-
-
- Remarks if any precede the move's definition. Prisoner lines,
- commentary blocks, marks and user data all follow the move
- definition line and may occur in any order among themselves.
- Variations on the move must follow all other move data.
-
-
- 4.4 Diagrams
- --------
-
- Each diagram occupies a specific place in the tree of moves,
- variations and diagrams associated with an event.
-
- A diagram is defined by a board region to be displayed when the
- diagram is shown. Unless otherwise specified, the region is the
- same as the parent event's board size. The region can be any
- rectangular subarea of any board between 2x2 and 19x19 in size;
-
- Each diagram contains zero or more of the following:
-
- - remarks in the file that apply to the diagram and are
- typically seen only by a person viewing the file directly;
-
- - a list of Black and/or White setup stones that will be
- displayed only when the diagram is displayed; these stones
- have no bearing on the flow of play that precedes or
- follows the diagram;
-
- - a list of stones/moves to hide when the diagram is
- displayed; i.e., to remove temporarily from the display
- when the diagram is shown and to restore to view when the
- diagram is taken down;
-
- - commentary that applies to the diagram;
-
- - board marks - letters or special characters or shapes that
- normally relate to the commentary and will be displayed on
- the board when the diagram itself becomes displayed, and
- only then; these marks can apply to regular moves in the
- sequence and/or to the diagram's setup stones;
-
- - blocks of user-defined data that apply to the diagram.
-
-
- A diagram's structure in a file looks like this:
-
- Remarks
- Diagram definition (DIAGRAM keyword)
- Setup stones
- Hide moves/stones
- Marks
- Commentary
- User data
-
-
- Remarks if any precede the diagram's definition. Setup lines,
- hide-stone lines, commentary blocks, marks and user data all
- follow the diagram definition line and may occur in any order
- among themselves.
-
-
-
- 5. Keywords
- ========
-
- 5.1 List of Keywords
- ----------------
-
- Event keyword
-
- EVENT begin next event: game, problem, joseki, etc.
-
-
- Header keywords per EVENT
-
- ANALYSIS person(s) who provided the commentary
- BLACK Black player's name, rank etc.
- DATE date(s) on which game was played
- HANDICAP handicap count (informational only)
- KOMI komi
- PLACE location(s) where game was played
- RECORDER person(s) who recorded the data
- RESULT result of the game
- RULES Japanese (the default) or Chinese
- SOURCE source for data: book, journal, etc.
- TIMELIMIT time limits for one or both players
- WHITE White player's name, rank etc.
-
-
- Data keywords per EVENT
-
- B next Black move(s)
- BOARDSIZE size of square board for event
- COM begin a commentary block
- DIAGRAM begin definition of a diagram
- ENDCOM end a commentary block
- ENDUSER end a user-defined block
- ENDVAR end a variation sequence
- HIDE stones/moves to hide in a diagram
- MARK board markers related to commentary
- PRISONER prisoners taken by current move
- REMARK file-writer's remark on event, move, diagram
- SETUP setup B/W stones for an event or diagram
- UNMARK remove some previously-defined MARKs
- USER begin a user-defined block
- VAR begin a variation sequence
- W next White move(s)
-
-
- 5.2 Header Keywords
- ---------------
-
- Header keywords represent informational data about the current
- event. Each header line consists of a keyword optionally followed
- by free-form text that represents the header data. This text may
- contain any amount of white space.
-
- Each header keyword can be repeated within an event. In the case
- of generally textual data such as source, place, analysis, etc.,
- the total data is the sum from all the repeated lines. In the
- case of normally once-only data such as Black player, komi, etc.,
- the last line encountered should be taken as the correct data. An
- application may treat multiple occurences of once-only data lines
- as an error condition but is not required to do so.
-
- A note on handicaps: Exact board locations for a given number of
- handicap stones are usually ambiguous. For this reason, handicap
- stones are placed in specific locations using the SETUP keyword.
- HANDICAP keyword data is informational and does not necessarily
- have to match the actual setup.
-
- Below are valid examples of header keywords.
-
- Analysis Jim Kerwin, professional 1-dan
- ANALYSIS Kato 9 Dan
- BLACK Honinbo Shusaku
- black Alan Chen (9 years old)
- Black
- Date 8 March 1990
- Date 3-21-48
- date November 21-24, 1847
- DATE Dec 9, 1938 and Mar 3-4, 1939
- Date June 3 and 7, 1958
- HANDICAP 0
- Handicap 7
- komi 5
- Komi 3 1/2
- KOMI 4.5
- Place
- PLACE Kyoto (April) and Tokyo (May)
- place US Go Congress, Denver
- Recorder Ishi Press
- RECORDER Phil Straus (playing Black)
- RESULT White wins by resignation
- result Black by 3
- Result Black resigns at move 186
- RULES Japanese
- Rules CHINESE
- Rules
- SOURCE "Invincible: The Games of Shusaku"
- SOURCE John Powers, Kiseido Publishing Co., Tokyo 1982
- Timelimit 1 hour
- WHITE James Redmond 5-dan (made 6-dan after this game)
-
-
- 5.3. Notation for Keyword Specifications
- -----------------------------------
-
- <> nonrepeatable required data field with no
- embedded white space
-
- <>* repeatable required data field, each occurence of
- which contains no embedded white space
-
- [] nonrepeatable optional data field that may have
- embedded white space if so indicated
-
- []* repeatable optional data field, each occurence of
- which may contain white space if so indicated
-
- n positive integer
-
- n-n sequence of positive integers increasing from the
- first number n to second, inclusive: e.g., 21-29
-
- loc board location of form cn, where the character c,
- in the (case-insensitive) set a b c ... not
- including i, represents the column starting from
- the left, and the number n represents the row
- starting from the bottom; e.g. A3 r17 F6
-
- cc one or two characters in the standard ASCII range
- 33 decimal to 126 decimal inclusive; the blank
- character ASCII 32 is not included; if the first
- character is \ then c, d, s or t as the second
- character indicates a special character (see next
- notation)
-
- \C special marker character, under DOS outside the
- ASCII range 32-126; case-insensitive; one of
-
- \d diamond ASCII 4
- \t triangle ASCII 30
- \c check mark ASCII 251
- \s square ASCII 9
-
-
- | "or"; precedes next in a series of alternate
- entries in a data field; e.g. <#n | loc>
-
-
-
- 5.4 Specifications for Non-Header Keywords
- --------------------------------------
-
- _________________________________________________________________
-
- B <n> <loc | PASS>
-
- Next move by Black.
-
- The move number <n> must be greater than 0.
-
- Consecutive B lines in a file are not required to have
- consecutive move numbers, though applications may choose to
- treat nonconsecutive numbers as an error condition.
-
- Examples
- B 17 q3
- B 21 pass
- _________________________________________________________________
-
- BOARDSIZE <n>
-
- Size of current event's square board, between 2 and 19
- inclusive. If no boardsize is indicated for an event, 19x19
- is assumed.
-
- Examples
- BOARDSIZE 2
- BOARDSIZE 9
- BOARDSIZE 13
- _________________________________________________________________
-
- COM [title data]
-
- Begin block of commentary on current event, move or diagram.
-
- If there is no current move or previously-defined setup
- stones in the current event, apply commentary to the event
- as a whole.
-
- All other data after the COM keyword on the line is treated
- as "title" data for the comment that follows. Title data may
- contain white space.
-
- The next keyword line in an SF file after a COM line must be
- an ENDCOM line. COM blocks cannot be nested. All lines
- between a COM and an ENDCOM are treated as commentary text.
-
- Examples
-
- COM
- COM JK's notes \c + !
- COM The famous "ear-reddening" move
- _________________________________________________________________
-
- ENDCOM
-
- End block of commentary.
-
- A line starting with ENDCOM must follow each COM line. All
- lines between the COM and ENDCOM are treated as commentary
- text.
-
- Example
-
- ENDCOM
- _________________________________________________________________
-
- DIAGRAM [<nXn> | <loc loc>]
-
- Begin definition of a diagram and specify its board region.
-
- The region of a diagram is any rectangular subarea of any
- board of size 2x2 through 19x19. If no region is indicated,
- a diagram occupies the full BOARDSIZE of the current event.
- A full-board diagram of a certain size is given by nXn where
- n is in the range 2 to 19.
-
- If a diagram's size is different from the current event's
- BOARDSIZE, it is up to the application to decide whether or
- not to clear the board's display, or to put up a separate
- window with the diagram, or whatever.
-
- Diagram title and commentary data is contained in COM/ENDCOM
- blocks as with regular B and W moves.
-
- See also the HIDE keyword discussion.
-
- Examples
- DIAGRAM (use current event boardsize)
- DIAGRAM 19x19 (full 19x19 board)
- DIAGRAM a19 t1 (full 19x19 board)
- DIAGRAM 9X9 (full 9x9 board)
- DIAGRAM a1 j9 (9x9 lower-left corner of board)
- DIAGRAM b5 j12
- DIAGRAM b12 j5 (same region as previous example)
- _________________________________________________________________
-
- ENDUSER
-
- End a block of user-defined data.
-
- Must be preceded in the file by a USER line.
-
- Example
-
- ENDUSER
- _________________________________________________________________
-
- ENDVAR
-
- End a variation sequence.
-
- Must be preceded in the file by a VAR line.
-
- Example
-
- ENDVAR
- _________________________________________________________________
-
- EVENT [event title]
-
- Start the next game/problem/joseki/diagram/etc.
-
- An EVENT line terminates the current sequence if any and
- terminates the current event if any.
-
- All other data on the line after the EVENT keyword is
- treated as title commentary on the event. Such title data
- may contain white space.
-
- Examples
-
- EVENT Problem 6
- EVENT Joseki for 3-4 point attacked from 5-4 point
- EVENT Honinbo 1989 Final
- _________________________________________________________________
-
- HIDE [loc | #n | #n-n]*
-
- For a DIAGRAM, temporarily remove from display the indicated
- stones, which are specified either by board location or by
- move numbers in order to support removal of regularly played
- moves as well as handicap/setup stones.
-
- See the syntax discussion under MARK.
-
- Examples
- HIDE #21
- HIDE #3-9 q9 R11 #17
- _________________________________________________________________
-
- MARK [ALL | loc | #n | #n-n | \C@loc | \C@#n | \C@#n-n |
- cc@loc | cc@#n | cc@#n-n]*
-
-
- Board marks (highlights) attached to the current event,
- move or diagram. If no move or diagram exists in the current
- event then the marks apply to the empty board.
- Both kinds of indicator for move locations - move number or
- stone location - are supported because handicap/setup stones
- can be marked and because move numbers can be ambiguous
- within a variation sequence: does the number apply to the
- move within the variation, or to a move with the same number
- in a higher-level variation or in the main game?
-
- Board marks are instructions to a program to display or
- undisplay special letters or shapes on the board, usually in
- conjunction with commentary. The sequence of mark keylines
- is important: a read-write application must preserve the
- sequence in which MARKs and UNMARKs are defined. For
- example, the below lines in the order presented cause moves
- 1-5, 11, and 21-33 to have their move numbers displayed:
-
- MARK #1-33
- UNMARK #6-20
- MARK #11
-
- A different order would result in a different display.
-
-
- Data fields:
-
- ALL
- show move numbers on all visible numbered stones (does
- not show numbers on setup or handicap stones)
- example MARK All
-
- loc
- show move number on stone at this location
- example MARK Q8
-
- #n
- show number on most recent move with this number
- example MARK #21 #233
-
- #n-n
- show move numbers on a range of moves
- example MARK #21-28 #221-233
-
- \C@#n
- special character on specified move number
- example MARK \s@#221 \t@#18
-
- \C@#n-n
- special character on all of specified range of moves
- example MARK \t@#21-30
-
- \C@loc
- special character at board location; can be at a stone
- example MARK \t@Q5 \S@R1 \T@m3
-
- cc@loc
- one or two characters at a location; case is retained;
- can be at a stone
- example MARK a@R3 B0@o9 +@A6 X@r7
-
- cc@#n
- place one or two characters on a numbered move
- example MARK aa@#33 X@#102
-
- cc@#n-n
-
- place one or two characters on a range of moves
- example MARK x@#81-90 ..@#320-323
- _________________________________________________________________
-
- PRISONER [#n | loc]*
-
- Prisoner(s) taken by current move.
-
- Both forms of move/stone indicator are supported - move
- index and board location - because handicap and setup stones
- can be captured.
-
- Examples
- PRISONER #22 Q9 F3 #28
- PRISONER #25 #3 #11 #33
- _________________________________________________________________
-
- REMARK [free-form text]
-
- A remark in a file is normally meant for view only by a
- person who is directly reading or editing the file.
-
- Each remark applies to the next EVENT, SETUP, B or W move,
- or DIAGRAM in the file. Each of these keyword types can have
- any number of remarks preceding it in a file.
-
- Examples
- REMARK file test.go
- REMARK Jack - are the next 3 lines OK?
- REMARK Diagram 3 of 9
- _________________________________________________________________
-
- SETUP [<B | W> [loc]*]*
-
- Place unnumbered setup stones for an event or diagram,
- including handicap stones for a game. In general, all setup
- stones in an event or diagram are considered one generalized
- "move": they are all displayed or undisplayed as a unit in a
- single step.
-
- An event or diagram can have any number of SETUP lines.
- Either B or W must precede any list of setup stones to
- indicate their color. Multiple sets of different-colored
- setup stones can follow the SETUP keyword on a line.
-
- Only the first SETUP line in a series of setup lines can
- have an associated REMARK. Only the last of a series of
- SETUP lines can have MARKs, UNMARKs, commentary or user-
- defined data.
-
- Examples
- SETUP B d4 q4 d16 q16
- SETUP W a6 B a7 R11 J9 W b5 B M4
- _________________________________________________________________
-
- UNMARK [ALL | loc | #n | #n-n]*
-
-
- Board marks attached to the current event, move or diagram.
- If no move or diagram exists in the current event then the
- unmarks apply to the empty board. An UNMARK removes a MARK
- previously specified. A series of MARK and UNMARK keywords
- can be used to build Boolean operations on the marks to be
- displayed.
-
- See the discussion under MARK for details.
-
- Examples
- UNMARK All
- UNMARK Q8 #21 r3 #39-43
-
- _________________________________________________________________
-
- USER [user-defined data of any format whatsoever]
-
- Begin a block of user-defined data.
-
- This line, and all lines after it and up to and including
- the next ENDUSER line, define a block of user data.
-
- USER/ENDUSER blocks may not be nested
-
- Examples
- USER
- USER Ishi inventory
- USER Printed diagram #4 of 8
- _________________________________________________________________
-
- VAR [cc]
-
- Begin a variation sequence.
-
- The variation in question applies to the current move, which
- must be a B or W keyword-prefixed move.
-
- The optional one- or two-character marker may be placed by a
- display application at the variation's board location as a
- visual cue, or the character(s) may represent sequencing
- numbers or letters with no special display significance.
-
- Example
- VAR
- VAR b
- VAR 10
- _________________________________________________________________
-
- W <n> <loc | PASS>
-
- Next move by White.
-
- The move number <n> must be greater than 0.
-
- See the discussion under keyword B for more details.
-
- Examples
- W 38 R19
- w 99 pass
-
-
-
- 6. General Error Conditions
- ========================
-
- A keyword line that is missing required data is in error.
-
- Duplicate or out-of-sequence move numbers within a sequence
- usually implies an error condition. For example, "B 12 Q3"
- followed by "B 11 R5" or "B 12 R8" probably implies an error. In
- certain cases an application may choose to accept out-of-sequence
- moves. In all cases, however, duplicate moves indicate errors.
-
- In general, a missing move index implies an error condition. For
- example, if Black 19 is followed by B 21, a White move is
- probably missing. This may be an acceptable condition for certain
- application; it is up to the application to decide.
-
- Certain keyword fields may have, after their required and/or
- optional data, further data on the line. Most applications will
- ignore such extra data. It is NOT necessarily an error condition
- for extra data to be present. For example, the ENDVAR keyword has
- no further required or optional data; a line such as "ENDVAR back
- to main game" should not generate an error, but a program that
- reads a file with such a line is not expected to write the extra
- data to an output file. If the specification for a keyword would
- cause extra data to be parsed, and if that data has incorrect
- format, than an error condition would however be indicated. For
- example, the line "B 22 Q3 R7" should be seen as an error.
-
-
-
- 7. Sample Valid-Format Data
- ========================
-
- The below data is valid-format with respect to the Standard.
- Nearly all of the keywords are represented in this data, and most
- data-field variations for the keywords are represented.
-
- Remark testspec.go
- Remark Three-event SF file for illustration and testing
- event
- B 1 R16
- W 2 D17
- B 3 Q3
- W 4 P17
- B 5 C4
- W 6 E3
- B 7 Q5
- W 8 C6
- B 9 D6
- W 10 D7
- B 11 E6
- W 12 E7
- B 13 E4
- W 14 D3
- B 15 C7
- W 16 C8
- B 17 B7
- W 18 F7
- B 19 B8
- W 20 F4
- B 21 F6
- W 22 C9
- B 23 G7
- W 24 G8
- B 25 H6
- W 26 J3
- B 27 E9
- W 28 B9
- B 29 F8
- W 30 D8
- B 31 G9
- W 32 H8
- B 33 H9
- W 34 J8
- B 35 J9
- W 36 K8
- B 37 D11
- W 38 C12
- B 39 C11
- W 40 B11
- B 41 B12
- W 42 B13
- B 43 D12
- W 44 A12
- PRISONER B12
- B 45 C13
- W 46 C14
- B 47 B12
- PRISONER C12
- W 48 F10
- B 49 F9
- W 50 C12
- PRISONER B12
- B 51 D13
- W 52 B6
- B 53 B5
- W 54 A8
- B 55 C5
- W 56 A7
- PRISONER B8 #17 C7
- B 57 B12
- PRISONER C12
- W 58 G5
-
-
- Event Yose Problem 7
- Source Page 164 of "Basic Techniques of Go"
- Source By Haruyama and Nagahara
- Source Ishi Press, Berkeley-Tokyo, 1969
- Black Haruyama 6-dan
- White Nagahara 4-dan
- Komi 0
- Boardsize 10
- Timelimit 30 minutes each
- Handicap 1
- Result Black wins by 1
- Rules Japanese
- Analysis The authors
- Recorder W. Lobb
- Date 8 March 1990
- Place Concord MA
- Setup w e10 f9 j9 k9 b8 f8 g8 h8 k8 b7 c6 h6 k6
- Setup b B9 C9 D9 E9 A8 C8 E8 J8 D7 E7 F7 G7 H7 J7 K7 D6 J6
- Setup w C5 G5 H5 J5 K5 B4 C4 F4 G4 a3 b3 e3 f3 a2 c2 d2 e2 b2
- Setup b d5 f5 d4 e4 h4 j4 k4 c3 d3 g3 j3 f2 g2 h2
- Com Yose Problem 7.
- How should Black play so as to win by one point?
- Endcom
- B 1 h9
- W 2 h10
- b 3 f10
- Mark #1-2
- com
- Black 1 and 3 are kiri (cut) and horikomi tesuji. The meaning of
- these moves will become clear in a moment.
- endcom
- w 4 g10
- PRISONER #3
- b 5 b6
- COM \d
- Black 5 is the atekomi tesuji and is worth 1 point with
- sente for Black.
- ENDCOM
- w 6 a6
- b 7 c7
- w 8 b5
- PRISONER b6
- b 9 f1
- w 10 f6
- b 11 E5
- w 12 G6
- b 13 E1
- w 14 D1
- b 15 D10
- w 16 g9
- Prisoner h9
- b 17 a9
- w 18 a7
- b 19 f10
- prisoner E10
- w 20 j2
- b 21 k2
- w 22 E10
- prisoner #19
- b 23 A5
- w 24 A4
- prisoner #23
- b 25 F10
- PRISONer E10
- User Print-Diagram 1 of 10
- MARK All
- numbase -22
- partial c1 k8
- show 12 28
- Ko information goes here
- Enduser
- w 26 J1
- b 27 H1
- w 28 E10
- Prisoner #25
- b 29 j10
- w 30 k10
- prisoner #29
- b 31 f10
- PRISONER e10
- COM
- After Black takes ko at 31, White has no more ko threats. Black
- wins by 1 point, having 15 points against White's 14.
- ENDCOM
-
-
- EVENT Problem 1 from Ishigure
- COM
- Adapted from page 111 of "In the Beginning"
- By Ikuro Ishigure, Ishi Press 1973
- ENDCOM
- BOARDSIZE 19
- SETUP B R16 C4 R5 P17 O5 W E17 Q3 E3 Q8 P5 P4
- SETUP W O6 N6 Q10 B P6 Q6 O7 W O4 N4 L3 B P8 O3 N5 M5
- COM Problem 1
- Black to play.
- ENDCOM
- B 1 Q12
- MARK 10@R12 8@Q13 8@R13 8@C17 8@C16 8@D15 \S@q10
- MARK \t@Q8 8@L5 7@P9 7@J17 7@J16 7@K16
- COM \D \c
- Black 1 is the best move and scores 10.
-
- The focal point of the game as it now stands is the unsettled
- position on the right side. Black should make a pincer play
- either at 1 or at '10', attacking the white stones marked \T and
- \s while forming territory in front of his shimari.
-
- If you chose to play one line higher, at one of the points
- marked 8 in the upper right, you can take credit for finding the
- right direction of play, but you are being too timid.
- ENDCOM
- VAR 8
- B 1 M7
- COM Score: 8
- ENDCOM
- W 2 R13
- MARK m7
- COM
- Black 1, capturing two stones and tying Black's forces
- together, is an important point, but White 2 makes White's
- position safe, too, and robs Black of territory on the right
- side.
- ENDCOM
- VAR
- W 2 p7
- MARK M7
- COM
- This is not good for White.
- ENDCOM
- USER Some user data here.
- More user data.
- Last line of user data.
- ENDUSER
- ENDVAR
- ENDVAR
-
- VAR 8
- B 1 D5
- COM Score: 8
- ENDCOM
- W 2 M6
- B 3 L5
- W 4 L6
- B 5 K5
- W 6 L8
- MARK ALL
- UNMARK #6
- MARK \t@L8
- COM
- If Black plays on the left side, 1 looks best, but then White
- will play 2, 4 and \t, and be one move ahead on the right side
- of where he comes out in the main sequence.
- ENDCOM
- ENDVAR
-
- VAR 7
- B 1 Q9
- COM Score: 7
- ENDCOM
- W 2 R9
- B 3 P9
- W 4 r13
- MARK #1 r9 p9 X@r10
- COM
- If Black plays at 1 and 3, White will extend to 4, with
- nothing to fear from Black's cutting at X.
- ENDCOM
- ENDVAR
-
- W 2 M6
- VAR
- W 2 P9
- B 3 L5
- MARK p9
- COM
- If White answers Black 1 directly by playing, say, 2, Black
- will capture at 3. White, his three stones on the right side
- sandwiched between two strong black positions, faces a dreary
- prospect. White cannot play this way; the fight in the main
- sequence is inevitable.
- ENDCOM
- ENDVAR
- B 3 L5
- W 4 L6
- B 5 K5
- W 6 L8
- MARK all a@k6
- COM
- After Black 1, White should push out into the center with 2 and
- 4, then jump to 6 (or, if he prefers, keep pushing at 'a'). This
- starts a four-way fight between two weak black groups and two
- weak white ones. It will be difficult, but Black has already
- staked out his claim on the best ground by playing 1.
- ENDCOM
- VAR
- DIAGRAM
- HIDE q12 r16 p17 e17 c4 e3 l5 k5 l6 m6
- MARK 1@q8 2@o5 3@p5 4@p6 5@p4 6@q6 7@o6 8@o7 9@n6 10@p8
- MARK 11@q10 12@o3 13@o4 14@n5 15@n4 16@m5 17@l3
- COM
- For your reference, the position in the lower right
- corner arose from this pincer joseki.
- ENDCOM
- ENDVAR
- SHAR_EOF
- fi
- if test -f 'makefile'
- then
- echo shar: "will not over-write existing file 'makefile'"
- else
- cat << \SHAR_EOF > 'makefile'
- #
- # filename: makefile
- #
- # Turbo C 2.0 make file for SF - Standard Format parser
-
- OBJS = sf.obj sfread.obj sfrecord.obj
-
- CC=tcc
- OPTS=-c -mm -O.
-
- #
- # RULES
- #
-
- .c.obj:
- $(CC) $(OPTS) $*.c
-
- .asm.obj:
- tasm $*,$*,,/MX;
-
- #
- # DEPENDENCIES
- #
-
- sf.exe: $(OBJS)
- tlink /e /c @sf.lnk
- SHAR_EOF
- fi
- if test -f 'readme'
- then
- echo shar: "will not over-write existing file 'readme'"
- else
- cat << \SHAR_EOF > 'readme'
- file: readme
- date: 31 May 90
-
-
- Parser SF for Standard-Format Go Files
-
-
- Enclosed is a program, SF, that reads Standard Format files and
- echoes to the screen their input plus any errors found. If SF is
- run without arguments it explains itself and exits.
-
- Complete source code for the program is included. This code
- builds under Turbo C 2.0 and runs under DOS 3.0+. Graphics are
- not required or used.
-
- SF as a file-reader conforms in nearly all respects to the Format
- spec dated 17 March 1990. Both GoScribe 2.0 and this program
- deviate from that spec in the following significant ways:
-
- 1. EVENT title data is pushed into a commentary block
- attached to the event.
-
- 2. Commentary title data is pushed into the body of the
- commentary and loses its identity as a distinct title.
-
- 3. All data associated with header keywords - Analysis,
- Date, Recorder, Handicap, etc. - is pushed into a
- commentary block associated with the current event.
-
- 4. Diagrams are full-board only. I.e., diagrams that occupy
- only a region of the board are not supported.
-
-
- In addition, GoScribe 2.0 does not read or remember "variation
- marks": optional 1- or 2-character strings associated with each
- variation move.
- SHAR_EOF
- fi
- if test -f 'sf.c'
- then
- echo shar: "will not over-write existing file 'sf.c'"
- else
- cat << \SHAR_EOF > 'sf.c'
- /******** Copyright (C) 1990 Oxbow Research Inc. ************************
-
- Filename: sf.c
-
- Main module for standalone reading of Standard Format Go files
- Includes general utility routines, both Go-related and not
-
- Development begun: 8 March 1990 Wayne A. Lobb
-
- ****************************************************************************/
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
-
- #include "stdform.h"
-
- /*
- * sfread.c
- */
- extern long int fileline;
- extern int movenum;
-
- static char *read_err_strings[] =
- {
- "Not enough memory",
- "Unable to use data",
- "Unusable board size",
- "Size changed after move",
- "Unusable board location",
- "Out of sequence?",
- "Unopened comment",
- "Unclosed comment",
- "Comment too long",
- "Unopened user data",
- "Unclosed user data",
- "User data too long",
- "Unopened variation",
- "Unclosed variation",
- "Incomplete move data",
- "Unusable move number",
- "Unusable move range",
- "Unusable prisoner",
- "Unusable variation",
- "Unusable board mark",
- "Setup after B/W move",
- "Setup comment deleted",
- "Setup un/mark deleted",
- };
-
-
-
- /**************************************************************************\
-
- EXECUTION STARTS HERE
-
- \**************************************************************************/
-
- main (argc, argv)
- int argc;
- char *argv[]; /* program name and game-file name */
- {
- FILE *fopen();
- FILE *infile;
-
- if ( argc < 2 )
- {
- printf("\nParser for Standard-Format Go Data Files\n");
- printf( "Echoes input data and errors to screen\n\n");
- printf( "Usage: sf <game-file name>\n");
- printf( "Example: sf example.go\n\n");
- exit(0);
- }
-
- if ( (infile = fopen(argv[1], "r")) == (FILE *)NULL )
- {
- printf("\nUnable to find or to open file %s\n", argv[1]);
- exit(-1);
- }
-
- printf("\n");
- read_std_file(infile);
-
- fclose(infile);
- exit(0);
- }
-
-
-
- /*
- * ECHO_READ_ERROR
- *
- */
- echo_read_error (index, str)
- int index; /* in read_err_strings[] */
- char *str; /* supplementary string */
- {
- int ch;
-
- printf("\n*** Line %-6ld move %-3d ", fileline, movenum);
-
- if ( index < 0 || index >= MAXREADERRS )
- printf(" Unknown read error %s\n", str);
- else
- printf("%s %s\n", read_err_strings[index], str);
-
- printf("*** Press Y or y to continue, any other key to quit.\n");
-
- while ( !kbhit() )
- ;
-
- if ( (ch = getch()) == 0 )
- ch = BIT7 | getch();
-
- if ( tolower(ch) == 'y' )
- return(S_OK);
-
- return(S_QUIT);
- }
-
-
- /*--------------------------------------------------------------------------*\
- General Go-related utilities
- \*--------------------------------------------------------------------------*/
-
- static char *column_letters = "abcdefghjklmnopqrst";
-
- /*
- * COLUMN_FROM_INDEX
- *
- */
- column_from_index (boardsize, index, cptr)
- int boardsize;
- int index; /* 1...boardsize */
- int *cptr; /* column letter */
- {
- *cptr = NODATA;
-
- if ( index < 1 || index > boardsize )
- return(FALSE);
-
- *cptr = (int)(column_letters[index-1]);
- return(TRUE);
- }
-
-
- /*
- * INDEX_FROM_COLUMN
- *
- */
- index_from_column (ch, index)
- int ch; /* column letter */
- int *index; /* 1...eventsize */
- {
- int i, count, lch;
-
- *index = NODATA;
- lch = tolower(ch);
- count = strlen(column_letters);
-
- for ( i = 0; i < count; ++i )
- {
- if ( lch == column_letters[i] )
- {
- *index = i+1;
- return(TRUE);
- }
- }
-
- return(FALSE);
- }
-
-
-
- /*--------------------------------------------------------------------------*\
- General non-Go-related utilities
- \*--------------------------------------------------------------------------*/
-
- /*
- * SHAVE_STRING
- *
- */
- shave_string (str)
- char str[];
- {
- int i, j, len;
-
- len = strlen(str);
-
- i = 0;
- while ( i < len && isspace(str[i]) )
- ++i;
-
- j = 0;
- while ( i < len )
- str[j++] = str[i++];
-
- while ( j < len )
- str[j++] = '\0';
-
- i = strlen(str) - 1;
- while ( i >= 0 && isspace(str[i]) )
- str[i--] = '\0';
-
- }
-
-
- /*
- * NEXT_WORD
- *
- * Returns number of characters placed in 'wordbuf'.
- * Passed buffer is assumed to be null-terminated.
- * Passed 'wordbuf' is assumed to have room for null terminator at end.
- */
- next_word (buf, offset, wordbuf, maxword)
- char *buf;
- int *offset; /* starting offset in buf */
- char wordbuf[]; /* filled by this routine */
- int maxword; /* max chars allowable in worbuf[] */
- {
- int i;
-
- memset(wordbuf, 0, maxword+1);
-
- /*
- * skip white space
- */
- while ( isspace(buf[*offset]) )
- ++(*offset);
-
- /*
- * advance to end or to next white char, copying up to allowable chars
- */
- i = 0;
- while ( buf[*offset] != '\0' && !isspace(buf[*offset]) )
- {
- if ( i < maxword )
- wordbuf[i++] = buf[*offset];
-
- ++(*offset);
- }
-
- return(i);
- }
-
- SHAR_EOF
- fi
- if test -f 'sf.lnk'
- then
- echo shar: "will not over-write existing file 'sf.lnk'"
- else
- cat << \SHAR_EOF > 'sf.lnk'
- d:\tc2\lib\c0m sf sfread sfrecord
- sf
- sf
- d:\tc2\lib\mathm d:\tc2\lib\cm
- SHAR_EOF
- fi
- if test -f 'sfread.c'
- then
- echo shar: "will not over-write existing file 'sfread.c'"
- else
- cat << \SHAR_EOF > 'sfread.c'
- /******** Copyright (C) 1990 Oxbow Research Inc. ************************
-
- Filename: sfread.c
-
- Reads Standard Format Go files (to the extent that GoScribe 2.0 does)
-
- Development begun: 8 March 1990 Wayne A. Lobb
-
- Builds under Turbo C 2.0 and runs under DOS 3.0+ without graphics.
-
- No warranties are made or implied. No claims are made about
- beauty, rigor or portability of this code. It does work, however.
-
- Motivated by and based on work done in late 1989 by Bob High of AGA.
-
- May be used for any and all purposes whatever EXCEPT sale.
-
- ****************************************************************************/
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
-
- #include "stdform.h"
-
- /*------------------------------------------------------------------------*\
- Global constants and structures
- \*------------------------------------------------------------------------*/
- int echo = FALSE; /* TRUE = echo each input line to screen */
-
- long int fileline;
- int movenum; /* move number in current event, for echoing errors */
-
-
- /*------------------------------------------------------------------------*\
- Standard Format keywords and their handlers
- \*------------------------------------------------------------------------*/
- static int read_remark();
- static int read_event(), read_boardsize(), record_head_data(), read_setup();
- static int read_bmove(), read_wmove(), read_prisoners();
- static int read_mark(), read_unmark(), read_com(), read_endcom();
- static int read_user(), read_enduser();
- static int read_var(), read_endvar();
- static int read_diagram(), read_hide();
-
- static FILE_KEY keys[MAXFILEKEY] =
- {
- { "Analysis", record_head_data },
- { "B", read_bmove },
- { "Black", record_head_data },
- { "BOARDSIZE", read_boardsize },
- { "COM", read_com },
- { "Date", record_head_data },
- { "DIAGRAM", read_diagram },
- { "ENDCOM", read_endcom },
- { "ENDUSER", read_enduser },
- { "ENDVAR", read_endvar },
- { "EVENT", read_event },
- { "Handicap", record_head_data },
- { "HIDE", read_hide },
- { "Komi", record_head_data },
- { "MARK", read_mark },
- { "Place", record_head_data },
- { "PRISONER", read_prisoners },
- { "Recorder", record_head_data },
- { "REMARK", read_remark },
- { "Result", record_head_data },
- { "Rules", record_head_data },
- { "SETUP", read_setup },
- { "Source", record_head_data },
- { "Timelimit", record_head_data },
- { "UNMARK", read_unmark },
- { "USER", read_user },
- { "VAR", read_var },
- { "W", read_wmove },
- { "White", record_head_data }
- };
-
-
- /*------------------------------------------------------------------------*\
- Local constants and structures
- \*------------------------------------------------------------------------*/
-
- static char *empty_string = "";
-
- /*
- * buffers
- */
- static char remarkbuf[MAXREMLEN]; /* remark(s) prefixed to current move */
- static char cbuf[MAXCOMLEN]; /* commentary postfixed to current move */
- static char userbuf[MAXUSERLEN]; /* user-data postfixed to current move */
-
- /*
- * events
- */
- static int eventcount; /* number of distinct EVENTs so far in the file */
- static int eventsize; /* current event's board size, default MAXBOARD */
- static int movecount; /* moves in current event NOT counting setups */
- static int setupcount; /* setup stones in current event */
-
- /*
- * moves etc. within events
- */
- static int indiagram; /* TRUE if current data applies to a diagram */
- static int incomment; /* TRUE if currently within commentary block */
- static int comment_status; /* S_OK or S_ERR, latter if overflow found */
- static int inuser; /* TRUE if currently within user block */
- static int user_status; /* S_OK or S_ERR, latter if overflow found */
- static int read_vardepth; /* stacked depth of variations */
-
-
- /**************************************************************************\
-
- EXECUTION STARTS HERE
-
- \**************************************************************************/
-
-
- /*
- * READ_STD_FILE
- *
- * Read Standard-Format game file
- */
- read_std_file (infile)
- FILE *infile;
- {
- char *fgets();
- char linebuf[MAXLINELEN];
-
- init_reading(infile);
- memset(linebuf, 0, sizeof(linebuf));
-
- while ( fgets(linebuf, MAXLINELEN, infile) != (char *)NULL )
- {
- ++fileline;
-
- if ( parse_file_line(linebuf) == S_QUIT )
- return(S_ERR);
-
- memset(linebuf, 0, sizeof(linebuf));
- }
-
- if ( incomment )
- echo_read_error(RE_COM_UNCLOSED, empty_string);
-
- if ( inuser )
- echo_read_error(RE_USER_UNCLOSED, empty_string);
-
- if ( read_vardepth > 0 )
- echo_read_error(RE_VAR_UNCLOSED, empty_string);
-
- return( record_reset_movetext() );
- }
-
-
- /*
- * parse_file_line
- *
- */
- static parse_file_line (buf)
- char *buf;
- {
- int i, offset, parsed, status;
- char nextword[MAXLINELEN];
-
- shave_string(buf);
-
- /*
- * get keyword
- */
- offset = 0;
- next_word(buf, &offset, nextword, MAXLINELEN-1);
-
- /*
- * add a line to current move's commentary?
- */
- if ( incomment && strcmpi(nextword, keys[K_ENDCOM].keyword) != 0 )
- return( add_comment_line(buf) );
-
- /*
- * add a line to current move's user-defined data?
- */
- if ( inuser && strcmpi(nextword, keys[K_ENDUSER].keyword) != 0 )
- return( add_user_line(buf) );
-
- /*
- * parse some other nonempty line
- */
- status = S_OK;
- parsed = FALSE;
-
- if ( strlen(nextword) > 0 )
- {
- for ( i = 0; !parsed && i < MAXFILEKEY; ++i )
- {
- if ( keys[i].handler != NULL &&
- strcmpi(nextword, keys[i].keyword) == 0 )
- {
- parsed = TRUE;
- status = (*keys[i].handler)(i, buf+offset);
- }
- }
-
- if ( parsed )
- return(status);
- else
- return( echo_read_error(RE_UNPARSED, buf) );
- }
-
- return(S_OK);
- }
-
-
- /*
- * init_reading
- *
- */
- static init_reading (infile)
- FILE *infile;
- {
- movenum = 0;
- movecount = 0;
- fileline = 0L;
- eventcount = 0;
- setupcount = 0;
-
- inuser = FALSE;
- incomment = FALSE;
- indiagram = FALSE;
- read_vardepth = 0;
- eventsize = MAXBOARD;
-
- fseek(infile, 0L, SEEK_SET);
- clear_buffers();
- }
-
-
- /*
- * clear_buffers
- *
- */
- static clear_buffers ()
- {
- memset(cbuf, 0, sizeof(cbuf));
- memset(userbuf, 0, sizeof(userbuf));
- memset(remarkbuf, 0, sizeof(remarkbuf));
- }
-
-
-
- /*------------------------------------------------------------------------*\
- Keyword handler routines in alphabetical order
- \*------------------------------------------------------------------------*/
-
- /*
- * read_bmove
- *
- */
- static read_bmove (keyindex, buf)
- int keyindex;
- char *buf;
- {
- int col, row, index, offset;
- char nextword[MAXLINELEN];
-
- if ( echo )
- printf("%s %s\n", keys[keyindex].keyword, buf);
-
- indiagram = FALSE;
-
- if ( record_reset_movetext() == S_QUIT )
- return(S_QUIT);
-
- /*
- * get move number
- */
- offset = 0;
- if ( next_word(buf, &offset, nextword, MAXLINELEN-1) == 0 )
- return( echo_read_error(RE_PARTIALMOVE, empty_string) );
-
- if ( (index = atoi(nextword)) < 1 )
- return( echo_read_error(RE_MOVENUMBER, nextword) );
-
- movenum = index;
-
- /*
- * get board location
- */
- if ( next_word(buf, &offset, nextword, MAXLINELEN-1) == 0 )
- return( echo_read_error(RE_PARTIALMOVE, empty_string) );
-
- col = row = 0;
- if ( strcmpi(nextword, "Pass") != 0 &&
- strcmpi(nextword, "Tenuki") != 0 )
- {
- if ( !decode_location(eventsize, nextword, &col, &row) )
- return( echo_read_error(RE_LOCATION, nextword) );
- }
-
- /*
- * record move
- */
- ++movecount;
- return( record_move(indiagram, BLACKPC, index, col, row) );
- }
-
-
- /*
- * read_boardsize
- *
- */
- static read_boardsize (keyindex, buf)
- int keyindex;
- char *buf;
- {
- int size;
-
- if ( echo )
- printf("%s %s\n", keys[keyindex].keyword, buf);
-
- indiagram = FALSE;
-
- if ( (size = atoi(buf)) > MAXBOARD || size < MINBOARD )
- return( echo_read_error(RE_BOARDSIZE, buf) );
-
- if ( size != eventsize )
- {
- if ( setupcount > 0 || movecount > 0 )
- return( echo_read_error(RE_SIZE_TWICE, buf) );
-
- eventsize = size;
- }
-
- return( record_boardsize(eventsize) );
- }
-
-
- /*
- * read_com
- *
- */
- static read_com (keyindex, buf)
- int keyindex;
- char *buf;
- {
- if ( echo )
- printf("%s %s\n", keys[keyindex].keyword, buf);
-
- if ( incomment )
- return( echo_read_error(RE_COM_UNCLOSED, empty_string) );
-
- incomment = TRUE;
- comment_status = S_OK;
-
- shave_string(buf);
-
- if ( strlen(buf) > 0 )
- {
- strcat(buf, "\n\n");
- return( add_comment_line(buf) );
- }
-
- return(S_OK);
- }
-
-
- /*
- * read_diagram
- *
- */
- static read_diagram (keyindex, buf)
- int keyindex;
- char *buf;
- {
- if ( echo )
- printf("%s %s\n", keys[keyindex].keyword, buf);
-
- indiagram = TRUE;
-
- if ( record_reset_movetext() == S_QUIT )
- return(S_QUIT);
-
- ++movecount;
-
- return( record_move(indiagram, BLACKPC, (-1), 0, 0) );
- }
-
-
- /*
- * read_endcom
- *
- */
- static read_endcom (keyindex, buf)
- int keyindex;
- char *buf;
- {
- if ( echo )
- printf("%s %s\n", keys[keyindex].keyword, buf);
-
- if ( !incomment )
- return( echo_read_error(RE_COM_UNOPENED, empty_string) );
-
- incomment = FALSE;
- comment_status = S_OK;
-
- return(S_OK);
- }
-
-
- /*
- * read_enduser
- *
- */
- static read_enduser (keyindex, buf)
- int keyindex;
- char *buf;
- {
- if ( echo )
- printf("%s %s\n", keys[keyindex].keyword, buf);
-
- if ( !inuser )
- return( echo_read_error(RE_USER_UNOPENED, empty_string) );
-
- inuser = FALSE;
- user_status = S_OK;
-
- return(S_OK);
- }
-
-
- /*
- * read_endvar
- *
- */
- static read_endvar (keyindex, buf)
- int keyindex;
- char *buf;
- {
- if ( echo )
- printf("%s %s\n", keys[keyindex].keyword, buf);
-
- indiagram = FALSE;
-
- if ( record_reset_movetext() == S_QUIT )
- return(S_QUIT);
-
- if ( movecount < 1 )
- {
- if ( echo_read_error(RE_VAR_NOMOVE, empty_string) == S_QUIT )
- return(S_QUIT);
- }
-
- if ( read_vardepth < 1 )
- return( echo_read_error(RE_VAR_UNOPENED, empty_string) );
-
- --read_vardepth;
- return( record_endvar() );
- }
-
-
- /*
- * read_event
- *
- */
- static read_event (keyindex, buf)
- int keyindex;
- char *buf;
- {
- if ( echo )
- printf("%s %s\n", keys[keyindex].keyword, buf);
-
- indiagram = FALSE;
-
- if ( record_reset_movetext() == S_QUIT )
- return(S_QUIT);
-
- if ( movecount > 0 && eventcount == 0 )
- eventcount = 2;
- else
- ++eventcount;
-
- movenum = 0;
- movecount = 0;
- setupcount = 0;
- eventsize = MAXBOARD;
-
- shave_string(buf);
-
- if ( strlen(buf) > 0 )
- {
- strcat(buf, "\n\n");
- add_comment_line(buf);
- }
-
- return( record_event() );
- }
-
-
-
- /*
- * read_hide
- *
- */
- static read_hide (keyindex, buf)
- int keyindex;
- char *buf;
- {
- int col, row, offset;
- char nextword[MAXLINELEN];
-
- if ( echo )
- printf("%s %s\n", keys[keyindex].keyword, buf);
-
- if ( !indiagram )
- return( echo_read_error(RE_MARK, keys[keyindex].keyword) );
-
- offset = 0;
-
- while ( next_word(buf, &offset, nextword, MAXLINELEN-1) > 0 )
- {
- if ( decode_location(eventsize, nextword, &col, &row) )
- {
- if ( record_hide(col, row) == S_QUIT )
- return(S_QUIT);
- }
- }
-
- return(S_OK);
- }
-
-
- /*
- * read_mark
- *
- */
- static read_mark (keyindex, buf)
- int keyindex;
- char *buf;
- {
- char *strrchr();
-
- int i, j, from, to, col, row, offset, atoffset;
- char nextword[MAXLINELEN], parseword[MAXLINELEN], letters[MAXLINELEN];
-
- if ( echo )
- printf("%s %s\n", keys[keyindex].keyword, buf);
-
- /*
- * formats for marks:
- * ALL show all move numbers
- * <location> move number at location: q8 A5
- * #<number> move number #211
- * #<num>-<num> range of move numbers #31-42
- * <cc>@<loc> 1 or 2 letters at loc a@r14 10@d17
- * (special chars: \t \c \d \s)
- * <cc>@#<num> 1 or 2 chars on move zz@#59
- * <cc>@#<num>-<num> 1 or 2 chars on move range x@#3-7 21@#9-12
- */
-
- offset = 0;
-
- while ( next_word(buf, &offset, nextword, MAXLINELEN-1) > 0 )
- {
- memset(letters, 0, sizeof(letters));
-
- if ( strcmpi(nextword, "all") == 0 )
- {
- if ( record_mark(TRUE, 0, 0, letters, 0, 0) == S_QUIT )
- return(S_QUIT);
- }
- else
- {
- atoffset = (-1);
- row = col = from = to = NODATA;
-
- j = strlen(nextword);
-
- for ( i = j-1; i >= 0; --i )
- {
- if ( nextword[i] == '@' )
- {
- atoffset = i;
- strncpy(letters, nextword, i);
- break;
- }
- }
-
- if ( atoffset >= 0 )
- strcpy(parseword, nextword + atoffset + 1);
- else
- strcpy(parseword, nextword);
-
- if ( strlen(letters) > 2 )
- {
- if ( echo_read_error(RE_MARK, nextword) == S_QUIT )
- return(S_QUIT);
- }
- else if ( decode_location(eventsize, parseword, &col, &row) )
- {
- if ( record_mark(FALSE, 0, 0, letters, col, row) == S_QUIT )
- return(S_QUIT);
- }
- else if ( decode_move_range(parseword, &from, &to) )
- {
- if ( record_mark(FALSE, from, to, letters, 0, 0) == S_QUIT )
- return(S_QUIT);
- }
- else if ( echo_read_error(RE_MARK, nextword) == S_QUIT )
- return(S_QUIT);
- }
- }
-
- return(S_OK);
- }
-
-
- /*
- * read_prisoners
- *
- */
- static read_prisoners (keyindex, buf)
- int keyindex;
- char *buf;
- {
- int col, row, from, to, offset;
- char nextword[MAXLINELEN];
-
- if ( echo )
- printf("%s %s\n", keys[keyindex].keyword, buf);
-
- if ( movecount < 1 || indiagram )
- return( echo_read_error(RE_PRISONER, buf) );
-
- /*
- * formats for prisoner records:
- * <location> capture stone at location: q8 A5
- * #<number> capture numbered move #211 #31
- */
-
- offset = 0;
-
- while ( next_word(buf, &offset, nextword, MAXLINELEN-1) > 0 )
- {
- from = to = row = col = 0;
-
- if ( decode_location(eventsize, nextword, &col, &row) )
- {
- if ( record_prisoner(0, col, row) == S_QUIT )
- return(S_QUIT);
- }
- else if ( decode_move_range(nextword, &from, &to) )
- {
- if ( from != to )
- {
- if ( echo_read_error(RE_MOVERANGE, nextword) == S_QUIT )
- return(S_QUIT);
- }
- else
- {
- if ( record_prisoner(from, 0, 0) == S_QUIT )
- return(S_QUIT);
- }
- }
-
- else if ( echo_read_error(RE_PRISONER, nextword) == S_QUIT )
- return(S_QUIT);
- }
-
- return(S_OK);
- }
-
-
- /*
- * read_remark
- *
- */
- static read_remark (keyindex, buf)
- int keyindex;
- char *buf;
- {
- if ( echo )
- printf("%s %s\n", keys[keyindex].keyword, buf);
-
- shave_string(buf);
-
- if ( strlen(buf) == 0 )
- return(S_OK);
-
- if ( strlen(remarkbuf) + strlen(buf) > MAXREMLEN-1 )
- return(S_OK);
-
- strcat(remarkbuf, buf);
- strcat(remarkbuf, "\n");
- return(S_OK);
- }
-
-
- /*
- * read_setup
- *
- */
- static read_setup (keyindex, buf)
- int keyindex;
- char *buf;
- {
- int col, row, color, newcolor, offset;
- char nextword[MAXLINELEN];
-
- if ( echo )
- printf("%s %s\n", keys[keyindex].keyword, buf);
-
- if ( record_reset_movetext() == S_QUIT )
- return(S_QUIT);
-
- if ( movecount > 0 && !indiagram )
- return( echo_read_error(RE_SETUP_LATE, buf) );
-
- color = NODATA;
- newcolor = NODATA;
-
- /*
- * each data field must be one of <blackmove>, <whitemove> or <location>
- */
- offset = 0;
-
- while ( next_word(buf, &offset, nextword, MAXLINELEN-1) > 0 )
- {
- if ( decode_color(nextword, &newcolor) )
- {
- color = newcolor;
- }
- else
- {
- if ( !decode_location(eventsize, nextword, &col, &row) )
- {
- if ( echo_read_error(RE_LOCATION, nextword) == S_QUIT )
- return(S_QUIT);
- }
- else if ( color == NODATA )
- {
- if ( echo_read_error(RE_PARTIALMOVE, empty_string) == S_QUIT )
- return(S_QUIT);
- }
- else
- {
- if ( record_move(indiagram, color, 0, col, row) == S_QUIT )
- return(S_QUIT);
-
- ++setupcount;
- }
- }
- }
-
- return(S_OK);
- }
-
-
- /*
- * read_unmark
- *
- */
- static read_unmark (keyindex, buf)
- int keyindex;
- char *buf;
- {
- int from, to, col, row, offset;
- char nextword[MAXLINELEN];
-
- if ( echo )
- printf("%s %s\n", keys[keyindex].keyword, buf);
-
- /*
- * formats for unmarks:
- * ALL hide all marks
- * <location> hide mark at location: q8 A5
- * #<number> hide mark on move #211
- * #<num>-<num> hide on range of moves #31-42
- */
-
- offset = 0;
-
- while ( next_word(buf, &offset, nextword, MAXLINELEN-1) > 0 )
- {
- if ( strcmpi(nextword, "all") == 0 )
- {
- if ( record_unmark(TRUE, 0, 0, 0, 0) == S_QUIT )
- return(S_QUIT);
- }
- else
- {
- row = col = from = to = 0;
-
- if ( decode_location(eventsize, nextword, &col, &row) )
- {
- if ( record_unmark(FALSE, 0, 0, col, row) == S_QUIT )
- return(S_QUIT);
- }
- else if ( decode_move_range(nextword, &from, &to) )
- {
- if ( record_unmark(FALSE, from, to, 0, 0) == S_QUIT )
- return(S_QUIT);
- }
- else if ( echo_read_error(RE_MARK, nextword) == S_QUIT )
- return(S_QUIT);
- }
- }
-
- return(S_OK);
- }
-
-
- /*
- * read_user
- *
- */
- static read_user (keyindex, buf)
- int keyindex;
- char *buf;
- {
- if ( echo )
- printf("%s %s\n", keys[keyindex].keyword, buf);
-
- if ( inuser )
- return( echo_read_error(RE_USER_UNCLOSED, empty_string) );
-
- inuser = TRUE;
- user_status = S_OK;
-
- shave_string(buf);
- return( add_user_line(buf) );
- }
-
-
- /*
- * read_var
- *
- */
- static read_var (keyindex, buf)
- int keyindex;
- char *buf; /* optional variation 1- or 2-letter mark */
- {
- if ( echo )
- printf("%s %s\n", keys[keyindex].keyword, buf);
-
- indiagram = FALSE;
-
- if ( record_reset_movetext() == S_QUIT )
- return(S_QUIT);
-
- if ( movecount < 1 )
- return( echo_read_error(RE_VAR_NOMOVE, empty_string) );
-
- ++read_vardepth;
- return( record_var(buf) );
- }
-
-
- /*
- * read_wmove
- *
- */
- static read_wmove (keyindex, buf)
- int keyindex;
- char *buf;
- {
- int col, row, index, offset;
- char nextword[MAXLINELEN];
-
- if ( echo )
- printf("%s %s\n", keys[keyindex].keyword, buf);
-
- indiagram = FALSE;
-
- if ( record_reset_movetext() == S_QUIT )
- return(S_QUIT);
-
- /*
- * get move number
- */
- offset = 0;
- if ( next_word(buf, &offset, nextword, MAXLINELEN-1) == 0 )
- return( echo_read_error(RE_PARTIALMOVE, empty_string) );
-
- if ( (index = atoi(nextword)) < 1 )
- return( echo_read_error(RE_MOVENUMBER, nextword) );
-
- movenum = index;
-
- /*
- * get board location
- */
- if ( next_word(buf, &offset, nextword, MAXLINELEN-1) == 0 )
- return( echo_read_error(RE_PARTIALMOVE, empty_string) );
-
- col = row = 0;
- if ( strcmpi(nextword, "Pass") != 0 &&
- strcmpi(nextword, "Tenuki") != 0 )
- {
- if ( !decode_location(eventsize, nextword, &col, &row) )
- return( echo_read_error(RE_LOCATION, nextword) );
- }
-
- ++movecount;
- return( record_move(indiagram, WHITEPC, index, col, row) );
- }
-
-
- /*
- * record_head_data
- *
- */
- static record_head_data (keyindex, buf)
- int keyindex;
- char *buf;
- {
- char fulldata[MAXLINELEN];
-
- if ( echo )
- printf("%s %s\n", keys[keyindex].keyword, buf);
-
- shave_string(buf);
-
- if ( strlen(buf) == 0 )
- return(S_OK);
-
- memset(fulldata, 0, sizeof(fulldata));
- sprintf(fulldata, "%s: ", keys[keyindex].keyword);
- strcat(fulldata, buf);
- strcat(fulldata, "\n\n");
- return( add_comment_line(fulldata) );
- }
-
-
- /*
- * record_reset_movetext
- *
- */
- static record_reset_movetext ()
- {
- if ( strlen(remarkbuf) > 0 )
- {
- if ( record_remark(remarkbuf) == S_QUIT )
- return(S_QUIT);
- }
-
- if ( strlen(cbuf) > 0 )
- {
- add_comment_line(" "); /* pad end of commentary a tad */
-
- if ( record_commentary(cbuf) == S_QUIT )
- return(S_QUIT);
- }
-
- if ( strlen(userbuf) > 0 )
- {
- if ( record_userdata(userbuf) == S_QUIT )
- return(S_QUIT);
- }
-
- clear_buffers();
- return(S_OK);
- }
-
-
- /*------------------------------------------------------------------------*\
- Parsing-specific utilities
- \*------------------------------------------------------------------------*/
-
- /*
- * add_comment_line
- *
- */
- static add_comment_line (buf)
- char *buf;
- {
- int buflen, cbuflen;
-
- if ( comment_status != S_OK )
- return(S_OK);
-
- /*
- * if nonempty comment, install paragraph or pad end with a space
- */
- if ( (cbuflen = strlen(cbuf)) > 0 && cbuflen < MAXCOMLEN-2 )
- {
- if ( (buflen = strlen(buf)) == 0 )
- {
- strcpy(buf, "\n\n");
- }
- else if ( !isspace(buf[buflen-1]) && !isspace(cbuf[cbuflen-1]) )
- {
- strcat(cbuf, " ");
- cbuflen += 1;
- }
- }
-
- /*
- * append new text only if it's nonempty and won't cause overflow;
- * allow an extra character for next pad-space
- */
- if ( (buflen = strlen(buf)) == 0 )
- return(S_OK);
-
- if ( buflen + cbuflen + 1 > MAXCOMLEN )
- return( echo_read_error(RE_COM_TOO_LONG, buf) );
-
- strcat(cbuf, buf);
- return(S_OK);
- }
-
-
- /*
- * add_user_line
- *
- */
- static add_user_line (buf)
- char *buf;
- {
- int ubuflen;
-
- if ( user_status != S_OK )
- return(S_OK);
-
- /*
- * add to user buffer if room; allow 1 char for CRLF
- */
- if ( (ubuflen = strlen(userbuf)) + strlen(buf) + 1 > MAXUSERLEN-1 )
- {
- user_status = S_ERR;
- return( echo_read_error(RE_USER_TOO_LONG, buf) );
- }
-
- /*
- * prefix this line with CRLF. then append it
- */
- if ( ubuflen > 0 )
- strcat(userbuf, "\n");
-
- strcat(userbuf, buf);
-
- return(S_OK);
- }
-
-
- /*
- * DECODE_LOCATION
- *
- * Returns TRUE if passed buf consists exactly of a valid location;
- * if so, fills column and row indexes in range 1...boardsize.
- * Otherwise, returns FALSE.
- */
- decode_location (boardsize, buf, colptr, rowptr)
- int boardsize;
- char *buf;
- int *colptr, *rowptr;
- {
- int buflen;
-
- *colptr = *rowptr = NODATA;
-
- if ( (buflen = strlen(buf)) < 2 || buflen > 3 )
- return(FALSE);
-
- if ( !index_from_column((int)(buf[0]), colptr) || *colptr > boardsize )
- return(FALSE);
-
- if ( (*rowptr = atoi(buf+1)) < 1 || *rowptr > boardsize )
- {
- *rowptr = NODATA;
- return(FALSE);
- }
-
- return(TRUE);
- }
-
-
- /*
- * ENCODE_LOCATION
- *
- */
- encode_location (board_size, col, row, str)
- int board_size;
- int col, row; /* 1...board_size */
- char str[]; /* place 2- or 3-letter composed string here */
- {
- int colname;
-
- strcpy(str, "???");
-
- if ( !column_from_index(board_size, col, &colname) ||
- row < 1 || row > board_size )
- {
- return;
- }
-
- sprintf(str, "%c%d", (char)(colname), row);
- }
-
-
- /*
- * DECODE_COLOR
- *
- * Returns TRUE if passed buf consists exactly of a
- * valid stone-color keyword; if so, fills in the color index.
- * Otherwise, returns FALSE.
- */
- decode_color (buf, colorptr)
- char *buf;
- int *colorptr;
- {
- *colorptr = NODATA;
-
- if ( strcmpi(buf, keys[K_BLACKMOVE].keyword) == 0 )
- *colorptr = BLACKPC;
- else if ( strcmpi(buf, keys[K_WHITEMOVE].keyword) == 0 )
- *colorptr = WHITEPC;
- else
- return(FALSE);
-
- return(TRUE);
- }
-
-
- /*
- * DECODE_MOVE_RANGE
- *
- * Returns TRUE if passed buffer consists exactly of a move number or
- * a range of move numbers; if so, fills start and end numbers.
- * Otherwise, returns FALSE.
- */
- decode_move_range (buf, fromptr, toptr)
- char *buf;
- int *fromptr, *toptr;
- {
- int i, j;
- char numstr[5];
-
- *fromptr = *toptr = 0;
-
- if ( buf[0] != '#' )
- return(FALSE);
-
- /*
- * get starting number
- */
- i = 1;
- j = 0;
- memset(numstr, 0, sizeof(numstr));
- while ( j < 4 && isdigit(buf[i]) )
- numstr[j++] = buf[i++];
- if ( (*fromptr = atoi(numstr)) < 1 )
- {
- *fromptr = 0;
- return(FALSE);
- }
-
- /*
- * get ending number if any
- */
- *toptr = *fromptr;
- if ( buf[i++] != '-' )
- return(TRUE);
-
- j = 0;
- memset(numstr, 0, sizeof(numstr));
- while ( j < 4 && isdigit(buf[i]) )
- numstr[j++] = buf[i++];
- if ( (*toptr = atoi(numstr)) < 1 )
- {
- *fromptr = *toptr = 0;
- return(FALSE);
- }
-
- return(TRUE);
- }
- SHAR_EOF
- fi
- if test -f 'sfrecord.c'
- then
- echo shar: "will not over-write existing file 'sfrecord.c'"
- else
- cat << \SHAR_EOF > 'sfrecord.c'
- /******** Copyright (C) 1990 Oxbow Research Inc. ************************
-
- Filename: sfrecord.c
-
- Echoes data read from Standard Format Go files
-
- Development begun: 8 March 1990 Wayne A. Lobb
-
- ****************************************************************************/
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
-
- #include "stdform.h"
-
- static FILE *outfile = stdout;
- static int boardsize = MAXBOARD;
- static int at_variation = FALSE;
- static int variation_depth = 0;
- static char var_indent[31];
-
-
- /*
- * INIT_RECORDING
- *
- */
- init_recording ()
- {
- memset(var_indent, 0, sizeof(var_indent));
- }
-
-
- /*
- * RECORD_BOARDSIZE
- *
- */
- record_boardsize (size)
- int size;
- {
- at_variation = FALSE;
- fprintf(outfile, "Board size: %d\n", size);
- boardsize = size;
- return(S_OK);
- }
-
-
- /*
- * RECORD_COMMENTARY
- *
- */
- record_commentary (buf)
- char *buf;
- {
- at_variation = FALSE;
- echo_text("Commentary", buf);
- return(S_OK);
- }
-
-
- /*
- * echo_text
- *
- */
- static echo_text (type_str, data_str)
- char *type_str, *data_str;
- {
- int i, indentlen;
- char partial_data[61];
-
- memset(partial_data, 0, sizeof(partial_data));
-
- indentlen = strlen(var_indent);
- strncpy(partial_data, data_str, 56-indentlen);
-
- if ( strlen(data_str) > 56-indentlen )
- strcat(partial_data, " ...");
-
- for ( i = 0; i < 61; ++i )
- if ( partial_data[i] == '\n' )
- partial_data[i] = ' ';
-
- fprintf(outfile, "%s%s: %s\n", var_indent, type_str, partial_data);
- }
-
-
- /*
- * RECORD_ENDVAR
- *
- */
- record_endvar ()
- {
- at_variation = FALSE;
- fprintf(outfile, "%sEnd var\n\n", var_indent);
-
- if ( --variation_depth < 10 )
- memset(var_indent + 3*variation_depth, '\0', 3);
-
- return(S_OK);
- }
-
-
- /*
- * RECORD_EVENT
- *
- */
- record_event ()
- {
- at_variation = FALSE;
- fprintf(outfile, "\n\n---------- Event ----------\n");
- return(S_OK);
- }
-
-
- /*
- * RECORD_HIDE
- *
- */
- record_hide (col, row)
- int col, row; /* board location */
- {
- char hide_loc[5];
-
- at_variation = FALSE;
- encode_location(boardsize, col, row, hide_loc);
- fprintf(outfile, "%sHide %s\n", var_indent, hide_loc);
- return(S_OK);
- }
-
-
- /*
- * RECORD_MARK
- *
- */
- record_mark (all, from, to, letters, col, row)
- int all; /* TRUE = show all move numbers */
- int from, to; /* range of move numbers if applicable */
- char *letters; /* 1 or 2 letters at location or on stone */
- int col, row; /* board location if applicable */
- {
- char mark_loc[5];
-
- at_variation = FALSE;
-
- fprintf(outfile, "%sMark", var_indent);
-
- if ( all )
- {
- fprintf(outfile, " all move numbers\n");
- return(S_OK);
- }
-
- if ( strlen(letters) > 0 )
- fprintf(outfile, " \"%s\"", letters);
- else
- fprintf(outfile, " number");
-
- if ( from > 0 && to > 0 )
- {
- if ( from != to )
- fprintf(outfile, " on moves %d to %d\n", from, to);
- else
- fprintf(outfile, " on move %d\n", from);
- }
- else
- {
- encode_location(boardsize, col, row, mark_loc);
- fprintf(outfile, " at point %s\n", mark_loc);
- }
-
- return(S_OK);
- }
-
-
- /*
- * RECORD_MOVE
- *
- */
- record_move (indiagram, color, index, col, row)
- int indiagram; /* TRUE or FALSE */
- int color; /* BLACKPC or WHITEPC */
- int index; /* 0 = setup move, else assumed > 0 */
- int col, row;
- {
- char move_color[2], move_loc[5];
-
- move_color[0] = 'W';
- move_color[1] = '\0';
- if ( color == BLACKPC )
- move_color[0] = 'B';
-
- encode_location(boardsize, col, row, move_loc);
-
- if ( indiagram )
- {
- fprintf(outfile, "%sDiagram", var_indent);
-
- if ( col > 0 && row > 0 )
- fprintf(outfile, " setup %s %s", move_color, move_loc);
-
- fprintf(outfile, "\n");
- }
- else if ( at_variation )
- {
- fprintf(outfile,
- "%sVariation %s %s\n", var_indent, move_color, move_loc);
- }
- else
- {
- if ( index != 0 )
- fprintf(outfile,
- "%sMove %s %d %s\n", var_indent, move_color, index, move_loc);
- else
- fprintf(outfile,
- "%sSetup %s %s\n", var_indent, move_color, move_loc);
- }
-
- at_variation = FALSE;
- return(S_OK);
- }
-
-
- /*
- * RECORD_PRISONER
- *
- */
- record_prisoner (number, col, row)
- int number; /* move number if appropriate */
- int col, row; /* board location if appropriate */
- {
- char pris_loc[5];
-
- fprintf(outfile, "%sKill move", var_indent);
-
- if ( number > 0 )
- fprintf(outfile, " %d\n", number);
- else
- {
- encode_location(boardsize, col, row, pris_loc);
- fprintf(outfile, " at %s\n", pris_loc);
- }
-
- return(S_OK);
- }
-
-
- /*
- * RECORD_REMARK
- *
- */
- record_remark (buf)
- char *buf;
- {
- at_variation = FALSE;
- echo_text("Remark", buf);
- return(S_OK);
- }
-
-
- /*
- * RECORD_UNMARK
- *
- */
- record_unmark (all, from, to, col, row)
- int all; /* TRUE = hide all marks */
- int from, to; /* range of move numbers if applicable */
- int col, row; /* board location if applicable */
- {
- char mark_loc[5];
-
- fprintf(outfile, "%sUnmark", var_indent);
-
- if ( all )
- {
- fprintf(outfile, " all marks\n");
- }
- else if ( from > 0 && to > 0 )
- {
- if ( from != to )
- fprintf(outfile, " numbers on moves %d to %d\n", from, to);
- else
- fprintf(outfile, " number on move %d\n");
- }
- else
- {
- encode_location(boardsize, col, row, mark_loc);
- fprintf(outfile, " mark on point or stone at %s\n", mark_loc);
- }
-
- at_variation = FALSE;
- return(S_OK);
- }
-
-
- /*
- * RECORD_USERDATA
- *
- */
- record_userdata (buf)
- char *buf;
- {
- at_variation = FALSE;
- echo_text("User data", buf);
- return(S_OK);
- }
-
-
- /*
- * RECORD_VAR
- *
- */
- record_var (buf)
- char *buf; /* optional 1- or 2-letter variation mark */
- {
- at_variation = TRUE;
-
- if ( ++variation_depth <= 10 )
- strcat(var_indent, " ");
-
- return(S_OK);
- }
- SHAR_EOF
- fi
- if test -f 'stdform.h'
- then
- echo shar: "will not over-write existing file 'stdform.h'"
- else
- cat << \SHAR_EOF > 'stdform.h'
- /******** Copyright (C) 1990 Oxbow Research Inc. ************************
-
- Filename: stdform.h
-
- Header for parsing Standard Format Go files
-
- Development begun: 8 March 1990 Wayne A. Lobb
-
- ****************************************************************************/
-
- /*------------------------------------------------------------------------*\
- General constants
- \*------------------------------------------------------------------------*/
- #define TRUE 1
- #define FALSE 0
-
- #define BIT7 128 /* for extended characters */
-
- #define S_OK 0 /* everything's A-OK */
- #define S_ERR 1 /* error(s) found */
- #define S_QUIT 2 /* terminate process */
-
- typedef int (*PROC_PTR)(); /* pointer to function that returns integer */
-
- /*------------------------------------------------------------------------*\
- Go-related constants
- \*------------------------------------------------------------------------*/
- #define NODATA (-1)
-
- #define MINBOARD 2
- #define MAXBOARD 19
-
- #define BLACKPC 0
- #define WHITEPC 1
-
- /*
- * move types
- */
- #define EVENTMOVE 0
- #define SETUPMOVE 1
- #define GAMEMOVE 2
- #define VARIATION 3
- #define DIAGRAM 4
-
- /*------------------------------------------------------------------------*\
- File-i/o-related constants
- \*------------------------------------------------------------------------*/
- #define MAXLINELEN 81 /* 1 + max acceptable input line */
- #define MAXKEYWORDLEN 15 /* max length of a file-line keyword */
- #define MAXREMLEN 300 /* max length of one event/move's remarks */
- #define MAXCOMLEN 5000 /* max length of one move's commentary */
- #define MAXUSERLEN 5000 /* max length of one move's user data */
-
- /*------------------------------------------------------------------------*\
- Standard Format keywords
- \*------------------------------------------------------------------------*/
- /*
- * keyword indexes
- */
- #define MAXFILEKEY 29
-
- #define K_ANALYSIS 0
- #define K_BLACKMOVE 1
- #define K_BLACKPLAYER 2
- #define K_BOARDSIZE 3
- #define K_COM 4
- #define K_DATE 5
- #define K_DIAGRAM 6
- #define K_ENDCOM 7
- #define K_ENDUSER 8
- #define K_ENDVAR 9
- #define K_EVENT 10
- #define K_HANDICAP 11
- #define K_HIDE 12
- #define K_KOMI 13
- #define K_MARK 14
- #define K_PLACE 15
- #define K_PRISONER 16
- #define K_RECORDER 17
- #define K_REMARK 18
- #define K_RESULT 19
- #define K_RULES 20
- #define K_SETUP 21
- #define K_SOURCE 22
- #define K_TIMELIMIT 23
- #define K_UNMARK 24
- #define K_USER 25
- #define K_VAR 26
- #define K_WHITEMOVE 27
- #define K_WHITEPLAYER 28
-
- /*
- * keyword-handler data structure
- */
- typedef struct file_key_data
- {
- char keyword[MAXKEYWORDLEN];
- PROC_PTR handler;
- }
- FILE_KEY;
-
- /*------------------------------------------------------------------------*\
- Parsing-related error strings ("RE" = Read Error)
- \*------------------------------------------------------------------------*/
- #define MAXREADERRS 23
-
- #define RE_NOMEMORY 0
- #define RE_UNPARSED 1
- #define RE_BOARDSIZE 2
- #define RE_SIZE_TWICE 3
- #define RE_LOCATION 4
- #define RE_SEQUENCE 5
- #define RE_COM_UNOPENED 6
- #define RE_COM_UNCLOSED 7
- #define RE_COM_TOO_LONG 8
- #define RE_USER_UNOPENED 9
- #define RE_USER_UNCLOSED 10
- #define RE_USER_TOO_LONG 11
- #define RE_VAR_UNOPENED 12
- #define RE_VAR_UNCLOSED 13
- #define RE_PARTIALMOVE 14
- #define RE_MOVENUMBER 15
- #define RE_MOVERANGE 16
- #define RE_PRISONER 17
- #define RE_VAR_NOMOVE 18
- #define RE_MARK 19
- #define RE_SETUP_LATE 20
- #define RE_SETUP_COM 21
- #define RE_SETUP_MARK 22
- SHAR_EOF
- fi
- if test -f 'testbad.go'
- then
- echo shar: "will not over-write existing file 'testbad.go'"
- else
- cat << \SHAR_EOF > 'testbad.go'
- remark testbad.go - test Standard Format parsing problems
-
- B 1 A8
- B R16
- W 2
- boardsize 13
- B 0 Q3
- W 1 t20
- b 10 a 4
- PRISONER B 12 #0 #1-5
-
- EVENT
- BOARDSIZE 0
- BOARDSIZE 19
- B 20 A4
- SETUP R16
- SETUP B A 4
- MARK 10R12 8 @Q13 abc@R13 \s@a20
- ENDCOM
- ENDUSER
- ENDVAR
- VAR
- USER
- SHAR_EOF
- fi
- exit 0
- # End of shell archive
-