{ 03_san_notation.pas -- encoding and decoding moves in SAN.
  Pascal translation of ../examples/03_san_notation.c.

  Functions demonstrated:
    SANDecodeAux() -- parse a SAN string into a move pointer
    SANEncode()    -- format a move pointer back into a SAN string

  A "move" inside the SAN Kit is not something you build yourself;
  it's always a pointer (PMove, mptrT in the C original) into the
  list of currently legal moves, produced by the move generator (see
  04_move_generation.c, not yet translated into Pascal). SANDecodeAux()
  looks up a typed-in SAN string against that list and returns a
  pointer to the matching legal move, or nil if the text doesn't
  match any legal move from the current position.

  Note TSanBuf (sankit.pas): it's a fixed 16-byte array (sanL = 16
  in sandef.h), not a Pascal string. Copy your text into one of
  these -- PascalToSanBuf() below does exactly what the C original's
  own strncpy()+manual nul-termination did -- rather than trying to
  pass a Pascal string straight to SANDecodeAux(), which expects a
  plain nul-terminated char* (see SanBufPtr() in sankit.pas).
}

program san_notation;

uses
  SanKit;

{ pad a string with trailing spaces to at least Width characters --
  Pascal's own field-width formatting (Write(s:Width)) right-justifies
  rather than left-justifies, so this replaces the C original's
  "%-6s" instead }
function PadRight(const s: string; Width: Integer): string;
begin
  PadRight := s;
  while Length(PadRight) < Width do
    PadRight := PadRight + ' ';
end;

{ copy a Pascal string into a TSanBuf, truncated to sanL - 1
  characters and nul-terminated, exactly like the C original's
  strncpy(buf, text, sanL - 1); buf[sanL - 1] = '\0'; }
procedure PascalToSanBuf(const s: string; var buf: TSanBuf);
var
  i, n: Integer;
begin
  FillChar(buf, SizeOf(buf), 0);
  n := Length(s);
  if n > sanL - 1 then
    n := sanL - 1;
  for i := 1 to n do
    buf[i - 1] := s[i];
end;

procedure TryDecode(const text: string);
var
  buf, canon: TSanBuf;
  mptr: PMove;
begin
  PascalToSanBuf(text, buf);

  mptr := SANDecodeAux(SanBufPtr(buf));
  if mptr = nil then
    WriteLn('  ', PadRight(text, 6), ' -> not a legal move here')
  else
    begin
      FillChar(canon, SizeOf(canon), 0);
      SANEncode(mptr, SanBufPtr(canon));
      WriteLn('  ', PadRight(text, 6), ' -> legal; canonical SAN is "',
              SanBufPtr(canon), '"');
    end;
end;

begin
  SANInit;
  optnv[optn_nabd] := 1;
  optnv[optn_namd] := 1;

  WriteLn('From the starting position:');
  TryDecode('e4');            { a normal pawn push }
  TryDecode('Nf3');           { a normal piece move }
  TryDecode('e5');            { illegal: no black pawn can reach e5 yet }
  TryDecode('Nc3');           { legal, alternate knight }
  TryDecode('O-O');           { illegal: can't castle yet }
end.
