Пример #1
0
  /**
   * This method finds the ordering of all the line segments that are removable from the current
   * board state in the current turn for each player.
   *
   * @param pieceMap
   * @param currentPlayerColor
   * @return An example output could be: {set: ["white", "segment from a to b"] ["white", "segment
   *     from b to c"] ["black", "segment from x to y"] ["black", "segment from z to a"; after that
   *     "white", "segment from a to b"] ["black", "segment from d to f"] }
   */
  private Set<List<Pair<PieceColor, Line.Segment>>> getRemovableLineOrderingsSetFromGipfBoard(
      Map<Position, Piece> pieceMap, PieceColor currentPlayerColor) {
    Set<List<Pair<PieceColor, Line.Segment>>> removableLineSetOrderingsFromGipfboard =
        new HashSet<>();
    PieceColor opponentColor = currentPlayerColor == WHITE ? BLACK : WHITE;

    Set<Line.Segment> removableLineSegmentsCurrentPlayer =
        getRemovableLineSegments(pieceMap, currentPlayerColor);

    // This loop checks for all line segments that can be removed by the current player.
    for (Line.Segment lineSegment : removableLineSegmentsCurrentPlayer) {
      // Create a copy of the piecemap where the removed segment is removed
      HashMap<Position, Piece> segmentRemovedPieceMap = new HashMap<>(pieceMap);
      segmentRemovedPieceMap
          .keySet()
          .removeAll(lineSegment.getOccupiedPositions(segmentRemovedPieceMap));

      List<Pair<PieceColor, Line.Segment>> removableLineSegmentOrdering =
          Collections.singletonList(new Pair<>(currentPlayerColor, lineSegment));

      // - I have to use removableLineSegmentList because the removableLineSegmentOrdering is
      // already in use.
      // - If the current player can remove at least 1 more segment, the board state that results
      // will be checked
      //   after that for more subsequent segments that can be removed
      Set<List<Pair<PieceColor, Line.Segment>>> removableLineSetOrderingsCurrentPlayer =
          getRemovableLineOrderingsSetFromGipfBoard(segmentRemovedPieceMap, currentPlayerColor);

      if (removableLineSetOrderingsCurrentPlayer.size() > 0) {
        for (List<Pair<PieceColor, Line.Segment>> removableLineSegmentList :
            removableLineSetOrderingsCurrentPlayer) {
          List<Pair<PieceColor, Line.Segment>> ordering =
              new ArrayList<>(removableLineSegmentOrdering);

          ordering.addAll(removableLineSegmentList);
          removableLineSetOrderingsFromGipfboard.add(ordering);
        }
      } else {
        removableLineSetOrderingsFromGipfboard.add(removableLineSegmentOrdering);
      }

      // Now check for the line segments removable by the opponent
      // Because if this code is ran, the current player can remove line segments. If this is the
      // case, the current player
      // must remove line segments before the opponent gets its turn.
      for (Line.Segment lineSegmenRemovableByOpponent :
          getRemovableLineSegments(segmentRemovedPieceMap, opponentColor)) {
        // See for the comments in the similar lines above
        HashMap<Position, Piece> opponentSegmentRemovedPieceMap =
            new HashMap<>(segmentRemovedPieceMap);
        opponentSegmentRemovedPieceMap
            .keySet()
            .removeAll(
                lineSegmenRemovableByOpponent.getOccupiedPositions(opponentSegmentRemovedPieceMap));

        List<Pair<PieceColor, Line.Segment>> opponentRemovableLineSegmentOrdering =
            Collections.singletonList(new Pair<>(opponentColor, lineSegmenRemovableByOpponent));

        Set<List<Pair<PieceColor, Line.Segment>>> removableLineSetOrderingsOpponent =
            getRemovableLineOrderingsSetFromGipfBoard(
                opponentSegmentRemovedPieceMap, opponentColor);

        if (removableLineSetOrderingsOpponent.size() > 0) {
          for (List<Pair<PieceColor, Line.Segment>> removableLineSegmentOpponentList :
              removableLineSetOrderingsOpponent) {
            List<Pair<PieceColor, Line.Segment>> ordering =
                new ArrayList<>(opponentRemovableLineSegmentOrdering);

            ordering.addAll(removableLineSegmentOpponentList);
            removableLineSetOrderingsFromGipfboard.add(ordering);
          }
        } else {
          removableLineSetOrderingsFromGipfboard.add(opponentRemovableLineSegmentOrdering);
        }
      }
    }
    if (removableLineSegmentsCurrentPlayer.size() == 0) {
      // The current player can't remove any line segments, so the opponent can try to remove line
      // segments
      for (Line.Segment lineSegment : getRemovableLineSegments(pieceMap, opponentColor)) {
        // See for the comments the similar lines above
        HashMap<Position, Piece> segmentRemovedPieceMap = new HashMap<>(pieceMap);
        segmentRemovedPieceMap
            .keySet()
            .removeAll(lineSegment.getOccupiedPositions(segmentRemovedPieceMap));

        List<Pair<PieceColor, Line.Segment>> removableLineSegmentOrdering =
            Collections.singletonList(new Pair<>(opponentColor, lineSegment));

        Set<List<Pair<PieceColor, Line.Segment>>> removableLineSetOrderingsOpponent =
            getRemovableLineOrderingsSetFromGipfBoard(segmentRemovedPieceMap, opponentColor);

        if (removableLineSetOrderingsOpponent.size() > 0) {
          for (List<Pair<PieceColor, Line.Segment>> removableLineSegmentList :
              removableLineSetOrderingsOpponent) {
            List<Pair<PieceColor, Line.Segment>> ordering =
                new ArrayList<>(removableLineSegmentOrdering);

            ordering.addAll(removableLineSegmentList);
            removableLineSetOrderingsFromGipfboard.add(ordering);
          }
        } else {
          removableLineSetOrderingsFromGipfboard.add(removableLineSegmentOrdering);
        }
      }
    }

    return removableLineSetOrderingsFromGipfboard;
  }
