/* Pepito v1.59  -- file: genjug.c --
   Copyright (c) 2000-2 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

#include "genjug.h"


/*
   Funcion que genera las capturas y promociones a partir de una posicion
   dada (se prueban primero en la busqueda normal y son las unicas consi-
   deradas en la quiescente), devolviendo el puntero a la proxima posicion
   vacia en la pila de jugadas.

                                                     SHL
                                                     ---
   bits en jugada:                6 -> desde           0
                                  6 -> hacia           6
                                  4 -> captura        12
                                  4 -> promocion      16
                                  1 -> al paso        20       (0x100000)
                                  1 -> enroque corto  21       (0x200000)
                                  1 -> enroque largo  22       (0x400000)
                                  1 -> peon de 2      23       (0x800000)
                                 12 -> MVV / LVA      24

*/


#define UNDER_PROMOTION
#define GEN_ROTATED

list_jug       *GenCaps(list_jug * ptrjug)
{
    entero64        mapa_destino;
    entero64        mapa_pieza;
    int             cas_fin,
                    cas_ini;
#ifndef GEN_ROTATED
    entero64        ocupadas = Blancas | Negras;
#endif


//-------------   GEN CAPS CABALLOS B ---------------------------------
    if (Turno) {
        Gen_Jugs_MSB(CaballosB, AtaquesCaballo, Negras, CABALLO_VAL);
#ifdef GEN_ROTATED
        Gen_Jugs_MSB(AlfilesB, AtaquesAlfil, Negras, ALFIL_VAL);
        Gen_Jugs_MSB(TorresB, AtaquesTorre, Negras, TORRE_VAL);
        Gen_Jugs_MSB(DamasB, AtaquesDama, Negras, DAMA_VAL);
#endif

#ifndef GEN_ROTATED
        mapa_pieza = AlfilesB|DamasB;
        while (mapa_pieza) {
            cas_ini = Msb(mapa_pieza);
            mapa_pieza ^= MASK[cas_ini];
            mapa_destino = VACIO_ALFIL[cas_ini] & Negras;
            while (mapa_destino) {
                cas_fin = Msb(mapa_destino);
                mapa_destino ^= MASK[cas_fin];
                if (!(ENTRE[cas_ini][cas_fin] & ocupadas)) {
                    ptrjug->jug = cas_ini | (cas_fin << 6) | (Tablero[cas_fin] << 12);
                    (ptrjug++)->valor = VALOR[Tablero[cas_fin]] - ALFIL_VAL;
                } else
                    mapa_destino &= ~ENTRE[cas_ini][cas_fin];
            }
        }

        mapa_pieza = TorresB|DamasB;
        while (mapa_pieza) {
            cas_ini = Msb(mapa_pieza);
            mapa_pieza ^= MASK[cas_ini];
            mapa_destino = VACIO_TORRE[cas_ini] & Negras;
            while (mapa_destino) {
                cas_fin = Msb(mapa_destino);
                mapa_destino ^= MASK[cas_fin];
                if (!(ENTRE[cas_ini][cas_fin] & ocupadas)) {
                    ptrjug->jug = cas_ini | (cas_fin << 6) | (Tablero[cas_fin] << 12);
                    (ptrjug++)->valor = VALOR[Tablero[cas_fin]] - TORRE_VAL;
                } else
                    mapa_destino &= ~ENTRE[cas_ini][cas_fin];
            }
        }
#endif


//-------------    GEN CAPS REY B   -------------------------------------------

        mapa_destino = AtaquesRey(PosReyB) & Negras;
        while (mapa_destino) {
            cas_fin = Msb(mapa_destino);
            mapa_destino ^= MASK[cas_fin];
            ptrjug->jug = PosReyB | (cas_fin << 6) | (Tablero[cas_fin] << 12);
            (ptrjug++)->valor = VALOR[Tablero[cas_fin]] - 10 * PEON_VAL;
        }

//-------------    GEN CAPS PEONES B    ---------------------------------------

        mapa_destino = ((PeonesB & FILA_1) >> 8) & ~(Blancas | Negras);

        while (mapa_destino) {
            cas_fin = Lsb(mapa_destino);
            cas_ini = cas_fin + 8;
            mapa_destino ^= MASK[cas_fin];
            ptrjug->jug = cas_ini | (cas_fin << 6) | (DAMA_B << 16);
            (ptrjug++)->valor = -PEON_VAL + DAMA_VAL;

#ifdef UNDER_PROMOTION
            ptrjug->jug = cas_ini | (cas_fin << 6) | (CABALLO_B << 16);
            (ptrjug++)->valor = -PEON_VAL + CABALLO_VAL;
            ptrjug->jug = cas_ini | (cas_fin << 6) | (TORRE_B << 16);
            (ptrjug++)->valor = -PEON_VAL + TORRE_VAL;
            ptrjug->jug = cas_ini | (cas_fin << 6) | (ALFIL_B << 16);
            (ptrjug++)->valor = -PEON_VAL + ALFIL_VAL;
#endif
        }

        mapa_destino = ((PeonesB & ~COLUMNA_0) >> 9) & (Negras | MASK[AlPaso]);
        while (mapa_destino) {
            cas_fin = Msb(mapa_destino);
            mapa_destino ^= MASK[cas_fin];

            if (cas_fin <= H8) {
                ptrjug->jug = (cas_fin + 9) | (cas_fin << 6) | (Tablero[cas_fin] << 12) | (DAMA_B << 16);
                (ptrjug++)->valor = -PEON_VAL + DAMA_VAL + VALOR[Tablero[cas_fin]];
#ifdef UNDER_PROMOTION
                ptrjug->jug = (cas_fin + 9) | (cas_fin << 6) | (Tablero[cas_fin] << 12) | (CABALLO_B << 16);
                (ptrjug++)->valor = -PEON_VAL + CABALLO_VAL + VALOR[Tablero[cas_fin]];
                ptrjug->jug = (cas_fin + 9) | (cas_fin << 6) | (Tablero[cas_fin] << 12) | (TORRE_B << 16);
                (ptrjug++)->valor = -PEON_VAL + TORRE_VAL + VALOR[Tablero[cas_fin]];
                ptrjug->jug = (cas_fin + 9) | (cas_fin << 6) | (Tablero[cas_fin] << 12) | (ALFIL_B << 16);
                (ptrjug++)->valor = -PEON_VAL + ALFIL_VAL + VALOR[Tablero[cas_fin]];
#endif
            } else {
                ptrjug->jug = (cas_fin + 9) | (cas_fin << 6) |
                    ((Tablero[cas_fin] ? Tablero[cas_fin] : PEON_N + 0x100) << 12);
                (ptrjug++)->valor = -PEON_VAL + (Tablero[cas_fin] ? VALOR[Tablero[cas_fin]] : PEON_VAL);

            }
        }

        mapa_destino = ((PeonesB & ~COLUMNA_7) >> 7) & (Negras | MASK[AlPaso]);
        while (mapa_destino) {
            cas_fin = Msb(mapa_destino);
            mapa_destino ^= MASK[cas_fin];

            if (cas_fin <= H8) {
                ptrjug->jug = (cas_fin + 7) | (cas_fin << 6) | (Tablero[cas_fin] << 12) | (DAMA_B << 16);
                (ptrjug++)->valor = -PEON_VAL + DAMA_VAL + VALOR[Tablero[cas_fin]];
#ifdef UNDER_PROMOTION
                ptrjug->jug = (cas_fin + 7) | (cas_fin << 6) | (Tablero[cas_fin] << 12) | (CABALLO_B << 16);
                (ptrjug++)->valor = -PEON_VAL + CABALLO_VAL + VALOR[Tablero[cas_fin]];
                ptrjug->jug = (cas_fin + 7) | (cas_fin << 6) | (Tablero[cas_fin] << 12) | (TORRE_B << 16);
                (ptrjug++)->valor = -PEON_VAL + TORRE_VAL + VALOR[Tablero[cas_fin]];
                ptrjug->jug = (cas_fin + 7) | (cas_fin << 6) | (Tablero[cas_fin] << 12) | (ALFIL_B << 16);
                (ptrjug++)->valor = -PEON_VAL + ALFIL_VAL + VALOR[Tablero[cas_fin]];
#endif
            } else {
                ptrjug->jug = (cas_fin + 7) | (cas_fin << 6) |
                    ((Tablero[cas_fin] ? Tablero[cas_fin] : PEON_N + 0x100) << 12);
                (ptrjug++)->valor = -PEON_VAL + (Tablero[cas_fin] ? VALOR[Tablero[cas_fin]] : PEON_VAL);
            }
        }
    }                           // if Turno de las blancas
    else {
        Gen_Jugs_LSB(CaballosN, AtaquesCaballo, Blancas, CABALLO_VAL);
#ifdef GEN_ROTATED
        Gen_Jugs_LSB(AlfilesN, AtaquesAlfil, Blancas, ALFIL_VAL);
        Gen_Jugs_LSB(TorresN, AtaquesTorre, Blancas, TORRE_VAL);
        Gen_Jugs_LSB(DamasN, AtaquesDama, Blancas, DAMA_VAL);
#endif


#ifndef GEN_ROTATED
        mapa_pieza = AlfilesN|DamasN;
        while (mapa_pieza) {
            cas_ini = Lsb(mapa_pieza);
            mapa_pieza ^= MASK[cas_ini];
            mapa_destino = VACIO_ALFIL[cas_ini] & Blancas;
            while (mapa_destino) {
                cas_fin = Lsb(mapa_destino);
                mapa_destino ^= MASK[cas_fin];
                if (!(ENTRE[cas_ini][cas_fin] & ocupadas)) {
                    ptrjug->jug = cas_ini | (cas_fin << 6) | (Tablero[cas_fin] << 12);
                    (ptrjug++)->valor = VALOR[Tablero[cas_fin]] - ALFIL_VAL;
                } else
                    mapa_destino &= ~ENTRE[cas_ini][cas_fin];
            }
        }

        mapa_pieza = TorresN|DamasN;
        while (mapa_pieza) {
            cas_ini = Lsb(mapa_pieza);
            mapa_pieza ^= MASK[cas_ini];
            mapa_destino = VACIO_TORRE[cas_ini] & Blancas;
            while (mapa_destino) {
                cas_fin = Lsb(mapa_destino);
                mapa_destino ^= MASK[cas_fin];
                if (!(ENTRE[cas_ini][cas_fin] & ocupadas)) {
                    ptrjug->jug = cas_ini | (cas_fin << 6) | (Tablero[cas_fin] << 12);
                    (ptrjug++)->valor = VALOR[Tablero[cas_fin]] - ALFIL_VAL;
                } else
                    mapa_destino &= ~ENTRE[cas_ini][cas_fin];
            }
        }
#endif
//-------------    GEN CAPS REY N    --------------------------------------

        mapa_destino = AtaquesRey(PosReyN) & Blancas;
        while (mapa_destino) {
            cas_fin = Lsb(mapa_destino);
            mapa_destino ^= MASK[cas_fin];
            ptrjug->jug = PosReyN | (cas_fin << 6) | (Tablero[cas_fin] << 12);
            (ptrjug++)->valor = VALOR[Tablero[cas_fin]] - 10 * PEON_VAL;
        }
//-------------    GEN CAPS PEONES N    ------------------------------------

        mapa_destino = ((PeonesN & FILA_6) << 8) & ~(Blancas | Negras);
        while (mapa_destino) {
            cas_fin = Msb(mapa_destino);
            cas_ini = cas_fin - 8;
            mapa_destino ^= MASK[cas_fin];
            ptrjug->jug = cas_ini | (cas_fin << 6) | (DAMA_N << 16);
            (ptrjug++)->valor = -PEON_VAL + DAMA_VAL;
#ifdef UNDER_PROMOTION
            ptrjug->jug = cas_ini | (cas_fin << 6) | (CABALLO_N << 16);
            (ptrjug++)->valor = -PEON_VAL + CABALLO_VAL;
            ptrjug->jug = cas_ini | (cas_fin << 6) | (TORRE_N << 16);
            (ptrjug++)->valor = -PEON_VAL + TORRE_VAL;
            ptrjug->jug = cas_ini | (cas_fin << 6) | (ALFIL_N << 16);
            (ptrjug++)->valor = -PEON_VAL + ALFIL_VAL;
#endif
        }

        mapa_destino = ((PeonesN & ~COLUMNA_0) << 7) & (Blancas | MASK[AlPaso]);

        while (mapa_destino) {
            cas_fin = Lsb(mapa_destino);
            mapa_destino ^= MASK[cas_fin];

            if (cas_fin >= A1) {
                ptrjug->jug = (cas_fin - 7) | (cas_fin << 6) | (Tablero[cas_fin] << 12) | (DAMA_N << 16);
                (ptrjug++)->valor = -PEON_VAL + DAMA_VAL + VALOR[Tablero[cas_fin]];
#ifdef UNDER_PROMOTION
                ptrjug->jug = (cas_fin - 7) | (cas_fin << 6) | (Tablero[cas_fin] << 12) | (CABALLO_N << 16);
                (ptrjug++)->valor = -PEON_VAL + CABALLO_VAL + VALOR[Tablero[cas_fin]];
                ptrjug->jug = (cas_fin - 7) | (cas_fin << 6) | (Tablero[cas_fin] << 12) | (TORRE_N << 16);
                (ptrjug++)->valor = -PEON_VAL + TORRE_VAL + VALOR[Tablero[cas_fin]];
                ptrjug->jug = (cas_fin - 7) | (cas_fin << 6) | (Tablero[cas_fin] << 12) | (ALFIL_N << 16);
                (ptrjug++)->valor = -PEON_VAL + ALFIL_VAL + VALOR[Tablero[cas_fin]];
#endif
            } else {
                ptrjug->jug = (cas_fin - 7) | (cas_fin << 6) |
                    ((Tablero[cas_fin] ? Tablero[cas_fin] : PEON_B + 0x100) << 12);
                (ptrjug++)->valor = -PEON_VAL + (Tablero[cas_fin] ? VALOR[Tablero[cas_fin]] : PEON_VAL);
            }
        }

        mapa_destino = ((PeonesN & ~COLUMNA_7) << 9) & (Blancas | MASK[AlPaso]);
        while (mapa_destino) {
            cas_fin = Lsb(mapa_destino);
            mapa_destino ^= MASK[cas_fin];

            if (cas_fin >= A1) {
                ptrjug->jug = (cas_fin - 9) | (cas_fin << 6) | (Tablero[cas_fin] << 12) | (DAMA_N << 16);
                (ptrjug++)->valor = -PEON_VAL + DAMA_VAL + VALOR[Tablero[cas_fin]];
#ifdef UNDER_PROMOTION
                ptrjug->jug = (cas_fin - 9) | (cas_fin << 6) | (Tablero[cas_fin] << 12) | (CABALLO_N << 16);
                (ptrjug++)->valor = -PEON_VAL + CABALLO_VAL + VALOR[Tablero[cas_fin]];
                ptrjug->jug = (cas_fin - 9) | (cas_fin << 6) | (Tablero[cas_fin] << 12) | (TORRE_N << 16);
                (ptrjug++)->valor = -PEON_VAL + TORRE_VAL + VALOR[Tablero[cas_fin]];
                ptrjug->jug = (cas_fin - 9) | (cas_fin << 6) | (Tablero[cas_fin] << 12) | (ALFIL_N << 16);
                (ptrjug++)->valor = -PEON_VAL + ALFIL_VAL + VALOR[Tablero[cas_fin]];
#endif
            } else {
                ptrjug->jug = (cas_fin - 9) | (cas_fin << 6) |
                    ((Tablero[cas_fin] ? Tablero[cas_fin] : PEON_B + 0x100) << 12);
                (ptrjug++)->valor = -PEON_VAL + (Tablero[cas_fin] ? VALOR[Tablero[cas_fin]] : PEON_VAL);
            }
        }

    }                           // fin turno negras
    return ptrjug;
}                               // fin GenCaps

