/* Pepito v1.59  -- file: atqs.c --
   Copyright (c) 2000-02 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
//-----------------------------------------------------------------------------------
entero64        AtaquesHacia(register int casilla)
{
    return (
            (AtaquesTorre(casilla) & (DamasB | DamasN | TorresB | TorresN)) |
         (AtaquesAlfil(casilla) & (DamasB | DamasN | AlfilesB | AlfilesN)) |
            (AtaquesCaballo(casilla) & (CaballosB | CaballosN)) |
            (AtaquesRey(casilla) & (ReyB | ReyN)) |
            (AtaquesPeonN(casilla) & PeonesB) |
            (AtaquesPeonB(casilla) & PeonesN)
    );
}
//----------------------------------------------------------------------------------
/*entero64        AtaquesDesde(register int casilla)
{

#ifdef TEST_ARRAY_BOUNDS
    assert(casilla >= 0);
    assert(casilla < 64);
#endif

    switch (Tablero[casilla]) {

    case DAMA_B:
    case DAMA_N:
        return AtaquesDama(casilla);
    case CABALLO_B:
    case CABALLO_N:
        return AtaquesCaballo(casilla);
    case ALFIL_B:
    case ALFIL_N:
        return AtaquesAlfil(casilla);
    case TORRE_B:
    case TORRE_N:
        return AtaquesTorre(casilla);
    case PEON_B:
        return AtaquesPeonB(casilla);
    case PEON_N:
        return AtaquesPeonN(casilla);
    case REY_B:
    case REY_N:
        return AtaquesRey(casilla);
    }
    return 0;
}*/
//----------------------------------------------------------------------------------
/*
entero64        AtaquesB()
{
    register entero64 mapa_pieza,
                    mapa_atqs = 0;
    register int    cas_ini;

    // atqs caballos

    mapa_pieza = CaballosB;

    while (mapa_pieza) {
        cas_ini = Msb(mapa_pieza);

#ifdef TEST_ARRAY_BOUNDS
        assert(cas_ini >= 0);
        assert(cas_ini < 64);
#endif
        mapa_pieza ^= MASK[cas_ini];
        mapa_atqs |= AtaquesCaballo(cas_ini);
    }

    // atqs alfiles

    mapa_pieza = AlfilesB;

    while (mapa_pieza) {
        cas_ini = Msb(mapa_pieza);

#ifdef TEST_ARRAY_BOUNDS
        assert(cas_ini >= 0);
        assert(cas_ini < 64);
#endif

        mapa_pieza ^= MASK[cas_ini];
        mapa_atqs |= AtaquesAlfil(cas_ini);
    }

    // atqs torres

    mapa_pieza = TorresB;

    while (mapa_pieza) {
        cas_ini = Msb(mapa_pieza);

#ifdef TEST_ARRAY_BOUNDS
        assert(cas_ini >= 0);
        assert(cas_ini < 64);
#endif

        mapa_pieza ^= MASK[cas_ini];
        mapa_atqs |= AtaquesTorre(cas_ini);
    }

    // atqs damas

    mapa_pieza = DamasB;

    while (mapa_pieza) {
        cas_ini = Msb(mapa_pieza);

#ifdef TEST_ARRAY_BOUNDS
        assert(cas_ini >= 0);
        assert(cas_ini < 64);
#endif

        mapa_pieza ^= MASK[cas_ini];
        mapa_atqs |= AtaquesDama(cas_ini);
    }

    // atqs rey

    mapa_atqs |= AtaquesRey(PosReyB);

    // atqs peones

    mapa_atqs |= ((PeonesB & ~COLUMNA_0) >> 9);
    mapa_atqs |= ((PeonesB & ~COLUMNA_7) >> 7);

    return mapa_atqs;
}
//----------------------------------------------------------------------------------
entero64        AtaquesN()
{
    register entero64 mapa_pieza,
                    mapa_atqs = 0;
    register int    cas_ini;

    // atqs caballos

    mapa_pieza = CaballosN;

    while (mapa_pieza) {
        cas_ini = Lsb(mapa_pieza);

#ifdef TEST_ARRAY_BOUNDS
        assert(cas_ini >= 0);
        assert(cas_ini < 64);
#endif

        mapa_pieza ^= MASK[cas_ini];
        mapa_atqs |= AtaquesCaballo(cas_ini);
    }

    // atqs alfiles

    mapa_pieza = AlfilesN;

    while (mapa_pieza) {
        cas_ini = Lsb(mapa_pieza);

#ifdef TEST_ARRAY_BOUNDS
        assert(cas_ini >= 0);
        assert(cas_ini < 64);
#endif

        mapa_pieza ^= MASK[cas_ini];
        mapa_atqs |= AtaquesAlfil(cas_ini);
    }

    // atqs torres

    mapa_pieza = TorresN;

    while (mapa_pieza) {
        cas_ini = Lsb(mapa_pieza);

#ifdef TEST_ARRAY_BOUNDS
        assert(cas_ini >= 0);
        assert(cas_ini < 64);
#endif

        mapa_pieza ^= MASK[cas_ini];
        mapa_atqs |= AtaquesTorre(cas_ini);
    }

    // atqs damas

    mapa_pieza = DamasN;

    while (mapa_pieza) {
        cas_ini = Lsb(mapa_pieza);

#ifdef TEST_ARRAY_BOUNDS
        assert(cas_ini >= 0);
        assert(cas_ini < 64);
#endif

        mapa_pieza ^= MASK[cas_ini];
        mapa_atqs |= AtaquesDama(cas_ini);
    }

    // atqs rey

    mapa_atqs |= AtaquesRey(PosReyN);

    // atqs peones

    mapa_atqs |= ((PeonesN & ~COLUMNA_0) << 7);
    mapa_atqs |= ((PeonesN & ~COLUMNA_7) << 9);

    return mapa_atqs;
}*/
//----------------------------------------------------------------------------------
int             ClavadaReyB(register int cas_ficha)
{

#ifdef TEST_ARRAY_BOUNDS
    assert(PosReyB >= 0);
    assert(PosReyB < 64);
    assert(cas_ficha >= 0);
    assert(cas_ficha < 64);
#endif

    if (DIRECCION[PosReyB][cas_ficha] == 0 || ENTRE[PosReyB][cas_ficha] & (Blancas | Negras))
        return 0;

    switch (DIRECCION[PosReyB][cas_ficha]) {
    case 1:
    case 5:
        if (ATAQUES_ALFIL_45[PosReyB][255 & (Rotado45 ^ MASK[ROTADO_45[cas_ficha]])
                                >> SHIFT_45[PosReyB]] & (DamasN | AlfilesN))
            return 1;
        break;

    case 2:
    case 6:
        if (ATAQUES_TORRE_FIL[PosReyB][255 & (((Blancas | Negras) ^ MASK[cas_ficha])
                                >> 8 * DIV8(PosReyB))] & (DamasN | TorresN))
            return 1;
        break;

    case 3:
    case 7:
        if (ATAQUES_ALFIL_315[PosReyB][255 & (Rotado315 ^ MASK[ROTADO_315[cas_ficha]])
                               >> SHIFT_315[PosReyB]] & (DamasN | AlfilesN))
            return 1;
        break;

    case 4:
    case 8:
        if (ATAQUES_TORRE_COL[PosReyB][255 & ((Rotado90 ^ MASK[ROTADO_90[cas_ficha]])
                                >> 8 * MOD8(PosReyB))] & (DamasN | TorresN))
            return 1;
        break;
    }                           // switch
    return 0;
}
//----------------------------------------------------------------------------------
int             ClavadaReyN(register int cas_ficha)
{

#ifdef TEST_ARRAY_BOUNDS
    assert(PosReyN >= 0);
    assert(PosReyN < 64);
    assert(cas_ficha >= 0);
    assert(cas_ficha < 64);
#endif

    if (DIRECCION[PosReyN][cas_ficha] == 0 || ENTRE[PosReyN][cas_ficha] & (Blancas | Negras))
        return 0;

    switch (DIRECCION[PosReyN][cas_ficha]) {
    case 1:
    case 5:
        if (ATAQUES_ALFIL_45[PosReyN][255 & (Rotado45 ^ MASK[ROTADO_45[cas_ficha]])
                                >> SHIFT_45[PosReyN]] & (DamasB | AlfilesB))
            return 1;
        break;

    case 2:
    case 6:
        if (ATAQUES_TORRE_FIL[PosReyN][255 & (((Blancas | Negras) ^ MASK[cas_ficha])
                                >> 8 * DIV8(PosReyN))] & (DamasB | TorresB))
            return 1;
        break;

    case 3:
    case 7:
        if (ATAQUES_ALFIL_315[PosReyN][255 & (Rotado315 ^ MASK[ROTADO_315[cas_ficha]])
                               >> SHIFT_315[PosReyN]] & (DamasB | AlfilesB))
            return 1;
        break;

    case 4:
    case 8:
        if (ATAQUES_TORRE_COL[PosReyN][255 & ((Rotado90 ^ MASK[ROTADO_90[cas_ficha]])
                                >> 8 * MOD8(PosReyN))] & (DamasB | TorresB))
            return 1;
        break;
    }                           // switch
    return 0;
}
//----------------------------------------------------------------------------------
int             Jaque(int turno_blancas)
{
    register int    cas_rey;
    entero64        target;

    if (turno_blancas) {
        // atqs caballos

        cas_rey = PosReyB;

        if (AtaquesCaballo(cas_rey) & CaballosN)
            return 1;

        target = AlfilesN | DamasN;
        if (target & VACIO_ALFIL[cas_rey] && AtaquesAlfil(cas_rey) & target)
            return 1;

        target = TorresN | DamasN;
        if (target & VACIO_TORRE[cas_rey] && AtaquesTorre(cas_rey) & target)
            return 1;

        if (AtaquesRey(cas_rey) & ReyN)
            return 1;

        if (AtaquesPeonB(cas_rey) & PeonesN)
            return 1;

    }                           // fin turno blancas
    else {
        cas_rey = PosReyN;

        if (AtaquesCaballo(cas_rey) & CaballosB)
            return 1;

        target = AlfilesB | DamasB;
        if (target & VACIO_ALFIL[cas_rey] && AtaquesAlfil(cas_rey) & target)
            return 1;

        target = TorresB | DamasB;
        if (target & VACIO_TORRE[cas_rey] && AtaquesTorre(cas_rey) & target)
            return 1;

        if (AtaquesRey(cas_rey) & ReyB)
            return 1;

        if (AtaquesPeonN(cas_rey) & PeonesB)
            return 1;
    }                           // fin turno negras

    return 0;
}
//-----------------------------------------------------------------------------
/*
int             HeDadoJaque(entero32 jug)
{
    if (jug & (ENROQUE_CORTO | ENROQUE_LARGO | AL_PASO))
        return Jaque(Turno);
    else {
        int             pos = (jug >> 6) & 0x3f; // hacia
        int             indx = Turno ? PosReyB : PosReyN;

        if (AtaquesDesde(pos) & MASK[indx])
            return 1;

        pos = jug & 0x3f;
//        printf("direc: %d\n",DIRECCION[indx][pos]);

        if (DIRECCION[indx][pos] && !(ENTRE[pos][indx] & (Blancas | Negras))) {
            int             direc = DIRECCION[indx][pos];
            entero64        target = direc & 1 ? (Turno ? DamasN | AlfilesN : DamasB | AlfilesB) :
            (Turno ? DamasN | TorresN : DamasB | TorresB);


            switch (direc) {
            case 1:
                return (int) ((ATAQUES_ALFIL_45[pos][255 & (Rotado45 >> SHIFT_45[pos])] & target) != (entero64) 0);
            case 2:
                return (int) ((ATAQUES_TORRE_FIL[pos][255 & ((Blancas | Negras) >> 8 * DIV8(pos))] & target) != (entero64) 0);
            case 3:
                return (int) ((ATAQUES_ALFIL_315[pos][255 & (Rotado315 >> SHIFT_315[pos])] & target) != (entero64) 0);
            case 4:
                return (int) ((ATAQUES_TORRE_COL[pos][255 & (Rotado90 >> 8 * MOD8(pos))] & target) != (entero64) 0);
            case 5:
                return (int) ((ATAQUES_ALFIL_45[pos][255 & (Rotado45 >> SHIFT_45[pos])] & target) != (entero64) 0);
            case 6:
                return (int) ((ATAQUES_TORRE_FIL[pos][255 & ((Blancas | Negras) >> 8 * DIV8(pos))] & target) != (entero64) 0);
            case 7:
                return (int) ((ATAQUES_ALFIL_315[pos][255 & (Rotado315 >> SHIFT_315[pos])] & target) != (entero64) 0);
            case 8:
                return (int) ((ATAQUES_TORRE_COL[pos][255 & (Rotado90 >> 8 * MOD8(pos))] & target) != (entero64) 0);
            }                   // switch
        }
        return 0;
    }
}
*/
//-----------------------------------------------------------------------------
int             Atacada(register int casilla, int turno_blancas)
{

#ifdef TEST_ARRAY_BOUNDS
    assert(casilla >= 0);
    assert(casilla < 64);
#endif

    if (turno_blancas) {
        if (AtaquesCaballo(casilla) & CaballosB)
            return 1;

        if (AtaquesAlfil(casilla) & (AlfilesB | DamasB))
            return 1;

        if (AtaquesTorre(casilla) & (TorresB | DamasB))
            return 1;

        if (AtaquesRey(casilla) & ReyB)
            return 1;

        if (((PeonesB & ~COLUMNA_0) >> 9) & MASK[casilla])
            return 1;

        if (((PeonesB & ~COLUMNA_7) >> 7) & MASK[casilla])
            return 1;
    }                           // fin turno blancas
    else {
        if (AtaquesCaballo(casilla) & CaballosN)
            return 1;

        if (AtaquesAlfil(casilla) & (AlfilesN | DamasN))
            return 1;

        if (AtaquesTorre(casilla) & (TorresN | DamasN))
            return 1;

        if (AtaquesRey(casilla) & ReyN)
            return 1;

        if (((PeonesN & ~COLUMNA_0) << 7) & MASK[casilla])
            return 1;

        if (((PeonesN & ~COLUMNA_7) << 9) & MASK[casilla])
            return 1;
    }                           // fin turno negras

    return 0;
}
