package net.demilich.metastone.game.behaviour; import java.util.HashMap; import net.demilich.metastone.game.Attribute; import net.demilich.metastone.game.GameContext; import net.demilich.metastone.game.Player; import net.demilich.metastone.game.cards.Card; import net.demilich.metastone.game.entities.Entity; public class TranspositionTable { private static int hash(Entity entity) { int hash = entity.getName().hashCode(); for (Attribute tag : entity.getAttributes().keySet()) { Object value = entity.getAttributes().get(tag); if (!(value instanceof Integer)) { continue; } hash = mergeHashes(hash, entity.getAttribute(tag).hashCode()); } return hash; } private static int mergeHashes(int hash1, int hash2) { int hash = 0; hash = hash * 33 ^ hash1; hash = hash * 33 ^ hash2; return hash; } private HashMap<Integer, Double> knownScores = new HashMap<Integer, Double>(); // private HashMap<Integer, GameContext> debug = new HashMap<Integer, // GameContext>(); private int cachedKey; private GameContext cachedState; public void clear() { knownScores.clear(); } public double getScore(GameContext context) { return knownScores.get(hash(context)); } private int hash(GameContext context) { if (context == cachedState) { return cachedKey; } int hash = context.getActivePlayerId(); for (Player player : context.getPlayers()) { hash = mergeHashes(hash, player.getMana()); hash = mergeHashes(hash, player.getMaxMana()); hash = mergeHashes(hash, hash(player.getHero())); for (Card handCard : player.getHand()) { hash = mergeHashes(hash, hash(handCard)); } for (Card deckCard : player.getDeck()) { hash = mergeHashes(hash, hash(deckCard)); } for (Entity minion : player.getMinions()) { hash = mergeHashes(hash, hash(minion)); hash = mergeHashes(hash, context.getTriggersAssociatedWith(minion.getReference()).size()); } } cachedState = context; cachedKey = hash; return hash; } public boolean known(GameContext context) { int key = hash(context); // if (knownScores.containsKey(key)) { // System.out.println("Identical game states found!"); // System.out.println("New: " + context); // System.out.println("Existing: " + debug.get(key)); // } return knownScores.containsKey(key); } public void save(GameContext context, double score) { int key = hash(context); knownScores.put(key, score); // debug.put(key, context); } }