//----------------------------------------------------------------------------------------

/*
   Funcion que calcula las jugadas restantes (ni capturas ni promociones).
*/

list_jug       *GenNoCaps(list_jug * ptrjug)
{
    entero64        mapa_destino;
    entero64        mapa_pieza;
    entero64        Vacias = (Blancas | Negras);        // inicialmente casillas
    // ocupadas
    int             cas_fin,
                    cas_ini;

    if (Turno) {
        if (Enroque & E_CORTO_B && !(Vacias & MASK_F1G1) && !(Negras & AtaquesHacia(F1))) {
            ptrjug->jug = E1 | (G1 << 6) | 0x200000;
            (ptrjug++)->valor = HistHeuristic[E1 | (G1 << 6)][1];
        }
        if (Enroque & E_LARGO_B && !(Vacias & MASK_B1C1D1) && !(Negras & AtaquesHacia(D1))) {
            ptrjug->jug = E1 | (C1 << 6) | 0x400000;
            (ptrjug++)->valor = HistHeuristic[E1 | (C1 << 6)][1];
        }
        Vacias = ~Vacias;

        Gen_Jugs_MSB_NC(CaballosB, AtaquesCaballo, Vacias);
        Gen_Jugs_MSB_NC(AlfilesB, AtaquesAlfil, Vacias);
        Gen_Jugs_MSB_NC(TorresB, AtaquesTorre, Vacias);
        Gen_Jugs_MSB_NC(DamasB, AtaquesDama, Vacias);

//-------------    GEN NO CAPS REY B   -------------------------------------------

        mapa_destino = AtaquesRey(PosReyB) & Vacias;
        while (mapa_destino) {
            cas_fin = Msb(mapa_destino);
            mapa_destino ^= MASK[cas_fin];
            ptrjug->jug = PosReyB | (cas_fin << 6);
            (ptrjug++)->valor = HistHeuristic[ptrjug->jug & 0xfff][1];
        }

//-------------    GEN NO CAPS PEONES B    ---------------------------------------

        mapa_destino = ((PeonesB & ~FILA_1) >> 8) & Vacias;

        mapa_pieza = ((mapa_destino & FILA_5) >> 8) & Vacias;

        while (mapa_destino) {
            cas_fin = Msb(mapa_destino);
            mapa_destino ^= MASK[cas_fin];
            ptrjug->jug = (cas_fin + 8) | (cas_fin << 6);
            (ptrjug++)->valor = HistHeuristic[ptrjug->jug & 0xfff][1];
        }

        while (mapa_pieza) {
            cas_fin = Msb(mapa_pieza);
            mapa_pieza ^= MASK[cas_fin];
            ptrjug->jug = (cas_fin + 16) | (cas_fin << 6) | 0x800000;
            (ptrjug++)->valor = HistHeuristic[ptrjug->jug & 0xfff][1];
        }

    }                           // fin turno blancas
    else {
        if (Enroque & E_CORTO_N && !(Vacias & MASK_F8G8) && !(Blancas & AtaquesHacia(F8))) {
            ptrjug->jug = E8 | (G8 << 6) | 0x200000;
            (ptrjug++)->valor = HistHeuristic[ptrjug->jug & 0xfff][0];
        }
        if (Enroque & E_LARGO_N && !(Vacias & MASK_B8C8D8) && !(Blancas & AtaquesHacia(D8))) {
            ptrjug->jug = E8 | (C8 << 6) | 0x400000;
            (ptrjug++)->valor = HistHeuristic[ptrjug->jug & 0xfff][0];
        }
        Vacias = ~Vacias;

        Gen_Jugs_LSB_NC(CaballosN, AtaquesCaballo, Vacias);
        Gen_Jugs_LSB_NC(AlfilesN, AtaquesAlfil, Vacias);
        Gen_Jugs_LSB_NC(TorresN, AtaquesTorre, Vacias);
        Gen_Jugs_LSB_NC(DamasN, AtaquesDama, Vacias);

//-------------    GEN NO CAPS REY N    --------------------------------------

        mapa_destino = AtaquesRey(PosReyN) & Vacias;
        while (mapa_destino) {
            cas_fin = Lsb(mapa_destino);
            mapa_destino ^= MASK[cas_fin];
            ptrjug->jug = PosReyN | (cas_fin << 6);
            (ptrjug++)->valor = HistHeuristic[ptrjug->jug & 0xfff][0];
        }

//-------------    GEN NO CAPS PEONES N    ------------------------------------

        mapa_destino = ((PeonesN & ~FILA_6) << 8) & Vacias;
        mapa_pieza = ((mapa_destino & FILA_2) << 8) & Vacias;

        while (mapa_destino) {
            cas_fin = Lsb(mapa_destino);
            mapa_destino ^= MASK[cas_fin];
            ptrjug->jug = (cas_fin - 8) | (cas_fin << 6);
            (ptrjug++)->valor = HistHeuristic[ptrjug->jug & 0xfff][0];
        }

        while (mapa_pieza) {
            cas_fin = Lsb(mapa_pieza);
            mapa_pieza ^= MASK[cas_fin];
            ptrjug->jug = (cas_fin - 16) | (cas_fin << 6) | 0x800000;
            (ptrjug++)->valor = HistHeuristic[ptrjug->jug & 0xfff][0];
        }

    }                           // fin turno negras

    return ptrjug;

}                               // fin GenNoCaps

