All Downloads are FREE. Search and download functionalities are using the official Maven repository.

chesspresso.position.AbstractMutablePosition Maven / Gradle / Ivy

/*
 * Chessplorer-Lib - an open source chess library written in Java
 * Copyright (C) 2016 Chessplorer.org
 * Copyright (C) 2012-2016 Gerhard Kalab
 * Copyright (C) 2002-2003 Bernhard Seybold
 *
 * 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.
 */
package chesspresso.position;


import chesspresso.*;
import java.util.*;
import chesspresso.move.Move;
import chesspresso.move.IllegalMoveException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 *
 * @author Bernhard Seybold
 * @author Andreas Rudolph
 */
public abstract class AbstractMutablePosition extends AbstractPosition implements MutablePosition
{
    private final static Logger LOGGER = LoggerFactory.getLogger( AbstractMutablePosition.class );
    protected PositionListener[] m_listeners;     // protected to allow fast read access
    protected PositionChangeListener[] m_changeListeners;
    protected boolean m_notifyListeners;      // ... to check whether or not to fire
    protected boolean m_notifyPositionChanged;

    /*================================================================================*/

    protected AbstractMutablePosition()
    {
        m_listeners = null;
        m_changeListeners = null;
        m_notifyListeners = true;
        m_notifyPositionChanged = true;
    }

    /*================================================================================*/

    public int getPiece(int sqi) {return Chess.stoneToPiece(getStone(sqi));}
    public int getColor(int sqi) {return Chess.stoneToColor(getStone(sqi));}
    public boolean isSquareEmpty(int sqi) {return getStone(sqi) == Chess.NO_STONE;}

    /*================================================================================*/

    public void toggleToPlay() {setToPlay(Chess.otherPlayer(getToPlay()));}

    /*================================================================================*/

    public void clear()
    {
        boolean notify = m_notifyPositionChanged;
        m_notifyPositionChanged = false;

        for (int sqi=0; sqi < Chess.NUM_OF_SQUARES; sqi++) {
            setStone(sqi, Chess.NO_STONE);
        }
        setSqiEP(Chess.NO_SQUARE);
        setCastles(NO_CASTLES);
        setToPlay(Chess.WHITE);
        setPlyNumber(0);
        setHalfMoveClock(0);

        m_notifyPositionChanged = notify;
        firePositionChanged();
    }

    public void setStart()
    {
        boolean notify = m_notifyPositionChanged;
        m_notifyPositionChanged = false;

        FEN.initFromFEN(this, FEN.START_POSITION, true);

        m_notifyPositionChanged = notify;
        firePositionChanged();
    }

    public void set(ImmutablePosition position)
    {
        boolean notify = m_notifyPositionChanged;
        m_notifyPositionChanged = false;

        for (int sqi=0; sqi < Chess.NUM_OF_SQUARES; sqi++) {
            setStone(sqi, position.getStone(sqi));
        }
        setCastles(position.getCastles());
        setSqiEP(position.getSqiEP());
        setToPlay(position.getToPlay());
        setPlyNumber(position.getPlyNumber());
        setHalfMoveClock(position.getHalfMoveClock());

        m_notifyPositionChanged = notify;
        firePositionChanged();
    }

    /*================================================================================*/
    // inverse

    public final void inverse()
    {
        /*---------- inverse stones ----------*/
        // avoid to have two same kings on the board at the same time
        int[] stones = new int[Chess.NUM_OF_SQUARES];
        for (int sqi = 0; sqi < Chess.NUM_OF_SQUARES; sqi++) {
            stones[sqi] = getStone(sqi);
            setStone(sqi, Chess.NO_STONE);
        }
        for (int sqi = 0; sqi < Chess.NUM_OF_SQUARES; sqi++) {
            int partnerSqi = Chess.coorToSqi(Chess.sqiToCol(sqi), Chess.NUM_OF_ROWS - Chess.sqiToRow(sqi) - 1);
            setStone(sqi, Chess.getOpponentStone(stones[partnerSqi]));
        }

        /*---------- inverse en passant square ----------*/
        int sqiEP = getSqiEP();
        if (sqiEP != Chess.NO_SQUARE) {
            setSqiEP(Chess.coorToSqi(Chess.sqiToCol(sqiEP), Chess.NUM_OF_ROWS - Chess.sqiToRow(sqiEP) - 1));
        }

        /*---------- inverse castles ----------*/
        int castles = getCastles();
        setCastles(NO_CASTLES);
        if ((castles & WHITE_SHORT_CASTLE) != 0) includeCastles(BLACK_SHORT_CASTLE);
        if ((castles & WHITE_LONG_CASTLE)  != 0) includeCastles(BLACK_LONG_CASTLE);
        if ((castles & BLACK_SHORT_CASTLE) != 0) includeCastles(WHITE_SHORT_CASTLE);
        if ((castles & BLACK_LONG_CASTLE)  != 0) includeCastles(WHITE_LONG_CASTLE);

        /*---------- inverse to play ----------*/
        toggleToPlay();
    }

    /*================================================================================*/
    // convenience methods

    public final void includeCastles(int whichCastles)
    {
        setCastles(getCastles() | whichCastles);
    }

    public final void excludeCastles(int whichCastles)
    {
        setCastles(getCastles() & (~whichCastles));
    }

    public final void resetHalfMoveClock()
    {
        setHalfMoveClock(0);
    }

    public final void incHalfMoveClock()
    {
        setHalfMoveClock(getHalfMoveClock() + 1);
    }

    /*================================================================================*/
    // trigger listeners

    protected void fireSquareChanged(int sqi)
    {
        if (m_notifyListeners && m_listeners != null) {
            int stone = getStone(sqi);
            for (int i=0; i
            }
        }
    }

    public final synchronized void setNotifyListeners(boolean notify)
    {
        m_notifyListeners = notify;
    }

    /*================================================================================*/
    // IChPositionChangeListener

    public final void addPositionChangeListener(PositionChangeListener listener)
    {
        //LOGGER.debug("addPositionChangeListener " + listener);
        if (m_changeListeners == null) {
            m_changeListeners = new PositionChangeListener[1];
            m_changeListeners[0] = listener;
        } else {
            PositionChangeListener[] oldListeners = m_changeListeners;
            m_changeListeners = new PositionChangeListener[oldListeners.length + 1];
            System.arraycopy(oldListeners, 0, m_changeListeners, 0, oldListeners.length);
            m_changeListeners[m_changeListeners.length-1] = listener;
        }

        listener.notifyPositionChanged(this);  // for initialization
        //for (int i=0; i
            }
        }
        //for (int i=0; i




© 2015 - 2025 Weber Informatics LLC | Privacy Policy