void Robot::move()
{
    Pos p = posAfterMove();
    if (world_->canMoveTo(p)) pos_ = p;
}
bool recruit(int s, int dpxx, int dpxy, int dpxz, int cs, int axis, int turns, int dx, int dy, int dz){
	/* By introducing seemingly redundant parameter dpxx, dpxy and dpxz
	   (which is simply the position difference between molecule s and cs), 
	   we could be sure that the position difference would always have a change between -1 and 1,
	   thus avoiding the unphysical rotation near the surface due to periodic boundary conditions.

	   note: do not use static variables in this function unless required, because the function is recursive.
	*/
	ppos dpx(dpxx, dpxy, dpxz), n_dir;
	mol[s].status = 2;
	cluster_series[cluster_size++] = s; // use cluster_series instead of checking molecule status in loops to improve efficiency
	if (turns){
		switch (axis){
		case 0: n_dir.set(1, 0, 0); break;
		case 1: n_dir.set(0, 1, 0); break;
		case 2: n_dir.set(0, 0, 1);
		}
	}
	else{
		n_dir.set(dx, dy, dz);
	}
	mol[s].cluster_eff_rad_diff2 = (double)mod2(dpx.crossproduct(n_dir.x, n_dir.y, n_dir.z)) / mod2(n_dir);
	int i, j, k;
	int s1;
	int oOrnt, nOrnt;
	double E0, Ef, Er;
	double pf, pr;
	ppos px_cnt = mol[s].px,
		 px_fwd = posAfterMove(dpxx, dpxy, dpxz, cs, axis, turns, dx, dy, dz),
		 px_rev = posAfterMove(dpxx, dpxy, dpxz, cs, axis, turns ? (4 - turns) : 0, -dx, -dy, -dz),
		 npx;
	px_fwd.adjust();
	px_rev.adjust();
	mol[s].px_cnt_backup = px_cnt;
	mol[s].px_fwd_dest = px_fwd;
	mol[s].ornt_cnt_backup = oOrnt = mol[s].ornt;
	mol[s].ornt_fwd_dest = nOrnt = orntRot[mol[s].ornt][axis][turns];
	bool accept = true;
	double judge_value;
	if (s == 210){
		i = 100;
	}
	for (i = -1; i <= 1; i++){
		for (j = -1; j <= 1; j++){
			for (k = -1; k <= 1; k++){
				npx = mol[s].px.plus(i, j, k);
				npx.adjust();
				if ((i || j || k) && stage[npx.x][npx.y][npx.z] >= 0){ // propose a link
					s1 = stage[npx.x][npx.y][npx.z];
					if (px_fwd == npx){ // forward move cause overlap
						switch (mol[s1].status){
						case 0: // recruit and accept (temp)
							if (mol[s].links >= 8){
								cout << "Warning: too many links for particle " << s << endl;
								break;
							}
							mol[s].link_with[mol[s].links] = s1;
							if (px_rev == npx)mol[s].link_with_pRatio[mol[s].links] = 1; // reverse also overlap
							else{ // reverse not overlap
								E0 = interactEnergy(s, s1);
								mol[s].put(px_rev.x, px_rev.y, px_rev.z, orntRot[oOrnt][axis][turns ? (4 - turns) : 0]);
								Er = interactEnergy(s, s1);
								mol[s].put(px_cnt.x, px_cnt.y, px_cnt.z, oOrnt);
								pr = (Er > E0) ? (1 - exp(-(Er - E0) / k_B / T)) : 0;
								mol[s].link_with_pRatio[mol[s].links] = pr / 1.0;
							}
							mol[s].links++;
							accept = recruit(s1, dpxx + i, dpxy + j, dpxz + k, cs, axis, turns, dx, dy, dz) && accept; // "accept" must be put after "&&"
							break;
						case 1: // unrecruit and deny
							accept = false;
							break;
						case 2: ;// do nothing because already recruited
						}
					}
					else{ // forward move do not cause overlap
						switch (mol[s1].status){
						case 0: // try to recruit
							E0 = interactEnergy(s, s1);
							mol[s].put(px_fwd.x, px_fwd.y, px_fwd.z, nOrnt);
							Ef = interactEnergy(s, s1);
							mol[s].put(px_cnt.x, px_cnt.y, px_cnt.z, oOrnt);
							pf = (Ef > E0) ? (1 - exp(-(Ef - E0) / k_B / T)) : 0;
							judge_value = judge(gen);
							if (judge_value < pf){ // link formed (where pf must be over 0.0)
								if (mol[s].links >= 8){
									cout << "Warning: too many links for particle " << s << endl;
									break;
								}
								mol[s].link_with[mol[s].links] = s1;
								if (px_rev == npx)mol[s].link_with_pRatio[mol[s].links] = 1; // reverse overlap
								else{ // reverse not overlap
									mol[s].put(px_rev.x, px_rev.y, px_rev.z, orntRot[oOrnt][axis][turns ? (4 - turns) : 0]);
									Er = interactEnergy(s, s1);
									mol[s].put(px_cnt.x, px_cnt.y, px_cnt.z, oOrnt);
									pr = (Er > E0) ? (1 - exp(-(Er - E0) / k_B / T)) : 0;
									mol[s].link_with_pRatio[mol[s].links] = pr / pf;
								}
								mol[s].links++;
								accept = recruit(s1, dpxx + i, dpxy + j, dpxz + k, cs, axis, turns, dx, dy, dz) && accept; // "accept" must be put after "&&"
							}
							break;
						case 1: case 2: ;// do nothing
						}
					}
					//calculate energy
				}
			}
		}
	}
	// do not prevent far away collisions
	return accept;
}