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

#ifndef _PINFO_H
#define _PINFO_H

#include "hashable.h"
#include "move.h"
#include "pool.h"
#include <stddef.h>

class Position_Info : public Hashable
{
    // this class represents one entry in the hash table.

    public:

    enum ValueType { Invalid, Valid, UpperBound, LowerBound, Pv };
    
    Position_Info();

    Position_Info( const Board &board, const int depth,
                   const byte age,
                   const ValueType hashflags,
                   const BOOL forced,
                   const BOOL in_check,
                   const int rep_count,
                   const int value,
                   const Move &best_move);

    Position_Info &operator = (const Position_Info &p)
    {
        if (this != &p)
        {
           my_depth = p.my_depth;
           my_age = p.my_age;
           my_flags = p.my_flags;
           my_hashcode = p.my_hashcode;
           my_xhashcode = p.my_xhashcode;
           my_value = p.my_value;
           start = p.start;
           dest = p.dest;
           promotion = p.promotion;
        }
        return *this;
    }
           
    Position_Info( const Position_Info &p)
      : my_depth(p.my_depth),
        my_age(p.my_age),
        my_flags(p.my_flags),
        my_hashcode(p.my_hashcode),
        my_xhashcode(p.my_xhashcode),
        my_value(p.my_value),
        start(p.start),
        dest(p.dest),
        promotion(p.promotion)
    {
    }
    
    // construct an object that can be used for searching:
    Position_Info( const Board &board, int rep_count );
    
    ValueType type() const
    {
        return (ValueType)(my_flags & 0x7);
    }
    
    BOOL forced() const
    {
         return (my_flags & 0x80) != 0;
    }
    
    BOOL in_check() const
    {
        return (my_flags & 0x40) != 0;
    }
    
    int deep_flag() const
    {
        return (my_flags & 0x10);
    }
    
    void set_deep_flag(BOOL b)
    {
       if (b)
          my_flags |= 0x10;
       else
          my_flags &= ~0x10;
    }

    int depth() const
    {
        return my_depth;
    }

    int age() const
    {
        return my_age;
    }
    
    int value() const
    {
        return my_value;
    }
    
    Move best_move() const;
    
    void *operator new (size_t size)
    {
	return allocator.allocate(size);
    }
    
    void *operator new (size_t, void *p)
    {
	return p;    
    }

    void operator delete( void *p )
    {
	allocator.free(p);    
    }
    
    static void freeAll( BOOL final )
    {
	allocator.freeAll(final);
    }
    

    // methods of class Hashable

    BOOL is_equal( const Hashable &c) const
    {
        Position_Info *p = (Position_Info*)&c;
        return (my_hashcode == p->my_hashcode) &&
               (my_xhashcode == p->my_xhashcode);
    }
    
    hash_t hash_code() const
    {
        return my_hashcode;
    }
    
    int16 xhash_code() const
    {
        return my_xhashcode;
    }

    private:

    signed char my_depth;
    byte my_age;
    byte my_flags;
    hash_t my_hashcode;
    int16 my_xhashcode;
    int16 my_value;
    //Move my_best_move;
    Square start, dest;
    Piece::PieceType promotion;
    static Pool allocator;
};

unsigned long hash_code(const Position_Info &p);

#endif
