/* Pepito v1.59  -- file: verif.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
*/

/* Este archivo contiene las rutinas para verificar si un índice hash es correcto dada una
   posición determinada (para depuración exclusivamente).                                  */

#ifndef UNIQUE_SOURCE_FILE
#  include "datos.h"
#endif

int             VerificaTab(int turno)
{
    int             i,
                    valida = 1,
                    piezasB,
                    piezasN,
                    numpeonesB,
                    numpeonesN;
    entero64        rotado45,
                    rotado315,
                    rotado90,
                    caballosB,
                    caballosN,
                    alfilesB,
                    alfilesN,
                    peonesB,
                    peonesN,
                    reyB,
                    reyN,
                    damasB,
                    damasN,
                    torresB,
                    torresN,
                    blancas,
                    negras,
                    hashglob;

    entero64        hashpeones = 0;
    int             materialB = 0,
                    materialN = 0,
                    posreyB = 0,
                    posreyN = 0;

    rotado45 = rotado315 = rotado90 = caballosB = caballosN = 0;
    alfilesB = alfilesN = peonesB = peonesN = reyB = reyN = 0;
    damasB = damasN = torresB = torresN = blancas = negras = 0;
    hashglob = piezasB = piezasN = numpeonesB = numpeonesN = 0;

    if (!turno)
        hashglob = ~hashglob;

    if (Enroque & E_CORTO_B)
        hashglob ^= HASH_E_CORTO_B;
    if (Enroque & E_LARGO_B)
        hashglob ^= HASH_E_LARGO_B;
    if (Enroque & E_CORTO_N)
        hashglob ^= HASH_E_CORTO_N;
    if (Enroque & E_LARGO_N)
        hashglob ^= HASH_E_LARGO_N;

    if (AlPaso != 64) {
        if (AlPaso > 32)        // TurnoBlancas
            hashglob ^= Zobrist(PEON_B, 56 + (AlPaso & 7));
        else
            hashglob ^= Zobrist(PEON_N, (AlPaso & 7));
    }
    for (i = 0; i < 64; i++) {
        if (Tablero[i] != VACIA) {
            rotado45 |= MASK[ROTADO_45[i]];
            rotado315 |= MASK[ROTADO_315[i]];
            rotado90 |= MASK[ROTADO_90[i]];
            hashglob ^= Zobrist(Tablero[i], i);

            if (Tablero[i] < PEON_N) {
                blancas |= MASK[i];
                switch (Tablero[i]) {
                case DAMA_B:
                    damasB |= MASK[i];
                    materialB += DAMA_VAL;
                    piezasB++;
                    break;
                case TORRE_B:
                    torresB |= MASK[i];
                    materialB += TORRE_VAL;
                    piezasB++;
                    break;
                case ALFIL_B:
                    alfilesB |= MASK[i];
                    materialB += ALFIL_VAL;
                    piezasB++;
                    break;
                case CABALLO_B:
                    caballosB |= MASK[i];
                    materialB += CABALLO_VAL;
                    piezasB++;
                    break;
                case REY_B:
                    reyB |= MASK[i];
                    posreyB = i;
                    break;
                case PEON_B:
                    peonesB |= MASK[i];
                    materialB += PEON_VAL;
                    hashpeones ^= Zobrist(PEON_B, i);
                    numpeonesB++;
                    break;
                }               // switch
            }                   // if
            else {
                negras |= MASK[i];
                switch (Tablero[i]) {
                case DAMA_N:
                    damasN |= MASK[i];
                    materialN += DAMA_VAL;
                    piezasN++;
                    break;
                case TORRE_N:
                    torresN |= MASK[i];
                    materialN += TORRE_VAL;
                    piezasN++;
                    break;
                case ALFIL_N:
                    alfilesN |= MASK[i];
                    materialN += ALFIL_VAL;
                    piezasN++;
                    break;
                case CABALLO_N:
                    caballosN |= MASK[i];
                    materialN += CABALLO_VAL;
                    piezasN++;
                    break;
                case REY_N:
                    reyN |= MASK[i];
                    posreyN = i;
                    break;
                case PEON_N:
                    peonesN |= MASK[i];
                    materialN += PEON_VAL;
                    hashpeones ^= Zobrist(PEON_N, i);
                    numpeonesN++;
                    break;
                }               // switch

            }                   // else
        }                       // if (no vacía)
    }                           // for


    if (blancas != Blancas) {
        Print("ERROR!!! BitBoard blancas incorrecto.\n");
        valida = 0;
    }
    if (negras != Negras) {
        Print("ERROR!!! BitBoard blancas incorrecto.\n");
        valida = 0;
    }
    if (materialB != MaterialB) {
        Print("ERROR!!! Material blancas incorrecto.\n");
        Print("Teórico: %d. Práctico: %d.\n", materialB, MaterialB);
        valida = 0;
    }
    if (materialN != MaterialN) {
        Print("ERROR!!! Material negras incorrecto.\n");
        Print("Teórico: %d. Práctico: %d.\n", materialN, MaterialN);
        valida = 0;
    }
    if (rotado45 != Rotado45) {
        Print("ERROR!!! Bitboard Rotado45 incorrecto.\n");
        valida = 0;
    }
    if (rotado315 != Rotado315) {
        Print("ERROR!!! Bitboard Rotado315 incorrecto.\n");
        valida = 0;
    }
    if (rotado90 != Rotado90) {
        Print("ERROR!!! Bitboard Rotado90 incorrecto.\n");
        valida = 0;
    }
    if (hashglob != HashGlob) {
        Print("ERROR!!! Hash global incorrecto.\n");
        Print("HashGlob: %ld\n", HashGlob);
        Print("hashGlob: %ld\n", hashglob);
        valida = 0;
    }
    if (damasB != DamasB) {
        Print("ERROR!!! Bitboard Damas blancas incorrecto.\n");
        valida = 0;
    }
    if (torresB != TorresB) {
        Print("ERROR!!! Bitboard Torres blancas incorrecto.\n");
        valida = 0;
    }
    if (alfilesB != AlfilesB) {
        Print("ERROR!!! Bitboard Alfiles blancos incorrecto.\n");
        valida = 0;
    }
    if (caballosB != CaballosB) {
        Print("ERROR!!! Bitboard Caballos blancos incorrecto.\n");
        valida = 0;
    }
    if (reyB != ReyB) {
        Print("ERROR!!! Bitboard Rey blanco incorrecto.\n");
        valida = 0;
    }
    if (posreyB != PosReyB) {
        Print("ERROR!!! Posición Rey blanco incorrecta.\n");
        valida = 0;
    }
    if (peonesB != PeonesB) {
        Print("ERROR!!! Bitboard Peones blancos incorrecto.\n");
        valida = 0;
    }
    if (damasN != DamasN) {
        Print("ERROR!!! Bitboard Damas negras incorrecto.\n");
        valida = 0;
    }
    if (torresN != TorresN) {
        Print("ERROR!!! Bitboard Torres negras incorrecto.\n");
        valida = 0;
    }
    if (alfilesN != AlfilesN) {
        Print("ERROR!!! Bitboard Alfiles negros incorrecto.\n");
        valida = 0;
    }
    if (caballosN != CaballosN) {
        Print("ERROR!!! Bitboard Caballos negros incorrecto.\n");
        valida = 0;
    }
    if (reyN != ReyN) {
        Print("ERROR!!! Bitboard Rey negro incorrecto.\n");
        valida = 0;
    }
    if (posreyN != PosReyN) {
        Print("ERROR!!! Posición Rey negro incorrecta.\n");
        valida = 0;
    }
    if (peonesN != PeonesN) {
        Print("ERROR!!! Bitboard Peones negros incorrecto.\n");
        valida = 0;
    }
    if (hashpeones != HashPeones) {
        Print("ERROR!!! Hash peones incorrecto.\n");
        valida = 0;
    }
    if (numpeonesB != NumPeonesB) {
        Print("ERROR!!! NumPeonesB incorrecto.\n");
        valida = 0;
    }
    if (numpeonesN != NumPeonesN) {
        Print("ERROR!!! NumPeonesN incorrecto.\n");
        valida = 0;
    }
    if (piezasB != PiezasB) {
        Print("ERROR!!! PiezasB incorrecto.\n");
        valida = 0;
    }
    if (piezasN != PiezasN) {
        Print("ERROR!!! PiezasN incorrecto.\n");
        valida = 0;
    }
    if (PosReyB != Msb(ReyB)) {
        Print("ERROR!!! PosReyB no concuerda con ReyB. (%d - %d)\n",
              PosReyB, Msb(ReyB));
        valida = 0;
    }
    if (PosReyN != Msb(ReyN)) {
        Print("ERROR!!! PosReyN no concuerda con ReyN.\n");
        valida = 0;
    }
    if (!valida)
        PintaTablero();


    return valida;
}

