#define MAT_Q			(1)
#define MAT_R			(2)
#define MAT_B			(2)
#define MAT_N			(2)
#define MAT_P			(8)
#define MATERIAL_SIZE	(MATH_SQUARE(MAT_Q+1)* MATH_SQUARE(MAT_R+1)* MATH_SQUARE(MAT_B+1)* MATH_SQUARE(MAT_N+1)* MATH_SQUARE(MAT_P+1)) 
#define MATERIAL_KEY(wp,wn,wb,wr,wq,bp,bn,bb,br,bq)	(\
	(bq) + \
	2*(wq) + \
	2*2*(br) + \
	2*2*3*(wr) + \
	2*2*3*3*(bb) + \
	2*2*3*3*3*(wb) + \
	2*2*3*3*3*3*(bn) + \
	2*2*3*3*3*3*3*(wn) + \
	2*2*3*3*3*3*3*3*(bp) + \
	2*2*3*3*3*3*3*3*9*(wp))

#define PAWN_VALUE      100
#define KNIGHT_VALUE    330
#define BISHOP_VALUE    330
#define ROOK_VALUE      500
#define QUEEN_VALUE     975
#define KING_VALUE    10000

const int PieceValues[] = {0, PAWN_VALUE, KNIGHT_VALUE, BISHOP_VALUE, ROOK_VALUE, QUEEN_VALUE, KING_VALUE};
const int PieceValuesPromote[] = {QUEEN_VALUE, KNIGHT_VALUE, ROOK_VALUE, BISHOP_VALUE};
#define PIECE_VALUE(piece)				(PieceValues[piece])
#define PIECE_VALUE_PROMOTE(result)		(PieceValuesPromote[result] - PAWN_VALUE)

int MatDiffValue[2][6]; // [colour][piece]
int MatKeyValue[2][6];
int MatDiffValuePromo[2][4]; 
int MatKeyValuePromo[2][4];
#define MAT_DIFF_VALUE(col,pc)			(MatDiffValue[col][pc-1])
#define MAT_KEY_VALUE(col,pc)			(MatKeyValue[col][pc-1])
#define MAT_KEY_VALUE_PROMO(col,pc)		(MatKeyValuePromo[col][pc-2])
#define MAT_DIFF_VALUE_PROMO(col,pc)	(MatDiffValuePromo[col][pc-2])

bool DrawRecognized(int wp, int wn, int wb, int wr, int wq, int bp, int bn, int bb, int br, int bq);
int SpecialRecognized(int wp, int wn, int wb, int wr, int wq, int bp, int bn, int bb, int br, int bq, bool *special);

//    __________________________________________________________
//   |  DATA BITFIELD   |    DESCRIPTION  |  BITS | FLAG | SPEC |
//   |__________________|_________________|_______|______|______|
//   |					|				  |	      |      |      |
//   |00000000 00111111 |	  phase		  | 1-6   |  0   |  -   |
//   |00000000 01000000 | material draw	  |  7    |  6   |  1   |
//   |00000000 10000000 | white shelter	  |  8    |  7   |  2   |
//   |00000001 00000000 | black shelter	  |  9    |  8   |  3   |
//   |00000010 00000000 |  bishop draw	  |  10   |  9   |  4   |
//   |00000100 00000000 |  rook endgame	  |  11   |  10  |  5   |
//   |00001000 00000000 |  pawn endgame	  |  12   |  11  |  6   |
//   |00010000 00000000 |   lazy eval	  |  13   |  12  |  7   |
//   |11110000 00000000 |	 reserved	  | 14-16 |  13  |  -   |
//   |__________________|_________________|_______|______|______|

class MaterialEntry {
public:	
	sint16 value;
	uint16 data;

