#include "search.h"
/*
   SQUIES

   does not examine: checks, skewer, forks, or removals
   does not recognize: stalemate
   does not recognize mate, unless QMATE defined
*/
//extern int feature[2][nbFeatures];
//extern const char * Feature_name[nbFeatures];

int squies(int alpha, int beta){

	int v, best, se, j, bm = 0;
	int flag, legal=0; 
	int do_prune = (beta == (alpha+1) && beta > -MATE+MAXPLY /* && alpha < MATE-MAXPLY */);
	//int i, temp;
	sMOVES * m;
	sMOVES * l;

	assert(alpha < beta);
	assert(alpha >= -MATE);
	assert(alpha < MATE);
	assert(beta > -MATE);
	assert(beta <= MATE);
	assert(!checkboard());

	++nodes;

	pvl[ply] = ply;


#ifndef FAST
	if(ply > qdepth) qdepth = ply;
#endif

	/* Too deep? */
	if(ply > MAXPLY-3)
	{
		return beta;
	}

	/*
	   o Search will NOT call quies while incheck. But,
	   o Recursive call from quies() could be check. [stm is in check!]
	   o If stm is in check, all but legal moves will be refuted by capturing King
	 *** UNLESS we stand pat or worse, fail high, or no CAPs ***
	 (but did snm checkmate us? why not 'bank on' NO )
	 o If snm in check, is ok for stm to FH on SE score, 
	 else capturing king will certainly fail high!
	 o If snm stalemated, we may lose win

	 o If stm stalemated, we may lose draw
	 */

#ifdef QMATE
	if (mhs->threat & IN_CHECK) {
		gen();
		legal = 0;
		l = last_move[ply];
		m = last_move[ply - 1];
		j = beta;
		while (m < l) {
			if (pseudoev[128 + kingsq[stm] - m->move.data.dest] == 0) {
				--l;
				*m = *l;
				continue;
			}

			domove(&m->move);

			if (inCheck(stm ^ 1)) {
				unmove();
				--l;
				*m = *l;

				continue;
			}

			if (m->move.data.type > CAQ) {
				unmove();
				++legal;
				--l;
				*m = *l;
				continue;
			}

			m->score -= fval[m->move.data.piece];

			unmove();

			++legal;
			++m;
		};

		last_move[ply] = l;


		if (legal == 0) {

			best = -MATE + ply;
			return best;
		}
	} 
#endif // QMATE

	se = evaluate();
	//se = force[stm] + types[BP|stm] - force[stm^1] - types[WP-stm];
	//return se;

	best = se;

	if(best > alpha){



		if(best >= beta){
#ifdef TRACE
			fprintf(trace, "\n");
#endif 


			/* stm^1 is trying a very bad idea that stm need not respond to */

			return best;
		}
		alpha = best;
	}



#ifdef QMATE
	if (mhs->threat & IN_CHECK) ;
	else genc();
#else
	if(genc()) return MATE+1-ply;
#endif


	l = last_move[ply];
	m = last_move[ply-1];


#ifdef HASHQ

	if(hashmove) tagpv(m, hashmove, 8000000);
#endif 

	for(; m < l; ++m){

		sortmvs(m);

		domove(&m->move);


		mhs->threat = 0;
#ifdef QMATE
		if (pseudoev[128 + kingsq[stm] - m->move.data.from] == 1
				|| pseudoev[128 + kingsq[stm] - m->move.data.dest] == 1
				|| (m->move.data.type == CAK && pseudoev[128 + kingsq[stm] - (m->move.data.dest - 1)] == 1)
				|| (m->move.data.type == CAQ && pseudoev[128 + kingsq[stm] - (m->move.data.dest + 1)] == 1)
				|| (m->move.data.type == ENP && pseudoev[128 + kingsq[stm] - (m->move.data.dest + (16 - (stm << 5)))] == 1)
		   ) {
			mhs->threat |= inCheck(stm);
		}
#endif // QMATE

#ifdef TRACE 
		move2str(&m->move, ms);

		fprintf(trace, "Q%10u_%d.%d %s (%d, %d, %d) ", (unsigned int)((mhs-1)->key), ply-1, m-last_move[ply-2]+1, ms, 0, -beta, -alpha); 
#endif 

#ifdef DELTAPRUNE

		/*
		   Here, delta pruning is simply a form of lazy eval.
		   We are reasonably sure full eval will FH after move
		   and quies() is called.

		   Passer [in end] and KS [in middle] can trump this
		   theory. .:.

		   We may gain considerably or remove threats against.

		   o Where offense is low and passers can run = 300!
		   o When Queen is near King [assume it has help!]
		   o Promotion adds Queen to KS issues 1/2 total KS ?
		   o King moves to shelter
		   o Queen capture can REMOVE large KS issue
		   o Capturing passer on 7th 200?
		   o Full eval recognizes drawn patterns 175

		   There are so many more, even worse:

		   o Check, Fork, Skewer, Hanging 
		 ***************************************************
		 But eval would miss these too! We're only trying to
		 avoid missing what a full eval might catch!!!
		 ***************************************************
		 */

		flag = 0;
		if(
				do_prune
				&& !big_potential_caps(&m->move)
				&& (alpha >= 0 || isdrawn() == 0)
				
		  ){
			if((v = se + mval[(mhs-1)->victim] + max(3 * (force[WHITE]+force[BLACK]), 100 * ((types[WP] > 0) || (types[BP] > 0)))) <= alpha)
			{

				/* 588 w|w/o/ checks Tuesday June 24 2008 
				   if(abs(v)<200) {
				   flag=-evaluate();
				   if(flag>v) {
				   flag = flag-v;

				   if(flag > alpha) { 
				   most=flag;
				   printf("(((%d)))\n", flag);

				   display();


				   getchar();

				   }
				   }
				   }*/
				   
				++red_delta;
				flag=1;
				unmove();
				continue;

			}
		}
#endif

#ifndef FAST 
		++qnodes;

#endif


		v = -squies(-beta, -alpha);


		unmove();

#ifdef TRACE
		fprintf(trace, "\n");
#endif

		if(stop_search) return 0;


		if(v > best)
		{
			if(v > alpha)
			{
				/*
				if(flag) {
					//printf("*");
					display();
					memset(feature, 0, sizeof(feature));
					temp = evaluate();
					for (i=0; i<nbFeatures; ++i) {
						printf("WHITE %s: %d\tBLACK %s: %d\n", Feature_name[i], feature[WHITE][i], Feature_name[i], feature[BLACK][i]);
					}
					printf("A Score B  Est Eval:	%d %d %d (%d %d)\n", alpha, v, beta, flag, temp);
					getchar();
				}
				*/

				if(v >= beta)
				{

#ifndef FAST 
					++fhn;
					fh1 += (int)(m == last_move[ply-1]); 
#endif
					return v;
				}

				alpha = v;



				/* update the PV */
				pv[ply][ply] = m->move; 
				for(j = ply + 1; j < pvl[ply + 1]; ++j)
					pv[ply][j] = pv[ply + 1][j];
				pvl[ply] = pvl[ply + 1];

			}
			best = v;
			bm = m->move.asint;

		}
		legal = 1;
	}


	return best;
}

