/* $Id$ Copyright (C) 2006-2007 by David Cotton This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package fr.free.jchecs.ai; import static fr.free.jchecs.core.PieceType.QUEEN; import java.util.Arrays; import fr.free.jchecs.core.Move; import fr.free.jchecs.core.Piece; /** * Trie les mouvements en fonction de l'historique de la recherche, puis par valeur des prises et * valeur des pièces. * * @author David Cotton */ final class HistorySorter implements ContextSorter { /** Identifiant de la classe pour la sérialisation. */ private static final long serialVersionUID = 6653686322537719840L; /** Priorité de base d'un mouvement présent dans l'historique. */ private static final int HISTORY_MOVE_PRIORITY = 1000000 * QUEEN.getValue(); /** Historique des mouvements. */ private final int [] _history = new int [ 64 * 64 ]; /** * Crée une nouvelle instance. */ HistorySorter() { // Rien de spécifique... } /** * Efface l'historique. */ public void clear() { Arrays.fill(_history, 0); } /** * Tri des mouvements. * * @param pMvt1 Premier mouvement. * @param pMvt2 Deuxième mouvement. * @return -1, 0, 1 en accord avec le contrat de compare(). */ public int compare(final Move pMvt1, final Move pMvt2) { int v1 = get(pMvt1); int v2 = get(pMvt2); final Piece prise1 = pMvt1.getCaptured(); final int vPiece1 = pMvt1.getPiece().getType().getValue(); if (prise1 == null) { v1 += vPiece1; } else { v1 += 1000 * prise1.getType().getValue(); v1 -= vPiece1; } final Piece prise2 = pMvt2.getCaptured(); final int vPiece2 = pMvt2.getPiece().getType().getValue(); if (prise2 == null) { v2 += vPiece2; } else { v2 += 1000 * prise2.getType().getValue(); v2 -= vPiece2; } if (v1 > v2) { return -1; } else if (v1 < v2) { return 1; } return 0; } /** * Renvoie l'évaluation d'un mouvement. * * @param pMouvement Mouvement à rechercher. * @return Valeur liée au mouvement (ou 0 si le mouvement n'est pas dans la liste). */ public int get(final Move pMouvement) { assert pMouvement != null; return _history[pMouvement.getFrom().getIndex() + 64 * pMouvement.getTo().getIndex()] + HISTORY_MOVE_PRIORITY; } /** * Ajoute un mouvement à l'historique. * * @param pMouvement Mouvement à mémoriser. */ public void put(final Move pMouvement) { assert pMouvement != null; _history[pMouvement.getFrom().getIndex() + 64 * pMouvement.getTo().getIndex()]++; } }