	void Store(sint16 val, int phase, bool mat_draw, bool w_shelter, bool b_shelter, bool bishop_draw, bool rook_eg, bool pawn_eg, bool lazy) {
		value = val;
		data = phase & 0x3F;
		if(mat_draw)		data |= (1<<6);
		if(w_shelter)		data |= (1<<7);
		if(b_shelter)		data |= (1<<8);
		if(bishop_draw)		data |= (1<<9);
		if(rook_eg)		    data |= (1<<10);
		if(pawn_eg)		    data |= (1<<11);
		if(lazy)			data |= (1<<12);
	}
	void Retrieve(sint16 *val,int *phase,bool *mat_draw,bool *w_shelter,bool *b_shelter,bool *bishop_draw,bool *rook_eg,bool *pawn_eg,bool *lazy) {
		*val = value;
		*phase = data & 0x3F;
		*mat_draw = data & (1<<6);
		*w_shelter = data & (1<<7);
		*b_shelter = data & (1<<8);
		*bishop_draw = data & (1<<9);
		*rook_eg = data & (1<<10);
		*pawn_eg = data & (1<<11);
		*lazy = data & (1<<12);
	}
};

MaterialEntry *material;

void MaterialInit() {

	// allocate memory
	material = (MaterialEntry*)malloc(MATERIAL_SIZE * sizeof(MaterialEntry));
	ASSERT(sizeof(MaterialEntry)==4);

	// init
	int i, k, tmp;
	int wp, wn, wb, wr, wq, 
		bp, bn, bb, br, bq;
	int key, diff, minors, majors, value, phase;	
	bool mat_draw, w_shelter, b_shelter, bishop_draw, special, rook_eg, pawn_eg, lazy;

	// material correction
	int val_1, val_2, val_3, val_4,
		w_minors, b_minors,	w_heavy, b_heavy;
	const int PAWN_MW_xx = 16,		PAWN_MW_xM = -20,		PAWN_MW_Hx = -19,		PAWN_MW_HM = 18,
			BISHOP_MW_xx = 23,		BISHOP_MW_xM = 50,		BISHOP_MW_Hx = 20,		BISHOP_MW_HM = 60,
			ROOK_MW_xx = 29,		ROOK_MW_xM = -2,		ROOK_MW_Hx = 9,			ROOK_MW_HM = 8,
			QUEEN_MW_xx = -18,		QUEEN_MW_xM = 102,		QUEEN_MW_Hx = 18,		QUEEN_MW_HM = -12,
			KNIGHT_MW_xxx = -31,	KNIGHT_MW_xMx = -20,	KNIGHT_MW_Hxx = -2,		KNIGHT_MW_HMx = -20,
			KNIGHT_MW_xxP = 17,		KNIGHT_MW_xMP = 20,		KNIGHT_MW_HxP = -20,	KNIGHT_MW_HMP = -19,
			BISHOP_PAIR_OP_x = -5,	BISHOP_PAIR_OP_P = -36,	BISHOP_PAIR_EG_x = -27,	BISHOP_PAIR_EG_P = 46;

	// values
	int MAX_SHELTER_VALUE = 140;
	
	// Mat..Value
	wp = wn = wb = wr = wq = bp = bn = bb = br = bq = 1;
	MAT_KEY_VALUE(WHITE, PAWN) = MATERIAL_KEY(wp,0,0,0,0,0,0,0,0,0);
	MAT_KEY_VALUE(WHITE, KNIGHT) = MATERIAL_KEY(0,wn,0,0,0,0,0,0,0,0);
	MAT_KEY_VALUE(WHITE, BISHOP) = MATERIAL_KEY(0,0,wb,0,0,0,0,0,0,0);
	MAT_KEY_VALUE(WHITE, ROOK) = MATERIAL_KEY(0,0,0,wr,0,0,0,0,0,0);
	MAT_KEY_VALUE(WHITE, QUEEN) = MATERIAL_KEY(0,0,0,0,wq,0,0,0,0,0);

	MAT_KEY_VALUE(BLACK, PAWN) = MATERIAL_KEY(0,0,0,0,0,bp,0,0,0,0);
	MAT_KEY_VALUE(BLACK, KNIGHT) = MATERIAL_KEY(0,0,0,0,0,0,bn,0,0,0);
	MAT_KEY_VALUE(BLACK, BISHOP) = MATERIAL_KEY(0,0,0,0,0,0,0,bb,0,0);
	MAT_KEY_VALUE(BLACK, ROOK) = MATERIAL_KEY(0,0,0,0,0,0,0,0,br,0);
	MAT_KEY_VALUE(BLACK, QUEEN) = MATERIAL_KEY(0,0,0,0,0,0,0,0,0,bq);

	MAT_KEY_VALUE(WHITE, KING) = 0;
	MAT_KEY_VALUE(BLACK, KING) = 0;

	MAT_DIFF_VALUE(WHITE, PAWN) = +PAWN_VALUE;
	MAT_DIFF_VALUE(WHITE, KNIGHT) = +KNIGHT_VALUE;
	MAT_DIFF_VALUE(WHITE, BISHOP) = +BISHOP_VALUE;
	MAT_DIFF_VALUE(WHITE, ROOK) = +ROOK_VALUE;
	MAT_DIFF_VALUE(WHITE, QUEEN) = +QUEEN_VALUE;

	MAT_DIFF_VALUE(BLACK, PAWN) = -PAWN_VALUE;
	MAT_DIFF_VALUE(BLACK, KNIGHT) = -KNIGHT_VALUE;
	MAT_DIFF_VALUE(BLACK, BISHOP) = -BISHOP_VALUE;
	MAT_DIFF_VALUE(BLACK, ROOK) = -ROOK_VALUE;
	MAT_DIFF_VALUE(BLACK, QUEEN) = -QUEEN_VALUE;

	MAT_DIFF_VALUE(WHITE, KING) = 0;
	MAT_DIFF_VALUE(BLACK, KING) = 0;

	for(i = KNIGHT; i <= QUEEN; i++)		// pieces to promote
		for(k = 0; k < 2; k++) {			// colour
			MAT_DIFF_VALUE_PROMO(k, i) = MAT_DIFF_VALUE(k, i) - MAT_DIFF_VALUE(k, PAWN);
			MAT_KEY_VALUE_PROMO(k, i) = MAT_KEY_VALUE(k, i) - MAT_KEY_VALUE(k, PAWN);
	}

	for(wp = 0; wp <= MAT_P; wp++)
	for(bp = 0; bp <= MAT_P; bp++)
	for(wn = 0; wn <= MAT_N; wn++)
	for(bn = 0; bn <= MAT_N; bn++)
	for(wb = 0; wb <= MAT_B; wb++)
	for(bb = 0; bb <= MAT_B; bb++)
	for(wr = 0; wr <= MAT_R; wr++)
	for(br = 0; br <= MAT_R; br++)
	for(wq = 0; wq <= MAT_Q; wq++)
	for(bq = 0; bq <= MAT_Q; bq++) {

		value = 0;	
		special = false;
		minors = wn + bn + wb + bb;
		majors = wr + br + 2*(wq + bq);
		key = MATERIAL_KEY(wp,wn,wb,wr,wq,bp,bn,bb,br,bq);	

		if(mat_draw = DrawRecognized(wp,wn,wb,wr,wq,bp,bn,bb,br,bq)) ;
		else value = SpecialRecognized(wp,wn,wb,wr,wq,bp,bn,bb,br,bq, &special); 

		// phase [0 - opening => 24 endgame]
		phase = PHASE_NB - 2*majors - minors;
		ASSERT(phase >= 0);
		ASSERT(phase <= PHASE_NB);

		// evaluate shelter?
		w_shelter = (bq >= 1 && (bn + bb + br) >= 1);
		b_shelter = (wq >= 1 && (wn + wb + wr) >= 1);
		if(w_shelter)	value -= ((PHASE_NB - phase) * MAX_SHELTER_VALUE) / PHASE_NB;
		if(b_shelter)	value += ((PHASE_NB - phase) * MAX_SHELTER_VALUE) / PHASE_NB;

		// possible bishop draw, rook endgame, pawn endgame & lazy eval
		bishop_draw = (wb == 1 && bb == 1 && (wn+wr+wq) <= 1 && (bn+br+bq) <= 1);
		rook_eg = (minors == 0 && wr == 1 && br == 1 && majors == 2);
		pawn_eg = (minors == 0 && majors == 0);
		lazy = (wn + wb + wr + wq >= 3) || (bn + bb + br + bq >= 3);

		// material correction
		// values was ganerated by auto tuning 
		// (see auto.h and instruction in main.cpp)
		w_heavy = wr + 2*wq;	
		b_heavy = br + 2*bq;
		w_minors = wb + wn;
		b_minors = bb + bn;		

		// pawn
		val_1 = (PAWN_MW_xx * (4-w_minors) + PAWN_MW_xM * w_minors) / 4;
		val_2 = (PAWN_MW_Hx * (4-w_minors) + PAWN_MW_HM * w_minors) / 4;
		value += wp * (val_1 * (4-w_heavy) + val_2 * w_heavy) / 4;
		val_1 = (PAWN_MW_xx * (4-b_minors) + PAWN_MW_xM * b_minors) / 4;
		val_2 = (PAWN_MW_Hx * (4-b_minors) + PAWN_MW_HM * b_minors) / 4;
		value -= bp * (val_1 * (4-b_heavy) + val_2 * b_heavy) / 4;
		// bishops	
		val_1 = (BISHOP_MW_xx * (4-w_minors) + BISHOP_MW_xM * w_minors) / 4;
		val_2 = (BISHOP_MW_Hx * (4-w_minors) + BISHOP_MW_HM * w_minors) / 4;
		value += wb * (val_1 * (4-w_heavy) + val_2 * w_heavy) / 4;
		val_1 = (BISHOP_MW_xx * (4-b_minors) + BISHOP_MW_xM * b_minors) / 4;
		val_2 = (BISHOP_MW_Hx * (4-b_minors) + BISHOP_MW_HM * b_minors) / 4;
		value -= bb * (val_1 * (4-b_heavy) + val_2 * b_heavy) / 4;
		// rooks	
		val_1 = (ROOK_MW_xx * (4-w_minors) + ROOK_MW_xM * w_minors) / 4;
		val_2 = (ROOK_MW_Hx * (4-w_minors) + ROOK_MW_HM * w_minors) / 4;
		value += wr * (val_1 * (4-w_heavy) + val_2 * w_heavy) / 4;
		val_1 = (ROOK_MW_xx * (4-b_minors) + ROOK_MW_xM * b_minors) / 4;
		val_2 = (ROOK_MW_Hx * (4-b_minors) + ROOK_MW_HM * b_minors) / 4;
		value -= br * (val_1 * (4-b_heavy) + val_2 * b_heavy) / 4;
		// queens	
		val_1 = (QUEEN_MW_xx * (4-w_minors) + QUEEN_MW_xM * w_minors) / 4;
		val_2 = (QUEEN_MW_Hx * (4-w_minors) + QUEEN_MW_HM * w_minors) / 4;
		value += wq * (val_1 * (4-w_heavy) + val_2 * w_heavy) / 4;
		val_1 = (QUEEN_MW_xx * (4-b_minors) + QUEEN_MW_xM * b_minors) / 4;
		val_2 = (QUEEN_MW_Hx * (4-b_minors) + QUEEN_MW_HM * b_minors) / 4;
		value -= bq * (val_1 * (4-b_heavy) + val_2 * b_heavy) / 4;
		// knights
		val_1 = (KNIGHT_MW_xxx * (4-w_minors) + KNIGHT_MW_xMx * w_minors) / 4;
		val_2 = (KNIGHT_MW_Hxx * (4-w_minors) + KNIGHT_MW_HMx * w_minors) / 4;
		val_3 = (val_1 * (4-w_heavy) + val_2 * w_heavy) / 4;
		val_1 = (KNIGHT_MW_xxP * (4-w_minors) + KNIGHT_MW_xMP * w_minors) / 4;
		val_2 = (KNIGHT_MW_HxP * (4-w_minors) + KNIGHT_MW_HMP * w_minors) / 4;
		val_4 = (val_1 * (4-w_heavy) + val_2 * w_heavy) / 4;
		value += wn * (val_3 * (8-wp) + val_4 * wp) / 8;
	
		val_1 = (KNIGHT_MW_xxx * (4-b_minors) + KNIGHT_MW_xMx * b_minors) / 4;
		val_2 = (KNIGHT_MW_Hxx * (4-b_minors) + KNIGHT_MW_HMx * b_minors) / 4;
		val_3 = (val_1 * (4-b_heavy) + val_2 * b_heavy) / 4;
		val_1 = (KNIGHT_MW_xxP * (4-b_minors) + KNIGHT_MW_xMP * b_minors) / 4;
		val_2 = (KNIGHT_MW_HxP * (4-b_minors) + KNIGHT_MW_HMP * b_minors) / 4;
		val_4 = (val_1 * (4-b_heavy) + val_2 * b_heavy) / 4;
		value -= bn * (val_3 * (8-bp) + val_4 * bp) / 8;
		// bishop pair	
		if(wb >= 2) {
			val_1 = (BISHOP_PAIR_OP_x * (8-wp) + BISHOP_PAIR_OP_P * wp) / 8; // op
			val_2 = (BISHOP_PAIR_EG_x * (8-wp) + BISHOP_PAIR_EG_P * wp) / 8; // eg
			value += ((phase * val_2 + (PHASE_NB - phase) * val_1) / PHASE_NB);
		} if(bb >= 2) {
			val_3 = (BISHOP_PAIR_OP_x * (8-bp) + BISHOP_PAIR_OP_P * bp) / 8; // op
			val_4 = (BISHOP_PAIR_EG_x * (8-bp) + BISHOP_PAIR_EG_P * bp) / 8; // eg
			value -= ((phase * val_4 + (PHASE_NB - phase) * val_3) / PHASE_NB);
		}
						
		// store		
		material[key].Store(value, phase, mat_draw, w_shelter, b_shelter, bishop_draw, rook_eg, pawn_eg, lazy);

		ASSERT(key <= MATERIAL_SIZE);
		ASSERT(key >= 0);
	}
}

