/* Pepito v1.59  -- file: eval.c --
   Copyright (c) 2000-01 Carlos del Cacho

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; see the file COPYING.  If not, write to
   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.

   Contact the author: guggenjaimito@yahoo.com
*/

#ifndef UNIQUE_SOURCE_FILE
#include "datos.h"
#endif
static int  EvalSeguridad(int *, int *);
static int  EvalApertura(void);
static int  CaballoB_Atrapado(int pos);
static int  CaballoN_Atrapado(int pos);
static int  Final_KBN_K(void);
static int  Final_KBB_K(void);

static int  EvalNingunoB(void);
static int  EvalCortoB(void);
static int  EvalLargoB(void);

static int  EvalNingunoN(void);
static int  EvalCortoN(void);
static int  EvalLargoN(void);

static int  TablasAlfilPeonDeTorreB();
static int  TablasAlfilPeonDeTorreN();

#define EVAL_PEONES
#define SHOW_EVAL_POSSIBLE           0
#define LAZY_EVAL                    1
#define LAZY_EXIT                    (2*PEON_VAL)
#define USE_CACHE                    1
#define USE_PHASH                    1
#define EVAL_CLAVADAS                0
#define EVAL_ATQ_DEBIL               1
#define EVAL_SEGURIDAD               1
#define TROPISMO                     1
#define DEBUG_PEONES                 0

#if DEBUG_PEONES
#define DebugEval(a, x)    Print("score: %d (%c%d)\n", a, 'a' + (x&7), 8 - (x>>3));
#else
#define DebugEval(a, x)
#endif

//-----------------------------------------------------------------------
#define CUADRANTE_DER_B              (entero64)0xf0f0f0f000000000
#define CUADRANTE_IZQ_B              (entero64)0xf0f0f0f00000000
#define CUADRANTE_DER_N              (entero64)0xf0f0f0f0
#define CUADRANTE_IZQ_N              (entero64)0xf0f0f0f
#define MITAD_N                      (entero64)0xffffffff
#define MITAD_B                      (entero64)0xffffffff00000000
#define CENTRO                       (entero64)0x0000001818000000
#define CENTRO_EX                    (entero64)0x0000002424000000
#define ANILLO_CENTRO                (entero64)0x00003c24243c0000
#define CASILLAS_BLANCAS             (entero64)0xaa55aa55aa55aa55
#define EXTERIOR_TABLERO             (entero64)0xff818181818181ff
#define DESARROLLO_N                 (entero64)0x66
#define DESARROLLO_B                 (entero64)0x6600000000000000
//-----------------------------------------------------------------------
#define MAS_PIEZAS                    (PEON_VAL)
#define DUO_PEONES                    2
#define PEON_PASADO_ESTATICO          5
#define PEON_DOBLADO                 -4
#define PEON_DEBIL                   -6
#define PEON_DEF_PEON                 3
#define PEON_CUASI_PASADO            10
#define DONDE_CREES_Q_VAS           -30
#define ATAQUE_DEBIL                  4
#define PEON_CENTRAL_BLOQUEADO      -10
#define PEON_REZAGADO                -5
#define MEDIO_PASADO                 10

//#define BONUS_2_ALFILES              30
#define ALFIL_ATRAPADO             -180

#define CABALLO_ATRAPADO           -150
#define CABALLO_EN_FINAL            -30

#define TORRE_COL_ABIERTA            15
#define TORRE_COL_SEMIABIERTA         7
#define DOBLA_TORRES                 10
#define TORRE_ATRAPADA               -5
#define TORRE_EN_COL_REY              6
#define TORRE_APOYO_PASADO           10
#define TORRE_CONTRA_PASADO           4

#define DAMA_DESCOLOCADA           (-10)

#define ENROCADO_CORTO               14
#define ENROCADO_LARGO                6
#define AMENAZA_PASILLO              -8
#define OPOSICION_REY                 7

#define CLAVA_REY_CONTRARIO          12

#define BONUS_TURNO                   4
//--------------------------------------------------------------------------------------------
static const int PEON_PASADO[8] = {0, 5, 15, 30, 55, 75, 100, 0};
static const int PEON_PASADO_BLOQ[8] = {0, 5, 15, 20, 40, 60, 85, 0};
static const int REY_APOYA_PASADO[8] = {0, 0, 0, 0, 5, 20, 60, 100};

static const int PASA_ALEJA_REY[15] = {30, 25, 20, 15, 10, 0, 0, 0, 0, 0, 10, 15, 20, 25, 30};
static const int MOV_ALFIL[14] = {-10, -5, 2, 3, 5, 6, 7, 8, 10, 10, 10, 10, 10, 10};
//static const int MOV_ALFIL[14] = {-15, -5, 2, 3, 5, 10, 15, 15, 15, 15, 15, 15, 15, 15};
static const int MOV_TORRE[15] = {-5, - 3, 2, 3, 4, 5, 6, 7, 8, 8, 8, 8, 8, 8, 8};
//static const int MOV_CABALLO[9] = {-15, -4, 1, 2, 3, 4, 5, 7, 7};
//recargo especial x tener + de 1 peon aislado (o doblado)
//static const int BONUS_AISLADOS[9] = {0, 0, -10, -20, -25, -27, -29, -31, -33};
static const int BONUS_AISLADOS[9] = {0, 0, -10, -30, -45, -47, -49, -51, -53};
static const int BONUS_EXPUESTOS_PEPI[9] = {0, -5, -15, -40, -40, -40, -40, -40, -40};
static const int BONUS_EXPUESTOS_OTRO[9] = {0, -5, -10, -15, -20, -20, -20, -20, -20};
static const int PASADO_FUERTE[8] = {0, 0, 0, 10, 15, 30, 70, 0};

static const int BONUS_SEPTIMA[] = {0, 25, 100, 300, 300, 300, 300};
static const int ALFIL_MALO[9] = {0, 0, 0, -25, -50, -70, -70, -70, -70};

//static const int BONUS_DOBLADOS[9] = { 0, 0,   0, -12, -14, -16, -18, -20, -22};

static const int PEON_AISLADO[8] = {0, -5, -5, -5, -5, -5, -5, 0};

static const int ATACA_REY[] = {0, 7, 15, 35, 60, 100, 150};
static const int BONUS_2_ALFILES[] = { 60, 60, 60, 60, 55, 45, 40, 35, 30,
                                       30, 30, 30, 30, 30, 30, 30, 30 };


static const int TROPISMO_AC[]={3,3,2,1,0,0,0,0};
static const int TROPISMO_TC[]={4,3,1,0,0,0,0,0};
static const int TROPISMO_T[]={3,3,3,0,0,0,0,0};
static const int TROPISMO_D[]={5,5,3,2,0,0,0,0};

static const int EVAL_TROPISMO[] = {0,1,2,5,8,12,15,18,20,22,
                                    25,27,30,30,30,30,30,30,30,
                                    30,30,30,30,30,30,30,30,30,
                                    30,30,30,30,30,30,30,30,30 };

static const int PESO_TROPISMO[28] = {
    25, 28, 32, 32, 32, 36, 40,
    48, 52, 52, 52, 52, 52, 52,
    52, 52, 52, 52, 52, 52, 52,
    52, 52, 52, 52, 52, 52, 52
};

//---------------------------------------------------------------------------------------------
#define PeonRezagadoB(casilla_peon)                                                     \
   !(PeonesB & PASADO[0][casilla_peon]) &&                                                   \
   PopCnt(AtaquesPeonB(casilla_peon-8) & PeonesN) > PopCnt(AtaquesPeonN(casilla_peon-8) & PeonesB)

#define PeonRezagadoN(casilla_peon)                                                     \
   !(PeonesN & PASADO[1][casilla_peon]) &&                                                   \
   PopCnt(AtaquesPeonN(casilla_peon+8) & PeonesB) > PopCnt(AtaquesPeonB(casilla_peon+8) & PeonesN)

#define PeonPasado(peones_contrario, color_propio, casilla_peon)              \
   !(peones_contrario & PASADO[color_propio][casilla_peon])

#define PeonAislado(peones_propios,casilla_peon)           \
   !(peones_propios & AISLADO[pos&7])

#define PeonDoblado(peones_propios,casilla_peon)           \
   (peones_propios & COLUMNA[casilla_peon&7])

#define DuoPeones(peones_propios, casilla_peon)            \
   (ATAQUES_TORRE_FIL[casilla_peon][255] & peones_propios)

#define PeonDefendidoPorPeon(atq_propios, pos)         \
   (MASK[pos] & atq_propios)

//------ para aplicar simetría y no duplicar tablas -----

static const int MIRROR[64] = {
    56, 57, 58, 59, 60, 61, 62, 63,
    48, 49, 50, 51, 52, 53, 54, 55,
    40, 41, 42, 43, 44, 45, 46, 47,
    32, 33, 34, 35, 36, 37, 38, 39,
    24, 25, 26, 27, 28, 29, 30, 31,
    16, 17, 18, 19, 20, 21, 22, 23,
    8, 9, 10, 11, 12, 13, 14, 15,
    0, 1, 2, 3, 4, 5, 6, 7
};


static const int   TABLA_CABALLO[] = {
    -20, -10, -5, -5, -5, -5, -10, -20,
    -10, -1, 1, 2, 2, 1, -1, -10,
    -10, 3, 5, 3, 3, 5, 3, -10,
    -10, 1, 6, 8, 8, 6, 1, -10,
    -10, 1, 6, 8, 8, 6, 1, -10,
    -10, 1, 5, 3, 3, 5, 1, -10,
    -10, -1, 1, 2, 2, 1, -1, -10,
    -20, -10, -5, -5, -5, -5, -10, -20
};

static const int TABLA_ALFIL[] = {
-10, -5, -5, -5, -5, -5, -5, -5,
    -5, 0, 0, 0, 0, 0, 0, -5,
    -5, 0, 2, 2, 2, 2, 0, -5,
    -5, 0, 2, 4, 4, 2, 0, -5,
    -5, 0, 2, 4, 4, 2, 0, -5,
    -5, 0, 2, 5, 5, 2, 0, -5,
    -5, 2, 3, 0, 0, 3, 2, -5,
-10, -5, -5, -5, -5, -5, -5, -10};

