<!-- RUBY-BACKUP · part 474 -->
h.cos(ba)*0.8;
    branch.rotation.x = -Math.sin(ba)*0.8;
    g.add(branch);
    /* leaves */
    var leaves = new THREE.Mesh(new THREE.SphereGeometry(0.6, 8, 8),
      new THREE.MeshStandardMaterial({color: 0x3a7a3a, roughness: 0.9}));
    leaves.position.set(Math.cos(ba)*1.2, 3.2, Math.sin(ba)*1.2);
    g.add(leaves);
  }
  /* beggar — sitting in the branches */
  var skin = new THREE.MeshStandardMaterial({color: 0xb88858, roughness: 0.85});
  var rags = new THREE.MeshStandardMaterial({color: 0x7a6a5a, roughness: 1});
  var beggar = new THREE.Group();
  var bHead = new THREE.Mesh(new THREE.SphereGeometry(0.14, 12, 12), skin);
  bHead.position.y = 0.5; beggar.add(bHead);
  /* wide grin */
  var grin = new THREE.Mesh(new THREE.TorusGeometry(0.07, 0.015, 6, 12, Math.PI),
    new THREE.MeshStandardMaterial({color: 0x4a2a1a}));
  grin.position.set(0.1, 0.45, 0); grin.rotation.y = Math.PI/2; grin.rotation.z = Math.PI;
  beggar.add(grin);
  var bBody = new THREE.Mesh(new THREE.CylinderGeometry(0.15, 0.18, 0.5, 8), rags);
  bBody.position.y = 0.15; beggar.add(bBody);
  /* holding a cup out */
  var cup = new THREE.Mesh(new THREE.CylinderGeometry(0.08, 0.06, 0.12, 10),
    new THREE.MeshStandardMaterial({color: 0xaa8833, metalness: 0.6, roughness: 0.5}));
  cup.position.set(0.25, 0.3, 0.2); beggar.add(cup);
  var arm = new THREE.Mesh(new THREE.CylinderGeometry(0.04, 0.04, 0.4, 6), skin);
  arm.position.set(0.15, 0.3, 0.15); arm.rotation.z = -1.0;
  beggar.add(arm);
  beggar.position.set(0.8, 2.2, 0.3);
  beggar.rotation.z = -0.3; /* lounging */
  g.add(beggar);
  g.position.set(x, y, z);
  var t = Math.random()*10;
  var anim = setInterval(function(){
    t += 0.03;
    /* swinging legs, content */
    beggar.rotation.z = -0.3 + Math.sin(t)*0.08;
    cup.position.y = 0.3 + Math.sin(t*2)*0.03; /* jingling cup */
  }, 50);
  g.userData.anim = anim;
  return g;
}
function buildQuestionGuy(x, y, z){
  var g = new THREE.Group();
  var skin = new THREE.MeshStandardMaterial({color: 0xd4a574, roughness: 0.7});
  var robe = new THREE.MeshStandardMaterial({color: 0x4a4a6a, roughness: 0.85});
  /* thoughtful pose — hand on chin */
  var head = new THREE.Mesh(new THREE.SphereGeometry(0.15, 16, 16), skin);
  head.position.y = 1.45; head.rotation.x = -0.15; /* looking up, thinking */
  g.add(head);
  /* furrowed brow */
  var brow = new THREE.Mesh(new THREE.BoxGeometry(0.02, 0.02, 0.12),
    new THREE.MeshStandardMaterial({color: 0x2a1a0a}));
  brow.position.set(0.12, 1.5, 0);
  g.add(brow);
  var body = new THREE.Mesh(new THREE.CylinderGeometry(0.2, 0.28, 1.0, 12), robe);
  body.position.y = 0.8; g.add(body);
  /* hand on chin */
  var arm = new THREE.Mesh(new THREE.CylinderGeometry(0.045, 0.04, 0.4, 8), robe);
  arm.position.set(0.15, 1.15, 0.15); arm.rotation.z = -0.8;
  g.add(arm);
  var hand = new THREE.Mesh(new THREE.SphereGeometry(0.05, 10, 10), skin);
  hand.position.set(0.1, 1.35, 0.08);
  g.add(hand);
  /* question marks — floating */
  var questions = [
    'Why is the sky?',
    'What is a thought?',
    'Where does lost go?',
    'Who asks the asker?'
  ];
  var qIdx = 0;
  var qCv = document.createElement('canvas');
  qCv.width = 512; qCv.height = 64;
  var qCtx = qCv.getContext('2d');
  var qTex = new THREE.CanvasTexture(qCv);
  var qLabel = new THREE.Mesh(new THREE.PlaneGeometry(2.5, 0.31),
    new THREE.MeshBasicMaterial({map: qTex, transparent: true}));
  qLabel.position.set(0, 2.0, 0);
  g.add(qLabel);
  function drawQuestion(){
    qCtx.clearRect(0, 0, 512, 64);
    qCtx.fillStyle = '#aaccff';
    qCtx.font = 'italic 28px Georgia';
    qCtx.textAlign = 'center';
    qCtx.fillText(questions[qIdx], 256, 42);
    qTex.needsUpdate = true;
    qIdx = (qIdx+1) % questions.length;
  }
  drawQuestion();
  var qTimer = setInterval(drawQuestion, 4000);
  g.userData.qTimer = qTimer;
  g.position.set(x, y, z);
  var t = 0;
  var anim = setInterval(function(){
    t += 0.02;
    /* pacing — back and forth, thinking */
    g.position.x = x + Math.sin(t*0.5)*1.5;
    g.rotation.y = Math.cos(t*0.5) > 0 ? Math.PI/2 : -Math.PI/2;
    head.rotation.x = -0.15 + Math.sin(t*2)*0.05;
  }, 50);
  g.userData.anim = anim;
  return g;
}
function placeThreeSouls(){
  if(typeof scene==='undefined' || typeof mePos==='undefined') return;
  var px = mePos.x, pz = mePos.z;
  /* broken robot — near the underworld */
  var br = buildBrokenRobot((px-175)*0.13, 0, (pz+125)*0.13);
  scene.add(br);
  /* beggar in tree — near storm beach */
  var tb = buildTreeBeggar((px-175)*0.13, 0, (pz-115)*0.13);
  scene.add(tb);
  /* question guy — near wormholes */
  var qg = buildQuestionGuy((px+175)*0.13, 0, (pz+125)*0.13);
  scene.add(qg);
  if(!DARK_PLACES) DARK_PLACES = [];
  DARK_PLACES.push(br, tb, qg);
  codeStatus('three more souls — broken robot, tree beggar, question guy.');
}

/* GOOD SOULS — they come by and give missions */
var MISSION_GIVERS = [];
var MISSIONS = [
  {giver: 'Kai', soul: 'broken robot', text: '