/*
 * Copyright (C) Bernhard Seybold. All rights reserved.
 *
 * This software is published under the terms of the LGPL Software License,
 * a copy of which has been included with this distribution in the LICENSE.txt
 * file.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 *
 * $Id: CompactPosition.java,v 1.1 2002/12/08 13:27:35 BerniMan Exp $
 */

package chesspresso.position;

import chesspresso.*;

/**
 * An implementation of the position interface.
 *
 * The class is optimized for memory footprint. Each instance uses only 36 bytes
 * for internal representation (plus some overhead for java internals).
 *
 * @author  Bernhard Seybold
 * @version $Revision: 1.1 $
 */
public class CompactPosition extends AbstractPosition
{

    private final static int
        SQI_EP_SHIFT          =  0,   SQI_EP_MASK           = 0x07F,  // [0, 128[
        CASTLES_SHIFT         =  7,   CASTLES_MASK          = 0x00F,  // [0, 15]
        TO_PLAY_SHIFT         = 11,   TO_PLAY_MASK          = 0x001,  // [0 | 1]
        PLY_NUMBER_SHIFT      = 12,   PLY_NUMBER_MASK       = 0x3FF,  // [0, 1024[
        HALF_MOVE_CLOCK_SHIFT = 22,   HALF_MOVE_CLOCK_MASK  = 0xFF;   // [0, 128[
    
    /*================================================================================*/
    
    private int[] m_stones;   // 32 bytes
    private int m_flags;      //  4 bytes
    
    /*================================================================================*/
    
    public CompactPosition()
    {
        // TODO
    }
    
    public CompactPosition(ImmutablePosition position)
    {
        m_stones = new int[Chess.NUM_OF_SQUARES / 8];
        for (int sqi=0; sqi < Chess.NUM_OF_SQUARES; sqi += 8) {
            m_stones[sqi / 8] =  (position.getStone(sqi    ) + Chess.MAX_PIECE)        +
                                ((position.getStone(sqi + 1) + Chess.MAX_PIECE) <<  4) +
                                ((position.getStone(sqi + 2) + Chess.MAX_PIECE) <<  8) +
                                ((position.getStone(sqi + 3) + Chess.MAX_PIECE) << 12) +
                                ((position.getStone(sqi + 4) + Chess.MAX_PIECE) << 16) +
                                ((position.getStone(sqi + 5) + Chess.MAX_PIECE) << 20) +
                                ((position.getStone(sqi + 6) + Chess.MAX_PIECE) << 24) +
                                ((position.getStone(sqi + 7) + Chess.MAX_PIECE) << 28);
        }
        
        m_flags = ((position.getSqiEP() - Chess.NO_SQUARE)       << SQI_EP_SHIFT) +
                   (position.getCastles()                        << CASTLES_SHIFT) +
                  ((position.getToPlay() == Chess.WHITE ? 0 : 1) << TO_PLAY_SHIFT) +
                   (position.getPlyNumber()                      << PLY_NUMBER_SHIFT) +
                   (position.getHalfMoveClock()                  << HALF_MOVE_CLOCK_SHIFT);
    }

    /*================================================================================*/
    
    public int getStone(int sqi)   {
    	return ((m_stones[sqi / 8] >> (4 * (sqi & 0x7))) & 0xF) - Chess.MAX_PIECE;
    }    	
    public int getSqiEP()          {return ((m_flags >> SQI_EP_SHIFT) & SQI_EP_MASK) + Chess.NO_SQUARE;}
    public int getCastles()        {return ((m_flags >> CASTLES_SHIFT) & CASTLES_MASK);}
    public int getToPlay()         {return ((m_flags >> TO_PLAY_SHIFT) & TO_PLAY_MASK) == 0 ? Chess.WHITE : Chess.BLACK;}
    public int getPlyNumber()      {return ((m_flags >> PLY_NUMBER_SHIFT) & PLY_NUMBER_MASK);}
    public int getHalfMoveClock()  {return ((m_flags >> HALF_MOVE_CLOCK_SHIFT) & HALF_MOVE_CLOCK_MASK);}
    
}
@@ -1719,32 +1719,148 @@
 O%0D%0A    %7D%0D%0A    %0D%0A
+    public CompactPosition(int%5B%5D stones, int flags) %7B%0D%0A    %09m_stones = stones;%0D%0A    %09m_flags = flags;%0D%0A    %7D%0D%0A    %0D%0A
     public Compa
@@ -3968,9 +3968,129 @@
 %0D%0A    %0D%0A
+    public int%5B%5D getStones() %7B%0D%0A    %09return m_stones;%0D%0A    %7D%0D%0A    public int getFlags() %7B%0D%0A    %09return m_flags;%0D%0A    %7D%0D%0A
 %7D

add constructor to generate a CompactPosition from binary data