Пример #2
0
  public Set<Move> getAllowedMoves() {
    // If there is already a winn
    if (gipfBoardState.players.winner() != null) {
      return Collections.emptySet();
    }

    // Create a set of incomplete moves containing the starting positions and directions for the
    // current piece
    Set<Move> potentialMoves = getPotentialStartMoves(getCurrentPiece());

    // If the current piece is a GIPF piece, the player is also allowed to place normal pieces.
    if (getCurrentPiece().getPieceType() == GIPF)
      potentialMoves.addAll(
          getPotentialStartMoves(Piece.of(NORMAL, getCurrentPiece().getPieceColor())));

    // These moves are marked as complete so a temporary game won't ask for user input.
    potentialMoves.stream().forEach(m -> m.isCompleteMove = true);

    Set<Move> potentialMovesIncludingLineSegmentRemoval = new HashSet<>();
    for (Move potentialMove : potentialMoves) {
      try {
        Map<Position, Piece> temporaryPieceMap = new HashMap<>(getGipfBoardState().getPieceMap());
        temporaryPieceMap.put(potentialMove.startPos, potentialMove.addedPiece);
        movePiecesTowards(
            temporaryPieceMap, potentialMove.getStartingPosition(), potentialMove.getDirection());

        Set<List<Pair<PieceColor, Line.Segment>>> RLineOrderingsSet =
            getRemovableLineOrderingsSetFromGipfBoard(
                temporaryPieceMap, getCurrentPiece().getPieceColor());
        if (RLineOrderingsSet.size() > 0) {
          for (List<Pair<PieceColor, Line.Segment>> RLineOrdering : RLineOrderingsSet) {
            Set<Position> piecesToWhite = new HashSet<>();
            Set<Position> piecesToBlack = new HashSet<>();
            Set<Position> piecesRemoved = new HashSet<>();

            for (Pair<PieceColor, Line.Segment> RLine : RLineOrdering) {
              Line.Segment removedSegment = RLine.getValue();

              // The color of the player who removed the line
              PieceColor colorRemoved = RLine.getKey();

              // Determine per segment to whom the pieces are given. Pieces can only be given to the
              // player
              // who removed the line, or deleted from the game.
              Set<Position> occupiedPositions =
                  removedSegment.getOccupiedPositions(temporaryPieceMap);
              Set<Position> piecesFromSegmentBackToReserve =
                  occupiedPositions
                      .stream()
                      .filter(
                          position ->
                              temporaryPieceMap.get(position).getPieceColor() == colorRemoved)
                      .collect(toSet());
              Set<Position> piecesFromSegmentRemoved =
                  occupiedPositions
                      .stream()
                      .filter(position -> !piecesFromSegmentBackToReserve.contains(position))
                      .collect(toSet());

              if (colorRemoved == WHITE) piecesToWhite.addAll(piecesFromSegmentBackToReserve);
              if (colorRemoved == BLACK) piecesToBlack.addAll(piecesFromSegmentBackToReserve);
              piecesRemoved.addAll(piecesFromSegmentRemoved);
            }

            // And finally add the move
            // the constructor will define this as a complete move, because all the parameters have
            // a value.
            potentialMovesIncludingLineSegmentRemoval.add(
                new Move(
                    potentialMove.addedPiece,
                    potentialMove.startPos,
                    potentialMove.direction,
                    piecesToWhite,
                    piecesToBlack,
                    piecesRemoved));
          }
        } else {
          // If no line segments can be removed, just add the original move
          potentialMovesIncludingLineSegmentRemoval.add(potentialMove);
        }
      } catch (InvalidMoveException e) {
        // We don't consider this move if it is invalid
      }
    }

    return potentialMovesIncludingLineSegmentRemoval;
  }