//
/* ----------------------------------------------------------------------------------------------
    semi_cnd.java	半導体									ver. 1.00 (JDK 1.02)
    														ueyama@infonet.co.jp  1999.03.02
---------------------------------------------------------------------------------------------- */

import java.applet.Applet;
import java.awt.*;
import java.util.*;
import java.awt.image.*;

public class semi_cnd extends Applet implements Runnable
{
	int			Btn=0;										// クリックされたボタンの No.
	int			Atom[][]=new int[7][5];						// 0: Silicon  1: arsenic  2: boron
	int			Ex[][][]=new int[7][5][4];					// 電子位置 X
	int			Ey[][][]=new int[7][5][4];					// 電子位置 Y
	int			Bx0=0, By0=0;								// 正孔初期位置
	int			NorP=0;										// 2: P型  1: N型  0:真性半導体
	int			Hx=0, Hy=0, He;								// hole の位置
	int			Tx=999, Ty=999, Te=0;
	int			Wait=256;
	int			Ww=size().width, Wh=size().height;
	int			Ax=0,Ay=0, Bx=0,By=0;
	boolean		Sw=false;									// t: ON  f: OFF
	Button		bt_n, bt_p, bt_t, bt_slow, bt_fast, bt_sw;
	Graphics	gr;
	Thread		th=null;
	Color		electron		=new Color(51,102,255);
	Color		free_electron	=new Color(0,51,204);
	Color		hole			=new Color(255,51,153);
	Color		transient_hole	=new Color(153,153,153);
	int			R,G,B,   Bg;
	int			Data[]=new int[500*285];
	int 		T;
	Image		img;
	Image		Gif;
	Random		Rnd=new Random();
	
	/*
	position of electrons (Hph);		     |  |
										     |  |
										----      ---- (3)
										      ○
										----      ---- (2)
										     |  |
										     |  |

										    (0)(1)

	*/
//				Hpx[(Te/2)?Hx%2:Hy%2][Te][0 or 1; (ramdom)]			// next Hole data
//	position of electrons;   0     1     2      3        0     1     2      3
	int			Hpx[][][]={{{0,0},{0,0},{ 1,1},{ 1,1}},{{0,0},{0,0},{ 1,1},{ 1,1}}};
	int			Hpy[][][]={{{0,1},{0,1},{-1,0},{-1,0}},{{0,1},{0,1},{-1,0},{-1,0}}};
	int			Hph[][][]={{{3,3},{3,3},{ 0,0},{ 0,0}},{{2,2},{2,2},{ 1,1},{ 1,1}}};
	
	public void start()
	{
		if(th==null)
		{
			th=new Thread(this);
			th.start();
		}
	}
	
	public void init()
	{
		R=Integer.parseInt(getParameter("bg_red"));
		G=Integer.parseInt(getParameter("bg_green"));
		B=Integer.parseInt(getParameter("bg_blue"));
		Bg=0xff000000+R*0x10000+G*0x100+B;
		setBackground(new Color(R,G,B));
		
		MediaTracker mt=new MediaTracker(this);
		Gif=getImage(getCodeBase(),"semi_cnd.gif");
		mt.addImage(Gif, 0);
		try
		{
			mt.waitForID(0);
		}
		catch(InterruptedException e){};
		
		Panel p=new Panel();
		p.add(bt_n   =new Button("N"));
		p.add(bt_p   =new Button("P"));
		p.add(bt_t   =new Button("T"));
		p.add(bt_slow=new Button("<<"));
		p.add(bt_fast=new Button(">>"));
		p.add(bt_sw  =new Button(" ON "));
		setLayout(new BorderLayout());
		add("South",p);
		atom_init();
		gr=getGraphics();
		img=createImage(500,285);
	}
	
	// 画像の表示  m=0:原子  n=0:Silicon 1:arsenic 2:boron   m=1:電極 n=0:"+"  n=1:"-"
	public void dsp_a(int x, int y, int m, int n, Graphics g)
	{
		Graphics	gx=g.create();
		int			l=(m==0)?23:36, o=(m==0)?17:0;
		gx.clipRect(x+o,y+o,l,l);
		gx.drawImage(Gif,x+o-(m*69+n*l),y+o,this);
		gx.dispose();
	}
	
