/******************************************************************************
 ** $Id: Absprache.java 848 2016-01-02 13:42:30Z wmh $
 ** Diese Datei ist Bestandteil der Java-Quelltexte des Würfelspiels JaFuffy.
 ** Lauffähig ab Java 6.
 ******************************************************************************
 ** Copyright (C) Wolfgang Hauck <wolfgang.hauck@3kelvin.de>
 ******************************************************************************
 ** This program is free software: you can redistribute it and/or modify
 ** it under the terms of the GNU General Public License as published by
 ** the Free Software Foundation, either version 3 of the License, or
 ** (at your option) any later version.
 **
 ** This program is distributed in the hope that it will be useful,
 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 ** GNU General Public License for more details.
 **
 ** You should have received a copy of the GNU General Public License
 ** along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************
 ** Die aktuellste Version von JaFuffy findet sich im Internet unter
 ** <http://jafuffy.3kelvin.de>.
 **
 ** Kommentare, Fehler oder Erweiterungswünsche bitte per E-Mail senden an
 ** <jafuffy@3kelvin.de>.
 ******************************************************************************/
package jafuffy.bedienung;

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Hashtable;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRootPane;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

import jafuffy.Eigenschaften;
import jafuffy.logik.Beginner;
import jafuffy.logik.Bot;
import jafuffy.logik.Manager;
import jafuffy.logik.Spieler;
import jafuffy.logik.Turnier;
import jafuffy.logik.Variante;

/**
 * Dialog zum Spielbeginn, Absprache der Spielbedingungen. Eingabe der Spielernamen, der Spielvariante und der Anzahl
 * der Spiele (optional). Start des Turniers.
 */
@SuppressWarnings("serial")
public class Absprache extends JDialog implements PropertyChangeListener {

    /** Ermöglicht Aktivierung und Deaktivierung eines Bots. */
    static class Botselektion extends JCheckBox implements ActionListener {

        /** Schriftfarbe, falls Bot inaktiv ist. */
        private static final Color BOT_INAKTIV_FARBE = Color.GRAY;
        /** Schriftfarbe, falls Bot aktiv ist. */
        private static final Color BOT_AKTIV_FARBE = Color.ORANGE.darker();

        /** Benötigt, weil Bot nicht für alle Varianten zur Verfügung steht. */
        private final JComboBox<Variante> variantenauswahl;

        /**
         * Konstruiert das Auswahlfeld, welches den Bot aktivieren oder deaktivieren kann.
         *
         * @param kuenstlich
         *            Gibt an, ob ein Bot anfänglich aktiv ist.
         * @param nominierung
         *            Zugehöriges Nominierungsfeld.
         * @param variantenauswahl
         *            Variantenauswahl, welche die Verfügbarkeit des Bots beeinflusst.
         */
        Botselektion(boolean kuenstlich, Nominierung nominierung, JComboBox<Variante> variantenauswahl) {
            super("Bot");
            this.variantenauswahl = variantenauswahl;
            addActionListener(nominierung);
            setIcon(BOT_RUHT);
            setRolloverIcon(BOT_AKTIV);
            setSelectedIcon(BOT_AKTIV);
            setSelected(kuenstlich);
            setToolTipText("<html>" + "<p>Wenn angewählt, übernimmt <i>JaFuffy</i> die Rolle des Spielers.</p>"
                    + "<p><small>Bot steht bei erweiterten Regeln nicht zur Verfügung.</small></p>" + "</html>");
            addActionListener(this);
            aktualisiere();
        }

        @Override
        public void actionPerformed(ActionEvent event) {
            aktualisiere();
        }

        /** Aktualisiert die Schriftfarbe. */
        private void aktualisiere() {
            boolean botfaehig = variantenauswahl.getSelectedItem() != Variante.ERWEITERT;
            setEnabled(botfaehig);
            if (botfaehig) {
                if (isSelected()) {
                    setForeground(BOT_AKTIV_FARBE);
                } else {
                    setForeground(BOT_INAKTIV_FARBE);
                }
            } else {
                setSelected(false);
                setForeground(Color.LIGHT_GRAY);
            }
        }

    }

