package de.tu_dresden.inf.ggp06_2.resolver;
import java.util.ArrayList;
import java.util.List;
import de.tu_dresden.inf.ggp06_2.resolver.astvisitors.AbstractVisitor;
import de.tu_dresden.inf.ggp06_2.resolver.fuzzy.FuzzyResolution;
import de.tu_dresden.inf.ggp06_2.resolver.fuzzy.FuzzySubstitution;
import de.tu_dresden.inf.ggp06_2.resolver.scope.GameStateScope;
import de.tu_dresden.inf.ggp06_2.simulator.flags.TimerFlag;
/**
*
* @author Nick (initial author of JavaProver )
* @author Ingo Keller - General Game Playing course student at TUD
* @author Arsen Kostenko - General Game Playing course student at TUD
*
*/
public final class Variable extends Term {
/**
* variable counter
*/
static int variableCounter = Integer.MIN_VALUE + 1;
/**
* As string for now, but should be a number for faster matching
* the constructor could use a static map to make the conversation from
* string to internal number
*/
final String variable;
/**
* internal numerical variable interpretation of the variable
*/
final int number;
/**
* Variable list
*/
final ArrayList<Variable> varList;
/**
* Simple constructor for a random new variable.
*
*/
public Variable() {
variable = "?" + variableCounter++;
number = variable.hashCode();
varList = new ArrayList<Variable>();
varList.add(this);
}
/**
* Create a new variable with given string as its content.
* @param string Basic string for assigning properties of
* a variable.
*/
public Variable(String string) {
variable = string.toUpperCase();
number = variable.hashCode();
varList = new ArrayList<Variable>();
varList.add(this);
}
/**
* Simply defaults to false. No other variables
* can occur inside a variable.
*
* @param var Variable to check
* @return Should return true if given variable
* occurs inside an expression. In this
* case defaults to false, however.
*/
@Override
public boolean isPresent(Variable var) {
return equals(var);
}
/**
* This method tries to map the variable to an expression using the given
* substitution.
*
* @param sigma Substitution
* @return If the variable is mapable it returns a expression; the variable
* otherwise.
*/
@Override
public Expression apply(Substitution sigma) {
return sigma.containsKey(this) ? sigma.get(this) : this;
}
/**
* @param obj Object to compare to.
* @return Returns true if parameter is a variable with
* the same internal number.
*/
@Override
public final boolean equals( Object obj ) {
return (obj instanceof Variable) && number == obj.hashCode();
}
/**
* @param obj Object to compare to.
* @return Returns true if parameter is a variable with
* the same internal number.
*/
public final boolean equals( Variable obj ) {
return number == obj.number;
}
/**
* @return Returns the hashCode of the object.
*/
@Override
public final int hashCode() {
return number;
}
/**
* @return Returns the string representation of variable. If it is a anonym
* variable it will return the variable number.
*/
@Override
public final String toString() {
return variable;
}
/**
* This method returns a new list of variables.
*
* @return Returns itself wrapped by a dummy list.
*/
@Override
public final List<Variable> getVariables() {
return varList;
}
/**
* Calculates the most generale unifier.
*
* @param target Expression to unify with.
* @param sigma Substitution to consider while
* performing unification
*/
@Override
public Substitution mgu(Expression target, Substitution sigma) {
Expression subThis = this.apply(sigma);
Expression subTarget = target.apply(sigma);
if ( !subThis.equals( this ) )
return subThis.mgu(subTarget, sigma);
else if ( subTarget.isPresent( this ) )
return null;
else if ( subTarget instanceof Variable ) {
Variable newV = new Variable();
Substitution psi = new Substitution(sigma);
psi.addAssociation( this, newV );
psi.addAssociation( (Variable) subTarget, newV );
return psi;
} else {
Substitution psi = new Substitution(sigma);
psi.addAssociation( this, subTarget );
return psi;
}
}
/**
* Variables are expected to unify with everything :) so
* the reply for fuzzy evaluation is trivially <code>Expression.fuzzyOne</code>
*
* @param sigma State of resolution
* @param scope GDL rules scope
* @param flag Timer flag
*/
@Override
protected FuzzyResolution fuzzyEvaluateBody(
FuzzySubstitution sigma, GameStateScope scope,
List<Expression> guard, TimerFlag flag)
throws InterruptedException {
FuzzyResolution resolution = new FuzzyResolution();
resolution.add( sigma );
resolution.setFuzzyValue( Expression.fuzzyOne );
return resolution;
}
@Override
public final boolean isGround() {
return false;
}
/**
* This method provokes a class cast exception since if we would like to
* throw an own exception here, we would have to put everything into
* try/catch blocks.
*/
@Override
public final Atom getKeyAtom() {
Object dummy = this;
return (Atom) dummy;
}
@Override
public final void processVisitor(AbstractVisitor visitor) {
visitor.visitVariable(this);
}
}