///|
fn main raise {
  // 1. core geometry
  let a = @hex.Hex::make(0, 0)
  let b = @hex.Hex::make(4, -2)
  println("distance \{a.label()} -> \{b.label()} = \{a.distance(b)}")
  let lb = StringBuilder()
  for i, c in a.line(b) {
    if i > 0 {
      lb.write_string(" ")
    }
    lb.write_string(c.label())
  }
  println("line \{a.label()} -> \{b.label()}: \{lb}")
  println(
    "range 2 has \{@hex.Hex::range(a, 2).length()} cells; ring 2 has \{@hex.Hex::ring(a, 2).length()}",
  )

  // 2. pathfinding around a wall on column q = 1
  fn passable(c : @hex.Hex) -> Bool {
    !(c.q == 1 && c.r != -1)
  }
  match @path.find_path(a, b, passable, fn(_f, _t) { 1.0 }) {
    Some(steps) => {
      let buf = StringBuilder()
      for i, c in steps {
        if i > 0 {
          buf.write_string(" -> ")
        }
        buf.write_string(c.label())
      }
      println(
        "A* path (\{steps.length() - 1} steps, detouring the wall): \{buf}",
      )
    }
    None => println("no path")
  }

  // 3. field of view with a blocking wall at (1, 0)
  fn transparent(c : @hex.Hex) -> Bool {
    !(c.q == 1 && c.r == 0)
  }
  let seen = @fov.compute(a, 2, transparent)
  let sb = StringBuilder()
  for i, c in seen {
    if i > 0 {
      sb.write_string(", ")
    }
    sb.write_string(c.label())
  }
  println("visible cells (\{seen.length()}): \{sb}")

  // 4. symmetric FOV: bidirectional line of sight
  let sym = @fov.compute_symmetric(a, 2, transparent)
  println("symmetric fov: \{sym.length()} cells (one-way saw \{seen.length()})")

  // 5. multi-source Dijkstra: two friendly cities, nearest-source map
  let multi = @path.Reachability::compute_multi(
    [@hex.Hex::make(-2, 1), @hex.Hex::make(2, -1)],
    10.0,
    fn(_c) { true },
    fn(_f, _t) { 1.0 },
  )
  match multi.cost_to(a) {
    Some(c) =>
      println("multi-source: origin is \{c} steps from the nearest city")
    None => println("multi-source: origin unreachable")
  }

  // 6. region-shaped hex map with ASCII rendering
  let terrain : @hexmap.HexMap[String] = @hexmap.HexMap::make(
    @hexmap.Region::rectangle(4, 3),
    ".",
  )
  terrain.set(@hex.Hex::make(0, 0), "X")
  terrain.set(@hex.Hex::make(2, 1), "~")
  println("hexmap 4x3 rectangle (X you, ~ water):")
  println(terrain.render(fn(v) { v }))
}