    /** Festlegung auf künstliche Intelligenz oder menschlichen Spieler mit Nameneingabe. */
    static class Nominierung extends JPanel implements ActionListener, DocumentListener {

        /** Karte für menschlichen Spieler. */
        private static final String MENSCH = "Mensch";
        /** Karte für künstliche Intelligenz. */
        private static final String BOT = "Bot";

        /** Benötigt zur Aktualisierung des Absprachedialogs aufgrund von Namenseingaben. */
        private final Absprache absprache;
        /** Nameneingabe für menschlichen Spieler. */
        private final JTextField spielernameneingabe = new JTextField(SPALTEN);
        /** Name der künstlichen Intelligenz. */
        private final JTextField botnamenanzeige = new JTextField();
        /** Gibt an, ob die künstliche Intelligenz die Rolle als Spieler übernehmen soll. */
        private boolean kuenstlich;

        /**
         * Konstruiert ein Eingabefeld für die Nameneingabe oder Namenanzeige.
         *
         * @param name
         *            Der Name des Spielers aus den gespeicherten Einstellungen.
         * @param kuenstlich
         *            Gibt an, ob aus den gespeicherten Einstellungen ein Bot aktiv ist.
         * @param absprache
         *            Der Dialog, dessen Aussehen an dieses Objekt angepasst werden muss.
         */
        Nominierung(String name, boolean kuenstlich, Absprache absprache) {
            super(new CardLayout());
            this.absprache = absprache;
            this.kuenstlich = kuenstlich;
            add(spielernameneingabe, MENSCH);
            add(botnamenanzeige, BOT);
            initialisiere(name, kuenstlich);
        }

        /** Bearbeitet die Entscheidung zur künstlichen Intelligenz. */
        @Override
        public void actionPerformed(ActionEvent event) {
            String kommando = event.getActionCommand();
            if (kommando.equals("Bot")) {
                JCheckBox entscheidung = (JCheckBox) event.getSource();
                CardLayout layout = (CardLayout) getLayout();
                kuenstlich = entscheidung.isSelected();
                if (kuenstlich) {
                    layout.show(this, BOT);
                } else {
                    layout.show(this, MENSCH);
                }
                absprache.aktualisiere();
            } else if (kommando.equals("Var")) {
                @SuppressWarnings("unchecked")
                JComboBox<Variante> variantenauswahl = (JComboBox<Variante>) event.getSource();
                boolean botfaehig = variantenauswahl.getSelectedItem() != Variante.ERWEITERT;
                if (!botfaehig) {
                    kuenstlich = false;
                    CardLayout layout = (CardLayout) getLayout();
                    layout.show(this, MENSCH);
                }
            }
        }

        @Override
        public void changedUpdate(DocumentEvent event) {
            absprache.aktualisiere();
        }

        @Override
        public void insertUpdate(DocumentEvent event) {
            absprache.aktualisiere();
        }

        @Override
        public void removeUpdate(DocumentEvent event) {
            absprache.aktualisiere();
        }

        /**
         * Setzt die Namensbelegung des menschlichen Spielers und Bot-Verwendung.
         *
         * @param name
         *            Name des menschlichen Spielers, aus den Eigenschaften übernommen.
         * @param kuenstlich
         *            Gibt an, ob ein Bot als Vorbelegung die Rolle des Spielers übernehmen soll.
         */
        private void initialisiere(String name, boolean kuenstlich) {
            CardLayout layout = (CardLayout) getLayout();
            if (kuenstlich) {
                layout.show(this, BOT);
            } else {
                layout.show(this, MENSCH);
            }
            spielernameneingabe.setText(name);
            spielernameneingabe.getDocument().addDocumentListener(this);
            botnamenanzeige.setEditable(false);
            botnamenanzeige.setEnabled(false);
        }

        /** @return Gibt an, ob künstliche intelligenz Rolle des Spielers übernehmen soll. */
        boolean kuenstlich() {
            return kuenstlich;
        }

        /** @return Name des Spielers (künstlich oder menschlich). */
        String name() {
            String name = kuenstlich ? botnamenanzeige.getText() : spielernameneingabe.getText();
            return name.trim();
        }