static const int TABLA_TORRE[] = {
    -5, 0, 0, 0, 0, 0, 0, -5,
    -5, 0, 0, 0, 0, 0, 0, -5,
    -5, 0, 0, 0, 0, 0, 0, -5,
    -5, 0, 0, 0, 0, 0, 0, -5,
    -5, 0, 0, 0, 0, 0, 0, -5,
    -5, 0, 0, 0, 0, 0, 0, -5,
    -5, 0, 0, 0, 0, 0, 0, -5,
    -2, 0, 3, 3, 3, 3, 0, -2};

static const int TABLA_DAMA[] = {
-10, -10, -10, -10, -10, -10, -10, -10,
    -10, 0, 0, 0, 0, 0, 0, -10,
    -5, 0, 4, 4, 4, 4, 0, -5,
    -5, 0, 4, 8, 8, 4, 0, -5,
    -5, 0, 4, 8, 8, 4, 0, -5,
    -5, 0, 4, 4, 4, 4, 0, -5,
    -5, 0, 4, 0, 0, 0, 0, -5,
-10, -10, -5, 0, -2, -5, -10, -10};

static const int TABLA_REY[] = {
    -30, -30, -30, -30, -30, -30, -30, -30,
    -30, -30, -30, -30, -30, -30, -30, -30,
    -30, -30, -30, -30, -30, -30, -30, -30,
    -30, -30, -30, -30, -30, -30, -30, -30,
    -30, -30, -30, -30, -30, -30, -30, -30,
    -30, -30, -30, -30, -30, -30, -30, -30,
    -3,   -2,  -5, -10, -10,  -5, -2,   -3,
    -5,   -1,   0,  -5,  -5,  -2,  0,   -5};

static const int TABLA_REY_FINAL[] = {
   -5,  0,  0,  1,  1, -2,  0, -5,
   -4,  7, 10, 10, 10, 10,  7, -4,
    0, 10, 15, 20, 20, 15, 10,  0,
    1, 10, 20, 30, 30, 20, 10,  1,
    1, 10, 20, 30, 30, 20, 10,  1,
    0, 10, 15, 20, 20, 15, 10,  0,
   -4,  7, 10, 10, 10, 10,  7, -4,
   -5,  0,  0,  1,  1, -2,  0, -5};


static const int KING_STORM[] = {
    0, 0, 0, 0, 0, 0, 0, 0,
    16, 16, 16, 30, 30, 16, 16, 16,
    12, 12, 12, 25, 25, 5, 5, 5,
    6, 7, 10, 15, 12, 5, 5, 5,
    3, 3, 7, 10, 10, 0, 0, 0,
    1, 1, 1, 4, 4, -7, -7, -7,
    0, 0, 0, -2, -2, -10, -10, -10,
    0, 0, 0, 0, 0, 0, 0, 0};

static const int QUEEN_STORM[] = {
    0, 0, 0, 0, 0, 0, 0, 0,
    16, 16, 16, 30, 30, 16, 16, 16,
    5, 5, 12, 25, 25, 12, 12, 12,
    5, 5, 10, 15, 12, 8, 7, 6,
    0, 0, 7, 10, 10, 5, 3, 3,
    -7, -7, -7, 4, 4, 1, 1, 1,
    -10, -10, -10, -2, -2, 5, 5, 5,
    0, 0, 0, 0, 0, 0, 0, 0};

static const int AUMENTA[] = {128, 128, 128, 128, 128, 128, 128, 128,
    115, 115, 102, 102, 90, 64, 51, 38,
    26, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0};

static const int DISMINUYE[] = {0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 13, 26, 38, 51, 64, 77,
    90, 102, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128};

static const int ENROQUE_MINUS[28] = {0, -3, -8, -12, -16, -30, -35,
    -40, -55, -80, -100, -110, -120, -130,
    -130, -135, -140, -140, -140, -140, -140,
-140, -140, -140, -140, -140, -140, -140};

/*
static const int AUMENTA_PASA[] = { 11, 11, 11, 10, 10,  9, 11, 11,
                                    10, 10, 10,  9,  9,  9,  8,  8,
                                     7,  7,  7,  6,  6,  5,  5,  4, 
                                     4,  4,  4,  4,  4,  4,  4,  4, 4 };
*/

static const int PASADO_ALEJADO[] = {110, 50, 50, 50, 40, 40, 40, 40, 
                                      40, 30, 20, 10,  5,  0,  0,  0,
                                       0 , 0,  0,  0,  0,  0,  0,  0, 
                                       0,  0,  0,  0,  0,  0,  0,  0, 0 };


static const int AUMENTA_PASA[] = { 11, 11, 11, 10, 10,  9, 11, 11, 
                                    10, 10, 10, 10, 10, 10,  9,  8,
                                     7,  7,  6,  6,  5,  5,  5,  4, 
                                     4,  3,  3,  3,  3,  3,  3,  3, 3 }; 


//----------------------------------------------------------
static const signed char OUTPOST[64] = {
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 2, 2, 0, 0, 0,
    0, 3, 4, 8, 8, 4, 3, 0,
    0, 5, 6, 9, 9, 6, 5, 0,
    0, 0, 2, 4, 4, 2, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
};

// fases de la partida en función del material

#define MEDIO_JUEGO_INI      1
#define MEDIO_JUEGO_FIN      2
#define FINAL                3
#define APERTURA             0


static int PMaterialB, PMaterialN;
extern int SafetyFlags;


#if SHOW_EVAL_POSSIBLE
int             show;
#endif

