pgg2PunishGr.java

/**
 * A public goods game simulation defined in
 * "Competition of individual and institutional punishments in spatial public goods game"
 * By A. Szolnoki, et. al, Phys. Rev. E84, 046106 (2011)
 *
 **/

import java.awt.*; // uses the abstract windowing toolkit
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

public class pgg2PunishGr extends JPanel implements Runnable {

    private Thread myTh;
    // private Thread currentThread;
    private boolean halt_;
    pgg2Punishments game;
    drawPattern draw;

    static int maxSize = 800; // width of window in pixels
    static int size = 200; // lattice size; can be any divisor of maxSize
    /* グラフィック関係変数 */
    JButton restart, stopBtn, exitBtn;
    JLabel label_r, label_K, label_gamma, label_beta, label_m;
    JSlider set_r, set_gamma, set_beta, set_K, set_m;
    double scale1 = 100.0, scale2 = 50.0; /* スライダーのスケール */

    /* コンストラクタ */
    pgg2PunishGr3() {
        /* パラメータ初期値 */
        double ini_r = 2.1, ini_m = 1.0, ini_gamma = 1.0, ini_beta = 2.5, ini_K = 0.5;

        draw = new drawPattern(maxSize, size);  // ゲームのパターン描画オブジェクト

        /* ボタン生成 */
        restart = new JButton("start");
        stopBtn = new JButton("stop");
        exitBtn = new JButton("終了");

        /* スライドバー生成 */
        set_r = new JSlider(JSlider.HORIZONTAL, 0, 300, (int) (ini_r * scale1));
        set_beta = new JSlider(JSlider.HORIZONTAL, 0, 300,
                (int) (ini_beta * scale1));
        set_gamma = new JSlider(JSlider.HORIZONTAL, 0, 300,
                (int) (ini_gamma * scale1));
        set_K = new JSlider(JSlider.HORIZONTAL, 0, 100, (int) (ini_K * scale2));
        set_m = new JSlider(JSlider.HORIZONTAL, 25, 100, (int) (ini_m * scale1));

        /* ラベル生成 */
        label_r = new JLabel(String.valueOf(ini_r));
        label_m = new JLabel(String.valueOf(ini_m));
        label_gamma = new JLabel(String.valueOf(ini_gamma));
        label_beta = new JLabel(String.valueOf(ini_beta));
        label_K = new JLabel(String.valueOf(ini_K));

        /* パネルにスライドバー、ラベルを貼る */
        /* 各パネルに、スライドバーとラベルを横に並べる */
        JPanel panel_K = new JPanel();
        panel_K.add(new JLabel("K"));
        panel_K.add(set_K);
        panel_K.add(label_K);
        JPanel panel_m = new JPanel();
        panel_m.add(new JLabel("m"));
        panel_m.add(set_m);
        panel_m.add(label_m);
        JPanel panel_r = new JPanel();
        panel_r.add(new JLabel("r"));
        panel_r.add(set_r);
        panel_r.add(label_r);
        JPanel panel_beta = new JPanel();
        panel_beta.add(new JLabel("beta"));
        panel_beta.add(set_beta);
        panel_beta.add(label_beta);
        JPanel panel_gamma = new JPanel();
        panel_gamma.add(new JLabel("gamma"));
        panel_gamma.add(set_gamma);
        panel_gamma.add(label_gamma);

        /* 親パネルにボタンと、スライドバー・ラベル を並べる */
        JPanel p = new JPanel();
        p.setLayout(new GridLayout(8, 1));
        p.add(restart);
        p.add(stopBtn);
        p.add(panel_K);
        p.add(panel_m);
        p.add(panel_r);
        p.add(panel_gamma);
        p.add(panel_beta);
        p.add(exitBtn);

        add(p, BorderLayout.NORTH);

        /* スライダーやボタンにリスナーをつける */
        set_r.addChangeListener(new ChangeListener() {
            public void stateChanged(ChangeEvent e) {
                label_r.setText(Double.toString(set_r.getValue() / scale1));
            }
        });
        set_gamma.addChangeListener(new ChangeListener() {
            public void stateChanged(ChangeEvent e) {
                label_gamma.setText(Double.toString(set_gamma.getValue()
                        / scale1));
            }
        });
        set_beta.addChangeListener(new ChangeListener() {
            public void stateChanged(ChangeEvent e) {
                label_beta.setText(Double.toString(set_beta.getValue() / scale1));
            }
        });
        set_K.addChangeListener(new ChangeListener() {
            public void stateChanged(ChangeEvent e) {
                label_K.setText(Double.toString(set_K.getValue() / scale2));
            }
        });
        set_m.addChangeListener(new ChangeListener() {
            public void stateChanged(ChangeEvent e) {
                label_m.setText(Double.toString(set_m.getValue() / scale1));
            }
        });
        restart.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                /*
                 * startボタンが押されたら、ゲームオブジェクトを作成し、 スレッドをスタートさせる
                 */
                game = new pgg2Punishments(size);
                game.setParameters(set_gamma.getValue() / scale1,
                        set_beta.getValue() / scale1,
                        set_r.getValue() / scale1, set_K.getValue() / scale2,
                        set_m.getValue() / scale1);
                thread_start();
            }
        });
        stopBtn.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                stop();
            }
        });
        exitBtn.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                System.exit(0);
            }
        });
    }

    /* main */
    public static void main(String[] args) {


        // パラメータセットのGUIを作成し、表示
        JFrame setParamFrame = new JFrame("パラメータセット");
        pgg2PunishGr3 ctr = new pgg2PunishGr3();
        setParamFrame.getContentPane().add(ctr, BorderLayout.CENTER);
        setParamFrame.setSize(300, 300);
        setParamFrame.setLocation(600, 20);
        setParamFrame.setVisible(true);

    }

    /* *************** End of Main ******************** */

    /* GUIで操作できるようにrunnableインターフェイスに基づいてスレッドを操作をする */
    public void thread_start() { /* startボタンにより呼び出す */
        halt_ = false;
        myTh = new Thread(this);
        myTh.start(); /* start()によりrun()が実行される */
    }

    public void stop() { /* stopボタンで呼び出す */
        halt_ = true;
        myTh.interrupt();
    }

    public void run() {
        int i, j;
        /* halt_==falseの間、繰り返し */
        game.initializePlayers();
        while (!halt_) {
            i = (int) (Math.random() * size); // (i,j)をランダムに選んで、
            j = (int) (Math.random() * size); // 戦略アップデートを実行
            if (game.update_strategy(i, j))
                this.draw.colorSquare(i, j, game.s[i][j]);
        }
    }
}