/* General definition file for structures */

#ifndef CHESS_H
#define CHESS_H

// move structure to encapsulate several important move parameters
// note: The char used below is treated like an integer.

struct move_t {
  char from;                   // from square
  char to;                     // to square
  char type;                   // type of move (defined below)
  char promote;                // type of piece to promote to (defined below)
};

/*   Type of move  */
//     1 = capture
//     2 = castle
//     4 = en passant
//     8 = 2 square pawn advance (could leave an en passant square)
//    16 = pawn push 
//    32 = promotion

/*   Type of piece to promote to */
//     2 = Knight
//     3 = Bishop   
//     4 = Rook
//     5 = Queen 

// union of move_t and an integer to make comparison of 
// moves easier.  (as suggested in Tom Kerrigans simple chess program)

union move {
  move_t b;
  int t;           // assuming a 32 bit integer
};

// Add a score for sorting purposes to the move record

struct move_rec {
  move m;
  int score; 
};

// Define a move_list structure to carry these move records

struct move_list {
  int count;
  move_rec mv[256];
};

// Structure for a square

struct square {
  char type;             // type of piece (0 - 6)
  char side;             // side which owns square (1 = white)
};

// Structure for hash code and key of a position

typedef unsigned __int64 h_code;

#include "hash.h"

struct tree_search;
struct game_rec;

// Structure for current board position.

struct position {
  square sq[64];             // array of board squares
  char wtm;                  // flag for white to move
  int castle;                // castling status
  char ep;                   // location of an en-passant square (if any)
  int fifty;                 // fifty move count
  char has_castled[2];       // flag that side has castled
  int check;                 // is the side to move in check?
  int pieces[2];             // # of pieces(non-pawns)
  int material;              // material value from point of view of
                             // side to move
  int extend;              // extension flags

  char plist[2][7][10];      // piece lists
  move last;                 // last move made
  h_code hcode;              // hash code
  h_code pcode;              // pawn hash code

  /* moves.cpp */
  void allmoves(move_list *list, tree_search *ts);
  void add_move(int fsq, int tsq, move_list *list, char type, tree_search *ts);
  void pawn_moves(move_list *list, int sqr, tree_search *ts);
  void king_moves(move_list *list, int sqr, tree_search *ts);
  void knight_moves(move_list *list, int sqr, tree_search *ts);
  void bishop_moves(move_list *list, int sqr, tree_search *ts);
  void rook_moves(move_list *list, int sqr, tree_search *ts);

  /* captures.cpp */
  int captures(move_list *list, int delta_score);
  int add_capt(int fsq, int tsq, move_list *list, char type, int delta_score);
  int pawn_capts(move_list *list, int sqr, int ds);
  int king_capts(move_list *list, int sqr, int ds);
  int knight_capts(move_list *list, int sqr, int ds);
  int bishop_capts(move_list *list, int sqr, int ds);
  int rook_capts(move_list *list, int sqr, int ds);

  /* captchecks.cpp */
  void captchecks(move_list *list, int delta_score);
  void add_cc(int fsq, int tsq, move_list *list, char type, int delta_score);
  void pawn_cc(move_list *list, int sqr, int ds);
  void king_cc(move_list *list, int sqr, int ds);
  void knight_cc(move_list *list, int sqr, int ds);
  void bishop_cc(move_list *list, int sqr, int ds);
  void rook_cc(move_list *list, int sqr, int ds);

  /* exmove.cpp */
  int exec_move(move emove, int ply);
  int qexec_move(move emove, int ply);

  /* attacks.cpp */
  int simple_check(int move_sq);
  int dia_slide_attack(int A, int B);
  int dia_slide_attack_xray(int A, int B);
  int hor_slide_attack(int A, int B);
  int hor_slide_attack_xray(int A, int B);
  int attacks(int sqr, int side, int one);
  int knt_attacks(int sqr, int side, int one);
  int dia_attacks(int sqr, int side, int one);
  int hor_attacks(int sqr, int side, int one);

  /* score.cpp */
  //void init_score(int T, tree_search *ts);
  int score_pos(int alpha, int beta, game_rec *gr);
  int score_pawns(pawn_rec *pawns);
  int score_king(pawn_rec *pawns, game_rec *gr);
  int bishop_mobility(int sqr);
  int rook_mobility(int sqr);
  int knight_mobility(int sqr);
  int pawn_guard(int tsq, int side);

  /* check.cpp */
  int in_check();
  int in_check_mate();

  /* hash.cpp */
  void gen_code();

};

// structure for nodes in the search

struct search_node {
  position pos;
  move_list moves; 

  int ply;
 
  tree_search *ts;   // parent tree search
  game_rec *gr;      // parent game record

  search_node *prev;
  search_node *next;

  /* search.cpp */ 
  int pvs(int alpha, int beta, int depth);
  int qsearch(int alpha, int beta, int qply, int check_chain);

};

// structure for search data

struct tree_search {

  search_node n[MAXD+1];   // array of search positions
  move pc[MAXD+1][MAXD+1]; // triangular array for search
                           //    principle continuation
 
  int max_ply;             // max ply of current search
  int start_time;          // start time of current search
  int limit;               // nominal time limit of search
  int max_limit;           // absolute time limit of search
  int ponder;              // flag for pondering
  int last_ponder;         // flag for did we ponder last move?
  int ponder_time;         // record of time used on last pondering
  int ponder_time_double;       // time doublings required (pondering)
  int wbest, wply;              // whisper variables for search summary
  int turn;                     // Current game turn
  int root_alpha, root_beta;    // values at the root of search 
  int root_tb_score, root_wtm;
  int start_depth, max_depth;   // depths of search (starting, ending)  
  int last_depth;               // depth of previous search
  int fail;                     // fail high(+1)/low(-1) flag  
  int g_last;                   // last returned score of search 
  unsigned int nq_count;        // count of nodes in current qsearch
  int max_search_depth;         // search depth limit set by xboard   
  int max_search_time;          // search time limit set by xboard  

  int killer1[2], killer2[2], killer3[2]; // killer moves

  int history[64][64];          // table for history scores

  move hmove;                   // move from hash table

  move bookm;                   // move from opening book
  move ponder_move;             // move we are pondering

  // These are a collection of counters that keep track of search
  // statistics and timing checks.
  unsigned int interrupt_check_count;
  unsigned int node_count, eval_count, extensions, singular_extensions;
  unsigned int phash_count, hash_count, hmove_count, q_count;
  unsigned int null_cutoff, internal_iter, egtb_probes, egtb_hits;
  unsigned int fail_high, first_fail_high;

  int tsuite, analysis_mode;    // flags to determine whether we are in
                                //    analysis mode or a test suite

  // variables to support testsuite mode 
  float soltime;
  int bmcount; move bmoves[256];
  int best_score;
  char bmtype[3];      // "am" avoid move or "bm" best move string                              


  int best_depth;               // best depth reached (for testsuites) 
  int no_book;                  // counter for positions with no book moves

  /* search.cpp */
  move search(position p, int time_limit, int T, game_rec *gr);
  inline void pc_update(move pcmove, int ply);
  void search_display(int score);
  void log_search(int score);
   
  /* game_rec.cpp */
  void link_nodes(game_rec *gr);

};


// Structure for position in the opening book

struct book_rec {
 unsigned long long pos_code;  // position hash code
 int score;                    // score for position
 int gambit;                   // flag for gambit play
 int wins;                     // number of wins with this pos 
 int padding;                  // extra padding to book_rec to guarantee it falls on
                               //  word boundaries on 32 and 64 bit systems 
};

// Structure to hold all the data and flags for a game

struct game_rec {
 /* game positions */
  position pos;            // current position in the game
  position last;           // previous position in the game
  position temp;           // temporary position for book-keeping
  position reset;          // reset position for takebacks
 /* available moves */
  move_list movelist;      // list of pseudo-legal moves for current pos
  move best;               // best move for current position
 /* game history info */
  move game_history[MAX_GAME_PLY];  // list of move played
  h_code plist[MAX_GAME_PLY];       // hash codes of positions visited
 /* game control flags and counters */
  int T;                   // turn number
  int p_side;              // side taken by opponent
  int book;                // flag about whether to use book
  int both;                // opponent plays both sides (0 = false)
  int mttc;                // moves 'til time control
  int omttc;               // opponents moves 'til time control
  int inc;                 // time increment with each move (seconds)
  int over;                // game is over
  char overstring[40];     // game over message
  char lmove[10];          // string with last played move
  int learned;             // has book learning already happened?
  int learn_count;         // count of book moves to learn
  int learn_bk;            // flag to control book learning
  float base;              // base amount of time (seconds)
  float timeleft[2];       // total time left (centi-seconds)
  int knowledge_scale;     // variable to weaken EXchess (up to 100 for full strength)

 /* variables for TDleaf learning */
  int learn_scores;
  int predicted[MAX_GAME_PLY];
  position learn_rootpos[MAX_GAME_PLY];
  position learn_positions[MAX_GAME_PLY];
  int learn_root_scores[MAX_GAME_PLY];
  int td_learning;   // whether or not to learn

 /* search structure for searches */ 
  tree_search ts;

  game_rec();
  void setboard(const char inboard[256], const char ms, const char castle[5], const char ep[3]);
  void test_suite(const char *, const char *, int); 
}; 

#endif  /* CHESS_H */