int             Evaluacion(int alpha, int beta)
{
    entero64        BBpieza;
    int             pos;
    int             puntuacion;
    int             movilidad;
    entero64        BBatqs_pieza;
#if SHOW_EVAL_POSSIBLE
    int             bkup_score;
#endif
    int             maxB = INFINITO,
                    maxN = -INFINITO;
    int             final_tablero = 0;
    int             fase, material;
    const int       *TPEON;
    int             lazyscore;

#if EVAL_ATQ_DEBIL
    entero64        BBdebilesB,
                    BBdebilesN;
#endif
    entero64        BBatq_peonesB, BBatq_peonesN;
    entero64        BBpasadosB, BBpasadosN;
    int             eval_peones;
    unsigned char   pasadosB,
                    pasadosN

#if EVAL_ATQ_DEBIL               
                    ,debilB,
                    debilN
#endif 
                    ;

    int             suma_peones = NumPeonesB + NumPeonesN, candi_pasa, alejados;
    entrada_hash_p *paddr;
#if TROPISMO
    int tropismoB, tropismoN;
#endif
    int defB, defN, calcseg;

    tab.evals++;

    movilidad = puntuacion = 0;

    {
        if (suma_peones > 8 && (PiezasB + PiezasN) > 7)
            fase = MEDIO_JUEGO_INI;
        else if (suma_peones > 6 && (PiezasB + PiezasN) > 5)
            fase = MEDIO_JUEGO_FIN;
        else
            fase = FINAL;
    }

    PMaterialB = Min(32,(MaterialB - NumPeonesB * PEON_VAL) / PEON_VAL);
    PMaterialN = Min(32,(MaterialN - NumPeonesN * PEON_VAL) / PEON_VAL);

    material = MaterialB - MaterialN;
    if (PiezasB > PiezasN && (PMaterialB - PMaterialN) >= 1 &&
        (PMaterialB - PMaterialN) <= 3)
        {
        material += MAS_PIEZAS;
        }
    else if (PiezasN > PiezasB && (PMaterialN - PMaterialB) >= 1 &&
             (PMaterialN - PMaterialB) <= 3)
             {
        material -= MAS_PIEZAS;
        }

    if (fase < MEDIO_JUEGO_FIN)
        puntuacion += EvalApertura();
    else
    {
        if ((PiezasB + PiezasN) < 3) {
            if (PiezasN == 0 && !suma_peones) {
                   if (PopCnt(AlfilesB) == 2)
                       return (Turno ? Final_KBB_K() : -Final_KBB_K());
                   else if (AlfilesB && CaballosB)
                       return (Turno ? Final_KBN_K() : -Final_KBN_K());
            }
            if (PiezasB == 0) {
                if (!suma_peones) {
                    if (PopCnt(AlfilesN) == 2)
                    {
                        return (Turno ? -Final_KBB_K() : Final_KBB_K());
                    }
                    else if (AlfilesB && CaballosB)
                        return (Turno ? -Final_KBN_K() : Final_KBN_K());
                }
                if (PiezasN == 0) {
                    if (!(DISTANCIA[PosReyB][PosReyN] & 1) && !(AtaquesTeoricosAlfil(PosReyB) & ReyN))
                        puntuacion += Turno ? -OPOSICION_REY : OPOSICION_REY;
                }
            }
            if (AlfilesB && AlfilesN &&
                (AlfilesB & CASILLAS_BLANCAS ? AlfilesN & ~CASILLAS_BLANCAS : AlfilesN & CASILLAS_BLANCAS))
                final_tablero = 1;      // alfiles de distinto color
        }
        if (!NumPeonesB) {
            if (PMaterialB - PMaterialN <= 3 && (!DamasB || DamasN))
                maxB = TABLAS;
            else if (PiezasB == 2 && PopCnt(CaballosB) == 2 && !NumPeonesN)
                maxB = TABLAS;
        }
        if (!NumPeonesN) {
            if (PMaterialN - PMaterialB <= 3 && (!DamasN || DamasB))
                maxN = TABLAS;
            else if (PiezasN == 2 && PopCnt(CaballosN) == 2 && !NumPeonesB)
                maxN = TABLAS;
        }
    }

    BBatq_peonesB = ((PeonesB & ~COLUMNA_0) >> 9) | ((PeonesB & ~COLUMNA_7) >> 7);
    BBatq_peonesN = ((PeonesN & ~COLUMNA_0) << 7) | ((PeonesN & ~COLUMNA_7) << 9);

    // si podemos obtener la información de peones de la tabla nos ahorramos
    // el calcularla...

    TPEON = TABLA_PEON;

    if (fase != FINAL) {

        if ((Enroque & (REY_B_ENRQ_CORTO|REY_N_ENRQ_LARGO)) ==
            (REY_B_ENRQ_CORTO|REY_N_ENRQ_LARGO))
            TABLA_PEON = QUEEN_STORM;
        else if ((Enroque & (REY_N_ENRQ_CORTO|REY_B_ENRQ_LARGO)) ==
            (REY_N_ENRQ_CORTO|REY_B_ENRQ_LARGO))
            TABLA_PEON = KING_STORM;
    }

#if USE_PHASH
    paddr = tab.trans_tab_p + ((HashPeones ^ (long) TABLA_PEON) & PAWN_HASH_MASK);

    tab.p_hash_trys++;
    if (paddr->key == HashPeones) {
        tab.p_hash_hits++;
        eval_peones = paddr->eval_peones;
        pasadosB = paddr->pasadosB;
        pasadosN = paddr->pasadosN;
        candi_pasa = (int)paddr->candipasa;
        alejados = (int)paddr->alejados;

#if EVAL_ATQ_DEBIL               
        debilB = paddr->debilB;
        debilN = paddr->debilN;

        BBdebilesB = BBdebilesN = 0;
        while (debilB) {
            pos = (int) LSB[(int) debilB];
            BBdebilesB |= (PeonesB & COLUMNA[pos] & ~BBatq_peonesB);
            debilB &= debilB - 1;
        }

        while (debilN) {
            pos = (int) LSB[(int) debilN];
            BBdebilesN |= (PeonesN & COLUMNA[pos] & ~BBatq_peonesN);
            debilN &= debilN - 1;
        }
#endif
    } else
#endif
    {
        int             aislados = 0,
                        expuestos = 0,
#if EVAL_ATQ_DEBIL               
                        debilB = debilN = 0;
#endif

        entero64  BBpeones = PeonesB | PeonesN;


        pasadosB = pasadosN = 0;
        eval_peones = candi_pasa = alejados = 0;

#if EVAL_ATQ_DEBIL               
        BBdebilesB = BBdebilesN = 0;
#endif
        if ((PeonesB & (Mask(E4) | Mask(D4))) == (Mask(E4) | Mask(D4))) {
            eval_peones += 6;
            if (!(PeonesN & (Mask(E5) | Mask(D5))))
                eval_peones += 6;
            else if (PeonesB & (Mask(F4) | Mask(C4)))
                eval_peones += 4;
        }
        BBpieza = PeonesB;
        while (BBpieza) {
            pos = Msb(BBpieza);
            BBpieza ^= MASK[pos];
            eval_peones += TABLA_PEON[pos];

            if (DuoPeones(PeonesB, pos))
                eval_peones += DUO_PEONES;


            if (PeonDefendidoPorPeon(BBatq_peonesB, pos)) {
                eval_peones += PEON_DEF_PEON;
                goto NO_DEBIL;
            }
            if (Tablero[pos - 8] != PEON_N) {
                register int    atqs;

                atqs = PopCnt(AtaquesPeonB(pos - 8) & PeonesN);
                if (atqs < 2) {
                    register int    defs = PopCnt(AtaquesPeonN(pos - 8) & PeonesB);
                    if (defs && defs >= atqs)
                        goto NO_DEBIL;
                    if (!atqs && MASK[pos] & FILA_6 && ~PeonesN & MASK[pos - 16]) {
                        atqs = PopCnt(AtaquesPeonB(pos - 16) & PeonesN);
                        if (atqs < 2) {
                            defs = PopCnt(AtaquesPeonN(pos - 16) & PeonesB);
                            if (defs && defs >= atqs)
                                goto NO_DEBIL;
                        }
                    }
                }
            }
            if (PeonesB & (AtaquesPeonN(pos) << 8)) {
                register int    atqs,
                                defs;

                if (7 ^ (pos & 7) && BBatq_peonesB & MASK[pos + 9]) {     // columna != H
                    atqs = PopCnt(AtaquesPeonB(pos + 9) & PeonesN);
                    defs = PopCnt(AtaquesPeonN(pos + 9) & PeonesB);
                    if (defs >= atqs)
                        goto NO_DEBIL;
                }
                if (pos & 7 && BBatq_peonesB & MASK[pos + 7]) {   // columna != A
                    atqs = PopCnt(AtaquesPeonB(pos + 7) & PeonesN);
                    defs = PopCnt(AtaquesPeonN(pos + 7) & PeonesB);
                    if (defs >= atqs)
                        goto NO_DEBIL;
                }
            }
            eval_peones += PEON_DEBIL;

#if EVAL_ATQ_DEBIL               
            debilB |= MASK[pos & 7];
            BBdebilesB |= MASK[pos];
#endif
            if (PeonRezagadoB(pos))
                eval_peones += PEON_REZAGADO;
            if (PeonAislado(PeonesB, pos)) {
                aislados++;
                eval_peones += PEON_AISLADO[pos & 7];
            }
            if (!(PeonesN & COLUMNA[pos & 7]))
                expuestos++;

    NO_DEBIL:

            if (PeonDoblado(BBpieza, pos)) {
                eval_peones += PEON_DOBLADO;
            }
            if (PeonPasado(PeonesN, 1, pos)) {
                if ((pos&7) < 4)
                {
                   if (!(BBpeones & PAS_ALEJA_I[(pos&7)]) && !(pasadosB & MASK[pos & 7]))
                     alejados++;
                }
                else if (!(BBpeones & PAS_ALEJA_D[(pos&7)]) && !(pasadosB & MASK[pos & 7]) )
                  alejados++;
                pasadosB |= MASK[pos & 7];
                eval_peones += PEON_PASADO_ESTATICO;
            }
            else if (pos <= H4 && !(RAYO_N[pos] & PeonesN))
            {
              if ((!(pos&7) || !(RAYO_N[pos-1] & PeonesN)) ||
                  ((pos&7)==7 || !(RAYO_N[pos+1] & PeonesN)))
                  {
                     if (PopCnt(PeonesN & PASADO[1][pos]) == 1)
                        candi_pasa += MEDIO_PASADO;
                  }
            }

        }                       // while


        eval_peones += BONUS_AISLADOS[aislados] +
                       (RTurno? BONUS_EXPUESTOS_PEPI[expuestos] :
                                BONUS_EXPUESTOS_OTRO[expuestos]);
        aislados = 0;
        expuestos = 0;

        if ((PeonesN & (Mask(E5) | Mask(D5))) == (Mask(E5) | Mask(D5))) {
            eval_peones -= 6;
            if (!(PeonesN & (Mask(E4) | Mask(D4))))
                eval_peones -= 6;
            else if (PeonesB & (Mask(F5) | Mask(C5)))
                eval_peones -= 4;
        }
        BBpieza = PeonesN;

#if SHOW_EVAL_POSSIBLE
        Print("ev_peonesB: %d\n", eval_peones);
        bkup_score = eval_peones;
#endif

        if (TABLA_PEON == QUEEN_STORM)
        {
            TABLA_PEON = (const int *)KING_STORM;
        }
        else if (TABLA_PEON == KING_STORM)
        {
            TABLA_PEON = (const int *)QUEEN_STORM;
        }

        while (BBpieza) {
            pos = Lsb(BBpieza);
            BBpieza ^= MASK[pos];
            eval_peones -= TABLA_PEON[MIRROR[pos]];

            if (DuoPeones(PeonesN, pos))
                eval_peones -= DUO_PEONES;

            if (PeonDefendidoPorPeon(BBatq_peonesN, pos)) {
                eval_peones -= PEON_DEF_PEON;
                goto NO_DEBIL2;
            }
            if (~PeonesB & MASK[pos + 8]) {
                register int    atqs;

                atqs = PopCnt(AtaquesPeonN(pos + 8) & PeonesB);
                if (atqs < 2) {
                    register int    defs = PopCnt(AtaquesPeonB(pos + 8) & PeonesN);
                    if (defs && defs >= atqs)
                        goto NO_DEBIL2;
                    if (!atqs && MASK[pos] & FILA_1 && ~PeonesB & MASK[pos + 16]) {
                        atqs = PopCnt(AtaquesPeonN(pos + 16) & PeonesB);
                        if (atqs < 2) {
                            defs = PopCnt(AtaquesPeonB(pos + 16) & PeonesN);
                            if (defs && defs >= atqs)
                                goto NO_DEBIL2;
                        }
                    }
                }
            }
            if (PeonesN & (AtaquesPeonB(pos) >> 8)) {
                register int    atqs,
                                defs;
                if (7 ^ (pos & 7) && BBatq_peonesN & MASK[pos - 7]) {     // columna != H
                    if (!(atqs = PopCnt(AtaquesPeonN(pos - 7) & PeonesB)))
                        goto NO_DEBIL2;
                    defs = PopCnt(AtaquesPeonB(pos - 7) & PeonesN);
                    if (defs >= atqs)
                        goto NO_DEBIL2;
                }
                if (pos & 7 && BBatq_peonesN & MASK[pos - 9]) {   // columna != A
                    if (!(atqs = PopCnt(AtaquesPeonN(pos - 9) & PeonesB)))
                        goto NO_DEBIL2;
                    defs = PopCnt(AtaquesPeonB(pos - 9) & PeonesN);
                    if (defs >= atqs)
                        goto NO_DEBIL2;
                }
            }
            eval_peones -= PEON_DEBIL;

#if EVAL_ATQ_DEBIL               
            debilN |= MASK[pos & 7];
            BBdebilesN |= MASK[pos];
#endif

            if (PeonRezagadoN(pos))
                eval_peones -= PEON_REZAGADO;
            if (!(PeonesN & COLUMNA[pos & 7]))
                expuestos++;
            if (PeonAislado(PeonesN, pos)) {
                aislados++;
                eval_peones -= PEON_AISLADO[pos & 7];
            }
    NO_DEBIL2:

            if (PeonDoblado(BBpieza, pos)) {
                eval_peones -= PEON_DOBLADO;
            }
            if (PeonPasado(PeonesB, 0, pos)) {
                if ((pos&7) < 4)
                {
                   if (!(BBpeones & PAS_ALEJA_I[pos&7]) && !(pasadosN & MASK[pos & 7]))
                     alejados--;
                }
                else if (!(BBpeones & PAS_ALEJA_D[pos&7]) && !(pasadosN & MASK[pos & 7]))
                   alejados--;
                pasadosN |= MASK[pos & 7];
                eval_peones -= PEON_PASADO_ESTATICO;
            }
            else if (pos >= A5 && !(RAYO_S[pos] & PeonesB))
            {
              if ((!(pos&7) || !(RAYO_S[pos-1] & PeonesB)) ||
                  ((pos&7)==7 || !(RAYO_S[pos+1] & PeonesB)))
                  {
                     if (PopCnt(PeonesB & PASADO[0][pos]) == 1)
                       candi_pasa -= MEDIO_PASADO;
                  }
            }

            DebugEval(eval_peones, pos);
        }                       // while

        eval_peones -= BONUS_AISLADOS[aislados] +
                       (RTurno? BONUS_EXPUESTOS_OTRO[expuestos] :
                                BONUS_EXPUESTOS_PEPI[expuestos]);

        DebugEval(eval_peones, 0);


#if SHOW_EVAL_POSSIBLE
        Print("ev_peonesN: %d\n", eval_peones);
        bkup_score = puntuacion;
#endif

        paddr->key = HashPeones;
        paddr->eval_peones = eval_peones;
        paddr->pasadosB = pasadosB;
        paddr->pasadosN = pasadosN;
#if EVAL_ATQ_DEBIL               
        paddr->debilB = (unsigned char)debilB;
        paddr->debilN = (unsigned char)debilN;
#endif
        paddr->alejados = (signed char) alejados;
        paddr->candipasa = (signed char) candi_pasa;
    }

    TABLA_PEON = TPEON;


    BBpasadosB = 0;
    BBpasadosN = 0;

    if (pasadosB | pasadosN) {
        entero64        BBocupadas = Blancas | Negras;
        while (pasadosB) {
            pos = Lsb((PeonesB & COLUMNA[LSB[pasadosB]]));

            if (MASK[pos - 8] & BBocupadas)
                eval_peones += AUMENTA_PASA[PMaterialN] * PEON_PASADO_BLOQ[7 - (pos >> 3)] / 10;
            else
                eval_peones += AUMENTA_PASA[PMaterialN] * PEON_PASADO[7 - (pos >> 3)] / 10;

            pasadosB &= pasadosB - 1;

#if EVAL_ATQ_DEBIL               
            if (MASK[pos] & BBdebilesB)
            {
               if (COLUMNA[pos&7] & PeonesN & ~BBdebilesN)
                  eval_peones += DONDE_CREES_Q_VAS;
            }
            else
               eval_peones += PASADO_FUERTE[7 - (pos >> 3)];
#endif
            BBpasadosB |= MASK[pos];
            if (DISTANCIA[PosReyB][pos] == 1)
                eval_peones += REY_APOYA_PASADO[7 - (PosReyB >> 3)];
        }

        while (pasadosN) {
            pos = Msb((PeonesN & COLUMNA[LSB[pasadosN]]));

            if (MASK[pos + 8] & BBocupadas)
                eval_peones -= AUMENTA_PASA[PMaterialB] * PEON_PASADO_BLOQ[pos >> 3] / 10;
            else
                eval_peones -= AUMENTA_PASA[PMaterialB] * PEON_PASADO[pos >> 3] / 10;

            pasadosN &= pasadosN - 1;

#if EVAL_ATQ_DEBIL               
            if (MASK[pos] & BBdebilesN)
            {
               if (COLUMNA[pos&7] & PeonesB & ~BBdebilesB)
                 eval_peones -= DONDE_CREES_Q_VAS;
            }
            else
               eval_peones -= PASADO_FUERTE[pos >> 3];
#endif

            BBpasadosN |= MASK[pos];

            if (DISTANCIA[PosReyN][pos] == 1)
                eval_peones -= REY_APOYA_PASADO[PosReyN >> 3];
        }

        if (alejados)
          eval_peones += alejados * PASADO_ALEJADO[alejados > 0 ? PMaterialN : PMaterialB];

        /* carreras de peones pasados (un poco rudimentario pero mejor que
         * nada...) */
        {
            int              aux = 20,
                            aux2 = 20;
            if (PiezasN < 2) {
                if (!PiezasN) {

                    int dist;

                    if (!(PeonesN & ~COLUMNA_0)) {
                        if (ReyB & (COLUMNA_0 | COLUMNA_1) && !(RAYO_S[PosReyB & ~1] & PeonesN))
                            maxN = TABLAS;
                    }
                    else if (!(PeonesN & ~COLUMNA_7)) {
                        if (ReyB & (COLUMNA_6 | COLUMNA_7) && !(RAYO_S[PosReyB | 1] & PeonesN))
                            maxN = TABLAS;
                    }
                    BBpieza = BBpasadosB;
                    while (BBpieza) {
                        pos = Lsb(BBpieza);
                        BBpieza &= ~COLUMNA[pos & 7];
                        dist = Min(pos>>3,5);

                        if (AtaquesRey(pos) & BBpieza)
                           puntuacion += PEON_PASADO[7-(pos>>3)];

                        if (dist - Turno + 1 < DISTANCIA[pos & 7][PosReyN])
                            aux = Min(aux, dist + ((ReyB & RAYO_N[pos]) ? 1 : 0));
                        else if (dist < 4 && ReyB & PASADO[1][pos+8])
                        {
                            if (AtaquesRey(PosReyN) & MASK[pos])
                            {
                               if ((DISTANCIA[PosReyB][pos] - Turno) <= 1)
                                 aux = Min(aux, dist - Turno + 1);
                            }                   
                            else if (ReyB & PASADO[1][A6+(pos&7)] && (dist < 3 || PosReyB <= H8))
                              aux = Min(aux, dist);
                        }
                        else if (CASILLA_PEON_B[pos] & BBpasadosB & RAYO_N_AMPLIO[pos >> 3] & ~Mask(pos))
                        {
                              aux = Min(aux, dist);
                        }

                    }
                } else {

                    BBpieza = BBpasadosB;
                    if (BBpieza & (FILA_1 | FILA_2)) {
                        pos = Lsb(BBpieza & (FILA_2 | FILA_1));
                        if (DuoPeones(PeonesB, pos))
                            puntuacion += 6 * PEON_VAL;
                    }
                    while (BBpieza) {
                        pos = Lsb(BBpieza);
                        BBpieza &= ~COLUMNA[pos & 7];
                        puntuacion += PASA_ALEJA_REY[7 + (pos & 7) - (PosReyN & 7)];
                    }
                }
            }
            if (PiezasB < 2) {
                if (!PiezasB) {
                    int dist;

                    if (!(PeonesB & ~COLUMNA_0)) {
                        if (ReyN & (COLUMNA_0 | COLUMNA_1) && !(RAYO_N[PosReyN & ~1] & PeonesB))
                            maxB = TABLAS;
                    }
                    else if (!(PeonesB & ~COLUMNA_7)) {
                        if (ReyN & (COLUMNA_6 | COLUMNA_7) && !(RAYO_N[PosReyN | 1] & PeonesB))
                            maxB = TABLAS;
                    }

                    BBpieza = BBpasadosN;
                    while (BBpieza) {
                        pos = Msb(BBpieza);
                        BBpieza &= ~COLUMNA[pos & 7];
                        dist = Min(7-(pos>>3),5);

                        if (AtaquesRey(pos) & BBpieza)
                           puntuacion -= PEON_PASADO[pos>>3];

                        if (dist + Turno < DISTANCIA[PosReyB][A1 + (pos & 7)])
                          aux2 = Min(aux2, dist + ((ReyN & RAYO_S[pos]) ? 1 : 0));
                        else if (dist < 4 && ReyN & PASADO[0][pos-8])
                        {
                            if (AtaquesRey(PosReyB) & MASK[pos])
                            {
                               if ((DISTANCIA[PosReyN][pos] + Turno) <= 1)
                                 aux2 = Min(aux2, dist + Turno);
                            }
                            else if (ReyN & PASADO[0][A3+(pos&7)] && (dist < 3 || PosReyN >= A1))
                              aux2 = Min(aux2, dist);
                        }
                        else if (CASILLA_PEON_N[pos] & BBpasadosN & RAYO_S_AMPLIO[pos >> 3] & ~Mask(pos))
                              aux2 = Min(aux2, dist);
                    }
                } else {

                    BBpieza = BBpasadosN;
                    if (BBpieza & (FILA_6 | FILA_5)) {
                        pos = Msb(BBpieza & (FILA_5 | FILA_6));
                        if (DuoPeones(PeonesN, pos) || AtaquesPeonN(pos) & PeonesN)
                            puntuacion -= 6 * PEON_VAL;
                    }
                    while (BBpieza) {
                        pos = Lsb(BBpieza);
                        BBpieza &= ~COLUMNA[pos & 7];
                        puntuacion -= PASA_ALEJA_REY[7 + (pos & 7) - (PosReyB & 7)];
                    }
                }
            }
            if (aux < aux2)
                puntuacion += 8 * PEON_VAL;
            else if (aux2 < aux)
                puntuacion -= 8 * PEON_VAL;
        }

    }
#if SHOW_EVAL_POSSIBLE
    bkup_score = puntuacion;
#endif

    puntuacion += EvalSeguridad(&defB,&defN);

#if EVAL_SEGURIDAD
    calcseg = defB > 4 && PMaterialN > 12;
    calcseg |= (defN > 4 && PMaterialB > 12)<<1;
    calcseg &= SafetyFlags;
#endif

    if (PopCnt(AlfilesB) == 2)
        puntuacion += BONUS_2_ALFILES[suma_peones];

    if (AlfilesB & (Mask(A7) | Mask(H7))) {
        if (Tablero[H7] == ALFIL_B && Tablero[G6] == PEON_N && Atacada(G6, NEGRAS))
            puntuacion += ALFIL_ATRAPADO;
        else if (Tablero[A7] == ALFIL_B && Tablero[B6] == PEON_N && Atacada(B6, NEGRAS))
            puntuacion += ALFIL_ATRAPADO;
    }
    if (PopCnt(AlfilesN) == 2)
        puntuacion -= BONUS_2_ALFILES[suma_peones];

    if (AlfilesN & (Mask(A2) | Mask(H2))) {
        if (Tablero[H2] == ALFIL_N && Tablero[G3] == PEON_B && Atacada(G3, BLANCAS))
            puntuacion -= ALFIL_ATRAPADO;
        else if (Tablero[A2] == ALFIL_N && Tablero[B3] == PEON_B && Atacada(B3, BLANCAS))
            puntuacion -= ALFIL_ATRAPADO;
    }
    BBpieza = CaballosB & (Mask(A7) | Mask(A8) | Mask(H7) | Mask(H8));

    while (BBpieza) {
        pos = Msb(BBpieza);
        BBpieza ^= MASK[pos];
        if (CaballoB_Atrapado(pos))
            puntuacion += CABALLO_ATRAPADO;
    }

    BBpieza = CaballosN & (Mask(A2) | Mask(A1) | Mask(H2) | Mask(H1));

    while (BBpieza) {
        pos = Msb(BBpieza);
        BBpieza ^= MASK[pos];
        if (CaballoN_Atrapado(pos))
            puntuacion -= CABALLO_ATRAPADO;
    }

    if (TorresB & (FILA_0 | FILA_1) && PosReyN <= H7)
        puntuacion += BONUS_SEPTIMA[PopCnt((TorresB | DamasB) & (FILA_0|FILA_1))];
    if (TorresN & (FILA_6 | FILA_7) && PosReyB >= A2)
        puntuacion -= BONUS_SEPTIMA[PopCnt((TorresN | DamasN) & (FILA_6|FILA_7))];

    if (fase == FINAL)
    {
        if (PiezasB < 2 && TablasAlfilPeonDeTorreB())
           maxB = TABLAS;
        if (PiezasN < 2 && TablasAlfilPeonDeTorreN())
           maxN = TABLAS;
        if (candi_pasa)
        {
            eval_peones += candi_pasa;
            if (!PiezasN && candi_pasa > 0)
               eval_peones += (candi_pasa<<2);
            else if (!PiezasB && candi_pasa < 0)
               eval_peones += (candi_pasa<<2);
        }
    }

    if (material > maxB || material < maxN)
    {
        puntuacion += eval_peones;
        if (puntuacion > maxB || puntuacion < maxN)
        {
            puntuacion = material/PEON_VAL;
            return Turno ? puntuacion : -puntuacion;
        }
        else
          puntuacion >>= 1;
    }
    else
      puntuacion += material + eval_peones;


    if (final_tablero)
        puntuacion >>= 1;

#if LAZY_EVAL
    lazyscore = puntuacion;
    pos = Turno ? puntuacion : -puntuacion;

    if (pos > (beta + MaxPos[!Turno])
#if EVAL_SEGURIDAD
        && !(calcseg & (2 >> Turno))
#endif        
        ) {
        tab.lazy_evals++;
        return pos - MaxPos[!Turno];
    }
    if (pos < (alpha - MaxPos[Turno]) && !(calcseg & (1 << Turno))) {
        tab.lazy_evals++;
        return pos;
    }
#endif

#if EVAL_SEGURIDAD
    /* seguridad del rey */

#if SHOW_EVAL_POSSIBLE
   bkup_score = puntuacion;
#endif
   if (calcseg)
   {
      if (calcseg & 1) {
             int seguB;
             register int cnt;
             BBatqs_pieza = AtaquesRey(PosReyB);
             seguB = 0;
             do {
                 pos = Msb(BBatqs_pieza);
                 BBpieza = AtaquesHacia(pos);
                 BBatqs_pieza ^= MASK[pos];
                 if ((cnt = PopCnt(BBpieza & Negras)))
                 {
                    register int defensa;
                    cnt += 1 - (defensa = PopCnt(BBpieza & Blancas));
                    if (defensa == 1 && cnt > 1 && DamasN & BBpieza)
                      cnt += 4;
                    if (cnt > 0)
                      seguB += cnt;
                 }
             } while (BBatqs_pieza);
             if (defB > 12)
               defB = 12;

             if (seguB > 0)
               puntuacion -= DISMINUYE[PMaterialN] * defB * seguB / 32;
      }
      if (calcseg & 2) {
           int seguN;
           register int cnt;
           BBatqs_pieza = AtaquesRey(PosReyN);
           seguN = 0;
           do {
               pos = Msb(BBatqs_pieza);
               BBpieza = AtaquesHacia(pos);
               BBatqs_pieza ^= MASK[pos];
               if ((cnt = PopCnt(BBpieza & Blancas)))
               {
                  register int defensa;
                  cnt += 1 - (defensa = PopCnt(BBpieza & Negras));
                  if (defensa == 1 && cnt > 1 && DamasB & BBpieza)
                    cnt += 4;
                  if (pos > 0)
                    seguN += cnt;
               }
           } while (BBatqs_pieza);
           if (defN > 12)
             defN = 12;

           if (seguN > 0)
             puntuacion += DISMINUYE[PMaterialN] * defN * seguN / 32;
      }

#if LAZY_EVAL
      lazyscore = puntuacion;
      pos = Turno ? puntuacion : -puntuacion;

      if (pos > (beta + MaxPos[!Turno])) {
          tab.lazy_evals++;
          return beta;
      }
      if (pos < (alpha - MaxPos[Turno])) {
          tab.lazy_evals++;
          return alpha;
      }
#endif
   }

#if SHOW_EVAL_POSSIBLE
    Print("Seguridad Dinamica: %d %d\n",puntuacion-bkup_score, calcseg);
#endif

#endif

#if USE_CACHE
    if (tab.eval_cache[HashGlob & (CACHE_SIZE - 1)].key == HashGlob)
    {
        tab.eval_hits++;
        return tab.eval_cache[HashGlob & (CACHE_SIZE - 1)].valor;
    }
#endif

#if TROPISMO
    tropismoB = tropismoN = 0;
#endif

    BBpieza = CaballosB;
    while (BBpieza) {
        pos = Msb(BBpieza);
        BBpieza ^= MASK[pos];

#if EVAL_ATQ_DEBIL
        if (AtaquesCaballo(pos) & BBdebilesN)
            puntuacion += ATAQUE_DEBIL * PopCnt(AtaquesCaballo(pos) & BBdebilesN);
#endif

        if (!(PeonesN & PASADO[1][pos])) {
            puntuacion += OUTPOST[MIRROR[pos]];
            if (AtaquesPeonN(pos) & PeonesB) {
                puntuacion += OUTPOST[MIRROR[pos]] / 2;
                if (PopCnt(AtaquesPeonN(pos) & PeonesB) == 2)
                    puntuacion += 2*OUTPOST[MIRROR[pos]];
            }
        }

        if (PiezasB < 4 && PiezasB == PiezasN && PeonesN & (CUADRANTE_DER_N | CUADRANTE_DER_B)
            && PeonesN & (CUADRANTE_IZQ_N | CUADRANTE_IZQ_B))
            puntuacion += CABALLO_EN_FINAL - PiezasB * (CABALLO_EN_FINAL / 4);

//        movilidad += MOV_CABALLO[PopCnt(AtaquesCaballo(pos) & ~Blancas & ~BBatq_peonesN & ~PeonesN)];
#if TROPISMO
        tropismoB += TROPISMO_AC[DISTANCIA[pos][PosReyN]];
#endif
        puntuacion += TABLA_CABALLO[pos];

    }

#if SHOW_EVAL_POSSIBLE
    Print("puntuacion caballosB: %d.\n", puntuacion);
    bkup_score = puntuacion;
#endif
    BBpieza = CaballosN;
    while (BBpieza) {
        pos = Msb(BBpieza);
        BBpieza ^= MASK[pos];

#if EVAL_ATQ_DEBIL
        if (AtaquesCaballo(pos) & BBdebilesB)
            puntuacion -= ATAQUE_DEBIL * PopCnt(AtaquesCaballo(pos) & BBdebilesB);
#endif

        if (!(PeonesB & PASADO[0][pos])) {
            puntuacion -= OUTPOST[pos];
            if (AtaquesPeonB(pos) & PeonesN) {
                puntuacion -= OUTPOST[pos] / 2;
                if (PopCnt(AtaquesPeonB(pos) & PeonesN) == 2)
                    puntuacion -= 2*OUTPOST[pos];
            }
        }

        if (PiezasN < 4 && PiezasB == PiezasN && PeonesB & (CUADRANTE_DER_N | CUADRANTE_DER_B)
            && PeonesB & (CUADRANTE_IZQ_N | CUADRANTE_IZQ_B))
            puntuacion -= CABALLO_EN_FINAL - PiezasN * (CABALLO_EN_FINAL / 4);

//        movilidad -= MOV_CABALLO[PopCnt(AtaquesCaballo(pos) & ~Negras & ~BBatq_peonesB & ~PeonesB)];
#if TROPISMO
        tropismoN += TROPISMO_AC[DISTANCIA[pos][PosReyB]];
#endif
        puntuacion -= TABLA_CABALLO[pos];

    }

#if SHOW_EVAL_POSSIBLE
    Print("puntuacion caballosN: %d.\n", puntuacion);
    bkup_score = puntuacion;
#endif

    BBpieza = AlfilesB;
    while (BBpieza) {
        pos = Msb(BBpieza);
        BBpieza ^= MASK[pos];

#if EVAL_CLAVADAS
        if (ENTRE[pos][PosReyN] & Negras && PopCnt(ENTRE[pos][PosReyN] & (Blancas | Negras)) == 1 &&
            !(ENTRE[pos][PosReyN] & AlfilesN))
            puntuacion += CLAVA_REY_CONTRARIO;
#endif

        BBatqs_pieza = AtaquesAlfil(pos);
        movilidad += MOV_ALFIL[PopCnt(BBatqs_pieza & ~(PeonesB|BBatq_peonesN))];

#if EVAL_ATQ_DEBIL
        if (BBatqs_pieza & BBdebilesN)
            puntuacion += ATAQUE_DEBIL * PopCnt(BBatqs_pieza & BBdebilesN);
#endif


        if (AtaquesPeonN(pos) & PeonesB && !(PASADO[1][pos] & PeonesN))
            puntuacion += OUTPOST[MIRROR[pos]];

        if (PiezasB == 1) {
            if (MASK[pos] & CASILLAS_BLANCAS)
                puntuacion += ALFIL_MALO[PopCnt(PeonesB & CASILLAS_BLANCAS)];
            else
                puntuacion += ALFIL_MALO[PopCnt(PeonesB & ~CASILLAS_BLANCAS)];
        }

#if TROPISMO
        if (BBatqs_pieza & AtaquesRey(PosReyN))
          tropismoB += 3;
        else
          tropismoB += TROPISMO_AC[DISTANCIA[pos][PosReyN]];
#endif
        puntuacion += TABLA_ALFIL[pos];
    }

#if SHOW_EVAL_POSSIBLE
    Print("puntuacion alfilesB: %d.\n", puntuacion);
    bkup_score = puntuacion;
#endif

    BBpieza = AlfilesN;
    while (BBpieza) {
        pos = Msb(BBpieza);
        BBpieza ^= MASK[pos];

#if EVAL_CLAVADAS
        if (ENTRE[pos][PosReyB] & Blancas && PopCnt(ENTRE[pos][PosReyB] & (Blancas | Negras)) == 1 &&
            !(ENTRE[pos][PosReyB] & AlfilesB))
            puntuacion -= CLAVA_REY_CONTRARIO;
#endif
        BBatqs_pieza = AtaquesAlfil(pos);
        movilidad -= MOV_ALFIL[PopCnt(BBatqs_pieza & ~(PeonesN|BBatq_peonesB))];

#if EVAL_ATQ_DEBIL
        if (BBatqs_pieza & BBdebilesB)
            puntuacion -= ATAQUE_DEBIL * PopCnt(BBatqs_pieza & BBdebilesB);
#endif


        if (AtaquesPeonB(pos) & PeonesN && !(PASADO[0][pos] & PeonesB))
            puntuacion -= OUTPOST[MIRROR[pos]];


        if (PiezasN == 1) {
            if (MASK[pos] & CASILLAS_BLANCAS)
                puntuacion -= ALFIL_MALO[PopCnt(PeonesN & CASILLAS_BLANCAS)];
            else
                puntuacion -= ALFIL_MALO[PopCnt(PeonesN & ~CASILLAS_BLANCAS)];
        }


#if TROPISMO
        if (BBatqs_pieza & AtaquesRey(PosReyB))
          tropismoN += 3;
        else
          tropismoN += TROPISMO_AC[DISTANCIA[pos][PosReyB]];
#endif

        puntuacion -= TABLA_ALFIL[MIRROR[pos]];
    }

#if SHOW_EVAL_POSSIBLE
    Print("puntuacion alfilesN: %d.\n", puntuacion);
    bkup_score = puntuacion;
#endif

    BBpieza = TorresB;
    while (BBpieza) {

#if TROPISMO
        int tropC;
#endif

        pos = Msb(BBpieza);
        BBpieza ^= MASK[pos];

        if (!(COLUMNA[pos & 7] & PeonesB)) {
#if TROPISMO
            tropC = TROPISMO_TC[DISTANCIA[pos&7][PosReyN&7]];
#endif

            if (!(COLUMNA[pos & 7] & PeonesN)) {
                puntuacion += TORRE_COL_ABIERTA;
                if (BBpieza & COLUMNA[pos & 7])
                   puntuacion += DOBLA_TORRES;
            } else
            {
                puntuacion += TORRE_COL_SEMIABIERTA;
                if (COLUMNA[pos & 7] & BBdebilesN)
                  puntuacion += ATAQUE_DEBIL;
            }
        }
        else
        {
#if TROPISMO
            tropC = 0;
            if (!(RAYO_N[pos] & PeonesB))
              tropC = TROPISMO_TC[DISTANCIA[pos&7][PosReyN&7]];
            else
#endif
            if (COLUMNA[pos & 7] & BBpasadosB)
              puntuacion += TORRE_APOYO_PASADO;
        }
        puntuacion += TABLA_TORRE[pos];
#if TROPISMO
        tropismoB += Max(tropC,TROPISMO_T[DISTANCIA[pos][PosReyN]]);
#endif
    }

#if SHOW_EVAL_POSSIBLE
    Print("puntuacion torresB: %d.\n", puntuacion);
    bkup_score = puntuacion;
#endif

    BBpieza = TorresN;
    while (BBpieza) {

#if TROPISMO
        int tropC;
#endif
        pos = Msb(BBpieza);
        BBpieza ^= MASK[pos];

        if (!(COLUMNA[pos & 7] & PeonesN)) {
#if TROPISMO
            tropC = TROPISMO_TC[DISTANCIA[pos&7][PosReyB&7]];
#endif

            if (!(COLUMNA[pos & 7] & PeonesB)) {
            
                puntuacion -= TORRE_COL_ABIERTA;
                if (BBpieza & COLUMNA[pos & 7])
                  puntuacion -= DOBLA_TORRES;
            } else
            {
                puntuacion -= TORRE_COL_SEMIABIERTA;
                if (COLUMNA[pos & 7] & BBdebilesB)
                  puntuacion -= ATAQUE_DEBIL;
            }
        }
        else
        {
#if TROPISMO
            tropC = 0;
            if (!(PeonesN & RAYO_S[pos]))
               tropC = TROPISMO_TC[DISTANCIA[pos&7][PosReyB&7]];
            else
#endif
             if (COLUMNA[pos & 7] & BBpasadosN)
               puntuacion -= TORRE_APOYO_PASADO;
        }

        puntuacion -= TABLA_TORRE[MIRROR[pos]];
#if TROPISMO
        tropismoN += Max(tropC,TROPISMO_T[DISTANCIA[pos][PosReyB]]);
#endif
    }

#if SHOW_EVAL_POSSIBLE
    Print("puntuacion torresN: %d.\n", puntuacion);
    bkup_score = puntuacion;
#endif

    BBpieza = DamasB;
    while (BBpieza) {
#if TROPISMO
        int tropC;
#endif

        pos = Msb(BBpieza);
        BBpieza ^= MASK[pos];

/*
#if EVAL_ATQ_DEBIL
      BBatqs_pieza = AtaquesDama(pos);

      if (BBatqs_pieza & BBdebilesN)
        puntuacion += ATAQUE_DEBIL * PopCnt(BBatqs_pieza & BBdebilesN);
#endif*/

#if EVAL_CLAVADAS
        if (ENTRE[pos][PosReyN] & Negras && PopCnt(ENTRE[pos][PosReyN] & (Blancas | Negras)) == 1 &&
            !(AtaquesDesde(Msb(ENTRE[pos][PosReyN] & Negras)) & DamasB))
            puntuacion += CLAVA_REY_CONTRARIO;
#endif

        if (pos != D1 && ((CaballosB | AlfilesB) & DESARROLLO_B) ||
            DISTANCIA[pos & 7][PosReyB & 7] > 4)
            puntuacion += DAMA_DESCOLOCADA;

#if TROPISMO
        tropC = 0;
        if (!(RAYO_N[pos] & PeonesB))
          tropC = TROPISMO_TC[DISTANCIA[pos&7][PosReyN&7]];
        tropismoB += Max(tropC,TROPISMO_D[DISTANCIA[pos][PosReyN]]);
#endif
        puntuacion += TABLA_DAMA[pos];
    }

#if SHOW_EVAL_POSSIBLE
    Print("puntuacion damasB: %d.\n", puntuacion);
    bkup_score = puntuacion;
#endif

    BBpieza = DamasN;
    while (BBpieza) {
#if TROPISMO
        int tropC;
#endif
        pos = Msb(BBpieza);
        BBpieza ^= MASK[pos];

/*#if EVAL_ATQ_DEBIL
        BBatqs_pieza = AtaquesDama(pos);

        if (BBatqs_pieza & BBdebilesB)
          puntuacion -= ATAQUE_DEBIL * PopCnt(BBatqs_pieza & BBdebilesB);
#endif*/

#if EVAL_CLAVADAS
        if (ENTRE[pos][PosReyB] & Blancas && PopCnt(ENTRE[pos][PosReyB] & (Blancas | Negras)) == 1 &&
            !(AtaquesDesde(Msb(ENTRE[pos][PosReyB] & Blancas)) & DamasN))
            puntuacion -= CLAVA_REY_CONTRARIO;
#endif

        if (pos != D8 && ((CaballosN | AlfilesN) & DESARROLLO_N) ||
            DISTANCIA[pos & 7][PosReyN & 7] > 4)
            puntuacion -= DAMA_DESCOLOCADA;

#if TROPISMO
        tropC = 0;
        if (!(RAYO_S[pos] & PeonesN))
          tropC = TROPISMO_TC[DISTANCIA[pos&7][PosReyB&7]];
        tropismoN += Max(tropC,TROPISMO_D[DISTANCIA[pos][PosReyB]]);
#endif
        puntuacion -= TABLA_DAMA[MIRROR[pos]];
    }

#if SHOW_EVAL_POSSIBLE
    Print("puntuacion damasN: %d.\n", puntuacion);
    bkup_score = puntuacion;
#endif

    puntuacion += movilidad;

#if TROPISMO
    puntuacion += (PESO_TROPISMO[defN]*EVAL_TROPISMO[tropismoB] - PESO_TROPISMO[defB]*EVAL_TROPISMO[tropismoN])>>5;
#endif

#if SHOW_EVAL_POSSIBLE
    Print("evpeones: %d.\n", eval_peones);
#if TROPISMO
    Print("TropismoB: %d, (%d)\n",tropismoB,(PESO_TROPISMO[defN]*EVAL_TROPISMO[tropismoB])>>5);
    Print("TropismoN: %d, (%d)\n",tropismoN,(PESO_TROPISMO[defB]*EVAL_TROPISMO[tropismoN])>>5);
#endif
#endif

#if SHOW_EVAL_POSSIBLE
    Print("puntuacion colgadas: %d.\n", puntuacion);
    bkup_score = puntuacion;
#endif


#if SHOW_EVAL_POSSIBLE
    Print("puntuacion mat detrás: %d.\n", puntuacion);
    bkup_score = puntuacion;
#endif

#if SHOW_EVAL_POSSIBLE
    Print("movilidad: %d.\n",movilidad);
    Print("tbalance: %d.\n",TBalance);
#endif

#if LAZY_EVAL
    // maxima diferencia en favor de las blancas

    if (puntuacion - lazyscore > MaxPos[1])
        MaxPos[1] = puntuacion - lazyscore;

    // maxima diferencia en favor de las negras

    if (-puntuacion + lazyscore > MaxPos[0])
        MaxPos[0] = -puntuacion + lazyscore;
#endif

    puntuacion = Turno ? puntuacion + BONUS_TURNO : -puntuacion - BONUS_TURNO;

#if USE_CACHE
    tab.eval_cache[HashGlob & (CACHE_SIZE - 1)].key = HashGlob;
    tab.eval_cache[HashGlob & (CACHE_SIZE - 1)].valor = puntuacion;
#endif

    return puntuacion - (puntuacion % 3);
}
//--------------------------------------------------------------------------------------------
int             Repeticion(int modo)
{
    register int i;

    for (i = NumJug - 2; i >= Historial[NumJug].last_cap; i -= 2) {
        if (Historial[i].hash == HashGlob) {
            if (modo)
                return 1;
            else
                modo = 1;
        }
    }
    return (0);
}
//-------------------------------------------------------------------------------------------------------
int             MaterialInsuficiente(int turno)
{
    if (turno) {
        if (PeonesB || TorresB || DamasB)
            return 0;

        if (PiezasB < 2 || (PiezasB == 2 && PopCnt(CaballosB) == 2))
            return 1;
    } else {
        if (PeonesN || TorresN || DamasN)
            return 0;

        if (PiezasN < 2 || (PiezasN == 2 && PopCnt(CaballosN) == 2))
            return 1;
    }
    return 0;
}
//-------------------------------------------------------------------------------------------------------
int    EvalApertura()
{
    int             score = 0;

    if (Tablero[E2] == PEON_B && Tablero[E3] != VACIA)
        score += PEON_CENTRAL_BLOQUEADO;

    if (Tablero[D2] == PEON_B && Tablero[D3] != VACIA)
        score += PEON_CENTRAL_BLOQUEADO;

    if (Tablero[E7] == PEON_N && Tablero[E6] != VACIA)
        score -= PEON_CENTRAL_BLOQUEADO;

    if (Tablero[D7] == PEON_N && Tablero[E6] != VACIA)
        score -= PEON_CENTRAL_BLOQUEADO;

    if (Tablero[D4] == PEON_B && Tablero[D5] == PEON_N) {
        if (Tablero[C2] == PEON_B && Tablero[C3] == CABALLO_B)
            score += PEON_CENTRAL_BLOQUEADO;
        if (Tablero[C7] == PEON_B && Tablero[C6] == CABALLO_N)
            score -= PEON_CENTRAL_BLOQUEADO;
    }
    return score;
}
//-------------------------------------------------------------------------------------------------------
int    CaballoB_Atrapado(int pos)
{
    if (pos <= H7) {
        if (pos == A7) {
            if ((Tablero[C6] == PEON_N || Tablero[A6] == PEON_N) && Tablero[B7] == PEON_N)
                return 1;;
        } else if (pos == A8) {
            if (Tablero[A7] == PEON_N) {
                entero64        atqs = AtaquesHacia(C7);
                if (atqs & Negras && PopCnt(atqs & Negras) >= PopCnt(atqs & Blancas))
                    return 1;;
            }
        } else if (pos == H8) {
            if (Tablero[H7] == PEON_N) {
                entero64        atqs = AtaquesHacia(F7);
                if (atqs & Negras && PopCnt(atqs & Negras) >= PopCnt(atqs & Blancas))
                    return 1;
            }
        } else if (pos == H7) {
            if ((Tablero[F6] == PEON_N || Tablero[H6] == PEON_N) && Tablero[G7] == PEON_N)
                return 1;
        }
    }
    return 0;
}

