예제 #1
0
  /**
   * Parse a single line order.
   *
   * <p>Null arguments are not permitted, except for phaseType. If phaseType is
   * Phase.PhaseType.RETREAT, "Move" format orders will be made into Retreat orders, and convoyed
   * moves will be disallowed.
   */
  public NJudgeOrder parse(
      final dip.world.Map map,
      final OrderFactory orderFactory,
      final Phase.PhaseType phaseType,
      final String line)
      throws OrderException {
    // create order parsing context
    final ParseContext pc = new ParseContext(map, orderFactory, phaseType, line);

    // parse results. This also removes the trailing '.' from the order
    final ArrayList resultList = new ArrayList(5);
    final String newOrderLine = removeTrailingDot(parseResults(pc, resultList));

    if (Phase.PhaseType.ADJUSTMENT.equals(phaseType)) {
      return parseAdjustmentOrder(pc, newOrderLine);
    } else {
      // tokenize order
      final String[] tokens = tokenize(newOrderLine);

      // parse order prefix
      OrderPrefix prefix = new OrderPrefix(pc, tokens);

      // parse predicate
      Orderable order = parsePredicate(pc, prefix, tokens);

      // parse text results into real results
      List results = createResults(pc, order, resultList);

      // create NJudgeOrder
      return new NJudgeOrder(order, results, pc.isAdjustmentPhase());
    }
  } // parse()
예제 #2
0
  private Orderable parseMove(ParseContext pc, OrderPrefix op, final String[] tokens)
      throws OrderException {
    /*

    	3-StP: Army St Petersburg -> Moscow.  (*bounce*)

    	1-Smy: Army Constantinople -> Aegean Sea -> Greece.


    	keep parsing Locations until END or a -> is reached.
    	so we keep looking for a -> until no more are found.

    	if we have more than one, we'll add them to a list
    	and then add that to the order Move order.
    */

    LinkedList pathList = new LinkedList();
    int idx = op.tokenIndex;
    int movTokIdx = findNextMoveToken(idx, tokens);

    while (movTokIdx != -1) {
      Location loc = parseLocation(pc, idx, movTokIdx, tokens);
      pathList.addLast(loc.getProvince());

      idx = movTokIdx + 1;
      movTokIdx = findNextMoveToken(idx, tokens);
    }

    // add last location
    final Location loc = parseLocation(pc, idx, tokens.length, tokens);
    pathList.addLast(loc.getProvince());

    // create Move order
    if (pathList.size() == 1) {
      if (pc.isRetreatPhase()) {
        return pc.orderFactory.createRetreat(op.power, op.location, op.unit, loc);
      } else {
        return pc.orderFactory.createMove(op.power, op.location, op.unit, loc);
      }
    } else if (pathList.size() > 1) {
      if (pc.isRetreatPhase()) {
        throw new OrderException("Convoyed Retreat orders are not allowed. Order: " + pc.orderText);
      }

      // add source location at beginning of move list
      pathList.addFirst(op.location.getProvince());

      final Province[] route = (Province[]) pathList.toArray(new Province[pathList.size()]);

      return pc.orderFactory.createMove(op.power, op.location, op.unit, loc, route);
    } else {
      // this probably will not occur....
      throw new OrderException("Invalid movement path in Move order: " + pc.orderText);
    }
  } // parseMove()
예제 #3
0
  private NJudgeOrder parseAdjustmentOrder(ParseContext pc, String line) throws OrderException {
    Matcher m = ADJUSTMENT_PATTERN.matcher(line);

    // attempt
    if (m.find()) {
      /*
      	Groups:
      		1: Power
      		2: remove|build|default	(default is also a remove!)
      		3: fleet|army|wing
      		4: location

      */

      // parse power
      final Power power = parsePower(pc, m.group(1).trim());

      // parse unit type
      final Unit.Type unit = parseUnitType(pc, m.group(3));

      // parse location
      final Location location = parseLocation(pc, m.group(4).trim());

      // parse action
      final boolean isDefault = ("default".equalsIgnoreCase(m.group(2)));

      Orderable order = null;
      if ("build".equalsIgnoreCase(m.group(2))) {
        order = pc.orderFactory.createBuild(power, location, unit);
      } else {
        // remove or default
        order = pc.orderFactory.createRemove(power, location, unit);
      }

      NJudgeOrder njo = null;

      if (isDefault) {
        // power defaulted; order is contained in a substitutedResult
        SubstitutedResult substResult =
            new SubstitutedResult(null, order, "Power defaulted; unit removed.");

        njo = new NJudgeOrder(null, substResult, pc.isAdjustmentPhase());
      } else {
        njo =
            new NJudgeOrder(
                order,
                new OrderResult(order, OrderResult.ResultType.SUCCESS, null),
                pc.isAdjustmentPhase());
      }

      assert (njo != null);
      return njo;
    } else {
      // reuse variable 'm'
      m = ALTERNATE_ADJUSTMENT_PATTERN.matcher(line);
      if (m.find()) {
        // parse power
        final Power power = parsePower(pc, m.group(1).trim());

        // parse # (may be empty)
        // (if it is empty, set to 0)
        int numBuilds = 0;
        try {
          if (m.group(2).length() >= 1) {
            numBuilds = Integer.parseInt(m.group(2));
          }
        } catch (NumberFormatException e) {
          throw new OrderException(
              "Expected valid integer at \"" + m.group(2) + "\" for order: " + pc.orderText);
        }

        // parse if unused/unusable
        boolean isUnusable = false;
        final String group3Tok = m.group(3);
        if ("unused".equalsIgnoreCase(group3Tok) || "unusable".equalsIgnoreCase(group3Tok)) {
          isUnusable = true;
        }

        // parse if pending/waived
        final boolean isPending = "pending".equalsIgnoreCase(m.group(5));
        final boolean isWaived = "waived".equalsIgnoreCase(m.group(5));

        if (m.group(3) == null) {
          // Group3 is null when it is a 'regular' waive order.
          Result result = new Result(power, "Build waived.");
          return new NJudgeOrder(power, result);
        } else {
          // since we depend on external input, these should
          // be exceptions rather than asserts
          //
          assert (isUnusable);
          if (!isUnusable) {
            throw new IllegalStateException();
          }

          assert (isPending != isWaived);
          if (isPending == isWaived) {
            throw new IllegalStateException();
          }

          if (isPending) {
            // pending builds
            Result result =
                new Result(power, String.valueOf(numBuilds) + " unusable build(s) pending.");
            return new NJudgeOrder(power, numBuilds, 0, result);
          } else {
            // waived builds
            Result result =
                new Result(power, String.valueOf(numBuilds) + " unusable build(s) waived.");
            return new NJudgeOrder(power, 0, numBuilds, result);
          }
        }
      } else {
        throw new OrderException("Cannot parse adjustment order: " + pc.orderText);
      }
    }
  } // parseAdjustmentOrder()