        /**
         * Setzt den Namen des Bots.
         *
         * @param name
         *            Name.
         */
        void name(String name) {
            botnamenanzeige.setText(name);
        }

        /** Trimme die Eingabetext. */
        void trimme() {
            String name = spielernameneingabe.getText();
            spielernameneingabe.setText(name.trim());
        }
    }

    /** Namen für die Spieler, die von der künstlichen Intelligenz betrieben werden. */
    private static final String[] BOTNAMEN = { "Annabot", "Bennobot", "Clarabot", "Dragobot" };
    /** Auswahlicon für aktive Bots. */
    private static final ImageIcon BOT_AKTIV = Grafik.icon("Aktivbot.png");
    /** Auswahlicon für ruhenden Bot. */
    private static final ImageIcon BOT_RUHT = Grafik.icon("Ruhebot.png");
    /** Maximale Anzahl der Spiele pro Turnier. */
    private static final int ANZAHL = 20;
    /** Abstand vom Feldrahmen zum Inhalt. */
    private static final int FELDRAHMENABSTAND = 4;
    /** Abstand Feldrahmen zu Buttons. */
    private static final int BUTTONABSTAND = 2 * FELDRAHMENABSTAND;
    /** Abstand vom Dialograhmen zum Inhalt. */
    private static final int DIALOGRAHMENABSTAND = 4;
    /** Abstand der Feinticks (Spielanzahlauswahl). */
    private static final int FEINTICKS = 1;
    /** Abstand der Orientierungsticks (Spielanzahlauswahl). */
    private static final int ORIENTIERUNGSTICKS = 5;
    /** Anzahl der Spalten im Texteingabefeld. */
    private static final int SPALTEN = 8;
    /** Anzahl der Tick-Labels (Spielanzahlauswahl). */
    private static final int TICKLABELS = 5;

    /** Abbruch-Button. */
    private final JButton abbruch = new JButton("Abbruch");
    /** Einstellung der Spieleanzahl pro Turnier per Schieberegler. */
    private final JSlider anzahlschieberegler = new JSlider(0, ANZAHL);
    /** Beginnmodusauswahl. */
    private final JComboBox<Beginner> beginnmodusauswahl = new JComboBox<Beginner>(Beginner.values());
    /** Programm- und Turniereigenschaften. */
    private final Eigenschaften eigenschaften;
    /** Der Manager, welcher das aus der Absprache entstandene Turnier betreut. */
    private final Manager manager;
    /** OK-Button. */
    private final JButton ok = new JButton("OK");
    /** Regelvariantenauswahl. */
    private final JComboBox<Variante> variantenauswahl = new JComboBox<Variante>(Variante.values());
    /** Nominierungen der Mitspieler, sowohl menschliche Spieler und künstliche Intelligenzen. */
    private final Nominierung[] nominierungen = new Nominierung[Spieler.SPIELER];
    /** Auswahlboxen für künstliche Intelligenzen. */
    private final Botselektion[] botselektionen = new Botselektion[Spieler.SPIELER];

    /**
     * Konstruktor.
     *
     * @param eigenschaften
     *            Programm- und Turniereigenschaften.
     * @param manager
     *            Der betreuende Manager, welcher sich um Turnier kümmert, welche aus der Absprache entstehen.
     */
    public Absprache(Eigenschaften eigenschaften, Manager manager) {
        this.eigenschaften = eigenschaften;
        this.manager = manager;
        UIManager.addPropertyChangeListener(this);
        baue();
        aktiviere();
        aktualisiere();
        setTitle("JaFuffy (Daten für neues Turnier)");
        setIconImages(Oberflaeche.LOGOS);
        getRootPane().setBorder(
                new EmptyBorder(DIALOGRAHMENABSTAND, DIALOGRAHMENABSTAND, DIALOGRAHMENABSTAND, DIALOGRAHMENABSTAND));
        setModal(true);
        pack();
    }

