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

org.ggp.base.util.statemachine.sancho.RuntimeGameCharacteristics Maven / Gradle / Ivy

The newest version!
package org.ggp.base.util.statemachine.sancho;

import java.io.File;
import java.util.Set;

import org.apache.commons.configuration.AbstractConfiguration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.XMLPropertiesConfiguration;
import org.ggp.base.util.statemachine.sancho.MachineSpecificConfiguration.CfgItem;
import org.ggp.base.util.statemachine.sancho.StatsLogUtils.Series;

/**
 * Subclass of GameCharacterisics which adds characteristics that are specific to the game's runtime interpretation and
 * searching by Sancho.  These may vary dynamically.
 */
public class RuntimeGameCharacteristics extends GameCharacteristics
{
//  private static final Logger LOGGER = LogManager.getLogger();
//  private static final Logger STATS_LOGGER = LogManager.getLogger("stats");

  // The properties file in which game characteristics are stored.
  private static final String PROPS_FILE = "characteristics.xml";

  // Keys under which individual characteristics are stored.
  private static final String PLAN_KEY                      = "plan";
  private static final String NUM_ROLES_KEY                 = "num_roles";
  private static final String SIMULTANEOUS_KEY              = "simultaneous";
  private static final String PSEUDO_SIMULTANEOUS_KEY       = "pseudo_simultaneous";
  private static final String ITERATED_KEY                  = "iterated";
  private static final String NUM_FACTORS_KEY               = "num_factors";
  private static final String FACTORS_KEY                   = "factors";
  private static final String MAX_FACTOR_FAILURE_TIME       = "max_factor_failure_time";
  private static final String MOVES_IN_MULTIPLE_FACTORS_KEY = "moves_in_multiple_factors";
  private static final String MAX_BRANCHING_FACTOR_KEY      = "max_branching_factor";
  private static final String FIXED_LENGTH_KEY              = "fixed_length";
  private static final String CONTROL_MASK                  = "control_mask";

  private final XMLPropertiesConfiguration mConfigFile;
  private boolean             mLoadedConfig;
  private double              explorationBias         = 1.0;
  private double              mExactRolloutSampleSize = 1;
  private volatile int        mRolloutSampleSize;
  private int                 mMaxObservedChoices;
  final double                competitivenessBonus    = 2;
  private boolean             isFixedMoveCount        = false;
  private boolean             isFixedSum              = false;
  private double              mTerminalityDensity     = 0;
  private double              mAverageBranchingFactor = 1;
  private int                 earliestCompletion      = 0;
  final private int           fixedSampleSize         = MachineSpecificConfiguration.getCfgInt(CfgItem.FIXED_SAMPLE_SIZE);
  private String              mPlan                   = null;
  private int                 mNumFactors             = 0;
  private String              mFactors                = null;
  private int                 mMinLength              = 0;
  private int                 mMaxLength              = -1;
  private double              mAverageLength          = -1;
  private double              mStdDeviationLength     = 0;
  private double              mAverageNonDrawLength   = 0;
  private int                 mMinNonDrawLength       = 0;
  private double              mGoalsStability         = 0;
  private double              mLongDrawsProportion    = 0;
  private double              mAverageHyperSequenceLength = 0;
  private double              mVarianceHyperSequenceLength = 0;
  private long                mMaxFactorFailureTime   = 0;
  private String              mControlMask            = null;

  /**
   * Create game characteristics, loading any state from previous games.
   *
   * @param xiGameDirectory - the directory to load from.
   */
  public RuntimeGameCharacteristics(File xiGameDirectory)
  {
    super();
    setRolloutSampleSize(1);

    if ( xiGameDirectory != null )
    {
      mConfigFile = loadConfig(xiGameDirectory);
    }
    else
    {
      mConfigFile = null;
    }
  }

