package org.pokenet.server.battle.mechanics.intelligence; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.ArrayList; import java.util.Comparator; import java.util.Iterator; import java.util.Random; import java.util.TreeSet; import org.pokenet.server.battle.mechanics.PokemonType; /** * * @author Colin */ public class Situation { private ArrayList<Memory> m_memory = new ArrayList<Memory>(); private static final Random m_random = new Random(); private static final Situation m_inst = new Situation(); private static final String m_file = "knowledge"; private static int m_saves = 0; /** * Create a single Situation class. */ private Situation() { File f = new File(m_file); if (f.exists()) { loadFromFile(); } else { m_memory.add(new Memory(PokemonType.T_BUG, PokemonType.T_DARK, true, "Tackle") ); } } /** * Load the Situations database from a file. */ @SuppressWarnings("unchecked") private void loadFromFile() { try { File f = new File(m_file); FileInputStream file = new FileInputStream(f); ObjectInputStream obj = new ObjectInputStream(file); m_memory = (ArrayList)obj.readObject(); obj.close(); } catch (IOException e) { System.out.println(e.getMessage()); } catch (ClassNotFoundException e) { System.out.println(e.getMessage()); } } /** * Save the Situations database to a file. */ public synchronized void saveToFile() { try { File f = new File(m_file + m_saves++); FileOutputStream file = new FileOutputStream(f); ObjectOutputStream obj = new ObjectOutputStream(file); obj.writeObject(m_memory); obj.close(); } catch (IOException e) { System.out.println(e.getMessage()); } } /** * Get an instance of this class. */ public static Situation getInstance() { return m_inst; } /** * Get the score of a memory, based on past experience and its closeness * to a target. */ private static int getMemoryScore(Memory target, Memory mem) { // Offer a multiplicative factor based on closeness to the target. int factor = 0; if (target.m_low == mem.m_low) ++factor; if (target.m_me.equals(target.m_me)) ++factor; if (target.m_opponent.equals(target.m_opponent)) ++factor; // If it doesn't match at all, it will get a score of zero! return (target.m_score * factor); } /** * Find an exact match for a memory. */ private synchronized Memory findMemory(Memory target) { Iterator<Memory> i = m_memory.iterator(); while (i.hasNext()) { Memory mem = (Memory)i.next(); if (target.equals(mem)) { return mem; } } return null; } /** * Find whether a String is in a move list. */ private boolean isInMoveList(String entry, String[] moves) { /**if (entry == null) { return true; }**/ for (int i = 0; i < moves.length; ++i) { if (moves[i].equals(entry)) { return true; } } return false; } /** * Find the best move to use for the situation. */ @SuppressWarnings("unchecked") public synchronized String getBestMemory(final Memory target, String[] moves) { Comparator comp = new Comparator() { public int compare(Object o1, Object o2) { Memory a = (Memory)o1, b = (Memory)o2; int scoreA = getMemoryScore(target, a); int scoreB = getMemoryScore(target, b); if (scoreA < scoreB) { return -1; } else if (scoreA > scoreB) { return 1; } return 0; } }; TreeSet items = new TreeSet(comp); Iterator i = m_memory.iterator(); while (i.hasNext()) { Memory mem = (Memory)i.next(); if (!isInMoveList(mem.m_move, moves)) { continue; } if (getMemoryScore(target, mem) != 0) { items.add(mem); } } if ((items.size() == 0) || (m_random.nextDouble() <= 0.2)) { Memory best = (Memory)m_memory.get(m_random.nextInt(m_memory.size())); if (!isInMoveList(best.m_move, moves)) { return moves[m_random.nextInt(moves.length)]; } } if (m_random.nextDouble() <= 0.4) { Memory mem = (Memory)items.last(); return mem.m_move; } int half = items.size() / 2; if (half == 0) { Memory mem = (Memory)items.last(); return mem.m_move; } int start = m_random.nextInt(2) * half; int idx = start + m_random.nextInt(half); Iterator j = items.iterator(); int k = 0; while (j.hasNext()) { if (k++ == idx) { break; } j.next(); } Memory mem = (Memory)j.next(); return mem.m_move; } /** * Update a set of memories -- were they positive experiences? */ public synchronized void updateMemories(ArrayList<?> memories, boolean positive, int factor) { Iterator<?> i = memories.iterator(); while (i.hasNext()) { Memory target = (Memory)i.next(); Memory mem = findMemory(target); int delta = (positive ? 1 : -1) * factor; if (mem == null) { target.m_score = delta; m_memory.add(target); } else { mem.m_score += delta; } } } }