//-------------------------------------------------------------------------------------------------------
int    CaballoN_Atrapado(int pos)
{
    if (pos >= A2) {
        if (pos == A2) {
            if ((Tablero[A3] == PEON_B || Tablero[C3] == PEON_B) && Tablero[B2] == PEON_B)
                return 1;
        } else if (pos == H2) {
            if ((Tablero[H3] == PEON_B || Tablero[F3] == PEON_B) && Tablero[G2] == PEON_B)
                return 1;
        } else if (pos == A1) {
            if (Tablero[A2] == PEON_B) {
                entero64        atqs = AtaquesHacia(C2);
                if (atqs & Blancas && PopCnt(atqs & Blancas) >= PopCnt(atqs & Negras))
                    return 1;
            }
        } else if (pos == H1) {
            if (Tablero[H2] == PEON_B) {
                entero64        atqs = AtaquesHacia(F2);
                if (atqs & Blancas && PopCnt(atqs & Blancas) >= PopCnt(atqs & Negras))
                    return 1;
            }
        }
    }
    return 0;
}
//-------------------------------------------------------------------------------------------------------
int             Final_KBN_K()
{
    int             ptos;
    int             pos_perdedor[64] = {100, 90, 80, 70, 60, 50, 40, 30,
        90, 80, 70, 57, 45, 32, 20, 40,
        80, 70, 50, 37, 23, 10, 32, 50,
        70, 57, 37, 10, 0, 23, 45, 60,
        60, 45, 23, 0, 10, 37, 57, 70,
        50, 32, 10, 23, 37, 50, 70, 80,
        40, 20, 32, 45, 57, 70, 80, 90,
    30, 40, 50, 60, 70, 80, 90, 100};

    ptos = 900 - 6 * TAXI_CAB[PosReyB][PosReyN];
    if (PiezasB) {
        if (AlfilesB & CASILLAS_BLANCAS)
            return (ptos + pos_perdedor[PosReyN]);
        else
            return (ptos + pos_perdedor[(PosReyN & ~7) + 7 - (PosReyN & 7)]);
    } else {
        if (AlfilesN & CASILLAS_BLANCAS)
            return (ptos + pos_perdedor[PosReyB]);
        else
            return (ptos + pos_perdedor[(PosReyB & ~7) + 7 - (PosReyB & 7)]);
    }
}
//-----------------------------------------------------------------------------------
int             Final_KBB_K()
{
    int             ptos;
    int             pos_perdedor[64] = {100, 90, 80, 60, 60, 80, 90, 100,
        90, 80, 70, 50, 50, 32, 80, 90,
        80, 70, 50, 30, 30, 50, 70, 80,
        60, 50, 30, 10, 10, 30, 50, 60,
        60, 50, 30, 10, 10, 30, 50, 60,
        80, 70, 50, 30, 30, 50, 70, 80,
        90, 80, 70, 50, 50, 70, 80, 90,
    100, 90, 80, 60, 60, 80, 90, 100};

    ptos = 900 - 6 * TAXI_CAB[PosReyB][PosReyN];
    if (PiezasB)
        return (ptos + pos_perdedor[PosReyN]);
    else
        return (ptos + pos_perdedor[PosReyB]);
}