// DrawRecognized()

bool DrawRecognized(int wp, int wn, int wb, int wr, int wq, int bp, int bn, int bb, int br, int bq) {

	int wt = wp + wn + wb + wr + wq;	// white total
	int bt = bp + bn + bb + br + bq;	// black total

	if(wt <= 1 && bt <= 1) {
		if(wt == 0 && bt == 0)	return true; // KK
		if(wb == 1 && bt == 0)	return true; // KBK
		if(wn == 1 && bt == 0)	return true; // KNK
		if(wt == 0 && bb == 1)	return true; // KKB
		if(wt == 0 && bn == 1)	return true; // KKN
		if(wn == 1 && bn == 1)	return true; // KNKN
		if(wb == 1 && bb == 1)	return true; // KBKB
		if(wn == 1 && bb == 1)	return true; // KNKB
		if(wb == 1 && bn == 1)	return true; // KBKN
		if(wr == 1 && br == 1)	return true; // KRKR
		if(wq == 1 && bq == 1)	return true; // KQKQ
		if(wb == 1 && bp == 1)	return true; // KBKP
		if(wp == 1 && bb == 1)	return true; // KPKB

	} else if(wt <= 2 && bt <= 2) {
		if(wn == 2 && bt == 0)	return true; // KNNK
		if(wt == 0 && bn == 2)	return true; // KKNN
		if(wn == 2 && bn == 1 && bt == 1)	return true; // KNNKN
		if(wt == 1 && wn == 1 && bn == 2)	return true; // KNKNN
		if(wn == 2 && bb == 1 && bt == 1)	return true; // KNNKB
		if(wt == 1 && wb == 1 && bn == 2)	return true; // KBKNN
	}
	return false;
}

