public String evaluate(PropertySource ps, boolean localized) throws ExpressionException {

    if (getExpression().length() == 0) {
      return "";
    }

    // Default to the GameModule to satisfy properties if no
    // GamePiece supplied.
    source = ps == null ? GameModule.getGameModule() : ps;

    setNameSpace(expressionNameSpace);

    // Bind each undeclared variable with the value of the
    // corresponding Vassal property. Allow for old-style $variable$ references
    for (String var : variables) {
      String name = var;
      if (name.length() > 2 && name.startsWith("$") && name.endsWith("$")) {
        name = name.substring(1, name.length() - 1);
      }
      Object prop = localized ? source.getLocalizedProperty(name) : source.getProperty(name);
      String value = prop == null ? "" : prop.toString();
      if (value == null) {
        setVar(var, "");
      } else if ("true".equals(value)) {
        setVar(var, true);
      } else if ("false".equals(value)) {
        setVar(var, false);
      } else {
        try {
          setVar(var, Integer.valueOf(value).intValue());
        } catch (NumberFormatException e) {
          try {
            setVar(var, Float.valueOf(value).floatValue());
          } catch (NumberFormatException e1) {
            setVar(var, value);
          }
        }
      }
    }

    // Re-evaluate the pre-parsed expression now that the undefined variables have
    // been bound to their Vassal property values.

    setVar(THIS, this);
    setVar(SOURCE, source);

    String result = "";
    try {
      eval(MAGIC1 + "=" + MAGIC2 + "()");
      result = get(MAGIC1).toString();
    } catch (EvalError e) {
      final String s = e.getRawMessage();
      final String search = MAGIC2 + "();'' : ";
      final int pos = s.indexOf(search);
      throw new ExpressionException(getExpression(), s.substring(pos + search.length()));
    }

    return result;
  }
 public Object getLocalizedProperty(String name) {
   final Object value = source.getLocalizedProperty(name);
   return value == null ? "" : value.toString();
 }