all repos

tyess @ master

chess in typst

tyess/notation.typ (view raw)

Oleksandr Smirnov Oleksandr Smirnov
olexsmir@gmail.com
what's creamy, 27 days ago
1
#import "board.typ": file-to-col, square-to-coords
2
3
#let str-index-of(s, c) = {
4
  for i in range(s.len()) { if s.at(i) == c { return i } }
5
  none
6
}
7
8
#let parse-move(move-str) = {
9
  let s = move-str.trim()
10
  let suffix = ""
11
  if s.len() > 0 and (s.at(-1) == "+" or s.at(-1) == "#") {
12
    suffix = s.at(-1)
13
    s = s.slice(0, -1)
14
  }
15
16
  // promotion (e8=Q, e8)
17
  let promotion = none
18
  let idx = str-index-of(s, "=")
19
  if idx != none {
20
    promotion = s.slice(idx + 1, s.len())
21
    s = s.slice(0, idx)
22
  }
23
24
  // castling
25
  if lower(s) == "o-o" or s == "0-0" { return (kind: "castle", side: "kingside", suffix: suffix) }
26
  if lower(s) == "o-o-o" or s == "0-0-0" { return (kind: "castle", side: "queenside", suffix: suffix) }
27
28
  // determine piece type
29
  let ptype = "P"
30
  let pi = 0
31
  if s.len() > 0 and "KQRNBkqrn".contains(s.at(0)) {
32
    ptype = ("k": "K", "q": "Q", "r": "R", "n": "N").at(s.at(0), default: s.at(0))
33
    pi = 1
34
  }
35
36
  // find dest square
37
  let dest-start = -1
38
  for i in range(pi, s.len() - 1) {
39
    if "abcdefgh".contains(s.at(i)) and "12345678".contains(s.at(i + 1)) { dest-start = i }
40
  }
41
42
  if dest-start == -1 { return (kind: "error", raw: s) }
43
  let dest = square-to-coords(s.at(dest-start) + s.at(dest-start + 1))
44
45
  // check for capture by scanning for 'x' before destination
46
  let is-capture = false
47
  for i in range(pi, dest-start) {
48
    if s.at(i) == "x" {
49
      is-capture = true
50
      break
51
    }
52
  }
53
54
  // disambiguation between piece and destination
55
  let disambig = none
56
  if dest-start > pi {
57
    let between = s.slice(pi, dest-start)
58
    let capture-fix = if is-capture { between.replace("x", "") } else { between }
59
    if capture-fix.len() == 1 {
60
      if "abcdefgh".contains(capture-fix) { disambig = (type: "file", value: capture-fix) }
61
      else if "12345678".contains( capture-fix,) { disambig = (type: "rank", value: capture-fix) }
62
    } else if capture-fix.len() == 2 {
63
      if "abcdefgh".contains(capture-fix.at(0)) and "12345678".contains(capture-fix.at(1)) {
64
        disambig = (type: "square", value: capture-fix)
65
      }
66
    }
67
  }
68
69
  return (
70
    kind: "move",
71
    piece: ptype,
72
    dest: dest,
73
    capture: is-capture,
74
    promotion: promotion,
75
    suffix: suffix,
76
    disambig: disambig,
77
    raw: s,
78
  )
79
}