    @Override
    public void propertyChange(PropertyChangeEvent event) {
        if (event.getPropertyName().equals("Beginnen")) {
            setLocationRelativeTo((JRootPane) event.getNewValue());
            setVisible(true);
        } else if (event.getPropertyName().equals("lookAndFeel")) {
            SwingUtilities.updateComponentTreeUI(this);
            pack();
        }
    }

    @Override
    public void setVisible(boolean sichtbar) {
        ok.requestFocus();
        super.setVisible(sichtbar);
    }

    /** Aktiviert die Reaktionen der Buttonleiste auf Abbruch und OK. */
    private void aktiviere() {
        abbruch.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
                aktualisiere();
                setVisible(false);
            }
        });
        ok.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent event) {
                ArrayList<Spieler> spieler = uebernehmeSpieler();
                manager.betreibe(new Turnier(uebernehmeVariante(), spieler, erster(spieler), uebernehmeBeginnmodus(),
                        uebernehmeAnzahl()));
                setVisible(false);
            }
        });
        getRootPane().setDefaultButton(ok);
    }

    /**
     * Anzahl der Spiele pro Turnier.
     *
     * @return Anzahlauswahlfeld.
     */
    private JPanel anzahlauswahl() {
        JLabel label;
        label = new JLabel("Anzahl der Spiele im Turnier");
        label.setAlignmentX(Component.CENTER_ALIGNMENT);
        int anzahl = Integer.parseInt(eigenschaften.getProperty("Anzahl"));
        anzahlschieberegler.setValue(anzahl);
        anzahlschieberegler.setMinorTickSpacing(FEINTICKS);
        anzahlschieberegler.setMajorTickSpacing(ORIENTIERUNGSTICKS);
        anzahlschieberegler.setPaintTicks(true);
        anzahlschieberegler.setPaintLabels(true);
        anzahlschieberegler.setSnapToTicks(true);
        @SuppressWarnings("unchecked")
        Hashtable<Integer, JLabel> hashtable = anzahlschieberegler.createStandardLabels(TICKLABELS);
        hashtable.put(new Integer(0), new JLabel("beliebig"));
        anzahlschieberegler.setLabelTable(hashtable);
        JPanel anzahlfeld = new JPanel();
        anzahlfeld.setLayout(new BoxLayout(anzahlfeld, BoxLayout.Y_AXIS));
        anzahlfeld.add(label);
        anzahlfeld.add(Box.createVerticalStrut(FELDRAHMENABSTAND / 2));
        anzahlfeld.add(Box.createVerticalGlue());
        anzahlfeld.add(Box.createVerticalStrut(FELDRAHMENABSTAND / 2));
        anzahlfeld.add(anzahlschieberegler);
        return anzahlfeld;
    }

    /** Aufbau des Gesamtdialogs. */
    private void baue() {
        Container container = getContentPane();
        container.setLayout(new BoxLayout(container, BoxLayout.X_AXIS));
        container.add(nominierungsfeld());
        container.add(Box.createHorizontalStrut(DIALOGRAHMENABSTAND));
        JPanel regelnfeld = new JPanel(new BorderLayout());
        regelnfeld.add(regelnfeld(), BorderLayout.CENTER);
        container.add(regelnfeld);
        container.add(Box.createHorizontalStrut(DIALOGRAHMENABSTAND));
        JPanel buttonleiste = new JPanel(new BorderLayout());
        buttonleiste.add(buttonleiste(), BorderLayout.CENTER);
        container.add(buttonleiste);
    }

    /**
     * OK-Abbruch-Leiste.
     *
     * @return Buttonleiste.
     */
    private JPanel buttonleiste() {
        JPanel buttonleiste = new JPanel(new GridLayout(0, 1, 0, BUTTONABSTAND));
        buttonleiste.setBorder(new EmptyBorder(BUTTONABSTAND + FELDRAHMENABSTAND, FELDRAHMENABSTAND / 2, BUTTONABSTAND,
                FELDRAHMENABSTAND / 2));
        buttonleiste.add(ok);
        buttonleiste.add(abbruch);
        return buttonleiste;
    }

    /**
     * Bestimmt den ersten Spieler, der das Turnier eröffnet.
     *
     * @param spieler
     *            Alle teilnehmenden Spieler.
     * @return Startindex des eröffnenden Spieler.
     */
    private int erster(ArrayList<Spieler> spieler) {
        Erster erster = new Erster(spieler);
        erster.setLocationRelativeTo(this);
        erster.setVisible(true);
        return erster.erster();
    }

    /** Baut das Feld für die Auswahl des Beginnmodus auf. */
    private void konfiguriereBeginnmodusauswahl() {
        beginnmodusauswahl.setAlignmentX(Component.CENTER_ALIGNMENT);
        beginnmodusauswahl.setSelectedIndex(eigenschaften.beginnmodus());
        beginnmodusauswahl.setToolTipText("Auswahl, welcher Mitspieler jedes neue Spiel beginnt");
    }

    /** Baut das Feld zur Variantenauswahl auf. */
    private void konfiguriereVariantenauswahl() {
        variantenauswahl.setActionCommand("Var");
        variantenauswahl.setAlignmentX(Component.CENTER_ALIGNMENT);
        variantenauswahl.setSelectedIndex(eigenschaften.variante());
        variantenauswahl.setToolTipText("Nach welchen Spielregeln soll gespielt werden?");
    }

    /**
     * Baut das Nominierungsfeld zusammen, in dem Spieler menschlicher oder künstlicher Natur angemeldet werden.
     *
     * @return Nominierungsfeld.
     */
    private JPanel nominierungsfeld() {
        JPanel namenfeld = new JPanel(new GridBagLayout());
        namenfeld.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("Namen"),
                BorderFactory.createEmptyBorder(FELDRAHMENABSTAND / 2, FELDRAHMENABSTAND, FELDRAHMENABSTAND / 2,
                        FELDRAHMENABSTAND)));
        GridBagConstraints constraints = new GridBagConstraints();
        constraints.gridwidth = 1;
        constraints.weighty = 1;
        constraints.insets = new Insets(1, 0, 1, 0);
        for (int i = 0; i < Spieler.SPIELER; i++) {
            constraints.anchor = GridBagConstraints.LINE_START;
            constraints.gridx = 0;
            constraints.gridy = i;
            constraints.ipadx = 2 * FELDRAHMENABSTAND;
            constraints.fill = GridBagConstraints.VERTICAL;
            constraints.weightx = 0;
            String name = eigenschaften.getProperty("Spieler" + i);
            boolean kuenstlich = eigenschaften.aktiv("Bot" + i);
            nominierungen[i] = new Nominierung(name, kuenstlich, this);
            variantenauswahl.addActionListener(nominierungen[i]);
            botselektionen[i] = new Botselektion(kuenstlich, nominierungen[i], variantenauswahl);
            variantenauswahl.addActionListener(botselektionen[i]);
            namenfeld.add(botselektionen[i], constraints);
            constraints.anchor = GridBagConstraints.CENTER;
            constraints.gridx = 1;
            constraints.ipadx = FELDRAHMENABSTAND;
            constraints.weightx = 0;
            namenfeld.add(new JLabel(i + 1 + ". Spieler: ", SwingConstants.CENTER), constraints);
            constraints.anchor = GridBagConstraints.LINE_END;
            constraints.gridx = 2;
            constraints.ipadx = 0;
            constraints.fill = GridBagConstraints.BOTH;
            constraints.weightx = 1;
            namenfeld.add(nominierungen[i], constraints);
        }
        namenfeld.add(new JLabel());
        JLabel label = new JLabel("Viel Spaß!");
        label.setHorizontalAlignment(SwingConstants.CENTER);
        Font font = label.getFont().deriveFont(Font.ITALIC);
        label.setFont(font);
        constraints.anchor = GridBagConstraints.LINE_END;
        constraints.gridx = 2;
        constraints.gridy = Spieler.SPIELER;
        constraints.fill = GridBagConstraints.BOTH;
        constraints.weightx = 1;
        constraints.weighty = 2;
        constraints.insets = new Insets(FELDRAHMENABSTAND, 0, 0, 0);
        namenfeld.add(label, constraints);
        return namenfeld;
    }

    /**
     * Erstellt das Feld, in dem die Spielregeln festgelegt werden.
     *
     * @return Regelnfeld.
     */
    private JPanel regelnfeld() {
        konfiguriereVariantenauswahl();
        konfiguriereBeginnmodusauswahl();
        JPanel regelnfeld = new JPanel();
        regelnfeld.setLayout(new BoxLayout(regelnfeld, BoxLayout.Y_AXIS));
        regelnfeld.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("Regeln"),
                BorderFactory.createEmptyBorder(FELDRAHMENABSTAND / 2, FELDRAHMENABSTAND, FELDRAHMENABSTAND / 2,
                        FELDRAHMENABSTAND)));
        regelnfeld.add(beginnmodusauswahl);
        regelnfeld.add(Box.createVerticalStrut(1));
        regelnfeld.add(Box.createVerticalGlue());
        regelnfeld.add(Box.createVerticalStrut(1));
        regelnfeld.add(variantenauswahl);
        regelnfeld.add(Box.createVerticalStrut(FELDRAHMENABSTAND));
        regelnfeld.add(Box.createVerticalGlue());
        regelnfeld.add(Box.createVerticalStrut(FELDRAHMENABSTAND));
        regelnfeld.add(anzahlauswahl());
        regelnfeld.add(Box.createVerticalGlue());
        return regelnfeld;
    }

    /**
     * Bestimmt und übernimmt die Anzahl.
     *
     * @return Anzahl der Spiele pro Turnier.
     */
    private int uebernehmeAnzahl() {
        eigenschaften.setProperty("Anzahl", Integer.toString(anzahlschieberegler.getValue()));
        return anzahlschieberegler.getValue();
    }

    /**
     * Bestimmt und übernimmt den Beginnmodus.
     *
     * @return Beginnmodus.
     */
    private Beginner uebernehmeBeginnmodus() {
        Beginner beginnmodus = Beginner.values()[beginnmodusauswahl.getSelectedIndex()];
        eigenschaften.setProperty("Beginnmodus", beginnmodus.name());
        return beginnmodus;
    }

    /**
     * Bestimmt und übernimmt die teilnehmenden Spieler.
     *
     * @return Alle teilnehmenden Spieler.
     */
    private ArrayList<Spieler> uebernehmeSpieler() {
        ArrayList<Spieler> spieler = new ArrayList<Spieler>(Spieler.SPIELER);
        for (int index = 0; index < Spieler.SPIELER; index++) {
            eigenschaften.setProperty("Spieler" + index, "");
            eigenschaften.setProperty("Bot" + index, "");
        }
        int anzahl = 0;
        for (Nominierung nominierung : nominierungen) {
            nominierung.trimme();
            String name = nominierung.name();
            if (!name.isEmpty()) {
                if (nominierung.kuenstlich()) {
                    eigenschaften.setProperty("Bot" + anzahl, "aktiv");
                    spieler.add(new Bot(name, Turnier.RUNDEN));
                } else {
                    spieler.add(new Spieler(name, Turnier.RUNDEN));
                    eigenschaften.setProperty("Spieler" + anzahl, name);
                }
                anzahl++;
            }
        }
        return spieler;
    }

    /**
     * Bestimmt und übernimmt die Regelvariante.
     *
     * @return Regelvariante.
     */
    private Variante uebernehmeVariante() {
        Variante variante = (Variante) variantenauswahl.getSelectedItem();
        eigenschaften.setProperty("Variante", variante.name());
        return variante;
    }

    /** Verteilt die Namen der künstlichen Intelligenzen und passt Elemente des Dialogs an den aktuellen Zustand an. */
    void aktualisiere() {
        int spieleranzahl = 0;
        int botanzahl = 0;
        for (Nominierung nominierung : nominierungen) {
            nominierung.name(null);
            if (nominierung.kuenstlich()) {
                nominierung.name(BOTNAMEN[botanzahl]);
                spieleranzahl++;
                botanzahl++;
            } else if (!nominierung.name().isEmpty()) {
                spieleranzahl++;
            }
        }
        beginnmodusauswahl.setEnabled(spieleranzahl > 1);
        ok.setEnabled(spieleranzahl > 0);
    }

}
