Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auto-continuation of ladders #904

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions src/main/java/featurecat/lizzie/gui/Menu.java
Original file line number Diff line number Diff line change
Expand Up @@ -1162,6 +1162,23 @@ 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 clearBoard = new JMenuItem(resourceBundle.getString("Menu.game.clearBoard"));
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 @@ -614,6 +614,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 @@ -1642,6 +1683,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