  /**
   * Load previously saved per-game configuration from disk.
   *
   * @param xiGameDirectory - the directory to look in.
   *
   * @return the game configuration.
   */
  private XMLPropertiesConfiguration loadConfig(File xiGameDirectory)
  {
    if (MachineSpecificConfiguration.getCfgBool(CfgItem.DISABLE_LEARNING))
    {
//      LOGGER.debug("Learning disabled - not loading configuration");
      return null;
    }

    XMLPropertiesConfiguration lConfigFile = null;

    AbstractConfiguration.setDefaultListDelimiter(':');
    if (xiGameDirectory != null)
    {
      // Load any known game information from previous times we've played this game.
      File lPropsFile = new File(xiGameDirectory, PROPS_FILE);
      try
      {
        lConfigFile = new XMLPropertiesConfiguration(lPropsFile);

        numRoles  = lConfigFile.getInt(NUM_ROLES_KEY, 0);
        mLoadedConfig = (numRoles != 0);

        if (mLoadedConfig)
        {
          isSimultaneousMove             = lConfigFile.getBoolean(SIMULTANEOUS_KEY, false);
          isIteratedGame                 = lConfigFile.getBoolean(ITERATED_KEY, false);
          mNumFactors                    = lConfigFile.getInt(NUM_FACTORS_KEY, 0);
          mFactors                       = lConfigFile.getString(FACTORS_KEY, null);
          mMaxFactorFailureTime          = lConfigFile.getLong(MAX_FACTOR_FAILURE_TIME, 0);
          moveChoicesFromMultipleFactors = lConfigFile.getBoolean(MOVES_IN_MULTIPLE_FACTORS_KEY, false);
          mMaxObservedChoices            = lConfigFile.getInt(MAX_BRANCHING_FACTOR_KEY, 1);
          isFixedMoveCount               = lConfigFile.getBoolean(FIXED_LENGTH_KEY, false);
          if ( !MachineSpecificConfiguration.getCfgBool(CfgItem.DISABLE_SAVED_PLANS) )
          {
            mPlan                        = lConfigFile.getString(PLAN_KEY, null);
          }
          else
          {
//            LOGGER.debug("Persisted plans disbaled - not loading a plan");
          }
          mControlMask                   = lConfigFile.getString(CONTROL_MASK, null);
        }
      }
      catch (ConfigurationException lEx)
      {
//        LOGGER.warn("Corrupt configuration file: " + lEx);
        mLoadedConfig = false;
      }
    }

    return lConfigFile;
  }

  /**
   * @return true if the game characteristics have been loaded from file or false if they're just default
   * characteristics.
   */
  public boolean isConfigLoaded()
  {
    return mLoadedConfig;
  }

  /**
   * Save game characteristics to disk.
   */
  public void saveConfig()
  {
    if (MachineSpecificConfiguration.getCfgBool(CfgItem.DISABLE_LEARNING))
    {
//      LOGGER.debug("Learning disabled - not saving configuration");
      return;
    }

    if (mConfigFile == null)
    {
      // We were unable to open the config file (or create a blank one), so we can't save.
//      LOGGER.warn("Unable to save game configuration");
      return;
    }

    // Save what we've learned about this game
    mConfigFile.setProperty(NUM_ROLES_KEY,                 numRoles);
    mConfigFile.setProperty(SIMULTANEOUS_KEY,              isSimultaneousMove);
    mConfigFile.setProperty(PSEUDO_SIMULTANEOUS_KEY,       isPseudoSimultaneousMove);
    mConfigFile.setProperty(ITERATED_KEY,                  isIteratedGame);
    mConfigFile.setProperty(MAX_FACTOR_FAILURE_TIME,       mMaxFactorFailureTime);
    mConfigFile.setProperty(NUM_FACTORS_KEY,               mNumFactors);
    mConfigFile.setProperty(MOVES_IN_MULTIPLE_FACTORS_KEY, moveChoicesFromMultipleFactors);
    mConfigFile.setProperty(MAX_BRANCHING_FACTOR_KEY,      mMaxObservedChoices);
    mConfigFile.setProperty(FIXED_LENGTH_KEY,              isFixedMoveCount);
    if (mPlan        != null) {mConfigFile.setProperty(PLAN_KEY,     mPlan);}
    if (mControlMask != null) {mConfigFile.setProperty(CONTROL_MASK, mControlMask);}
    if (mFactors     != null) {mConfigFile.setProperty(FACTORS_KEY, mFactors);}

    try
    {
      mConfigFile.save();
    }
    catch (ConfigurationException lEx)
    {
//      LOGGER.warn("Failed to save configuration: " + lEx);
    }
  }

  public double getExplorationBias()
  {
    return explorationBias;
  }

  public void setExplorationBias(double value)
  {
    assert(value >= 0 && value <= 5);
    explorationBias = value;
  }