//-----------------------------------------------------------------------------------
int EvalNingunoB(void)
{
    register int defectosB=0, pos;

        defectosB = 6;

        if (PosStatus & E_CORTO_B)
            defectosB = Min(defectosB,EvalCortoB());

        if (PosStatus & E_LARGO_B)
            defectosB = Min(defectosB,EvalLargoB());

        pos = (PosReyB - 1) & 7;

        if (!(COLUMNA[pos] & PeonesN)) {
            defectosB++;
            if (!(COLUMNA[pos] & PeonesB))
                defectosB++;
        }
        pos = PosReyB & 7;

        if (!(COLUMNA[pos] & PeonesN)) {
            defectosB++;
            if (!(COLUMNA[pos] & PeonesB))
                defectosB += 3;
        }
        pos = (PosReyB + 1) & 7;

        if (!(COLUMNA[pos] & PeonesN)) {
            defectosB++;
            if (!(COLUMNA[pos] & PeonesB))
                defectosB++;
        }
        return defectosB;
}
//-----------------------------------------------------------------------------------
int EvalCortoB(void)
{
        register int defectosB=0;

        if (!(COLUMNA_5 & PeonesB)) {
            defectosB += 2;
            if (!(TorresB & COLUMNA_5))
                defectosB += 2;
        } else if (Tablero[F2] != PEON_B)
            defectosB++;

        if (!(COLUMNA_7 & PeonesB)) {
            defectosB += 2;
            if (!(TorresB & COLUMNA_7))
                defectosB += 2;
        } else if (Tablero[H2] != PEON_B) {
            defectosB += 1;
            if (Tablero[H3] != PEON_B)
                defectosB += 1;
        }
        if (!(COLUMNA_6 & PeonesB)) {
            defectosB += 2;
            if (!(TorresB & COLUMNA_6))
                defectosB += 3;
        } else if (Tablero[G2] != PEON_B) {
            defectosB++;
            if (Tablero[G3] != PEON_B)
                defectosB++;
            else if (Tablero[G2] == ALFIL_B)
                defectosB >>= 1;
            if (DamasN && ((PeonesN & (Mask(F3)|Mask(H3)))  ||
                 (!(AlfilesB & CASILLAS_BLANCAS) &&
                     AlfilesN & CASILLAS_BLANCAS)))
                defectosB += 3;
        }
        if (PosStatus & (REY_N_ENRQ_LARGO | E_LARGO_N)) {
            if (!(PeonesN & COLUMNA_5))
                defectosB += 2;
            if (!(PeonesN & COLUMNA_6))
                defectosB += 2;
            if (!(PeonesN & COLUMNA_7))
                defectosB += 2;
        }
        return defectosB;
}
//-----------------------------------------------------------------------------------
int EvalLargoB(void)
{
        register int defectosB=0;

        if (!(COLUMNA_0 & PeonesB)) {
            defectosB += 2;
            if (!(TorresB & COLUMNA_0))
                defectosB += 2;
        } else if (Tablero[A2] != PEON_B) {
            defectosB += 1;
            if (Tablero[A3] != PEON_B)
                defectosB += 1;
        }
        if (!(COLUMNA_1 & PeonesB)) {
            defectosB += 2;
            if (!(TorresB & COLUMNA_1))
                defectosB += 3;
        } else if (Tablero[B2] != PEON_B) {
            defectosB += 2;
            if (Tablero[G3] != PEON_B)
                defectosB += 1;
            else if (Tablero[B2] == ALFIL_B)
                defectosB >>= 1;
            else if (!(AlfilesB & ~CASILLAS_BLANCAS) &&
                     AlfilesN & ~CASILLAS_BLANCAS)
                defectosB += 3;
        }
        if (!(COLUMNA_2 & PeonesB)) {
            defectosB += 2;
            if (!(TorresB & COLUMNA_2))
                defectosB += 3;
        } else if (Tablero[C2] != PEON_B) {
            defectosB += 1;
            if (Tablero[C3] != PEON_B)
                defectosB += 1;
        }
        if (PosStatus & (REY_N_ENRQ_CORTO | E_CORTO_N)) {
            if (!(PeonesN & COLUMNA_0))
                defectosB += 2;
            if (!(PeonesN & COLUMNA_1))
                defectosB += 2;
            if (!(PeonesN & COLUMNA_2))
                defectosB += 2;
        }
        return defectosB;
}
//-----------------------------------------------------------------------------------
int EvalNingunoN(void)
{
        int defectosN =0, pos;

        defectosN = 6;

        if (PosStatus & E_CORTO_N)
            defectosN = Min(defectosN,EvalCortoN());

        if (PosStatus & E_LARGO_N)
            defectosN = Min(defectosN,EvalLargoN());

        pos = (PosReyN - 1) & 7;

        if (!(COLUMNA[pos] & PeonesB)) {
            defectosN++;
            if (!(COLUMNA[pos] & PeonesN))
                defectosN++;
        }
        pos = PosReyN & 7;
        if (!(COLUMNA[pos] & PeonesB)) {
            defectosN++;
            if (!(COLUMNA[pos] & PeonesN))
                defectosN += 3;
        }
        pos = (PosReyN + 1) & 7;
        if (!(COLUMNA[pos] & PeonesB)) {
            defectosN++;
            if (!(COLUMNA[pos] & PeonesN))
                defectosN++;
        }
        return defectosN;
}
 