	public void atom_init()
	{
		int x,y;
		
		for(x=0;x<7;x++)
		{
			for(y=0;y<5;y++)
			{
				Atom[x][y]=0;
				Ex[x][y][0]=50+x*57+22-4;	Ey[x][y][0]=(y+1)*57-4;
				Ex[x][y][1]=50+x*57+33-4;	Ey[x][y][1]=(y+1)*57-4;
				Ex[x][y][2]=50+(x+1)*57-4;	Ey[x][y][2]=y*57+33-4;
				Ex[x][y][3]=50+(x+1)*57-4;	Ey[x][y][3]=y*57+22-4;
			}
		}
	}
	
	public boolean collision(int x, int y)
	{
		int ex, ey;
		
		ex=(x+4-50)%57; ey=(y+4)%57;
		if((28-ex)*(28-ex)+(28-ey)*(28-ey)<=256) return true;		// 原子核との衝突 !!
		else return false;
	}
	
	public int random_position()
	{
		int	rp;
		
		rp=Rnd.nextInt()&255;
		if(rp>170) return -1;
		else if(rp>85) return 1;
		else return 0;
	}
	
	public void free_electron()										// 自由電子の表示
	{
		int x,y, rx,ry;
		
		Graphics ge=gr.create();
		ge.clipRect(55,6,390,276);
		
		for(x=0;x<7;x++)
		{
			for(y=0;y<5;y++)
			{
				if(Atom[x][y]==1)
				{
					if(Sw)
					{
						rx=random_position();
						ry=random_position();
						if(collision(Ax-(3+ry),Ay+ry)) Ay-=ry;
						else
						{
							Ax-=(3+ry); Ay+=ry;
						}
						if(Ax<53)
						{
							Ax=447;
							while(true)
							{
								Ay=Rnd.nextInt()&4095; Ay/=24; Ay+=57;
								if(Ay%57<16 || Ay%57>41) break;
							}
						}
					}
					ge.setColor(free_electron);
					ge.fillOval(Ax,Ay,9,9);
				}
			}
		}
		ge.dispose();
	}
	
	public void bg_edit(int c)
	{
		int x,y,n;
		
		for(x=0;x<9;x++)
		{
			for(y=0;y<9;y++)
			{
				if((x-4)*(x-4)+(y-4)*(y-4)>16) n=Bg;
				else n=c;
				Data[(By0+y)*500+Bx0+x]=n;
				Data[(By0+y)*500+Bx0+x]=c;
				Data[(By0+y)*500+Bx0+x]=n;
			}
		}
	}
	
	public void hole()
	{
		int c, i,j, x,y, rx,ry, m,n, nh, tx,ty;
		Graphics gh=gr.create();
		
		gh.clipRect(55,6,390,276);
		for(x=0;x<7;x++)
		{
			for(y=0;y<5;y++)
			{
				if(Atom[x][y]==2)
				{
					if(Math.abs(Bx-Tx)<2 && Math.abs(By-Ty)<2 && T>10)
					{
						if(Tx>60)
						{
							gh.setColor(electron);
							gh.fillOval(Tx,Ty,9,9);
						}
						gh.setColor(hole);
						gh.fillOval(Bx0,By0,9,9);
						bg_edit(0xff3366ff);
						
						Tx=Bx0; Ty=By0; Te=He;
						while(true)
						{
							n=Rnd.nextInt()&1;
							Hx=(Tx-50)/57; Hy=Ty/57;
							m=(Te/2==0)?  Hx%2:Hy%2;
							i=Hpx[m][Te][n]; j=Hpy[m][Te][n]; nh=Hph[m][Te][n];
							Hy+=j; He=nh;
							if(Hy>=0 && Hy<5 && Ey[Hx][Hy][He]<270) break;
						}
						Hx+=i;
						if(Hx==7)
						{
							Hx=0;
							Tx=52;
						}
						Bx=Ex[Hx][Hy][He]; By=Ey[Hx][Hy][He];
						Bx0=Bx; By0=By;
						T=0;
					}
					if(Sw)
					{
						gh.setColor(transient_hole);
						gh.fillOval(Bx0,By0,9,9);
						bg_edit(0xff666666);
						
						rx=random_position()+((Bx-Tx>0)?-1:1);
						ry=random_position()+((By-Ty>0)?-1:1);
						if(collision(Bx+rx,By+ry))
						{
							Bx-=rx; By-=ry;
						}
						else
						{
							Bx+=rx; By+=ry;
						}
						gh.setColor(free_electron);
						gh.fillOval(Bx,By,9,9);						// electron
					}
				}
			}
		}
		gh.dispose();
	}