  public double getExactRolloutSampleSize()
  {
    return mExactRolloutSampleSize;
  }

  public int getRolloutSampleSize()
  {
    return mRolloutSampleSize;
  }

  public void setRolloutSampleSize(double xiExactSampleSize)
  {
    int lOldSampleSize = mRolloutSampleSize;

    if (fixedSampleSize <= 0)
    {
      mExactRolloutSampleSize = xiExactSampleSize;

      mRolloutSampleSize = (int)(xiExactSampleSize + 0.5);
    }
    else
    {
      mRolloutSampleSize = fixedSampleSize;
    }

    if (lOldSampleSize != mRolloutSampleSize )
    {
      // Log the new sample rate.
      StringBuffer lLogBuf = new StringBuffer(1024);
      Series.SAMPLE_RATE.logDataPoint(lLogBuf, System.currentTimeMillis(), mRolloutSampleSize);
//      STATS_LOGGER.info(lLogBuf.toString());
    }
  }

  public double getCompetitivenessBonus()
  {
    return competitivenessBonus;
  }

  public void setIsFixedMoveCount()
  {
    isFixedMoveCount = true;
  }

  public boolean getIsFixedMoveCount()
  {
    return isFixedMoveCount;
  }

  public void setIsFixedSum()
  {
    isFixedSum = true;
  }

  public boolean getIsFixedSum()
  {
    return isFixedSum;
  }

  public void setTerminalityDensity(double value)
  {
    mTerminalityDensity = value;
  }

  public double getTerminalityDensity()
  {
    return mTerminalityDensity;
  }

  public void setAverageBranchingFactor(double value)
  {
    mAverageBranchingFactor = value;
  }

  public double getAverageBranchingFactor()
  {
    return mAverageBranchingFactor;
  }

  public void setEarliestCompletionDepth(int value)
  {
    earliestCompletion = value;
  }

  public int getEarliestCompletionDepth()
  {
    return earliestCompletion;
  }

  /**
   * @param xiNumChoices - the number of choices just observed.
   *
   * @return the maximum number of choices that any role has been observed to have.
   */
  public int getChoicesHighWaterMark(int xiNumChoices)
  {
    if (xiNumChoices > mMaxObservedChoices)
    {
      mMaxObservedChoices = xiNumChoices;
    }
    return mMaxObservedChoices;
  }

  /**
   * @return a pre-prepared plan guaranteed to score the highest possible score (for a puzzle).
   */
  public String getPlan()
  {
    return mPlan;
  }

  /**
   * Record a plan, from beginning to end, that's guaranteed to score the highest possible score.
   *
   * @param xiPlan - the plan.
   */
  public void setPlan(String xiPlan)
  {
    mPlan = xiPlan;
  }

  /**
   * Record the factors of a game.
   *
   * @param xiFactors - the factors.
   */
  public void setFactors(Set xiFactors)
  {
    assert(xiFactors != null) : "Don't call this method if factors are unknown";

    mNumFactors = xiFactors.size();

    if (mNumFactors == 1)
    {
      mFactors = "";
    }
    else
    {
      StringBuilder lBuilder = new StringBuilder();
      for (Factor lFactor : xiFactors)
      {
//        LOGGER.info("Factor: " + lFactor.toPersistentString());
        lBuilder.append(lFactor.toPersistentString());
        lBuilder.append(";");
      }
      lBuilder.setLength(lBuilder.length() - 1);
      mFactors = lBuilder.toString();
    }
  }

  /**
   * @return the number of factors or 0 if the number is unknown.  (Returns 1 if the game is know not to split into
   * multiple factors.)
   */
  public int getNumFactors()
  {
    return mNumFactors;
  }

  /**
   * @return a string representation of all the factors.
   */
  public String getFactors()
  {
    return mFactors;
  }

  public int getMaxLength()
  {
    return mMaxLength;
  }

  public void setMaxLength(int xiMaxLength)
  {
    mMaxLength = xiMaxLength;
  }

  public double getAverageLength()
  {
    return mAverageLength;
  }

  public void setAverageLength(double xiAverageNumTurns)
  {
    mAverageLength = xiAverageNumTurns;
  }

  public double getStdDeviationLength()
  {
    return mStdDeviationLength;
  }

