// Copyright 1994 by Jon Dart.  All Rights Reserved.

#ifndef _BOARD_H
#define _BOARD_H

#include "types.h"
#include "square.h"
#include "piece.h"
#include "bitmap.h"
#include "material.h"
#include <iostream.h>

class ExtendedMove;
class ReversibleMove;

class Board
{
   // This class encapsulates the chess board, and provides functions
   // for making and undoing moves.          

public: 

   friend class ReversibleMove;
   friend class ChessIO;
   friend class Scoring;
   
   enum CheckStatusType { InCheck, NotInCheck, Unknown };

   enum CastleType { CanCastleEitherSide,
                     CanCastleKSide,
                     CanCastleQSide,
                     CastledKSide,
                     CastledQSide,
                     CantCastleEitherSide};
          
   Board();
   // returns a board set up in its initial position, White to move.
           
  ~Board();
  
   // Copy constructor and assignment operator  
   Board(const Board &);
   Board &operator = (const Board &);

   void Reset();
   // resets it to initial position
           
#ifdef _DEBUG
   const Piece &operator[]( const Square sq ) const;
#else
   const Piece &operator[]( const Square sq ) const
   {
       return my_Contents[sq];
   }
#endif

   void Set_Contents( const Piece &p, const Square sq )
   {
       my_Contents[sq] = p;
   }
   
   void set_secondary_vars();
   // update all fields of the board, based on the piece positions.

   CastleType CastleStatus( const ColorType side ) const
   {
       return my_CastleStatus[side];        
   }
   
   void Set_CastleStatus( const CastleType t, const ColorType side )
   {
       my_CastleStatus[side] = t;
   }

   ColorType Side() const
   // side to move         
   {
       return my_Side;       
   }
   
   ColorType OppositeSide() const
   {
       return OppositeColor(my_Side);
   }
   
   void Set_Side( const ColorType side )
   {
       my_Side = side;
   }
   
   const Material &getMaterial( const ColorType side ) const
   {
       return my_Material[side];
   }
   
   const Bitmap &PawnBits( const ColorType side ) const
   {
       return pawn_bits[side];
   }
   
   byte PFileCount( const int rank, const ColorType side ) const
   {
       return my_PFileCount[rank][side];
   }

   const Square EnPassantSq( const ColorType side ) const
   {
       return my_EnPassantSq[side];     
   }
           
   void Set_EnPassantSq( const Square sq, const ColorType side )
   {
       my_EnPassantSq[side] = sq;
   }
           
   CheckStatusType CheckStatus( ) const;
   
   void set_check_status(CheckStatusType s)
   {
       my_CheckStatus = s;
   }

   const Square &KingPos( const ColorType side ) const
   {
        return my_KingPos[side];           
   }
           
   hash_t HashCode() const
   {
       return my_HashCode;
   }
   
   hash_t pawn_hash() const
   {
       return m_pawn_hash;
   }
   
   int operator == ( const Board &ABoard )
   {
       return my_HashCode == ABoard.HashCode();
   }
   
   static int Direction( const Square &sq1, const Square &sq2 );
   // If sq1 and sq2 are in a straight line, return its direction
   // (increment by which a piece at sq1 could move to sq2).  Other-
   // wise, return 0.      
   
   int Between( const Square &sq1, const Square &sq2, 
                Square *squares) const;
   // fills "squares" with a list of squares between sq1 and sq2 (in
   // a straight line), returns the # of squares.
   
   BOOL Clear( const Square &sq1, const Square &sq2 ) const;
   // returns "true" if there is a clear path between sq1 and sq2

   void MakeMove( const ExtendedMove &move );
   // makes a move

   void UndoMove( const ReversibleMove &rmove );
   // undoes a previous move.
           
   BOOL any_attacks(const Square &sq, const ColorType side) const;
   // Return "TRUE" if any piece of color "side" attacks "sq".

   BOOL any_attacks(const Square &sq, const ColorType side, Bitmap &source) const;
   // Return "TRUE" if any piece of color "side" attacks "sq".

   Bitmap calc_attacks(const Square &sq, const ColorType side) const;
   // Return a bit vector of all pieces of color "side" that attack "sq".
   
   Bitmap min_attacker(const Bitmap &, const ColorType side) const;
   // Return the least-valued piece of color "side" out of the bitmap.
   
   Bitmap pawn_attacks( const Square &sq, const ColorType side) const;
   // Return all squares attacked by a pawn of color "side" at square "sq".
   
   Bitmap all_pawn_attacks(const ColorType side) const;
   // Return all squares attacked by pawns of color "side".
   
   int bishop_mobility( const Square &sq) const;
   int rook_mobility(const Square &sq) const;

   friend istream & operator >> (istream &i, Board &board);
   friend ostream & operator << (ostream &o, const Board &board);

#if !defined(_WINDOWS) && defined(DEBUG_ATTACKS)
   // for debugging :
   void dump_attacks()
   {
       my_attacks.dump_attacks();           
   }
#endif   
   
   private:
           
   Piece my_Contents[64];
   ColorType my_Side;
   Square my_KingPos[2];
   Material my_Material[2];
   byte my_PFileCount[10][2];
   Square my_EnPassantSq[2];
   CastleType my_CastleStatus[2];
   hash_t my_HashCode;
   hash_t m_pawn_hash;
   CheckStatusType my_CheckStatus;

public:
   int move_count; // since last capture, pawn push or castle
   hash_t *rep_list; //  move history for repetition detection
   hash_t *rep_list_head; // head of history list
   Bitmap pawn_bits[2];
   Bitmap knight_bits[2];
   Bitmap bishop_bits[2];
   Bitmap rook_bits[2];
   Bitmap rooksqueens[2];
   Bitmap bishopsqueens[2];
   Bitmap queen_bits[2];
   Bitmap king_bits[2];
   Bitmap occupied[2];
   Bitmap occupiedR90[2];
   Bitmap occupiedDa1[2];
   Bitmap occupiedDa8[2];

private:
   void UpdateCastleStatus( const ColorType side, 
                            const Square sq );
   void undo_castling(const Square &kp,const Square &oldkingsq,
           const Square &newrooksq, const Square &oldrooksq);
};
  
#endif

