# SAN Kit — library examples

Fourteen short, self-contained C programs, each demonstrating one
corner of the SAN Kit library API. Where `../SAN_DOC` and the
top-level user guide document the *interactive* `san` program,
these show how to call the same underlying library functions
directly from your own C code.

## Building

```sh
cd ../SAN_SRC && make lib      # builds ../SAN_SRC/libsan.a (once)
cd ../examples && make         # builds every example below
```

Each example is a standalone binary named after its source file
(e.g. `./04_move_generation`). None of them take arguments except
`11_pgn_reading`, which takes a PGN filename, e.g.:

```sh
./11_pgn_reading ../SAN_MSC/RJF60.PGN
```

## What each one shows

| File | Demonstrates |
|---|---|
| `01_hello_board.c` | `SANInit()`, `SANDspBoard()`, `SANFENGen()` — the minimum needed to link against the library at all |
| `02_setup_position.c` | Loading a position via `SANFENSet()`, and building one square-by-square with `SANClrBoard()`/`SANPutSq()`/`SANUpdate()` |
| `03_san_notation.c` | Parsing SAN text to a move with `SANDecodeAux()`, formatting it back with `SANEncode()` |
| `04_move_generation.c` | `SANGenMoves()` and walking the resulting `curr_g` move list |
| `05_play_unplay.c` | `SANPlayMove()`/`SANUnplayMove()` and the `hn` move-history counter |
| `06_game_status.c` | `SANStatus()`, `SANWhiteInCheck()`, detecting checkmate |
| `07_perft_enumerate.c` | `SANEnumerate()` — the library's own perft/subtree-counting routine |
| `08_material_count.c` | `SANSetMaterial()`/`cpmv[]`, and an honest note that `SANPosEval()` is an unimplemented stub in this 1994 codebase |
| `09_pgn_tags.c` | PGN header tags (`SANTagLocate`/`SANTagUpdate`) and `SANPGNEventReport()` |
| `10_epd.c` | `SANEPDGenBasicCurrent()`/`SANEPDGenBasic()` |
| `11_pgn_reading.c` | Loading a game from a `.pgn` file with `SANRGSingle()` |
| `12_hashing.c` | The incremental position hash (`curr_e.e_mhca`/`e_mhcs`) vs. `SANHashCreate()` recomputed from scratch |
| `13_search_strategies.c` | Selecting a move-selection strategy per color (`ssv[]`) and using `SANSelect()` to drive it |
| `14_tokens_and_utils.c` | The small string toolkit: `SANToken()`, `SANCheckShortInteger()`/`SANEvalShortInteger()`, `SANCIEqStr()` |

## A few things worth knowing before you write your own

- **Always call `SANInit()` first**, exactly once. It seeds every
  global lookup table the rest of the library depends on and resets
  the board to the starting position.
- **`sanT` is `char[16]`, not `char *`.** Functions like
  `SANDecodeAux()` and `SANEncode()` take a `sanT` buffer. Copy your
  text into a local `sanT` (`strncpy(buf, "e4", sanL - 1)`, then
  null-terminate) rather than passing a string literal directly —
  otherwise modern GCC's bounds checking complains that the literal
  is shorter than the 16-byte parameter type.
- **Include `<time.h>` (and the other standard headers) before any
  `san*.h` header.** A couple of the SAN Kit's own headers (e.g.
  `sanutl.h`, which uses `time_t`) don't include what they use; see
  `_common.h` in this directory for the standard preamble every
  example here starts with.
- **A "move" is always a pointer into `curr_g`,** the move list most
  recently produced by `SANGenMoves()` — never a value you construct
  yourself. `SANDecodeAux()` and the search strategies all hand you
  one of these pointers rather than a move you build by hand.
- **Suppress the built-in board/move echo when you don't want it**
  by setting `optnv[optn_nabd] = 1;` and `optnv[optn_namd] = 1;`
  after `SANInit()` — `SANPlayMove()` prints the board and the move
  it just played by default (this is what the interactive `san`
  program's `nabd`/`namd` options control; see the user guide).