int SpecialRecognized(int wp, int wn, int wb, int wr, int wq, int bp, int bn, int bb, int br, int bq, bool *special) {
	
	int value = PAWN_VALUE*(wp-bp) + KNIGHT_VALUE*(wn-bn) + BISHOP_VALUE*(wb-bb) + ROOK_VALUE*(wr-br) + QUEEN_VALUE*(wq-bq);
	int wt = wp + wn + wb + wr + wq;	// white total
	int bt = bp + bn + bb + br + bq;	// black total
	int t = wt + bt;					// pieces total
	int ratio = 100;					// 0 means draw

	if(wt <= 1 && bt <= 1) {
		if(wn == 1 && bp == 1)	ratio = -5; // KNKP		
		if(wp == 1 && bn == 1)	ratio = -5; // KPKN		
		if(wr == 1 && bn == 1)	ratio = 10; // KRKN
		if(wn == 1 && br == 1)	ratio = 10; // KNKR
		if(wr == 1 && bb == 1)	ratio = 10; // KRKB
		if(wb == 1 && br == 1)	ratio = 10; // KBKR
		if(wq == 1 && br == 1)	ratio = 80; // KQKR
		if(wr == 1 && bq == 1)	ratio = 80; // KQKR
	} else if(wt <= 2 && bt <= 2) {
		if(wn == 2 && br == 1 && bt == 1)	ratio = -5;	// KNNKR
		if(wt == 1 && wr == 1 && bn == 2)	ratio = -5;	// KRKNN
		if(wp == 2 && bn == 1 && bt == 1)	ratio = -1; // KPPKN
		if(wt == 1 && wn == 1 && bp == 2)	ratio = -1; // KNKPP
		if(wp == 2 && bb == 1 && bt == 1)	ratio = -1; // KPPKB
		if(wt == 1 && wb == 1 && bp == 2)	ratio = -1; // KBKPP
		if(wp == 1 && wn == 1 && bn == 2)	ratio = -1;	// KNPKNN
		if(wn == 2 && bn == 1 && bp == 1)	ratio = -1;	// KNNKNP
		if(wp == 1 && wb == 1 && bn == 2)	ratio = -1;	// KBPKNN
		if(wn == 2 && bb == 1 && bp == 1)	ratio = -1;	// KNNKBP
		if(wb == 2 && bn == 1 && t == 3)	ratio = 60;	// KBBKN
		if(wn == 1 && bb == 2 && t == 3)	ratio = 60;	// KNKBB
		if(wb == 2 && bb == 1 && t == 3)	ratio = 10;	// KBBKB
		if(wb == 1 && bb == 2 && t == 3)	ratio = 10;	// KBKBB
		if(wb == 2 && bb == 1 && bp == 1)	ratio = 10;	// KBBKBP
		if(wb == 1 && wp == 1 && bb == 2)	ratio = 10;	// KBPKBB
		if(wb == 2 && bn == 1 && bp == 1)	ratio = 12;	// KBBKNP
		if(wn == 1 && wp == 1 && bb == 2)	ratio = 12;	// KNPKBB
		if(wq == 1 && wb == 1 && br == 2)	ratio = 25;	// KQBKRR
		if(wr == 2 && bq == 1 && bb == 1)	ratio = 25;	// KRRKQB
		if(wq == 1 && wn == 1 && br == 2)	ratio = 25;	// KQNKRR
		if(wr == 2 && bq == 1 && bn == 1)	ratio = 25;	// KRRKQN

		if(wp == 1 && wb == 1 && bb == 1 && bt == 1)	ratio = 10;	// KBPKB
		if(wt == 1 && wb == 1 && bb == 1 && bp == 1)	ratio = 10;	// KBKBP
		if(wp == 1 && wn == 1 && bn == 1 && bt == 1)	ratio = 10;	// KNPKN
		if(wt == 1 && wn == 1 && bn == 1 && bp == 1)	ratio = 10;	// KNKNP
		if(wp == 1 && wb == 1 && bn == 1 && bt == 1)	ratio = 10;	// KBPKN
		if(wt == 1 && wn == 1 && bb == 1 && bp == 1)	ratio = 10;	// KNKBP
		if(wp == 1 && wn == 1 && bb == 1 && bt == 1)	ratio = 10;	// KNPKB
		if(wt == 1 && wb == 1 && bn == 1 && bp == 1)	ratio = 10;	// KBKNP
		if(wr == 1 && wn == 1 && br == 1 && t == 3)		ratio = 3;	// KRNKR
		if(wr == 1 && br == 1 && bn == 1 && t == 3)		ratio = 3;	// KRKRN
		if(wr == 1 && wb == 1 && br == 1 && t == 3)		ratio = 6;	// KRBKR
		if(wr == 1 && br == 1 && bb == 1 && t == 3)		ratio = 6;	// KRKRB
		if(wb == 1 && wn == 1 && bb == 1 && t == 3)		ratio = 10;	// KBNKB
		if(wb == 1 && bn == 1 && bb == 1 && t == 3)		ratio = 10;	// KBKBN
		if(wb == 1 && wn == 1 && bn == 1 && t == 3)		ratio = 15;	// KBNKN
		if(wn == 1 && bn == 1 && bb == 1 && t == 3)		ratio = 15;	// KNKBN
		if(wb+bb + wn+bn == 4 && wt == 2 && bt == 2)	ratio = 15;	// KMMKMM
		if(wt == 1 && wr == 1 && bn == 1 && bp == 1)	ratio = -10;// KRKNP
		if(wn == 1 && wp == 1 && bt == 1 && br == 1)	ratio = -10;// KNPKR
		if(wt == 1 && wr == 1 && bb == 1 && bp == 1)	ratio = -10;// KRKBP
		if(wb == 1 && wp == 1 && bt == 1 && br == 1)	ratio = -10;// KBPKR
		if(wr == 1 && wn == 1 && br == 1 && bp == 1)	ratio = 10;	// KRNKRP
		if(wr == 1 && wb == 1 && br == 1 && bp == 1)	ratio = 10;	// KRBKRP
		if(wr == 1 && wp == 1 && br == 1 && bn == 1)	ratio = 10;	// KRPKRN
		if(wr == 1 && wp == 1 && br == 1 && bb == 1)	ratio = 10;	// KRPKRB		
		if(wb == 1 && wn == 1 && bb == 1 && bp == 1)	ratio = 25;	// KBNKBP
		if(wb == 1 && wp == 1 && bb == 1 && bn == 1)	ratio = 25;	// KBPKBN
		if(wb == 1 && wn == 1 && bn == 1 && bp == 1)	ratio = 25;	// KBNKNP
		if(wn == 1 && wp == 1 && bb == 1 && bn == 1)	ratio = 25;	// KNPKBN
	} else if(wt-wp == 1 && bt-bp == 1) {
		// simple endgames
		if(wn == 1 && bn == 1)							ratio = 115; // KNPsKNPs
		if(wn == 1 && bb == 1)							ratio = 95;  // KNPsKBPs
		if(wb == 1 && bn == 1)							ratio = 95;  // KBPsKNPs
		if(wb == 1 && bb == 1)							ratio = 110; // KBPsKNPs
		if(wq == 1 && bq == 1 && wp+bp < 7)				ratio = 80;  // KQPsKQPs
		if(wq == 1 && bq == 1 && wp+bp >= 7)			ratio = 90;  // KQPsKQPs
	} else if(wt-wp == 2 && bt-bp == 2) {		
		if(wn == 2 && bn == 2)							ratio = 105; // KNNPsKNNPs
		if(wb == 2 && bb == 2)							ratio = 110; // KBBPsKBBPs
		if(wr == 2 && br == 2)							ratio = 85;  // KRRPsKRRPs		
		if(wn == 1 && wb == 1 && bn == 2)				ratio = 110; // KBNPsKNNPs
		if(wn == 2 && bb == 1 && bn == 1)				ratio = 110; // KNNPsKBNPs
		if(wb == 2 && bb == 1 && bn == 1)				ratio = 107; // KBBPsKBNPs
		if(wb == 1 && wn == 1 && bb == 2)				ratio = 107; // KBNPsKBBPs
		if(wr == 1 && wn == 1 && br == 1 && bn == 1)	ratio = 108; // KRNPsKRNPs
		if(wr == 1 && wb == 1 && br == 1 && bn == 1)	ratio = 103; // KRBPsKRNPs
		if(wr == 1 && wn == 1 && br == 1 && bb == 1)	ratio = 103; // KRNPsKRBPs
	} else if((wt-wp) + (bt-bp) == 3) {		
		if(wq == 1 && wn == 1 && bq == 1)				ratio = 87; // KQNPsKQPs
		if(wq == 1 && wb == 1 && bq == 1)				ratio = 87; // KQBPsKQPs
		if(wq == 1 && bq == 1 && bn == 1)				ratio = 87; // KQPsKQNPs
		if(wq == 1 && bq == 1 && bb == 1)				ratio = 87; // KQPsKQBPs
	}

	// no pawns
	if((ratio == 100 && wp == 0 && value > 0 && value <= BISHOP_VALUE)
	|| (ratio == 100 && bp == 0 && value < 0 && value >= -BISHOP_VALUE))	
		ratio = 10 + 10*wb*wb;	
	
	*special = (ratio != 100);
	return value * (ratio - 100)/100;
}