// Copyright 1993 by Jon Dart.  All Rights Reserved

#include "stdafx.h"
#include "atckentr.h"
#include <stdio.h>

// data layout:

//bits	
//0-1	pawn attacks
//2-3	knight attacks
//4-5	bishop attacks
//6-7	rook attacks
//8-10	queen attacks
//11	king attacks
//12-15 total # of attacks

Attack_Entry::Attack_Entry() 
  : info(0)
{
}

static const int16 masks[] =
 { 0, 1, 4, 0x10, 0x40, 0x100, 0x800, 0 };

static const int16 masks2[] =
 { 0, 3, 0x0c, 0x30, 0xc0, 0x700, 0x800, 0};

void Attack_Entry::add_attack(const Piece::PieceType p)
{
   info += (masks[(int)p] + 0x1000);
}

void Attack_Entry::remove_attack(const Piece::PieceType p)
{
    info -= (masks[(int)p] + 0x1000);
}

Piece::PieceType Attack_Entry::remove_min_attacker()
{
    if (!any_attacks())
       return Piece::Empty;
    else if (num_attacks(Piece::Pawn))
    {
       remove_attack(Piece::Pawn);
       return Piece::Pawn;
    }
    else if (num_attacks(Piece::Knight))
    {
       remove_attack(Piece::Knight);
       return Piece::Knight;
    }
    else if (num_attacks(Piece::Bishop))
    {
       remove_attack(Piece::Bishop);
       return Piece::Bishop;
    }
    else if (num_attacks(Piece::Rook))
    {
       remove_attack(Piece::Rook);
       return Piece::Rook;
    }
    else if (num_attacks(Piece::Queen))
    {
       remove_attack(Piece::Queen);
       return Piece::Queen;
    }
    else 
    {
       remove_attack(Piece::King);
       return Piece::King;
    }
}

Piece::PieceType Attack_Entry::min_attacker() const
{
    if (!any_attacks())
       return Piece::Empty;
    else if (num_attacks(Piece::Pawn))
       return Piece::Pawn;
    else if (num_attacks(Piece::Knight))
       return Piece::Knight;
    else if (num_attacks(Piece::Bishop))
       return Piece::Bishop;
    else if (num_attacks(Piece::Rook))
       return Piece::Rook;
    else if (num_attacks(Piece::Queen))
       return Piece::Queen;
    else 
       return Piece::King;
}

unsigned Attack_Entry::num_attacks() const
{ 
       return (info & 0xf000) >> 12;
}

unsigned Attack_Entry::num_attacks(const Piece::PieceType p) const
{
    int16 info2 = info & masks2[(int)p];
    if (info2 == 0)
       return 0;
    switch (p)
    {
       case Piece::Pawn:
          return info2;
       case Piece::Knight:
          return info2 >> 2;
       case Piece::Bishop:
          return info2 >> 4;
       case Piece::Rook:
          return info2 >> 6;
       case Piece::Queen:
          return info2 >> 8;
       case Piece::King:
          return 1;
       default:
         return 0;
    }
}

ostream & operator << (ostream &o, Attack_Entry &entr)
{
    char text[50];
    sprintf(text,"%04x",entr.info);
    o << text;
    return o;
}
