← Chess results

Chess

Qwen 3.8 27B GGUF · full

Initial view of Chess

Reviews & generation details

Reviews

No human review yet. Unreviewed does not mean unsuccessful.

Generation context

Imported historical artifact. Its exact original instructions and lineage are not known.

Generation prompt · exact text unavailable

See the current prompt for reference. It may differ from the instructions used to generate this artifact.

Inspect original source 9,798 bytes · SHA-256 4be6fb8da18b

<script>
/* =====================================================================
   SECTION 5 — Move generation (pseudo-legal, then legality filtered)
   move: { from, to, piece, cap, promo?, dbl?, ep?, castle? }
===================================================================== */
function genPseudo(st, from){
  const bd = st.bd;
  const out = [];
  const p = bd[from];
  if (!p) return out;
  const w = isW(p), t = p.toLowerCase();
  const R = from >> 3, F = from & 7;
  const add = (to, extra) => out.push(Object.assign({ from, to, piece: p, cap: bd[to] || null }, extra || {}));

  if (t === 'p'){
    const dir = w ? -1 : 1, startR = w ? 6 : 1, promoR = w ? 0 : 7;
    const nr = R + dir;
    if (nr >= 0 && nr < 8){
      const one = nr * 8 + F;
      if (!bd[one]){
        if (nr === promoR){ for (const q of ['q','r','b','n']) add(one, { promo:q }); }
        else add(one);
        if (R === startR && !bd[(R + 2 * dir) * 8 + F]) add((R + 2 * dir) * 8 + F, { dbl:true });
      }
      for (const df of [-1, 1]){
        const f = F + df;
        if (f < 0 || f > 7) continue;
        const to = nr * 8 + f, tp = bd[to];
        if (tp){
          if (w ? !isW(tp) : isW(tp)){
            if (nr === promoR) for (const q of ['q','r','b','n']) add(to, { promo:q });
            else add(to);
          }
        } else if (to === st.ep){
          add(to, { ep:true });
        }
      }
    }
  }
  else if (t === 'n' || t === 'k'){
    for (const [dr, df] of (t === 'n' ? KN : KG)){
      const r = R + dr, f = F + df;
      if (r < 0 || r > 7 || f < 0 || f > 7) continue;
      const tp = bd[r * 8 + f];
      if (!tp || (w ? !isW(tp) : isW(tp))) add(r * 8 + f);
    }
    if (t === 'k') addCastles(st, out, w);
  }
  else {
    const dirs = t === 'r' ? RD : t === 'b' ? BD : QD;
    for (const [dr, df] of dirs){
      let r = R + dr, f = F + df;
      while (r >= 0 && r < 8 && f >= 0 && f < 8){
        const tp = bd[r * 8 + f];
        add(r * 8 + f);
        if (tp) break;
        r += dr; f += df;
      }
    }
  }
  return out;
}

/* Castling: rights + empty squares + not in check and not passing
   through (or into) an attacked square. King and rook targets only. */
function addCastles(st, out, w){
  const bd = st.bd, c = st.castling;
  const enemy = w ? 'b' : 'w';
  const att = s => attacked(bd, s, enemy);
  if (w){
    if (c.wk && bd[61] === null && bd[62] === null && bd[63] === 'R' &&
        !att(60) && !att(61) && !att(62))
      out.push({ from:60, to:62, piece:'K', cap:null, castle:'k' });
    if (c.wq && bd[59] === null && bd[58] === null && bd[57] === null && bd[56] === 'R' &&
        !att(60) && !att(59) && !att(58))
      out.push({ from:60, to:58, piece:'K', cap:null, castle:'q' });
  } else {
    if (c.bk && bd[5] === null && bd[6] === null && bd[7] === 'R' &&
        !att(4) && !att(5) && !att(6))
      out.push({ from:4, to:6, piece:'k', cap:null, castle:'k' });
    if (c.bq && bd[3] === null && bd[2] === null && bd[1] === null && bd[0] === 'R' &&
        !att(4) && !att(3) && !att(2))
      out.push({ from:4, to:2, piece:'k', cap:null, castle:'q' });
  }
}