//-----------------------------------------------------------------------------------
int EvalCortoN(void)
{
        register int defectosN=0;

        if (!(COLUMNA_5 & PeonesN))
        {
            defectosN += 2;
            if (!(TorresN & COLUMNA_5))
                defectosN += 2;
        }
        else if (Tablero[F7] != PEON_N)
            defectosN++;

        if (!(COLUMNA_6 & PeonesN)) {
            defectosN += 2;
            if (!(TorresN & COLUMNA_6))
                defectosN += 3;
        } else if (Tablero[G7] != PEON_N) {
            defectosN++;
            if (Tablero[G6] != PEON_N)
                defectosN++;
            else if (Tablero[G7] == ALFIL_N)
                defectosN >>= 1;
            if (DamasB && ((PeonesB & (Mask(F6)|Mask(H6)))  ||
                 (!(AlfilesN & ~CASILLAS_BLANCAS) &&
                     AlfilesB & ~CASILLAS_BLANCAS)))
                defectosN += 3;

        }
        if (!(COLUMNA_7 & PeonesN)) {
            defectosN += 2;
            if (!(TorresN & COLUMNA_7))
                defectosN += 2;
        } else if (Tablero[H7] != PEON_N) {
            defectosN += 1;
            if (Tablero[H6] != PEON_N)
                defectosN += 1;
        }
        if (PosStatus & (REY_B_ENRQ_LARGO | E_LARGO_B)) {
            if (!(PeonesB & COLUMNA_5))
                defectosN += 2;
            if (!(PeonesB & COLUMNA_6))
                defectosN += 2;
            if (!(PeonesB & COLUMNA_7))
                defectosN += 2;
        }
        return defectosN;
}
//-----------------------------------------------------------------------------------
int EvalLargoN(void)
{
        int defectosN = 0;
        if (!(COLUMNA_0 & PeonesN)) {
            defectosN += 2;
            if (!(TorresN & COLUMNA_0))
                defectosN += 2;
        } else if (Tablero[A7] != PEON_N) {
            defectosN += 1;
            if (Tablero[A6] != PEON_N)
                defectosN += 1;
        }
        if (!(COLUMNA_1 & PeonesN)) {
            defectosN += 2;
            if (!(TorresN & COLUMNA_1))
                defectosN += 3;
        } else if (Tablero[B7] != PEON_N) {
            defectosN += 2;
            if (Tablero[B6] != PEON_N)
                defectosN += 1;
            else if (Tablero[B7] == ALFIL_N)
                defectosN >>= 1;
            else if (!(AlfilesN & CASILLAS_BLANCAS) &&
                     AlfilesB & CASILLAS_BLANCAS && DamasB)
                defectosN += 3;
        }
        if (!(COLUMNA_2 & PeonesN)) {
            defectosN += 2;
            if (!(TorresN & COLUMNA_2))
                defectosN += 2;
        } else if (Tablero[C7] != PEON_N) {
            defectosN += 1;
            if (Tablero[C6] != PEON_N)
                defectosN += 1;
        }
        if (PosStatus & (REY_B_ENRQ_CORTO | E_CORTO_B)) {
            if (!(PeonesB & COLUMNA_0))
                defectosN += 2;
            if (!(PeonesB & COLUMNA_1))
                defectosN += 2;
            if (!(PeonesB & COLUMNA_2))
                defectosN += 2;
        }
        return defectosN;
}

