Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
Hiraoka committed Nov 13, 2021
2 parents 0c2eaab + 2b53a98 commit 5609316
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 0 deletions.
16 changes: 16 additions & 0 deletions src/main/java/featurecat/lizzie/gui/Menu.java
Original file line number Diff line number Diff line change
Expand Up @@ -1187,6 +1187,22 @@ public void actionPerformed(ActionEvent e) {
});
gameMenu.add(pass);

final JMenuItem continueLadder =
new JMenuItem(resourceBundle.getString("Menu.game.continueLadder"));
continueLadder.addActionListener(
new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (Lizzie.board.continueLadder() == 0)
JOptionPane.showMessageDialog(
Lizzie.frame,
String.format(
resourceBundle.getString("Menu.game.continueLadderFail"),
Lizzie.board.MINIMUM_LADDER_LENGTH_FOR_AUTO_CONTINUATION));
}
});
gameMenu.add(continueLadder);

gameMenu.addSeparator();

final JMenuItem editComment = new JMenuItem("Edit comment");
Expand Down
45 changes: 45 additions & 0 deletions src/main/java/featurecat/lizzie/rules/Board.java
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,47 @@ public void place(String namedCoordinate) {
}
}

// at least 5. increase this to avoid wrong detection of ladders
public final int MINIMUM_LADDER_LENGTH_FOR_AUTO_CONTINUATION = 5;

public int continueLadder() {
int k;
// Repeating continueLadderByOne() is inefficient. So what? :p
for (k = 0; continueLadderByOne(); k++) ;
Lizzie.frame.refresh();
return k;
}

private boolean continueLadderByOne() {
final int PERIOD = 4, CHECK_LENGTH = MINIMUM_LADDER_LENGTH_FOR_AUTO_CONTINUATION;
BoardHistoryList copiedHistory = history.shallowCopy();
int[][] pastMove = new int[CHECK_LENGTH][];
int dx = 0, dy = 0;
for (int k = 0; k < CHECK_LENGTH; k++) {
Optional<int[]> lastMoveOpt = copiedHistory.getLastMove();
if (!lastMoveOpt.isPresent()) return false;
int[] move = pastMove[k] = lastMoveOpt.get();
copiedHistory.previous();
if (k < PERIOD) continue;
// check repeated pattern
int[] periodMove = pastMove[k - PERIOD];
int deltaX = periodMove[0] - move[0], deltaY = periodMove[1] - move[1];
if (k == PERIOD) { // first periodical move
dx = deltaX;
dy = deltaY;
}
boolean isRepeated = (deltaX == dx && deltaY == dy);
boolean isDiagonal = (Math.abs(deltaX) == 1 && Math.abs(deltaY) == 1);
if (!isRepeated || !isDiagonal) return false;
}
int[] myPeriodMove = pastMove[PERIOD - 1];
int x = myPeriodMove[0] + dx, y = myPeriodMove[1] + dy;
boolean continued = isValidEmpty(x, y) && isValidEmpty(x + dx, y) && isValidEmpty(x, y + dy);
if (!continued) return false;
place(x, y);
return true;
}

/** for handicap */
public void flatten() {
Stone[] stones = history.getStones();
Expand Down Expand Up @@ -1675,6 +1716,10 @@ public boolean isCoordsEmpty(int x, int y) {
return true;
}

private boolean isValidEmpty(int x, int y) {
return isValid(x, y) && isCoordsEmpty(x, y);
}

public boolean setAsMainBranch() {
if (history.getCurrentHistoryNode().isMainTrunk()) return false;
BoardHistoryNode topNode = history.getCurrentHistoryNode().topOfFatherBranch();
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/l10n/DisplayStrings.properties
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,8 @@ Menu.game.continueGameWhite=Continue(Play white)
Menu.game.breakGame=Interrupt game(Space)
Menu.game.setInfo=Set gameInfo(I)
Menu.game.bestOne=Play best move(,)
Menu.game.continueLadder=Continue ladder
Menu.game.continueLadderFail=Play at least %d ladder moves successively before auto-continuation.
Menu.game.pass=Play pass(P)
Menu.game.clearBoard=Clear board(Ctrl+Home)
Menu.game.backToMain=Back to mainTrunk
Expand Down

0 comments on commit 5609316

Please sign in to comment.