package net.sf.colossus.gui; import java.awt.Color; import java.awt.Container; import java.awt.Dimension; import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JPanel; import javax.swing.WindowConstants; import net.sf.colossus.common.Constants; import net.sf.colossus.game.Legion; import net.sf.colossus.game.Proposal; import net.sf.colossus.guiutil.KDialog; import net.sf.colossus.guiutil.SaveWindow; /** * Negotiate allows making a new proposal to settle an engagement. * * @author David Ripton */ final class Negotiate extends KDialog { private final Legion attacker; private final Legion defender; private final List<Chit> attackerChits = new ArrayList<Chit>(); private final List<Chit> defenderChits = new ArrayList<Chit>(); private final ClientGUI gui; private Proposal proposal; private Point location; private final SaveWindow saveWindow; private final Marker attackerMarker; private final Marker defenderMarker; Negotiate(ClientGUI gui, Legion attacker, Legion defender) { super(gui.getBoard().getFrame(), gui.getOwningPlayer().getName() + ": " + attacker + " Negotiates with " + defender, false); this.gui = gui; this.attacker = attacker; this.defender = defender; Container contentPane = getContentPane(); contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS)); setBackground(Color.lightGray); // Don't allow closing without explicit decision: setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); attackerMarker = showLegion(attacker, attackerChits); attackerMarker.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { toggleAllDead(attackerChits); } }); defenderMarker = showLegion(defender, defenderChits); defenderMarker.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { toggleAllDead(defenderChits); } }); JButton button1 = new JButton("Offer"); button1.setMnemonic(KeyEvent.VK_O); JButton button2 = new JButton("Fight"); button2.setMnemonic(KeyEvent.VK_F); JPanel buttonPane = new JPanel(); contentPane.add(buttonPane); buttonPane.add(button1); button1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { doOffer(); } }); buttonPane.add(button2); button2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { doFight(); } }); pack(); saveWindow = new SaveWindow(gui.getOptions(), "Negotiate"); location = saveWindow.loadLocation(); if (location == null) { centerOnScreen(); location = getLocation(); } else { setLocation(location); } setVisible(true); repaint(); } private Marker showLegion(Legion legion, List<Chit> chits) { Box pane = new Box(BoxLayout.X_AXIS); pane.setAlignmentX(0); getContentPane().add(pane); int scale = 4 * Scale.get(); Marker marker = new Marker(legion, scale, legion.getLongMarkerId(), gui.getClient(), true); pane.add(marker); pane.add(Box.createRigidArea(new Dimension(scale / 4, 0))); List<String> imageNames = ((gui.getOracle()) .getLegionImageNames(legion)); Iterator<String> it = imageNames.iterator(); while (it.hasNext()) { String imageName = it.next(); final Chit chit = Chit.newCreatureChit(scale, imageName); chit.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { chit.toggleDead(); chit.repaint(); } }); chits.add(chit); pane.add(chit); } return marker; } void cleanup() { location = getLocation(); saveWindow.saveLocation(location); dispose(); gui.negotiateCallback(proposal, true); } /* * If not all are dead yet, mark all as dead; * but if all are dead, unmark all */ private void toggleAllDead(List<Chit> chits) { boolean allDead = true; for (Chit c : chits) { if (!c.isDead()) { allDead = false; } } for (Chit c : chits) { c.setDead(!allDead); } } private void doOffer() { // Count remaining chits. boolean attackersLeft = false; Iterator<Chit> it = attackerChits.iterator(); while (it.hasNext()) { Chit chit = it.next(); if (!chit.isDead()) { attackersLeft = true; break; } } boolean defendersLeft = false; it = defenderChits.iterator(); while (it.hasNext()) { Chit chit = it.next(); if (!chit.isDead()) { defendersLeft = true; break; } } // Ensure that at least one legion is completely eliminated. if (attackersLeft && defendersLeft) { gui.showMessageDialogAndWait("At least one legion must" + " be eliminated."); return; } if (!attackersLeft && !defendersLeft) { // Mutual destruction. proposal = new Proposal(attacker, defender, false, true, null, null); } else { Legion winnerLegion; List<Chit> winnerChits; if (!defendersLeft) { winnerLegion = attacker; winnerChits = attackerChits; } else { winnerLegion = defender; winnerChits = defenderChits; } // Ensure that the winning legion doesn't contain a dead // Titan. it = winnerChits.iterator(); while (it.hasNext()) { Chit chit = it.next(); if (chit.isDead() && chit.getId().startsWith(Constants.titan)) { gui.showMessageDialogAndWait("Titan cannot die unless his" + " whole stack dies."); return; } } // Remove all dead creatures from the winning legion. List<String> winnerLosses = new ArrayList<String>(); it = winnerChits.iterator(); while (it.hasNext()) { Chit chit = it.next(); if (chit.isDead()) { String name = chit.getId(); if (name.startsWith(Constants.titan)) { name = Constants.titan; } winnerLosses.add(name); } } proposal = new Proposal(attacker, defender, false, false, winnerLegion, winnerLosses); } // Exit this dialog. cleanup(); } private void doFight() { proposal = new Proposal(attacker, defender, true, false, null, null); // Exit this dialog. cleanup(); } }