Esempio n. 1
0
  public static String parseRollInfo(RollInfo rollInfo, String rollString) {
    // To really do this right, we change the token string
    // as we go along so that we maintain parser state by
    // means of the tokens rather than something more
    // explicit.  In truth, this is an ideal application
    // of flex and friends for a "mini-language" whose
    // statements evaluate to dice rolls.  Too much LISP
    // on the brain.  --bko
    final StringTokenizer st = new StringTokenizer(rollString, " ", true);

    try {
      String tok = st.nextToken("d");

      if ("d".equals(tok)) {
        rollInfo.times = 1;
      } else {
        rollInfo.times = Integer.parseInt(tok);

        if (st.hasMoreTokens()) {
          tok = st.nextToken("d"); // discard the 'd'

          if (!"d".equals(tok)) {
            return "Bad roll parsing in '" + rollString + "': missing 'd'";
          }
        } else {
          rollInfo.sides = 1;

          return "";
        }
      }

      String parseChars = "/\\|mM+-tT";
      rollInfo.sides = Integer.parseInt(st.nextToken(parseChars));

      if (rollInfo.sides < 1) {
        return "Bad roll parsing in '" + rollString + "': sides < 1: " + rollInfo.sides;
      }

      while (st.hasMoreTokens()) {
        tok = st.nextToken(parseChars);

        switch (tok.charAt(0)) {
          case '/':
            parseChars = "mM+-tT";

            final int keepTop = Integer.parseInt(st.nextToken(parseChars));

            if (keepTop > rollInfo.times) {
              return "Bad keepTop in '"
                  + rollString
                  + "': times: "
                  + rollInfo.times
                  + "; keepTop: "
                  + keepTop;
            }

            rollInfo.keepList = new boolean[rollInfo.times];

            // Rely on fact boolean is false by default.  --bko
            for (int i = rollInfo.times - keepTop; i < rollInfo.times; ++i) {
              rollInfo.keepList[i] = true;
            }

            break;

          case '\\':
            parseChars = "mM+-tT";

            final int keepBottom = Integer.parseInt(st.nextToken(parseChars));

            if (keepBottom > rollInfo.times) {
              return "Bad keepBottom in '"
                  + rollString
                  + "': times: "
                  + rollInfo.times
                  + "; keepBottom: "
                  + keepBottom;
            }

            rollInfo.keepList = new boolean[rollInfo.times];

            // Rely on fact boolean is false by default.  --bko
            for (int i = 0; i < keepBottom; ++i) {
              rollInfo.keepList[i] = true;
            }

            break;

          case '|':
            parseChars = "mM+-tT";
            tok = st.nextToken(parseChars);
            rollInfo.keepList = new boolean[rollInfo.times];

            final StringTokenizer keepSt = new StringTokenizer(tok, ",");

            while (keepSt.hasMoreTokens()) {
              rollInfo.keepList[Integer.parseInt(keepSt.nextToken(",")) - 1] = true;
            }

            break;

          case 'm':
            parseChars = "M+-tT";
            rollInfo.rerollBelow = Integer.parseInt(st.nextToken(parseChars));

            break;

          case 'M':
            parseChars = "m+-tT";
            rollInfo.rerollAbove = Integer.parseInt(st.nextToken(parseChars));

            break;

          case '+':
            parseChars = "tT";
            rollInfo.modifier = Integer.parseInt(st.nextToken(" "));

            break;

          case '-':
            parseChars = "tT";
            rollInfo.modifier = -Integer.parseInt(st.nextToken(" "));

            break;

          case 't':
            parseChars = "T";
            rollInfo.totalFloor = Integer.parseInt(st.nextToken(" "));

            break;

          case 'T':
            parseChars = "t";
            rollInfo.totalCeiling = Integer.parseInt(st.nextToken(" "));

            break;

          default:
            Logging.errorPrint(
                "Bizarre dice parser error in '" + rollString + "': not a valid delimiter");
            return "Bad roll parsing in '"
                + rollString
                + "': invalid delimiter '"
                + tok.charAt(0)
                + "'.";
        }
      }
    } catch (NumberFormatException ex) {
      if (Logging.isDebugMode()) {
        Logging.debugPrint("Bad roll string in '" + rollString + "': " + ex, ex);
      }
      return "Bad roll string in '" + rollString + "': " + ex;
    }
    return "";
  }