//------------------------------------------------------------------------------------

//    Funcion que calcula jugadas cuando hay jaque

list_jug       *GenJaqJugs(list_jug * ptrjug)
{
    entero64        mapa_destino;
    entero64        mapa_pieza,
                    a_obstruir;
    entero64        Vacias = ~(Blancas | Negras);
    entero64        piezas_jaque;
    int             cas_fin,
                    cas_ini,
                    cas_jaque;
    int             direc1 = 0,
                    direc2 = 0;

    if (Turno) {
        piezas_jaque = AtaquesHacia(PosReyB) & Negras;
        cas_jaque = LsbC(piezas_jaque);
        piezas_jaque ^= MASK[cas_jaque];
        if (Tablero[cas_jaque] != PEON_N)
            direc1 = DIRECCION[cas_jaque][PosReyB];

        if (piezas_jaque) {
            direc2 = Lsb(piezas_jaque);
            if (Tablero[cas_jaque] != PEON_N)
                direc2 = DIRECCION[direc2][PosReyB];
        }
        mapa_destino = AtaquesRey(PosReyB) & ~Blancas;

        while (mapa_destino) {
            cas_fin = Msb(mapa_destino);
            mapa_destino ^= MASK[cas_fin];
            if (!Atacada(cas_fin, 0) && DIRECCION[PosReyB][cas_fin] != direc1 &&
                DIRECCION[PosReyB][cas_fin] != direc2) {
                ptrjug->jug = PosReyB | (cas_fin << 6) | (Tablero[cas_fin] << 12);
                ptrjug++;
            }
        }

        if (!piezas_jaque) {
            a_obstruir = MASK[cas_jaque] | ENTRE[cas_jaque][PosReyB];

            Gen_Obstru_B(CaballosB, AtaquesCaballo);
            Gen_Obstru_B(AlfilesB, AtaquesAlfil);
            Gen_Obstru_B(TorresB, AtaquesTorre);
            Gen_Obstru_B(DamasB, AtaquesDama);

            //-------------    GEN OBSTRU PEONES B   --------------------------

            if (AlPaso == cas_jaque - 8) {
                if ((AlPaso & 7) && Tablero[AlPaso + 7] == PEON_B && !ClavadaReyB(AlPaso + 7)) {
                    ptrjug->jug = (AlPaso + 7) | (AlPaso << 6) | ((PEON_N + 0x100) << 12);
                    ptrjug++;
                }
                if ((AlPaso & 7) != 7 && Tablero[AlPaso + 9] == PEON_B && !ClavadaReyB(AlPaso + 9)) {
                    ptrjug->jug = (AlPaso + 9) | (AlPaso << 6) | ((PEON_N + 0x100) << 12);
                    ptrjug++;
                }
            }

            mapa_destino = ((PeonesB & ~COLUMNA_0) >> 9) & Negras & a_obstruir;

            while (mapa_destino) {
                cas_fin = Msb(mapa_destino);
                mapa_destino ^= MASK[cas_fin];
                if (!ClavadaReyB(cas_fin + 9)) {
                    if (cas_fin <= H8) {
                        ptrjug->jug = (cas_fin + 9) | (cas_fin << 6) | (Tablero[cas_fin] << 12) |
                            (DAMA_B << 16);
                        ptrjug++;

#ifdef UNDER_PROMOTION
                        ptrjug->jug = (cas_fin + 9) | (cas_fin << 6) | (Tablero[cas_fin] << 12) |
                            (CABALLO_B << 16);
                        ptrjug++;
                        ptrjug->jug = (cas_fin + 9) | (cas_fin << 6) | (Tablero[cas_fin] << 12) |
                            (TORRE_B << 16);
                        ptrjug++;
                        ptrjug->jug = (cas_fin + 9) | (cas_fin << 6) | (Tablero[cas_fin] << 12) |
                            (ALFIL_B << 16);
                        ptrjug++;
#endif
                    } else {
                        ptrjug->jug = (cas_fin + 9) | (cas_fin << 6) |
                            ((Tablero[cas_fin] ? Tablero[cas_fin] : PEON_N + 0x100) << 12);
                        ptrjug++;
                    }
                }
            }

            mapa_destino = ((PeonesB & ~COLUMNA_7) >> 7) & Negras & a_obstruir;

            while (mapa_destino) {
                cas_fin = Msb(mapa_destino);
                mapa_destino ^= MASK[cas_fin];
                if (!ClavadaReyB(cas_fin + 7)) {
                    if (cas_fin <= H8) {
                        ptrjug->jug = (cas_fin + 7) | (cas_fin << 6) | (Tablero[cas_fin] << 12) |
                            (DAMA_B << 16);
                        ptrjug++;
#ifdef UNDER_PROMOTION
                        ptrjug->jug = (cas_fin + 7) | (cas_fin << 6) | (Tablero[cas_fin] << 12) |
                            (CABALLO_B << 16);
                        ptrjug++;
                        ptrjug->jug = (cas_fin + 7) | (cas_fin << 6) | (Tablero[cas_fin] << 12) |
                            (TORRE_B << 16);
                        ptrjug++;
                        ptrjug->jug = (cas_fin + 7) | (cas_fin << 6) | (Tablero[cas_fin] << 12) |
                            (ALFIL_B << 16);
                        ptrjug++;
#endif
                    } else {
                        ptrjug->jug = (cas_fin + 7) | (cas_fin << 6) |
                            ((Tablero[cas_fin] ? Tablero[cas_fin] : PEON_N + 0x100) << 12);
                        ptrjug++;
                    }
                }
            }

            mapa_destino = (PeonesB >> 8) & Vacias;
            mapa_pieza = ((mapa_destino & FILA_5) >> 8) & Vacias & a_obstruir;
            mapa_destino &= a_obstruir;

            while (mapa_destino) {
                cas_fin = Msb(mapa_destino);
                mapa_destino ^= MASK[cas_fin];
                if (!ClavadaReyB(cas_fin + 8)) {
                    if (cas_fin <= H8) {
                        ptrjug->jug = (cas_fin + 8) | (cas_fin << 6) | (DAMA_B << 16);
                        ptrjug++;
#ifdef UNDER_PROMOTION
                        ptrjug->jug = (cas_fin + 8) | (cas_fin << 6) | (CABALLO_B << 16);
                        ptrjug++;
                        ptrjug->jug = (cas_fin + 8) | (cas_fin << 6) | (TORRE_B << 16);
                        ptrjug++;
                        ptrjug->jug = (cas_fin + 8) | (cas_fin << 6) | (ALFIL_B << 16);
                        ptrjug++;
#endif
                    } else {
                        ptrjug->jug = (cas_fin + 8) | (cas_fin << 6);
                        ptrjug++;
                    }
                }
            }

            while (mapa_pieza) {
                cas_fin = Msb(mapa_pieza);
                mapa_pieza ^= MASK[cas_fin];
                if (!ClavadaReyB(cas_fin + 16)) {
                    ptrjug->jug = (cas_fin + 16) | (cas_fin << 6) | 0x800000;
                    ptrjug++;
                }
            }

        }                       // fin if popcnt == 1
    }                           // if Turno de las blancas
    else {
        //------------------   GEN EVASIONES REY N  --------------------------------------

        piezas_jaque = AtaquesHacia(PosReyN) & Blancas;
        cas_jaque = MsbC(piezas_jaque);
        piezas_jaque ^= MASK[cas_jaque];
        if (Tablero[cas_jaque] != PEON_B)
            direc1 = DIRECCION[cas_jaque][PosReyN];

        if (piezas_jaque) {
            direc2 = Msb(piezas_jaque);
            if (Tablero[cas_jaque] != PEON_B)
                direc2 = DIRECCION[direc2][PosReyN];
        }
        mapa_destino = AtaquesRey(PosReyN) & ~Negras;

        while (mapa_destino) {
            cas_fin = Lsb(mapa_destino);
            mapa_destino ^= MASK[cas_fin];
            if (!Atacada(cas_fin, 1) && DIRECCION[PosReyN][cas_fin] != direc1 &&
                DIRECCION[PosReyN][cas_fin] != direc2) {
                ptrjug->jug = PosReyN | (cas_fin << 6) | (Tablero[cas_fin] << 12);
                ptrjug++;
            }
        }

        if (!piezas_jaque) {
            a_obstruir = MASK[cas_jaque] | ENTRE[cas_jaque][PosReyN];

            Gen_Obstru_N(CaballosN, AtaquesCaballo);
            Gen_Obstru_N(AlfilesN, AtaquesAlfil);
            Gen_Obstru_N(TorresN, AtaquesTorre);
            Gen_Obstru_N(DamasN, AtaquesDama);

            //-------------    GEN OBSTRU PEONES N   --------------------------

            if (AlPaso == cas_jaque + 8) {
                if ((AlPaso & 7) && Tablero[AlPaso - 9] == PEON_N && !ClavadaReyN(AlPaso - 9)) {
                    ptrjug->jug = (AlPaso - 9) | (AlPaso << 6) | ((PEON_B + 0x100) << 12);
                    ptrjug++;
                }
                if ((AlPaso & 7) != 7 && Tablero[AlPaso - 7] == PEON_N && !ClavadaReyN(AlPaso - 7)) {
                    ptrjug->jug = (AlPaso - 7) | (AlPaso << 6) | ((PEON_B + 0x100) << 12);
                    ptrjug++;
                }
            }
            mapa_destino = ((PeonesN & ~COLUMNA_0) << 7) & Blancas & a_obstruir;

            while (mapa_destino) {
                cas_fin = Lsb(mapa_destino);
                mapa_destino ^= MASK[cas_fin];
                if (!ClavadaReyN(cas_fin - 7)) {
                    if (cas_fin >= A1) {
                        ptrjug->jug = (cas_fin - 7) | (cas_fin << 6) | (Tablero[cas_fin] << 12) |
                            (DAMA_N << 16);
                        ptrjug++;
#ifdef UNDER_PROMOTION
                        ptrjug->jug = (cas_fin - 7) | (cas_fin << 6) | (Tablero[cas_fin] << 12) |
                            (CABALLO_N << 16);
                        ptrjug++;
                        ptrjug->jug = (cas_fin - 7) | (cas_fin << 6) | (Tablero[cas_fin] << 12) |
                            (TORRE_N << 16);
                        ptrjug++;
                        ptrjug->jug = (cas_fin - 7) | (cas_fin << 6) | (Tablero[cas_fin] << 12) |
                            (ALFIL_N << 16);
                        ptrjug++;
#endif
                    } else {
                        ptrjug->jug = (cas_fin - 7) | (cas_fin << 6) |
                            ((Tablero[cas_fin] ? Tablero[cas_fin] : PEON_B + 0x100) << 12);
                        ptrjug++;
                    }
                }
            }

            mapa_destino = ((PeonesN & ~COLUMNA_7) << 9) & Blancas & a_obstruir;

            while (mapa_destino) {
                cas_fin = Lsb(mapa_destino);
                mapa_destino ^= MASK[cas_fin];
                if (!ClavadaReyN(cas_fin - 9)) {
                    if (cas_fin >= A1) {
                        ptrjug->jug = (cas_fin - 9) | (cas_fin << 6) | (Tablero[cas_fin] << 12) |
                            (DAMA_N << 16);
                        ptrjug++;
#ifdef UNDER_PROMOTION
                        ptrjug->jug = (cas_fin - 9) | (cas_fin << 6) | (Tablero[cas_fin] << 12) |
                            (CABALLO_N << 16);
                        ptrjug++;
                        ptrjug->jug = (cas_fin - 9) | (cas_fin << 6) | (Tablero[cas_fin] << 12) |
                            (TORRE_N << 16);
                        ptrjug++;
                        ptrjug->jug = (cas_fin - 9) | (cas_fin << 6) | (Tablero[cas_fin] << 12) |
                            (ALFIL_N << 16);
                        ptrjug++;
#endif
                    } else {
                        ptrjug->jug = (cas_fin - 9) | (cas_fin << 6) |
                            ((Tablero[cas_fin] ? Tablero[cas_fin] : PEON_B + 0x100) << 12);
                        ptrjug++;
                    }
                }
            }

            mapa_destino = (PeonesN << 8) & Vacias;
            mapa_pieza = ((mapa_destino & FILA_2) << 8) & Vacias & a_obstruir;
            mapa_destino &= a_obstruir;

            while (mapa_destino) {
                cas_fin = Lsb(mapa_destino);
                mapa_destino ^= MASK[cas_fin];
                if (!ClavadaReyN(cas_fin - 8)) {
                    if (cas_fin >= A1) {
                        ptrjug->jug = (cas_fin - 8) | (cas_fin << 6) | (DAMA_N << 16);
                        ptrjug++;
#ifdef UNDER_PROMOTION
                        ptrjug->jug = (cas_fin - 8) | (cas_fin << 6) | (CABALLO_N << 16);
                        ptrjug++;
                        ptrjug->jug = (cas_fin - 8) | (cas_fin << 6) | (TORRE_N << 16);
                        ptrjug++;
                        ptrjug->jug = (cas_fin - 8) | (cas_fin << 6) | (ALFIL_N << 16);
                        ptrjug++;
#endif
                    } else {
                        ptrjug->jug = (cas_fin - 8) | (cas_fin << 6);
                        ptrjug++;
                    }
                }
            }

            while (mapa_pieza) {
                cas_fin = Lsb(mapa_pieza);
                mapa_pieza ^= MASK[cas_fin];
                if (!ClavadaReyN(cas_fin - 16)) {
                    ptrjug->jug = (cas_fin - 16) | (cas_fin << 6) | 0x800000;
                    ptrjug++;
                }
            }
        }                       // fin if popcnt == 1
    }                           // if Turno de las negras

    return ptrjug;
}                               // fin función

