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

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <assert.h>
#include "tipos.h"


// ver datos.c para una descripción +  ó - detallada del uso de cada variable

extern char     entrada[4096];
extern FILE    *log_file;
extern FILE    *gamelog_file;
extern FILE    *batch_file;
extern char     opp_name[256];
extern char     my_name[256];
extern char     site_name[256];
extern entero64 MASK[65];
extern entero64 FILA[8];
extern entero64 COLUMNA[8];
extern entero64 IZQUIERDA[8];
extern entero64 DERECHA[8];
extern entero64 ENTRE[64][64];
extern entero64 ATAQUES_TORRE_FIL[64][256];
extern entero64 ATAQUES_TORRE_COL[64][256];
extern entero64 ATAQUES_ALFIL_45[64][256];
extern entero64 ATAQUES_ALFIL_315[64][256];
extern entero64 ATAQUES_CABALLO[64];
extern entero64 ATAQUES_REY[64];
extern entero64 ATAQUES_PEON_B[64];
extern entero64 ATAQUES_PEON_N[64];
extern entero64 VACIO_ALFIL[64];
extern entero64 VACIO_TORRE[64];
extern entero64 ZOBRIST[12][64];
extern entero64 PASADO[2][64];
extern entero64 AISLADO[8];
extern entero64 PAS_ALEJA_D[8];
extern entero64 PAS_ALEJA_I[8];

extern entero64 RAYO_N[64];
extern entero64 RAYO_S[64];
extern entero64 RAYO_O[64];
extern entero64 RAYO_E[64];
extern entero64 RAYO_NE[64];
extern entero64 RAYO_NO[64];
extern entero64 RAYO_SE[64];
extern entero64 RAYO_SO[64];
extern entero64 RAYO_N_AMPLIO[8];
extern entero64 RAYO_S_AMPLIO[8];
extern entero64 CASILLA_PEON_B[64];
extern entero64 CASILLA_PEON_N[64];

extern int      CONTROL_INC;
extern int      LastProf;
extern int      MAXPROF;

extern int      Nalimov;
extern xboard_type xb_info;

extern char     DIRECCION[64][64];
extern char     TAXI_CAB[64][64];
extern char     DISTANCIA[64][64];


extern entero32 tiempo;
extern unsigned long HASH_SIZE;
extern unsigned long PAWN_HASH_SIZE;
extern unsigned long CACHE_SIZE;

extern jugada_ext pv[MAX_PROF + 1][MAX_PROF + 1];
extern jugada_ext pvdebug[MAX_PROF + 1];
extern entero64 debughash[MAX_PROF + 1];
extern int      pv_long[MAX_PROF + 1];
extern partida  tab;

extern int      ROTADO_90[64];
extern int      ROTADO_45[64];
extern int      ROTADO_315[64];
extern int      SHIFT_45[64];
extern int      SHIFT_315[64];
extern char     MSB[65536];
extern char     LSB[65536];
extern int      VALOR[13];
extern int      MaxPos[2];
extern char     EGTB_PATH[255];
extern unsigned long EGTB_CSIZE;
extern int      RESIGN_MARGIN;
extern int      DISPLAY_MARGIN;
extern int      UCI_MODE;
extern int      COORD_MODE;
extern int      GAME_STYLE;


extern char     BOOK_FILE[256];
extern int      BOOK_WIDTH;
extern int      BOOK_LEARN;
extern int      BOOK_RANDOM;
extern int      USE_BOOK;
extern int      ICS_MODE;

extern const int*TABLA_PEON;

extern char     *piece_rep;
extern char     *prompt;
extern lang_str_t lang_piece_str[];

// definición de funciones:

