// Game of Fanorona // David Eppstein, UC Irvine, 11 Jun 1997 // // UI for changing game parameters import java.awt.*; import java.util.*; import gui.*; class Options extends FlatPanel { // checkbox groups public static final int BOARD_ORIENTATION = 0; public static final int WHO_GOES_FIRST = 1; public static final int WHO_IS_WHITE = 2; public static final int WHO_IS_BLACK = 3; public static final int HOW_FAST = 4; public static final int MULTIPLE_CAPTURES = 5; public static final int NOTATION_TYPE = 6; public static final int NOTATION_LENGTH = 7; public static final int NUMBER_OF_GROUPS = 8; static CheckboxGroup groups[] = null; // checkbox parameters public static final int BLACK_AT_TOP = 0; public static final int WHITE_AT_TOP = 1; public static final int BLACK_GOES_FIRST = 2; public static final int WHITE_GOES_FIRST = 3; public static final int HUMAN_PLAYS_BLACK = 4; public static final int COMPUTER_PLAYS_BLACK = 5; public static final int HUMAN_PLAYS_WHITE = 6; public static final int COMPUTER_PLAYS_WHITE = 7; public static final int FAST_SPEED = 8; public static final int MEDIUM_SPEED = 9; public static final int SLOW_SPEED = 10; public static final int NO_MULTIPLE_CAPTURES = 11; public static final int MULTIPLE_CAPTURES_OK = 12; public static final int NOTATION_ALGEBRAIC = 13; public static final int NOTATION_NUMERIC = 14; public static final int NOTATION_LONG = 15; public static final int NOTATION_SHORT = 16; public static final int ONE_PLY = 17; public static final int TWO_PLY = 18; public static final int THREE_PLY = 19; public static final int NUMBER_OF_PARAMS = 20; static Option gameOptions[] = { new Option("Human plays the black pieces", HUMAN_PLAYS_BLACK, false, WHO_IS_BLACK), new Option("Computer plays the black pieces", COMPUTER_PLAYS_BLACK, true, WHO_IS_BLACK), new Option("Human plays the white pieces", HUMAN_PLAYS_WHITE, true, WHO_IS_WHITE), new Option("Computer plays the white pieces", COMPUTER_PLAYS_WHITE, false, WHO_IS_WHITE), new Option("Black's pieces start at top of board", BLACK_AT_TOP, true, BOARD_ORIENTATION), new Option("White's pieces start at top of board", WHITE_AT_TOP, false, BOARD_ORIENTATION), new Option("Black makes the first move", BLACK_GOES_FIRST, false, WHO_GOES_FIRST), new Option("White makes the first move", WHITE_GOES_FIRST, true, WHO_GOES_FIRST), new Option("Algebraic notation", NOTATION_ALGEBRAIC, true, NOTATION_TYPE), new Option("Numeric notation", NOTATION_NUMERIC, false, NOTATION_TYPE), new Option("Short move log format", NOTATION_SHORT, true, NOTATION_LENGTH), new Option("Long move log format", NOTATION_LONG, false, NOTATION_LENGTH), new Option("No multiple captures on first move", NO_MULTIPLE_CAPTURES, true, MULTIPLE_CAPTURES), new Option("Multiple captures on first move ok", MULTIPLE_CAPTURES_OK, false, MULTIPLE_CAPTURES), }; static Option levelOptions[] = { new Option("One-ply fixed depth search", ONE_PLY, true, HOW_FAST), new Option("Two-ply fixed depth search", TWO_PLY, false, HOW_FAST), new Option("Three-ply fixed depth search", THREE_PLY, false, HOW_FAST), new Option("1/4 to 1 1/2 seconds/move", FAST_SPEED, false, HOW_FAST), new Option("1 1/2 to 10 seconds/move", MEDIUM_SPEED, false, HOW_FAST), new Option("10 to 60 seconds/move", SLOW_SPEED, false, HOW_FAST), }; // code to add matching pairs of left and right panels transient Panel left = null; transient Panel right = null; void switchSides() { if (right != null) finishPanels(); Panel p = new FlatPanel(); p.setLayout(new StackLayout(StackLayout.VERTICAL)); if (left == null) left = p; else right = p; } Panel finishedPanel() { Panel p = new FlatPanel(); p.setLayout(new StackLayout(StackLayout.HORIZONTAL)); if (right != null) { p.add("Wide", left); p.add("Wide", right); } else p.add("Center", left); left = right = null; return p; } void finishPanels() { if (left == null) return; add("Wide", finishedPanel()); } void addComponent(String s, Component c) { if (right != null) right.add(s, c); else { if (left == null) switchSides(); left.add(s, c); } } void addOptions(Option optArray[], Container c, Game g, Color bg) { } // main inialization of options panel Game game; Option options[]; Options(Game g, Color bg, Color but, Option opts[]) { game = g; options = opts; setBackground(bg); setLayout(new StackLayout(StackLayout.VERTICAL)); if (groups == null) { game.setParameters(new BitSet(NUMBER_OF_PARAMS)); groups = new CheckboxGroup[NUMBER_OF_GROUPS]; for (int i = 0; i < groups.length; i++) { groups[i] = new CheckboxGroup(); } } // place all options in two-column layout, arranged by CheckboxGroup for (int i = 0; i < options.length; i++) { options[i].setCheckboxGroup(groups[options[i].group_index]); options[i].setGame(g); options[i].setBackground(bg); addComponent("Left", options[i]); if (i < options.length - 1 && options[i].group_index != options[i+1].group_index) switchSides(); } finishPanels(); // synchronize left/right // buttons switchSides(); // make new left panel for cancel new OptionCancel(game,this).colorize(but, Color.black, Color.gray, left); switchSides(); // make new right panel for ok new OptionOK(game,this).colorize(but, Color.black, Color.gray, right); finishPanels(); // finish up setAllOptions(); resetAllOptions(); // make checkbox groups synchronize up } void setAllOptions() { for (int i = 0; i < options.length; i++) options[i].set(); if (game.getBoard().previousPosition == null) game.resetBoard(); else game.updateParameters(); } void resetAllOptions() { for (int i = 0; i < options.length; i++) options[i].reset(); game.updateParameters(); // game's params havent changed but button activity may have } boolean dirty() { for (int i = 0; i < options.length; i++) if (options[i].dirty()) return true; return false; } // explain the need to use the buttons public void sayOk() { Fanorona.showMessage(this, "Confirm option changes by pressing OK button", false); } public boolean mouseEnter(Event e, int x, int y) { if (!dirty() || !isShowing()) return false; sayOk(); return true; } // called when a checkbox is changed. make buttons test active. public boolean action(Event e, Object what) { game.updateParameters(); if (dirty()) sayOk(); return true; } } class OptionCancel extends GameButton { Options options; public OptionCancel(Game g, Options o) { super(g, "Cancel"); options = o; } public boolean active() { if (options == null) return false; return options.dirty(); } public void action() { options.resetAllOptions(); Fanorona.showMessage(this, "Option changes cancelled", false); } public String status() { return "Cancel option changes"; } } class OptionOK extends GameButton { Options options; public OptionOK(Game g, Options o) { super(g, "OK"); options = o; } public boolean active() { if (options == null) return false; return options.dirty(); } public void action() { options.setAllOptions(); Fanorona.showMessage(this, "Options changed", false); } public String status() { return "Confirm option changes"; } } class Option extends Checkbox { int index, group_index; Game game; void setGame(Game g) { game = g; } Game getGame() { return game; } Option(String t, int i, boolean b, int gi) { super(t, null, b); game = null; index = i; group_index = gi; } void set() { if (game == null) return; if (getState()) game.getParameters().set(index); else game.getParameters().clear(index); } void reset() { if (game != null) setState(game.getParameters().get(index)); } boolean dirty() { return (game != null && getState() != game.getParameters().get(index)); } }