//-------------------------------------------------------
void            GeneraValidas(int pide_tablas)
{
    tab.jaque[0] = Jaque(Turno);
    if (tab.jaque[0])
        tab.max_stack[0] = GenJaqJugs(JugStack);
    else {
        tab.max_stack[0] = GenCaps(JugStack);
        tab.max_stack[0] = GenNoCaps(tab.max_stack[0]);
    }

    tab.have_book_move = 0;
    tab.max_stack[0] = SoloValidas(tab.max_stack[0]);

    if (pide_tablas) {
        if (Historial[NumJug].last_cap + 100 < NumJug) {
            xb_info.force = 1;
            tab.time_up = 2;
            Print("1/2-1/2 { 50 movimientos }\n");
        }
        if (Repeticion(0)) {
            xb_info.force = 1;
            tab.time_up = 2;
            Print("1/2-1/2 { Triple repetición }\n");
        } else if (MaterialInsuficiente(1) && MaterialInsuficiente(0)) {
            xb_info.force = 1;
            tab.time_up = 2;
            Print("1/2-1/2 { Material insuficiente }\n");
        } else if (tab.max_stack[0] == JugStack) {
            xb_info.force = 1;
            tab.time_up = 2;
            if (tab.jaque[0])
                Print("%s { Jaque mate }\n", Turno ? "0-1" : "1-0");
            else
                Print("1/2-1/2 { Ahogado }\n");
        }
    }
}

//-------------------------------------------------------------------------
/*
   Funcion que calcula jugadas que dan jaque.
*/

list_jug       *GenChecks(list_jug * ptrjug)
{
    entero64        mapa_destino;
    entero64        mapa_pieza;
    entero64        Vacias = ~(Blancas | Negras);       // inicialmente casillas
    // ocupadas
    int             cas_fin,
                    cas_ini;

    if (Turno) {
        Gen_ChecksB(AlfilesB | DamasB, AtaquesAlfil, Vacias);
        Gen_ChecksB(TorresB | DamasB, AtaquesTorre, Vacias);

        if (7 ^ (PosReyN & 7) && PosReyN < 47 && Tablero[PosReyN + 9] == VACIA
            && Tablero[PosReyN + 17] == PEON_B) {       // COL != H
            ptrjug->jug = (PosReyN + 17) | ((PosReyN + 9) << 6);
            (ptrjug++)->valor = -10 * PEON_VAL;

        }
        if (PosReyN & 7 && PosReyN < 49 && Tablero[PosReyN + 7] == VACIA
            && Tablero[PosReyN + 15] == PEON_B) {       // COL != A
            ptrjug->jug = (PosReyN + 15) | ((PosReyN + 7) << 6);
            (ptrjug++)->valor = -10 * PEON_VAL;
        }
    } else {
        Gen_ChecksN(AlfilesN | DamasN, AtaquesAlfil, Vacias);
        Gen_ChecksN(TorresN | DamasN, AtaquesTorre, Vacias);

        if (7 ^ (PosReyB & 7) && PosReyB > 14 && Tablero[PosReyB - 7] == VACIA
            && Tablero[PosReyB - 15] == PEON_N) {       // COL != H
            ptrjug->jug = (PosReyB - 15) | ((PosReyB - 7) << 6);
            (ptrjug++)->valor = -10 * PEON_VAL;

        }
        if (PosReyB & 7 && PosReyB > 16 && Tablero[PosReyB - 9] == VACIA
            && Tablero[PosReyB - 17] == PEON_N) {       // COL != A
            ptrjug->jug = (PosReyB - 17) | ((PosReyB - 9) << 6);
            (ptrjug++)->valor = -10 * PEON_VAL;
        }
    }
    return ptrjug;

}