void            InitMasks(entero64[65], entero64[8], entero64[8], entero64[64][64], entero64[8], entero64[8]);
void            InitMaskPeones(entero64[8], entero64[2][64]);
void            InitPasAlejados(entero64 * pas_alejaD, entero64 * pas_alejaI);
void            InitRayos(entero64 *, entero64 *, entero64 *, entero64 *, entero64 *, entero64 *, entero64 *, entero64 *);
void            InitDirec(char[64][64]);
void            InitAtqTorreFil(entero64[64][256]);
void            InitAtqTorreCol(entero64[64][256], entero64[64][256]);
void            InitAtqAlfil315(entero64[64][256], entero64[64][256]);
void            InitAtqAlfil45(entero64[64][256], entero64[64][256]);
void            InitAtqCaballo(entero64[64]);
void            InitAtqRey(entero64[64], entero64[64][256], entero64[64][256],
                                      entero64[64][256], entero64[64][256]);
void            InitAtqPeones(entero64[64], entero64[64]);
void            InitTaxiCab(char[64][64]);
void            InitValores(void);

void            FreeMoveList(nodo_jug *pl);
int             TestEPD(FILE **);
int             LeeEPD(char *linea, epd_info *info);
int             OutFEN(char *);
int             LeeLinea(FILE **, char *, int);
void            InitPos(int);
void            PosicionInicial(void);

list_jug       *GenCaps(list_jug *);
list_jug       *GenNoCaps(list_jug *);
list_jug       *GenJaqJugs(list_jug *);
list_jug       *GenChecks(list_jug *);
void            GeneraValidas(int);

void            RunTestGen(int ply, int xb_mode);

int             NegaScout(int, int, int, int, int, int);
int             Quiesce(int alpha, int beta, int prof, int ply);
void            Itera(entero32 *, int, entero32, int *bk_flag);
list_jug       *JugadasDeLibro(list_jug *limite);
void            PintaJugada(jugada_ext *ptrjug, void (*outfun)(char *fmt,...));
void            PintaJugadaCoord(entero32 jug);
list_jug       *SoloValidas(list_jug *);
int             PreProcesa();
void            GameLog(char *fmt,...);



list_jug       *Next_Upon_Value(list_jug *, list_jug *, int);
void            Calc_SSE(list_jug *, list_jug *);
list_jug       *EligeJugada(int);


int             SSE(entero32);
entero64        DescubreCap(int, int);
int             ShellSort(list_jug ptrjug[], list_jug ptrlim[]);

int             LeeJugada(char *, entero32 *);
void            Mueve(entero32);
void            DesMueve(void);
int             VerificaTab(int);
void            CambiaTurno(void);

int             Evaluacion(int, int);
void            EvalTest(int xb_mode);
int             Repeticion(int);
int             MaterialInsuficiente(int);

void            PintaTablero(void);
void            PintaBitBoard(entero64);

entero64        AtaquesHacia(int);
entero64        AtaquesDesde(int);
entero64        AtaquesB(void);
entero64        AtaquesN(void);
int             Atacada(int, int);
int             ClavadaReyB(int);
int             ClavadaReyN(int);
int             Jaque(int);
entero64        Casillas_A_Obstruir(int, int);

int             ProbeHash(entero32 *, int *, int *, int *, int *);
void            StuffHash(entero32, int, int, int, int, int);
void            ClearTables(int);

int             JugadaNoValida(entero32);
int             JugadaExtValida(jugada_ext *);


int             PopCnt(entero64);
unsigned int    iterative_popcount(entero64);
void            Init_MSB(char *, char *);
int             Msb(entero64);
int             Lsb(entero64);
int             MsbC(entero64);
int             LsbC(entero64);

int             InitTB();
int             ProbeTB(int ply);
int             Worth_Probing_EGTB(void);

int             ExtraeArg(char **, char *);

void            TimeReset(void);
entero32        TimeDiff(void);
entero32        AllocTime(int, int, entero32, int);
void            Config(void);

void            Perf(void);

int             LeeJugada(char *linea, entero32 * ptrjug);
int             MatchesPonderMove(char *linea);
int             PollInput(void);
int             ReadStdin(void);
int             ReadInputLine(char *string);
int             FullInput(void);
void            ReadString(char *string);