	public void paint(Graphics g)
	{
		int i,j,x,y,e,n,nh,rx,ry;
		int	qx,qy, x0,y0;
		rx=0; ry=0;
		
		qx=(Tx-50)/57; qy=Ty/57;
		g.clearRect(0,0,Ww,Wh);
		
		g.setColor(new Color(255,204,230));							// 電極の表示
		g.fillRect(0,0,55,285);
		g.setColor(new Color(204,204,255));
		g.fillRect(445,0,55,285);
		if(Sw)
		{
			dsp_a(10,124,1,0,gr);									// 電極の表示
			dsp_a(455,124,1,1,gr);
		}
		
		g.clipRect(55,6,390,276);
		for(x=0;x<7;x++)											// 原子の表示
		{
			for(y=0;y<5;y++)
			{
				x0=x%2*11+22; y0=y%2*11+22;
				g.setColor(new Color(0,0,0));
				g.fillRect(50+x*57,y*57+x%2*11+22,57,2);
				g.fillRect(50+x*57+y%2*11+22,y*57,2,57);
				g.setColor(new Color(153,153,153));
				for(i=1;i<19;i+=2)
				{
					g.fillRect(50+x*57+i*3,y*57+(x+1)%2*11+22,3,2);
					g.fillRect(50+x*57+(y+1)%2*11+22,y*57+i*3,2,3);
				}
				if(Atom[x][y]==1)									// arsenic
				{
					g.setColor(new Color(0,0,0));
					g.drawLine(50+x*57+49,y*57+6,50+x*57+29,y*57+26);
					g.drawLine(50+x*57+49,y*57+7,50+x*57+29,y*57+27);
					g.drawLine(50+x*57+50,y*57+7,50+x*57+30,y*57+27);
				}
				if(Atom[x][y]==2)									// boron
				{
					g.setColor(new Color(153,153,153));
					g.fillRect(50+x*57+29,y*57+x%2*11+22,28,2);
					g.fillRect(50+x*57+29,y*57+(x+1)%2*11+22,28,2);
					g.setColor(new Color(R,G,B));
					for(i=10;i<19;i+=2)
					{
						g.fillRect(50+x*57+i*3,y*57+x%2*11+22,3,2);
						g.fillRect(50+x*57+i*3,y*57+(x+1)%2*11+22,3,2);
					}
					g.setColor(new Color(0,0,0));
				}
			}
		}
		for(x=0;x<7;x++)											// 原子核の表示
		{
			for(y=0;y<5;y++) dsp_a(50+x*57,y*57,0,Atom[x][y],g);
		}
		g.setColor(electron);
		for(x=0;x<7;x++)											// 電子の表示
		{
			for(y=0;y<5;y++)
			{
				for(e=0;e<4;e++)
				{
					if(NorP==2 && x==qx && y==qy && e==Te) g.setColor(hole);
					g.fillOval(Ex[x][y][e],Ey[x][y][e],9,9);
					if(NorP==2) g.setColor(electron);
				}
			}
		}
	}
	