//----------------------------------------------------------------------------------------------------------
int             JugadaExtValida(register jugada_ext * ptrjug)
{
    register int    desde,
                    hacia;
    register int    captura;

    if (Turno) {
        if (ptrjug->pieza_mov > REY_B)
            return 0;
        captura = (ptrjug->jug >> 12) & 0xf;
        if (captura < PEON_N || captura == REY_N)
            return 0;
    } else {
        if (ptrjug->pieza_mov < PEON_N)
            return 0;
        captura = (ptrjug->jug >> 12) & 0xf;
        if (captura >= REY_B)
            return 0;
    }

    desde = ptrjug->jug & 0x3f;

    if (Tablero[desde] != ptrjug->pieza_mov)
        return 0;

    hacia = (ptrjug->jug >> 6) & 0x3f;

    if (Tablero[hacia] != captura && !(ptrjug->jug & AL_PASO && hacia == AlPaso))
        return 0;

    if (Turno) {
        switch (Tablero[desde]) {
        case CABALLO_B:
            if (AtaquesCaballo(desde) & MASK[hacia])
                return 1;
            else
                return 0;
        case ALFIL_B:
            if (AtaquesAlfil(desde) & MASK[hacia])
                return 1;
            else
                return 0;
        case TORRE_B:
            if (AtaquesTorre(desde) & MASK[hacia])
                return 1;
            else
                return 0;
        case DAMA_B:
            if (AtaquesDama(desde) & MASK[hacia])
                return 1;
            else
                return 0;
        case PEON_B:
            if (AtaquesPeonB(desde) & MASK[hacia] || MASK[desde - 8] & ~(Blancas | Negras))
                return 1;
            else
                return 0;
        case REY_B:
            if (AtaquesRey(desde) & MASK[hacia])
                return 1;
            else if (ptrjug->jug & ENROQUE_CORTO && Enroque & E_CORTO_B && !((Blancas | Negras) & MASK_F1G1)
                     && !(Negras & AtaquesHacia(F1)))
                return 1;
            else if (ptrjug->jug & ENROQUE_LARGO && Enroque & E_LARGO_B && !((Blancas | Negras) & MASK_B1C1D1)
                     && !(Negras & AtaquesHacia(D1)))
                return 1;
        default:
            return 0;
        }
    } else {
        switch (Tablero[desde]) {
        case CABALLO_N:
            if (AtaquesCaballo(desde) & MASK[hacia])
                return 1;
            else
                return 0;
        case ALFIL_N:
            if (AtaquesAlfil(desde) & MASK[hacia])
                return 1;
            else
                return 0;
        case TORRE_N:
            if (AtaquesTorre(desde) & MASK[hacia])
                return 1;
            else
                return 0;
        case DAMA_N:
            if (AtaquesDama(desde) & MASK[hacia])
                return 1;
            else
                return 0;
        case PEON_N:
            if (AtaquesPeonN(desde) & MASK[hacia] || MASK[desde + 8] & ~(Blancas | Negras))
                return 1;
            else
                return 0;

        case REY_N:
            if (AtaquesRey(desde) & MASK[hacia])
                return 1;
            else if (ptrjug->jug & ENROQUE_CORTO && Enroque & E_CORTO_N && !((Blancas | Negras) & MASK_F8G8)
                     && !(Blancas & AtaquesHacia(F8)))
                return 1;
            else if (ptrjug->jug & ENROQUE_LARGO && Enroque & E_LARGO_N && !((Blancas | Negras) & MASK_B8C8D8)
                     && !(Blancas & AtaquesHacia(D8)))
                return 1;
            return 0;
        default:
            return 0;
        }
    }
}