//-----------------------------------------------------------------------------------
__inline int    EvalSeguridad(int *defB, int *defN)
{

/*
    REY_B_ENRQ_CORTO    0x0400U
    REY_B_ENRQ_LARGO    0x0800U
    REY_N_ENRQ_CORTO    0x1000U
    REY_N_ENRQ_LARGO    0x2000U
*/

    static int (*EvalEstadoEnroqueB[3])(void) = { EvalNingunoB, EvalCortoB,
               EvalLargoB };
    static int (*EvalEstadoEnroqueN[3])(void) = { EvalNingunoN, EvalCortoN,
               EvalLargoN };

    static int ENRQ_EVAL[3] = { 0, ENROCADO_CORTO, ENROCADO_LARGO };

    int             eval = 0;
    int             defectosN = 0, defectosB;
    int             indx = (PosStatus>>10)&3;

    eval += ENRQ_EVAL[indx];

//    if (MaterialB >= MaterialN-2*PEON_VAL)
    {
       defectosB = EvalEstadoEnroqueB[indx]();
       

       if (PMaterialN < 20 && !defectosB)
         eval += AMENAZA_PASILLO;

       if (!DamasN)
         defectosB >>= 1;

       *defB = defectosB;

#if SHOW_EVAL_POSSIBLE
     Print("enroqueB: (defectosB = %d, pmaterialN = %d)\n", defectosB, PMaterialN);
#endif
    }

//    if (MaterialN >= MaterialB-2*PEON_VAL)
    {
       indx = (PosStatus>>12)&3;
       eval -= ENRQ_EVAL[indx];
       defectosN = EvalEstadoEnroqueN[indx]();

       if (PMaterialB < 20 && !defectosN)
          eval -= AMENAZA_PASILLO;

       if (!DamasB)
         defectosN >>= 1;

       *defN = defectosN;

#if SHOW_EVAL_POSSIBLE
     Print("enroqueN: (defectosN = %d, pmaterialB = %d)\n", defectosN, PMaterialB);
#endif
    }

    if (RTurno)
    {
      if (defectosB > defectosN +3)
        eval -= 15;
    }
    else if (defectosN > defectosB +3)
      eval += 15;

    eval += (DISMINUYE[PMaterialN] * (TABLA_REY[PosReyB] +
             ENROQUE_MINUS[defectosB]) -
             DISMINUYE[PMaterialB] * (TABLA_REY[MIRROR[PosReyN]] +
             ENROQUE_MINUS[defectosN]) +
             AUMENTA[PMaterialN] * TABLA_REY_FINAL[PosReyB] -
             AUMENTA[PMaterialB] * TABLA_REY_FINAL[MIRROR[PosReyN]])/128;

    return eval;
}