  public void setStdDeviationLength(double xiStdDeviationLength)
  {
    mStdDeviationLength = xiStdDeviationLength;
  }

  public int getMinLength()
  {
    return mMinLength;
  }

  public void setMinLength(int xiMinLength)
  {
    mMinLength = xiMinLength;
  }

  public double getAverageNonDrawLength()
  {
    return mAverageNonDrawLength;
  }

  public void setAverageNonDrawLength(double xiAverageNonDrawLength)
  {
    mAverageNonDrawLength = xiAverageNonDrawLength;
  }

  public int getMinNonDrawLength()
  {
    return mMinNonDrawLength;
  }

  public void setMinNonDrawLength(int xiMinNonDrawLength)
  {
    mMinNonDrawLength = xiMinNonDrawLength;
  }

  @Override
  public void report()
  {
    super.report();

//    LOGGER.info("Statistical characteristics");
//    LOGGER.info("  Range of lengths of sample games seen:          [" + getMinLength() + "," + getMaxLength() + "]");
//    LOGGER.info("  Average num turns:                              " + getAverageLength());
//    LOGGER.info("  Std deviation num turns:                        " + getStdDeviationLength());
//    LOGGER.info("  Average num turns for non-drawn result:         " + getAverageNonDrawLength());
//    LOGGER.info("  Average hyper-sequence length:                  " + getAverageHyperSequenceLength());
//    LOGGER.info("  Variance in hyper-sequence length:              " + getVarianceHyperSequenceLength());
//    LOGGER.info("  Goals stability:                                " + getGoalsStability());
//    LOGGER.info("  Proportion of max length games ending in draws: " + getLongDrawsProportion());
//    LOGGER.info("  Num factors:                                    " + getNumFactors());
//    LOGGER.info("  Max factor failure time (ms)                    " + getMaxFactorFailureTime());
//    LOGGER.info("  IsFixedSum                                      " + getIsFixedSum());
  }

  /**
   * @return goal stability factor (how well goals in non-terminal states predict the end result)
   */
  public double getGoalsStability()
  {
    return mGoalsStability;
  }

  /**
   * @param xiGoalsStability - goal stability factor (how well goals in non-terminal states predict the end result)
   */
  public void setGoalsStability(double xiGoalsStability)
  {
    mGoalsStability = xiGoalsStability;
  }

  /**
   * @return proportion of long games that were draws
   */
  public double getLongDrawsProportion()
  {
    return mLongDrawsProportion;
  }

  /**
   * Setter for proportion of long games that were draws
   * @param xiLongDrawProportion
   */
  public void setLongDrawsProportion(double xiLongDrawProportion)
  {
    mLongDrawsProportion = xiLongDrawProportion;
  }

  /**
   * @return average length of hyper-sequences observed
   */
  public double getAverageHyperSequenceLength()
  {
    return mAverageHyperSequenceLength;
  }

  /**
   * Setter for average length of hyper-sequences observed
   * @param xiAverageHyperSequenceLength
   */
  public void setAverageHyperSequenceLength(double xiAverageHyperSequenceLength)
  {
    mAverageHyperSequenceLength = xiAverageHyperSequenceLength;
  }

  /**
   * @return variance in length of hyper-sequences observed
   */
  public double getVarianceHyperSequenceLength()
  {
    return mVarianceHyperSequenceLength;
  }

  /**
   * Setter for variance in length of hyper-sequences observed
   * @param xiVarianceHyperSequenceLength
   */
  public void setVarianceHyperSequenceLength(double xiVarianceHyperSequenceLength)
  {
    mVarianceHyperSequenceLength = xiVarianceHyperSequenceLength;
  }

  /**
   * @return the maximum time, in milliseconds, that we've tried but failed to factor the game in.
   */
  public long getMaxFactorFailureTime()
  {
    return mMaxFactorFailureTime;
  }

  /**
   * Record a failure to factor the game in the specified time.
   *
   * @param xiFailureTime - the time in milliseconds.
   */
  public void factoringFailedAfter(long xiFailureTime)
  {
    if (xiFailureTime > mMaxFactorFailureTime)
    {
      mMaxFactorFailureTime = xiFailureTime;
    }
  }

  public void setControlMask(String xiMask)
  {
    mControlMask = xiMask;
  }

  public String getControlMask()
  {
    return mControlMask;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy