{"challengeId":"protein-fold","entry":"verifier.mjs","sha256":"7e67c8c1b87f52a77e94f1521898bd3c15696edffe23395ee78c250f9c3ae50b","scoreDirection":"maximize","scoreLabel":"H-H contacts","seedPolicy":{"mode":"fixed","testCount":1},"source":"// Frozen verifier for protein-fold. Self-contained (no imports). The HP sequence\n// below is the protein: H = hydrophobic, P = polar. The agent folds it on a 2D\n// square lattice as a self-avoiding walk (moves U/D/L/R between consecutive\n// residues) and scores the number of H–H \"topological contacts\": pairs of H\n// residues that sit on adjacent lattice cells but are NOT neighbors in the chain.\n// Maximizing those contacts is the classic HP protein-folding model — the\n// simplest computational stand-in for how a protein collapses into its core.\n// Pure integer lattice math; deterministic; seedPolicy \"fixed\".\n\nconst SEQ = 'HPHPPHHPHPPHPHHPPHPH';\nconst N = SEQ.length;\nconst STEP = { U: [0, 1], D: [0, -1], L: [-1, 0], R: [1, 0] };\n\nfunction gate(name, pass, detail) { return { name, pass, detail }; }\nfunction bad(name, detail) { return { ok: false, score: null, gates: [gate(name, false, detail)], behavior: {}, logs: [] }; }\n\nexport function verify(ctx) {\n  const moves = ctx.solution && typeof ctx.solution === 'object' ? ctx.solution.moves : undefined;\n  if (!Array.isArray(moves) || moves.length !== N - 1) {\n    return bad('structure', `expected { moves: [${N - 1} directions, each \"U\"/\"D\"/\"L\"/\"R\"] }`);\n  }\n  const xs = [0];\n  const ys = [0];\n  let x = 0, y = 0;\n  for (const mv of moves) {\n    const d = STEP[mv];\n    if (!d) return bad('structure', `invalid move \"${String(mv)}\" (use U/D/L/R)`);\n    x += d[0]; y += d[1];\n    xs.push(x); ys.push(y);\n  }\n  // self-avoiding: every occupied cell distinct\n  const seen = new Set();\n  for (let i = 0; i < N; i++) {\n    const key = xs[i] + ',' + ys[i];\n    if (seen.has(key)) return bad('self-avoiding', `the fold overlaps itself at cell ${key}`);\n    seen.add(key);\n  }\n  // count H-H topological contacts (adjacent on lattice, non-consecutive in chain)\n  let contacts = 0;\n  for (let i = 0; i < N; i++) {\n    if (SEQ[i] !== 'H') continue;\n    for (let j = i + 2; j < N; j++) {\n      if (SEQ[j] !== 'H') continue;\n      if (Math.abs(xs[i] - xs[j]) + Math.abs(ys[i] - ys[j]) === 1) contacts++;\n    }\n  }\n  return {\n    ok: true,\n    score: contacts,\n    gates: [gate('self-avoiding-fold', true, `valid self-avoiding fold with ${contacts} H-H contacts`)],\n    behavior: { contacts, residues: N },\n    logs: [`H-H contacts=${contacts}`],\n  };\n}\n"}