void            LeePGN(FILE ** ppfich, int pgn_mode);
int             BookInsert(epd_t *, int);
int             LearnFromLoss();

int             FullInput(void);
void            ReadString(char *string);
void            ClearIbuffer(void);
int             CountIArgs(void);
void            UnGetString(void);
void            GetRestofInput(char *str);
void            Print(char *fmt,...);
void            Log(char *fmt,...);
void            Kibitz(char *fmt,...);

int             ComandoProcesable(char *arg);

int             EstaAmenazado(int turno, int amenaza);
int             MantieneAmenaza(int turno, int amenaza);
int             PierdeUnaAmenaza(int turno, int amenaza);
int             PierdeAmenazas(int turno, int amenaza);
int             IniAmenazas();

int             BookProbe(int echo);
void            BookClose();
void            BookOpen(char *name);
int             BookLoaded();
int             BookAdmin();

int             ParseCommandLine(char *line);

void            MultiPV(entero32 *eleccion, int ponder_on, entero32 time_limit, int *bk_flag, int num_pvs);
extern int      FTbSetCacheSize(void *pv, unsigned long cbSize);


// funciones en línea adaptadas de FirstBit y LastBit
// de Bob Hyatt, para usarlas con el compilador MVC.
// Pepito parece que va más lento con ellas...
#ifndef USE_ASSEMBLY
#define MsbC Msb
#define LsbC Lsb
#endif
#if defined USE_ASSEMBLY && !defined LINUX

/*
__forceinline int Msb(entero64 a)
{
  __asm {
  mov  eax,  32
  bsr edx,  dword ptr a + 4
  jnz l1
  bsr edx,  dword ptr a
  xor eax,  eax
l1:
  add eax,  edx
  }
}
*/

// función alternativa sin saltos (D. Corbit)

__forceinline int Msb(entero64 a)
{
__asm {
        bsf eax,dword ptr [a+4]
        add eax,32
        bsf eax,dword ptr [a]
     }
}


__forceinline int Lsb(entero64 a)
{
  __asm {
  xor  eax,  eax
  bsf edx,  dword ptr a
  jnz l1
  bsf edx,  dword ptr a + 4
  mov eax,  32
l1:
  add eax,  edx
  }
}

#define MMX_POPCOUNT

#ifdef MMX_POPCOUNT
#include "amd3dx.h"

/* Athlon MMX optimized popcount function, based on AMD's Athlon
   optimization manuals */
__forceinline int PopCnt(entero64 v)
{
    static const __int64 C55 = 0x5555555555555555;
    static const __int64 C33 = 0x3333333333333333;
    static const __int64 C0F = 0x0F0F0F0F0F0F0F0F;

    __asm {
        movd            mm0, word ptr v;
        punpckldq       mm0, word ptr v + 4;
        movq            mm1, mm0;
        psrld           mm0, 1;
        pand            mm0, [C55];
        psubd           mm1, mm0;
        movq            mm0, mm1;
        psrld           mm1, 2;
        pand            mm0, [C33];
        pand            mm1, [C33];
        paddd           mm0, mm1;
        movq            mm1, mm0;
        psrld           mm0, 4;
        paddd           mm0, mm1;
        pand            mm0, [C0F];
        pxor            mm1, mm1;
        psadbw(mm0, mm1);
        movd            eax, mm0;
        emms;
    }
}
#else
__forceinline int PopCnt(entero64 a)
{

  __asm {
  mov  ecx,  dword ptr a
  xor eax,  eax
  test ecx,  ecx
  jz l1
l0:
  lea edx,  [ecx - 1]
  inc  eax
  and ecx,  edx
  jnz l0
l1:
  mov ecx,  dword ptr a + 4
  test ecx,  ecx
  jz l3
l2:
  lea edx,  [ecx - 1]
  inc  eax
  and ecx,  edx
  jnz l2
l3:
  }
}
#endif

#endif