//------------------------------------------------------------------------
int TablasAlfilPeonDeTorreB()
{
     entero64 BBpieza;
     int pos;

     if (AlfilesB)
     {
        if (AlfilesB & ~CASILLAS_BLANCAS)
        {
           if (!(PeonesB & ~COLUMNA_0))
           {
              if (ReyN & (Mask(A8) | Mask(B8) | Mask(A7) | Mask(B7)))
                 return 1;
              else if (!Turno)
              {
                 BBpieza = AtaquesRey(PosReyN) & (Mask(A8) | Mask(B8) | Mask(A7) | Mask(B7));
                 while (BBpieza)
                 {
                    pos = Msb(BBpieza);
                    BBpieza ^= MASK[pos];
                    if (!Atacada(pos, 1))
                       return 1;
                 }
              }
           }
        }
        else if (!(PeonesB & ~COLUMNA_7))
        {
           if (ReyN & (Mask(H8) | Mask(G8) | Mask(H7) | Mask(G7)))
             return 1;
           else if (!Turno)
           {
              BBpieza = AtaquesRey(PosReyN) & (Mask(H8) | Mask(G8) | Mask(H7) | Mask(G7));
              while (BBpieza)
              {
                 pos = Msb(BBpieza);
                 BBpieza ^= MASK[pos];
                 if (!Atacada(pos, 1))
                   return 1;
              }
           }
        }
     }

     return 0;
}

//------------------------------------------------------------------------
int TablasAlfilPeonDeTorreN()
{
     entero64 BBpieza;
     int pos;

     if (AlfilesN)
     {
        if (AlfilesN & CASILLAS_BLANCAS)
        {
           if (!(PeonesN & ~COLUMNA_0))
           {
              if (ReyB & (Mask(A1) | Mask(B1) | Mask(A2) | Mask(B2)))
                 return 1;
              else if (Turno)
              {
                 BBpieza = AtaquesRey(PosReyB) & (Mask(A1) | Mask(B1) | Mask(A2) | Mask(B2));
                 while (BBpieza)
                 {
                    pos = Msb(BBpieza);
                    BBpieza ^= MASK[pos];

                    if (!Atacada(pos, 0))
                      return 1;
                 }
              }
           }
        }
        else if (!(PeonesN & ~COLUMNA_7))
        {
           if (ReyB & (Mask(H1) | Mask(G1) | Mask(H2) | Mask(G2)))
              return 1;
           else if (Turno)
           {
              BBpieza = AtaquesRey(PosReyB) & (Mask(H1) | Mask(G1) | Mask(H2) | Mask(G2));
              while (BBpieza)
              {
                 pos = Msb(BBpieza);
                 BBpieza ^= MASK[pos];
                 if (!Atacada(pos, 0))
                   return 1;
              }
           }
        }
     }
     return 0;
}