function allPseudo(st){
  const out = [], bd = st.bd, w = st.turn === 'w';
  for (let i = 0; i < 64; i++){
    const p = bd[i];
    if (p && isW(p) === w) out.push(...genPseudo(st, i));
  }
  return out;
}

/* The legal-move generator: pseudo-legal, then reject anything that
   leaves the moving side's king attacked. The UI only ever shows what
   this function produces, so illegal states are unreachable. */
function legalMoves(st, from){
  const cands = from != null ? genPseudo(st, from) : allPseudo(st);
  const out = [];
  const enemy = opp(st.turn);
  for (const m of cands){
    const u = makeMove(st, m);
    if (!attacked(st.bd, findKing(st.bd, st.turn), enemy)) out.push(m);
    unmakeMove(st, m, u);
  }
  return out;
}

/* =====================================================================
   SECTION 6 — Make / unmake move
===================================================================== */
function makeMove(st, m){
  const u = { piece: m.piece, cap: null, ep: st.ep, cast: { ...st.castling }, half: st.half };
  const bd = st.bd, p = m.piece, w = isW(p), t = p.toLowerCase();
  bd[m.from] = null;
  if (m.ep){
    const cs = w ? m.to + 8 : m.to - 8;
    u.cap = bd[cs];
    bd[cs] = null;
  } else {
    u.cap = bd[m.to];
    bd[m.to] = null;
  }
  bd[m.to] = m.promo ? (w ? m.promo.toUpperCase() : m.promo) : p;
  if (m.castle){
    if (w){
      if (m.to === 61){ bd[61] = bd[63]; bd[63] = null; }
      else            { bd[59] = bd[56]; bd[56] = null; }
    } else {
      if (m.to === 6){ bd[5] = bd[7]; bd[7] = null; }
      else            { bd[3] = bd[0]; bd[0] = null; }
    }
  }
  const c = st.castling;
  if (t === 'k'){ if (w){ c.wk = c.wq = false; } else { c.bk = c.bq = false; } }
  if (m.from === 63 || m.to === 63) c.wk = false;
  if (m.from === 56 || m.to === 56) c.wq = false;
  if (m.from === 7  || m.to === 7)  c.bk = false;
  if (m.from === 0  || m.to === 0)  c.bq = false;
  const d = m.to - m.from;
  st.ep = (t === 'p' && (d === 16 || d === -16)) ? (m.from + m.to) >> 1 : null;
  st.half = (t === 'p' || u.cap) ? 0 : st.half + 1;
  if (st.turn === 'b') st.full++;
  st.turn = opp(st.turn);
  st.rep.push(posKey(st));
  return u;
}

function unmakeMove(st, m, u){
  st.turn = opp(st.turn);
  if (st.turn === 'b') st.full--;
  st.half = u.half;
  st.ep = u.ep;
  st.castling = u.cast;
  st.rep.pop();
  const bd = st.bd, p = u.piece, w = isW(p);
  bd[m.from] = p;
  if (m.ep){
    const cs = w ? m.to + 8 : m.to - 8;
    bd[cs] = u.cap;
    bd[m.to] = null;
  } else {
    bd[m.to] = u.cap;
  }
  if (m.castle){
    if (w){
      if (m.to === 61){ bd[63] = bd[61]; bd[61] = null; }
      else            { bd[56] = bd[59]; bd[59] = null; }
    } else {
      if (m.to === 6){ bd[7] = bd[5]; bd[5] = null; }
      else            { bd[0] = bd[3]; bd[3] = null; }
    }
  }
}

/* =====================================================================
   SECTION 7 — FEN, SAN, terminal states
===================================================================== */
function toFEN(st){
  const rows = [];
  for (let r = 0; r < 8; r++){
    let row = '', gap = 0;
    for (let f = 0; f < 8; f++){
      const p = st.bd[r * 8 + f];
      if (!p) gap++;
      else { if (gap){ row += gap; gap = 0; } row += p; }
    }
    if (gap) row += gap;
    rows.push(row);
  }
  const c = st.castling;
  const cc = (c.wk?'K':'') + (c.wq?'Q':'') + (c.bk?'k':'') + (c.bq?'q':'');
  return rows.join('/') + ' ' + st.turn + ' ' + (cc || '-') + ' ' +
         (st.ep == null ? '-' : sqName(st.ep)) + ' ' + st.half + ' ' + st.full;
}

function fromFEN(fen){
  const parts = fen.trim().split(/\s+/);
  const bd = new Array(64).fill(null);
  const rows = parts[0].split('/');
  for (let r = 0; r < 8; r++){
    let f = 0;
    for (const ch of rows[r]){
      if (ch >= '1' && ch <= '8') f += +ch;
      else { bd[r * 8 + f] = ch; f++; }
    }
  }
  const cast = parts[2] || '-';
  return {
    bd,
    turn: parts[1] === 'b' ? 'b' : 'w',
    castling: { wk: cast.includes('K'), wq: cast.includes('Q'), bk: cast.includes('k'), bq: cast.includes('q') },
    ep: (parts[3] && parts[3] !== '-') ? nameToSq(parts[3]) : null,
    half: +(parts[4] || 0),
    full: +(parts[5] || 1),
    rep: []
  };
}

/* Standard algebraic notation (without the +/# suffix, added by the caller). */
function san(st, m, legal){
  if (m.castle) return m.castle === 'k' ? 'O-O' : 'O-O-O';
  const t = m.piece.toLowerCase();
  let s = '';
  if (t !== 'p'){
    s = m.piece;
    const others = legal.filter(o => o !== m && o.piece === m.piece && o.to === m.to && o.from !== m.from);
    if (others.length){
      const sf = others.some(o => (o.from & 7) === (m.from & 7));
      const sr = others.some(o => (o.from >> 3) === (m.from >> 3));
      if (!sf) s += FILE_CH[m.from & 7];
      else if (!sr) s += String(8 - (m.from >> 3));
      else s += FILE_CH[m.from & 7] + String(8 - (m.from >> 3));
    }
  } else if (m.cap || m.ep){
    s = FILE_CH[m.from & 7];
  }
  if (m.cap || m.ep) s += 'x';
  s += sqName(m.to);
  if (m.promo) s += '=' + m.promo.toUpperCase();
  if (m.ep) s += ' e.p.';
  return s;
}

function insufficientMaterial(bd){
  const minors = [];
  for (let i = 0; i < 64; i++){
    const p = bd[i];
    if (!p || p === 'K' || p === 'k') continue;
    const t = p.toLowerCase();
    if (t === 'p' || t === 'r' || t === 'q') return false; // not a dead position
    minors.push({ t, i, w: isW(p) });
  }
  if (minors.length <= 1) return true;   // K vs K, K+B vs K, K+N vs K, K+B+B/K+N+N
  if (minors.length === 2 && minors[0].t === 'b' && minors[1].t === 'b'){
    const a = minors[0], b = minors[1];
    if (a.w !== b.w && (((a.i >> 3) + (a.i & 7)) & 1) === (((b.i >> 3) + (b.i & 7)) & 1))
      return true;                        // K+B vs K+B, same-square colour
  }
  return false;
}

/* Returns null if the game continues, else a result object. */
function terminalState(st, noMoves, chk){
  if (noMoves){
    if (chk) return { type:'mate', res: st.turn === 'w' ? '0-1' : '1-0',
                      title:'Checkmate', detail:(st.turn === 'w' ? 'Black' : 'White') + ' wins' };
    return { type:'stale', res:'\u00BD\u2013\u00BD', title:'Stalemate', detail:'Draw by stalemate' };
  }
  if (insufficientMaterial(st.bd))
    return { type:'mat', res:'\u00BD\u2013\u00BD', title:'Draw', detail:'Insufficient material' };
  if (st.half >= FIFTY_MOVE_LIMIT)
    return { type:'fifty', res:'\u00BD\u2013\u00BD', title:'Draw', detail:'Fifty-move rule' };
  const key = posKey(st);
  if (st.rep.filter(k => k === key).length >= 3)
    return { type:'rep', res:'\u00BD\u2013\u00BD', title:'Draw', detail:'Threefold repetition' };
  return null;
}
</script>