/* helper – robust coord access */
function cx(c) { return c.x ?? c[0] }
function cy(c) { return c.y ?? c[1] }

/* simple move-shape checks */
var deltas = {
  pawn: function (pc, dx, dy, grid, to) {
    var dir  = (pc.colour == 'white') ? -1 : 1;
    var base = (pc.colour == 'white') ? 6  : 1;
    var one  = (dy == dir && dx == 0 && length(grid.at(to)) == 0);
    var two  = (dy == 2 * dir && dx == 0 && cy(pc.coord) == base &&
               length(grid.at({ x: cx(pc.coord), y: cy(pc.coord)+dir })) == 0 &&
               length(grid.at(to)) == 0);
    var cap  = (dy == dir && Math.abs(dx) == 1 && length(grid.at(to)));
    return one || two || cap;
  },
  rook  : function (pc, dx, dy) { return (dx == 0 || dy == 0); },
  bishop: function (pc, dx, dy) { return Math.abs(dx) == Math.abs(dy); },
  queen : function (pc, dx, dy) { return (dx == 0 || dy == 0 || Math.abs(dx) == Math.abs(dy)); },
  knight: function (pc, dx, dy) { return (Math.abs(dx) == 1 && Math.abs(dy) == 2) ||
                                         (Math.abs(dx) == 2 && Math.abs(dy) == 1); },
  king  : function (pc, dx, dy) { return Math.max(Math.abs(dx), Math.abs(dy)) == 1; }
};

function clearLine(from, to, grid) {
  var dx = Math.sign(cx(to) - cx(from));
  var dy = Math.sign(cy(to) - cy(from));
  var x  = cx(from) + dx, y = cy(from) + dy;
  while (x != cx(to) || y != cy(to)) {
    if (length(grid.at({ x: x, y: y }))) return false;
    x += dx; y += dy;
  }
  return true;
}

function canMove(piece, from, to, grid) {
  var dx = cx(to) - cx(from);
  var dy = cy(to) - cy(from);
  var f  = deltas[piece.kind];
  if (!f || !f(piece, dx, dy, grid, to)) return false;
  if (piece.kind == 'knight') return true;
  return clearLine(from, to, grid);
}

return { canMove };
