// SpxJ.java for applet // Y. Sawada, 2007. MNHA /* */ import java.applet.Applet; import java.awt.*; import java.awt.event.*; public class SpxJ extends Applet implements ActionListener,MouseListener{ private Color[] c; // 捕食者が識別できる色 Environ w; private MothPop m; // 現生個体群 private MothPop a; // 祖先個体群 int[] gt; // 現世代捕食順番号 int gi; // 現世代捕食個体数 int gn; // 経過世代数 Image ImBf; Graphics bGr; //ステージ400×300,一点5×5:80×60コマ //     外枠:天地10,左10,右60 final int mww = 80; final int mhh = 60; final int uu = 5; //ステージのオフセットと右下マージン final int ofx = 60; final int ofy = 10; final int mgx = ofx; final int mgy = ofy; Label l1; Button b1, b2, b3; public void init(){ w = new Environ(); m = new MothPop(); a = new MothPop(); gt = new int[8]; //捕食順(注:0〜7なので,一匹目の番号はgt[0]に収容) c = new Color[16]; c[0] = new Color( 49, 49, 49);//外枠色 c[1] = new Color( 0, 0, 0);//黒 c[2] = new Color( 99, 156, 0);//背景の副次色 c[3] = new Color(165,165, 0);//背景の主要色,蛾の体色 c[4] = new Color(206, 99, 0);//背景の副次色,蛾の体色 c[5] = new Color(156, 49, 0);//背景の副次色,蛾の体色 c[6] = new Color(247,148, 0);//       蛾の体色 c[7] = new Color(247, 0,132);//死亡マーク ImBf= createImage(ofx + mww * uu + mgx, ofy + mhh * uu +mgy); setLayout(null); l1 = new Label("score", Label.CENTER); l1.setBounds(417+50,252,46,16); add(l1); b1 = new Button("D"); b1.setBounds(417+50,270,46,18); add(b1); b1.addActionListener(this); b2 = new Button("R"); b2.setBounds(417+50,290,46,18); add(b2); b2.addActionListener(this); b3 = new Button("NEXT SEASON"); b3.setBounds(110+50,110,200,100); b3.addActionListener(this); b3.setVisible(false); add(b3); addMouseListener(this); newWorld(); newSeason(); } // 蛾を新たに生成して配置,初代個体群として保存 public void newWorld(){ gn = 0; int[] ac = new int[8]; m.brtMoth(); for (int i = 0; i < 10; i++){ for (int j = 0; j < 8; j++){ ac[j] = (int)(Math.random()*4+3); } m.setMothChar(i,ac[0],ac[1],ac[2],ac[3],ac[4],ac[5],ac[6],ac[7]); a.setMothChar(i,ac[0],ac[1],ac[2],ac[3],ac[4],ac[5],ac[6],ac[7]); } m.devMoth(); } // 世代の更新 public void newSeason(){ gn = gn + 1; gi = 0; for (int i = 0; i < 8; i++){ gt[i] = -1; } } // 蛾の一個体を捕食 public void eatMoth(int i){ m.dthMoth(i); gt[gi] = i; gi = gi + 1; } // 釦処理 public void actionPerformed(ActionEvent e){ if(e.getSource()==b1){ // w.wodEnv(); m.brtMoth(); m.devMoth(); newSeason(); gn = gn - 1; repaint(); l1.setText(">"+ gn + ">"); }else if (e.getSource()==b2){ w.wodEnv(); newWorld(); newSeason(); repaint(); l1.setText("score"); }else if (e.getSource()==b3){ b3.setVisible(false); } } // マウス処理 public void mouseClicked(MouseEvent e){ // アプレット内をクリック int xx, yy; int tx, ty, tl; xx = (int)((e.getX()-ofx)/uu); yy = (int)((e.getY()-ofy)/uu); if((0<=xx) && (xx"+ gn + ">"); } } } public void mousePressed(MouseEvent e){ //System.out.print("Mp"); } public void mouseReleased(MouseEvent e){ //System.out.print("Mr"); } public void mouseEntered(MouseEvent e){ //System.out.print("Me"); } public void mouseExited(MouseEvent e){ //System.out.print("Mx"); } // アップデートをリペイントしない版に public void update(Graphics g){ paint(g); } // 描画 public void paint(Graphics g){ int xx, yy; int dv = 0; int dh = 0; int pp; int ii, jj; // 裏描画 bGr = ImBf.getGraphics(); bGr.setColor(c[0]); bGr.fillRect(0, 0, ofx + mww * uu + mgx, ofy + mhh * uu +mgy); bGr.setColor(c[2]); bGr.fillRect(ofx, ofy, mww * uu, mhh * uu); // 背景描画 for (int i = 0; i < mww; i++){ for (int j = 0; j < mhh; j++){ bGr.setColor(c[w.getEnv(i, j)]); bGr.fillRect(i*uu+ofx, j*uu+ofy, uu, uu); } } for (int i = 0; i < 10; i++){ // 「場」に蛾を描画 xx = (m.getMothX(i)); yy = (m.getMothY(i)); switch(m.getMothD(i)){ case 0: dv= 1; dh= 1; break; case 1: dv= 1; dh=-1; break; case 2: dv=-1; dh= 1; break; case 3: dv=-1; dh=-1; break; } for (int k = 0; k < 6; k++){ for (int l = 0; l < 6; l++){ ii = (int)(xx + (k-1) * dh); jj = (int)(yy + (l-1) * dv); pp = m.img[k][l]; if (pp > 0){ bGr.setColor(c[m.getMothChar(i, pp)]); bGr.fillRect(ii*uu+ofx, jj*uu+ofy,uu,uu); } } } // 「場」に食べあとを描画 switch(m.getMothL(i)){ case 0: bGr.setColor(c[7]); bGr.fillRect(xx*uu+ofx, yy*uu+ofy,uu,uu); break; default: break; } } // 左側モニタ部に初代個体群を描画 xx = 28; for (int i = 0; i < 10 ; i++){ yy = (i * 35) + 18; for (int k = 0; k < 6; k++){ for (int l = 0; l < 6; l++){ ii = (int)(k * uu - 12 + xx); jj = (int)(l * uu - 12 + yy); pp = a.img[k][l]; if (pp > 0){ bGr.setColor(c[a.getMothChar(i, pp)]); bGr.fillRect(ii, jj,uu,uu); } } } } // 右側モニタ部に捕食済蛾を描画 xx = 28 + ofx + mww * uu; for (int i = 0; i <= (gi) ; i++){ int iii; iii = gt[i]; if (iii >=0){ yy = (i * 35) + 18; switch(m.getMothD(iii)){ case 0: dv= 1; dh= 1; break; case 1: dv= 1; dh=-1; break; case 2: dv=-1; dh= 1; break; case 3: dv=-1; dh=-1; break; } for (int k = 0; k < 6; k++){ for (int l = 0; l < 6; l++){ ii = (int)(dh * (k * uu - 12) + xx); jj = (int)(dv * (l * uu - 12) + yy); pp = m.img[k][l]; if (pp > 0){ bGr.setColor(c[m.getMothChar(iii, pp)]); bGr.fillRect(ii, jj,uu,uu); } } } } } // 表へ転写 g.drawImage(ImBf, 0, 0, this); } } class MothPop{ int[][] img; // 発現形 int[] lfe; // 各個体の生死 int[][] chr; // 各個体の染色体 int[][] egg; // 各個体の染色体(卵) int[][] loc; // 各個体の静止の方向と位置 int mut; // 突然変異率(0〜100%) // ステージの大きさ(配置時に必要な値) final int mww = 80; final int mhh = 60; // 蛾個体群コンストラクタ public MothPop(){ // 体色発現パターン // //  012345  //          //0 146755  //1 425447  //2 6516    //3 74633   //4 54 3    //5 57      //          img = new int[6][6]; img[0][0] = 1; img[0][1] = 4; img[1][0] = 4; img[0][2] = 6; img[2][0] = 6; img[0][3] = 7; img[3][0] = 7; img[0][4] = 5; img[4][0] = 5; img[0][5] = 5; img[5][0] = 5; img[1][1] = 2; img[1][2] = 5; img[2][1] = 5; img[1][3] = 4; img[3][1] = 4; img[1][4] = 4; img[4][1] = 4; img[1][5] = 7; img[5][1] = 7; img[2][2] = 1; img[2][3] = 6; img[3][2] = 6; img[2][4] = 0; img[4][2] = 0; img[2][5] = 0; img[5][2] = 0; img[3][3] = 3; img[3][4] = 3; img[4][3] = 3; img[3][5] = 0; img[5][3] = 0; img[4][4] = 0; img[4][5] = 0; img[5][4] = 0; img[5][5] = 0; mut = 10; // 生死初期化(生) lfe = new int[10]; for (int i = 0; i < 10; i++){ lfe[i] = 1; } // 染色体初期化(全て虫固有色型) chr = new int[10][8]; for (int i = 0; i < 10; i++){ for (int j = 0; j < 8; j++){ chr[i][j] = 7; } } // 染色体初期化(全て虫固有色型) egg = new int[10][8]; for (int i = 0; i < 10; i++){ for (int j = 0; j < 8; j++){ egg[i][j] = 7; } } // 静止方向位置初期化(中央) loc = new int[10][3]; for (int i = 0; i < 10; i++){ loc[i][0] = 0; loc[i][1] = 40; loc[i][2] = 30; } } // 外からの個体群設定(開始時、初期個体群など) public void setMothChar(int id, int c0, int c1, int c2, int c3, int c4, int c5, int c6, int c7){ chr[id][0]=c0; chr[id][1]=c1; chr[id][2]=c2; chr[id][3]=c3; chr[id][4]=c4; chr[id][5]=c5; chr[id][6]=c6; chr[id][7]=c7; } // 外からの個体群配置(開始時、初期個体群など) public void setMothLoc(int id, int d, int x, int y){ loc[id][0]=d; loc[id][1]=x; loc[id][2]=y; } // 全個体の誕生 public void brtMoth(){ for (int i = 0; i < 10; i++){ lfe[i]=1; } } // 単一個体の被食死亡 public void dthMoth(int id){ lfe[id]=0; } // 世代の更新 public void generMoth(){ int ff = 0; int mm = 0; int cc = 0; // 生存二個体(次世代親)の抽出 for(int i = 0; i<10; i++){ if (lfe[i]==1){ cc = cc + 1; if (cc == 1){ ff = i; } else{ mm = i; } } } reproMoth(ff, mm); devMoth(); } // 増殖,世代更新 public void reproMoth(int f, int m){ int p; // 交雑 for(int i = 0; i<10; i++){ for(int j = 0; j<8; j++){ p = (int)(Math.random()*100); if (p < 50){ egg[i][j]=chr[f][j]; } else{ egg[i][j]=chr[m][j]; } } } // 突然変異 for(int i = 0; i<10; i++){ for(int j = 0; j<8; j++){ p = (int)(Math.random()*100); if (p < mut){ egg[i][j]=(int)(Math.random()*4+3); } } } // 発生,成長 for(int i = 0; i<10; i++){ for(int j = 0; j<8; j++){ chr[i][j]=egg[i][j]; } lfe[i]=1; } } // 各情報のゲッターメソッド(関数) public int getMothL(int id){ return lfe[id]; } public int getMothChar(int id, int c){ return chr[id][c]; } public int getMothD(int id){ return loc[id][0]; } public int getMothX(int id){ return loc[id][1]; } public int getMothY(int id){ return loc[id][2]; } // 蛾の静止方向(D:0〜3)と位置(X:6〜74, Y:6〜54) // ランダムに配置するが // 既存のものと近すぎる場合は決め直す public void devMoth(){ int dd; int nr; //近すぎ!フラグ final int ds = 150; //距離の二乗の限界(13以上は可) for (int i = 0; i < 10; i++){ loc[i][0] = (int)(Math.random()*4); nr = 1; while (nr == 1){ loc[i][1] = (int)(Math.random()*68+6); loc[i][2] = (int)(Math.random()*48+6); nr = 0; for (int j = 0; j < i; j++){ dd = (loc[i][1]-loc[j][1])*(loc[i][1]-loc[j][1]) + (loc[i][2]-loc[j][2])*(loc[i][2]-loc[j][2]); if (dd <= ds){ nr = 1; } } } } } } class Environ { int[][] wal; final int mww = 80; final int mhh = 60; // 環境のコンストラクタ public Environ(){ wal = new int[mww][mhh]; wodEnv();//環境構築2を使用 } // 各点の色番号を返す関数 public int getEnv(int x, int y){ return wal[x][y]; } // 環境構築0(全面主要色) public void newEnv(){ for (int i = 0; i < mww; i++){ for (int j = 0; j < mhh; j++){ wal[i][j] = 3; } } } // 環境構築1(2〜5をランダムに配置) public void renEnv(){ for (int i = 0; i < mww; i++){ for (int j = 0; j < mhh; j++){ wal[i][j] = (int)(Math.random()*4+2); } } } // 環境構築2(主要色ベースに葉と幹と葉を付加) public void wodEnv(){ int cc, xx, yy, rr; // 最背景:主要色 for (int i = 0; i < mww; i++){ for (int j = 0; j < mhh; j++){ wal[i][j] = 3; } } // 最景:葉 for (int i = 0; i < 150; i++){ cc = (int)(Math.random()*4+2); xx = (int)(Math.random()*mww); yy = (int)(Math.random()*mhh); wal[xx][yy] = cc; rr = (int)(Math.random()*1000); while (rr<=950){ xx = (xx + (int)(Math.random()*3) -1 + mww) % mww; yy = (yy + (int)(Math.random()*3) -1 + mhh) % mhh; wal[xx][yy] = cc; rr = (int)(Math.random()*1000); } } // 中景:幹 for (int i = 0; i < 20; i++){ cc = (int)(Math.random()*4+2); xx = (int)(Math.random()*mww); for (int j = 0; j < mhh; j++) wal[xx][j] = cc; rr = (int)(Math.random()*1000); while (rr<=750){ xx = (xx + (int)(Math.random()*3) -1 + mww) % mww; for (int j = 0; j < mhh; j++) wal[xx][j] = cc; rr = (int)(Math.random()*1000); } } // 前景:葉 for (int i = 0; i < 150; i++){ cc = (int)(Math.random()*4+2); xx = (int)(Math.random()*mww); yy = (int)(Math.random()*mhh); wal[xx][yy] = cc; rr = (int)(Math.random()*1000); while (rr<=950){ xx = (xx + (int)(Math.random()*3) -1 + mww) % mww; yy = (yy + (int)(Math.random()*3) -1 + mhh) % mhh; wal[xx][yy] = cc; rr = (int)(Math.random()*1000); } } } }