	public void run()
	{
		int x,y, r,g,b, ex,ey;
		
		while(th!=null)
		{
			if(NorP==1) free_electron();
			if(NorP==2) hole();
			try
			{
				th.sleep(Wait);
			}
			catch (InterruptedException e){}
			T++;
			if(Ax*Ay+Bx*By>0)
			{
				Graphics gx=gr.create();
				gx.clipRect(55,6,390,276);
				ex=(NorP==1)?Ax:Bx; ey=(NorP==1)?Ay:By;
				for(x=0;x<9;x++)
				{
					for(y=0;y<9;y++)
					{
						r=Data[(ey+y)*500+ex+x] & 0x00ff0000; r/=0x10000;
						g=Data[(ey+y)*500+ex+x] & 0x0000ff00; g/=0x100;
						b=Data[(ey+y)*500+ex+x] & 0x000000ff;
						gx.setColor(new Color(r,g,b));
						gx.drawRect(ex+x,ey+y,1,1);
					}
				}
				gx.dispose();
			}
			//		gr.fillOval(Ax,Ay,9,9);
			//		gr.fillOval(Bx,By,9,9);
		}
	}
	
	public boolean get_pixeldata()
	{
		update(img.getGraphics());
		PixelGrabber pg=new PixelGrabber(img,0,0,500,285,Data,0,500);
		try
		{
			pg.grabPixels();							// 画像データの取得
		}
		catch (InterruptedException ie) {return false;}
		if((pg.status() & ImageObserver.ABORT) !=0) {return false;}
		return true;
	}
	
	public boolean action(Event e, Object o)
	{
		Btn=0;
		if(e.target==bt_n)			Btn=1;
		else if(e.target==bt_p)		Btn=2;
		else if(e.target==bt_t)
		{
			atom_init();
		NorP=0;
			Ax=0; Ay=0;
			Bx=0; By=0; Tx=999; Ty=999;
		repaint();
			get_pixeldata();
		}
		else if(e.target==bt_slow)
		{
			Wait*=2; bt_fast.enable();
		}
		else if(e.target==bt_fast)
		{
			if(Wait>64)	Wait/=2;
			else		bt_fast.disable();
		}
		else if(e.target==bt_sw)
		{
			Sw=!Sw;
			bt_sw.setLabel((Sw)?"OFF":" ON ");
			
			if(Sw)
			{
				dsp_a(10,124,1,0,gr);								// 電極の表示
				dsp_a(455,124,1,1,gr);
				bt_n.disable(); bt_p.disable(); bt_t.disable();
			}
			else
			{
				gr.setColor(new Color(255,204,230));
				gr.fillRect(0,124,55,55);
				gr.setColor(new Color(204,204,255));
				gr.fillRect(445,124,55,55);
				bt_n.enable(); bt_p.enable(); bt_t.enable();
			}
		}
		if(Btn>0)
		{
			bt_n.disable(); bt_p.disable(); bt_t.disable(); bt_sw.disable();
		}
		return true;
	}
	
	public boolean mouseDown(Event e, int x, int y)
	{
		int i,j,k;
		
		if(x>55 && x<445 && y<278)
		{
			i=(x-50)/57; j=y/57; k=(i%2==0)?3:2;
			if(Btn==1 || Btn==2)
			{
				atom_init();
				Atom[i][j]=Btn;
				NorP=Btn;
				T=0;
			}
			if(Btn==1)											// arsenic doped
			{
				Ax=50+i*57+50-4; Ay=j*57+7-4;
				Bx=0; By=0; Tx=999; Ty=999;
			}
			if(Btn==2)											// boron doped
			{
				Tx=Ex[i][j][k]; Ty=Ey[i][j][k]; Te=k;
				Bx=Tx; By=Ty; Bx0=Bx; By0=By; He=k;
			}
			if(Btn>0)
			{
				repaint();
				get_pixeldata();
			}
			bt_n.enable(); bt_p.enable(); bt_t.enable(); bt_sw.enable();
			Btn=0;
		}
		return true;
	}
	
	public void stop()
	{
		if(th!=null)
		{
			th.stop();
			th=null;
		}
	}
}
//
戻る