Back to leaderboard

NexBot III

Created 9/9/2026

Active

w

Avg score

8.636

Wins

2356

Losses

3028

Win rate

14.6%

Total battles: 16114

Score history

Score trend over the last 200 battles

Avg: 8.636

Recent battles

Source

const TREE=(()=>{const t=[];const b=s=>{const i=t.length;t.push(null);if(s.length===10){const d=[...s].filter(x=>x==="D").length,c=s.match(/C+$/)?.[0].length||0,q=d===0||c>=4?"C":d>=2||s.at(-1)==="D"?"D":"C";t[i]=[-1,0,q==="D"?1:0];return i}const C=b(s+"C"),D=b(s+"D"),d=[...s].filter(x=>x==="D").length;t[i]=[d>=2||s.at(-1)==="D"?1:0,C,D];return i};b("");return t})();

const fresh=()=>({seen:0,c:0,d:0,cc:0,cd:0,dc:0,dd:0,lastD:0,mutualD:0,forgive:0,probe:0});

const valid=x=>x==="C"||x==="D";

const rebuild=(h,old)=>{
  const m=fresh();
  m.probe=Number.isFinite(old?.probe)?old.probe:0;

  for(const r of h){
    if(r.opponent==="D"){m.d++;m.lastD++}
    else{m.c++;m.lastD=0}

    if(r.you==="C"&&r.opponent==="C")m.cc++;
    if(r.you==="C"&&r.opponent==="D")m.cd++;
    if(r.you==="D"&&r.opponent==="C")m.dc++;

    if(r.you==="D"&&r.opponent==="D"){
      m.dd++;
      m.mutualD++;
    }else{
      m.mutualD=0;
    }
  }

  m.seen=h.length;
  return m;
};

const update=(h,old)=>{
  if(!old||typeof old!=="object"||old.seen!==h.length-1)return rebuild(h,old);

  const m=old,r=h.at(-1);

  if(r.opponent==="D"){m.d++;m.lastD++}
  else{m.c++;m.lastD=0}

  if(r.you==="C"&&r.opponent==="C")m.cc++;
  if(r.you==="C"&&r.opponent==="D")m.cd++;
  if(r.you==="D"&&r.opponent==="C")m.dc++;

  if(r.you==="D"&&r.opponent==="D"){
    m.dd++;
    m.mutualD++;
  }else{
    m.mutualD=0;
  }

  m.seen=h.length;
  return m;
};

const tree=h=>{
  if(h.length<10)return null;

  let k=0;

  for(const r of h.slice(-10)){
    const n=TREE[k];

    if(!n||n[0]===-1)return null;

    k=r.opponent==="D"?n[2]:n[1];

    if(!Number.isInteger(k)||k<0)return null;
  }

  const n=TREE[k];

  if(!n||n[0]!==-1)return null;

  return n[2]?"D":"C";
};

const periodic=h=>{
  if(h.length<14)return false;

  const a=h.slice(-12).map(x=>x.opponent).join("");

  for(const p of [2,3,4,5,6]){
    let ok=true;

    for(let i=p;i<a.length;i++){
      if(a[i]!==a[i-p]){
        ok=false;
        break;
      }
    }

    if(ok)return true;
  }

  return false;
};

const move=(h,m)=>{
  if(!h.length)return"C";

  const last=h.at(-1);
  const prev=h.at(-2);
  const recent=h.slice(-10);
  const rd=recent.filter(x=>x.opponent==="D").length;
  const rc=recent.length-rd;

  const retaliation=
    m.cd>=3&&
    m.cd/Math.max(1,m.c+m.d)>.25;

  const recovery=
    m.dc>=2&&
    m.dc/Math.max(1,m.dc+m.dd)>.45;

  if(m.lastD>=4)return"D";

  if(periodic(h)&&last.opponent==="D")return"D";

  if(m.forgive>0){
    if(last.opponent==="D"){
      m.forgive=0;
      return"D";
    }

    m.forgive--;

    if(m.forgive===0)return"C";

    return"D";
  }

  if(rd>=3){
    m.forgive=2;
    return"D";
  }

  if(last.opponent==="D"&&prev?.opponent!=="D")return"D";

  if(
    retaliation&&
    last.opponent==="C"&&
    prev?.opponent==="D"
  ){
    return recovery?"C":"D";
  }

  const t=tree(h);

  if(t==="D"&&rc>=7&&!retaliation)return"C";

  if(t==="C"&&rd>=2)return"D";

  if(t)return t;

  if(rd===0)return"C";

  if(rd===1&&last.opponent==="C")return"C";

  if(m.mutualD>=3){
    m.probe++;

    if(m.probe%4===0)return"C";

    return"D";
  }

  return last.opponent==="C"?"C":"D";
};

export default function bot({history=[],memory}){
  try{
    if(!Array.isArray(history)){
      return["D",memory||fresh()];
    }

    for(const r of history){
      if(
        !r||
        !valid(r.you)||
        !valid(r.opponent)
      ){
        return["D",memory||fresh()];
      }
    }

    const m=update(history,memory);
    const next=move(history,m);

    return[next==="C"?"C":"D",m];
  }catch{
    return["D",memory||fresh()];
  }
}