//
/* ------------------------------------------------------------------------------------------------------
    enigma.java		エニグマ											ver. 1.20 (JDK 1.02)
    																	ueyama@infonet.co.jp  2000.03.03
    																	update: 2007.08.16
------------------------------------------------------------------------------------------------------ */
import java.applet.*;
import java.awt.*;
import java.lang.Math;
import java.util.*;


public class enigma extends Applet
{
	int		Ref[] ={24,17,20,7,16,18,11,3,15,23,13,6,14,10,12,8,4,1,5,25,2,22,21,9,0,19};	// Reflector の接続
	int		Refx[]={2,3,4,5,6,7,8,5,5,9,10,8,8,10,8,5,6,3,7,3,4,4,4,9,2,3};					// 同上 表示用縦線位置
	int		Ro[][]={{21,19,17,4,6,8,10,12,14,5,18,20,22,0,24,2,16,1,7,11,25,9,3,13,15,23},	// Rotor の接続(往路)
					{13,17,10,9,19,3,8,11,25,21,2,22,6,16,7,5,23,1,15,24,14,4,18,20,12,0},
					{6,14,7,23,8,15,10,16,18,11,17,12,9,22,1,5,19,25,20,2,4,13,3,0,24,21}};
	int		Rh[][]={{13,17,15,22,3,9,4,18,5,21,6,19,7,23,8,24,16,2,10,1,11,0,12,25,14,20},	// Rotor の接続(帰路)
					{25,17,10,5,21,15,12,14,6,3,2,7,24,0,20,18,13,1,22,4,23,9,11,16,19,8},
					{23,14,19,22,20,15,0,2,4,12,6,9,11,21,1,5,7,10,8,16,18,25,13,3,24,17}};
	int		Qwer[]={16,22,4,17,19,25,20,8,14,0,18,3,5,6,7,9,10,15,24,23,2,21,1,13,12,11};	// キーの配列(文字)
	int		Rewq[]={9,22,20,11,2,12,13,14,7,15,16,25,24,23,8,17,0,3,10,4,6,21,1,19,18,5};	// キーの配列(位置)
	int		Lw[]={10,7,9,8,8,8,9,8,6,6,8,8,8,8,9,7,9,8,7,10,8,10,10,10,10,9};				// 暗号化文字の幅
	// キーの座標: q w  e  r   t   z   u   i   o   a  s  d   f   g   h   j   k   p  y  x  c   v   b   n   m   l
	int		Kx[]={ 7,52,97,142,187,232,277,322,367,27,72,117,162,207,252,297,342, 0,45,90,135,180,225,270,315,360,};
	int		Ky[]={ 0, 0, 0,  0,  0,  0,  0,  0,  0,27,27, 27, 27, 27, 27, 27, 27,54,54,54, 54, 54, 54, 54, 54, 54,};
	int		X=70, Y=25, Kox=70, Koy=384;								// Roter シンボルとキーの表示位置
	int		Cx=X-55, Cq=0, Ctx[]=new int[80];							// 暗号化文字表示位置、文字数、文字列
	int		R[]={0,0,0};												// Rotor No.
	int		Key=-1;														// キー入力文字
	int		Crp=-1;														// 暗号化文字
	Image	Img;
	AudioClip Ac1, Ac2, Ac3;
	Graphics  gr;
	
	public void init()
	{
		String bg=getParameter("bgcolor");								// 背景色の読み込み
		int bgc=Integer.valueOf(bg,16).intValue();
		setBackground(new Color(bgc)); 
		MediaTracker mt=new MediaTracker(this);
		Img=getImage(getCodeBase(), getParameter("figure"));			// gif ファイルの読み込み
		mt.addImage(Img, 0);
		try
		{
			mt.waitForID(0);
		}
		catch(InterruptedException e){};
		Ac1=getAudioClip(getCodeBase(), getParameter("audio_clip_1"));	// 効果音データの読み込み
		Ac2=getAudioClip(getCodeBase(), getParameter("audio_clip_2"));
		Ac3=getAudioClip(getCodeBase(), getParameter("audio_clip_3"));
		Random rnd=new Random();
		for(int i=0;i<3;i++) R[i]=Math.abs(rnd.nextInt())%26;			// 乱数による Rotor の初期設定
		gr=getGraphics();
	}

	public boolean inside(int x, int a, int b)
	{
		return (x<=Math.max(a,b) && x>=Math.min(a,b)) ? true:false;
	}
	
	public void dsp_g(int x, int y, int ver, int hol, int n)			// 画像の表示
	{
		int w=0,h=0, ox=0,oy=0;
		switch(n)
		{
			case  0: w= 11; h= 11; ox=  0; oy= 95; break;				// 文字 (alphabet)
			case  1: w= 25; h= 20; ox=  0; oy=  0; break;				// Rotor 回転位置
			case  2: w= 26; h= 21; ox=364; oy=118; break;				// Rotor INC ボタン
			case  3: w= 26; h= 21; ox=416; oy=118; break;				// Rotor DEC ボタン
			case  4: w= 26; h= 22; ox=286; oy=118; break;				// CLR ボタン
			case  5: w= 25; h= 25; ox=  0; oy= 20; break;				// キー
			case  6: w= 52; h= 11; ox=286; oy= 95; break;				// "Reflector"
			case  7: w= 61; h= 11; ox=338; oy= 95; break;				// "Slow Rotor"
			case  8: w= 74; h= 11; ox=399; oy= 95; break;				// "Medium Rotor"
			case  9: w= 60; h= 11; ox=473; oy= 95; break;				// "Fast Rotor"
			case 10: w= 26; h= 11; ox=533; oy= 95; break;				// "Lamp"
			case 11: w= 18; h= 11; ox=559; oy= 95; break;				// "Key"
			case 12: w=  6; h=  5; ox=468; oy=118; break;				// 矢印
			case 13: w= 10; h= 12; ox=286; oy=106; break;				// 暗号化文字
		}
		Graphics gx=gr.create();
		gx.clipRect(x,y,w,h);
		gx.drawImage(Img,x-(ox+w*hol),y-(oy+h*ver),this);
		gx.dispose();
	}
	
	public int dsp_ref(int n, int c)									// Reflector の表示
	{
		int x=X-Refx[n]*5-6, y0=Y+n*12+5, y1=Y+Ref[n]*12+5;
		gr.setColor(new Color(c));
		gr.drawLine(X,y0,x,y0);
		gr.drawLine(X,y1,x,y1);
		gr.drawLine(x,y0,x,y1);
		return Ref[n];
	}
	
	public int dsp_rotor(int n, int r, int c, boolean d)				// Rotor の表示 (d: true=往路)
	{
		int l=2, x=X+120*r, y1=(R[r]+n)%26, y2=(d)? (Ro[r][n]+R[r])%26:(Rh[r][n]+R[r])%26;
		gr.setColor(new Color(c));
		gr.drawLine(x+((d)?119:51), Y+y1*12+5, x+((d)?51:119), Y+y2*12+5);	// 配線の表示
		if(c>0) l=(d)? 5:6;												// 文字の表示色
		int y=(d)? y1:y2;
		dsp_g(X+r*120+120,Y+y*12,l,(R[r]+26-y)%26,0);					// Rotor 文字の表示 (右)
		y=(d)? y2:y1;
		dsp_g(X+r*120+ 40,Y+y*12,l,(R[r]+26-y)%26,0);					// Rotor 文字の表示 (左)
		return y2;
	}
	
	public int inc_roter()												// Rotor の回転
	{
		int i=2;
		R[2]=(R[2]+1)%26;												// Fast Rotor
		if(R[2]==0)
		{
			R[1]=(R[1]+1)%26; i--;										// Medium Rotor
			if(R[1]==0)
			{
				R[0]=(R[0]+1)%26; i--;									// Slow Rotor
			}
		}
		return i;
	}
	
	public void clr_rotor(int r)										// Rotor の表示消去
	{
		gr.setColor(new Color(224,224,240));
		gr.fillRect(X+r*120+40+11,Y+5,69,301);
	}
	
	public void dsp_key(int n, int c)									// キーボードのキーの表示
	{
		gr.setColor(new Color(0,0,0));
		gr.fillOval(Kx[n]+Kox-2,Ky[n]+Koy-2,29,29);						// 黒い円を描く
		dsp_g(Kx[n]+Kox,Ky[n]+Koy,c,Qwer[n],5);							// 文字を表示
	}
	
	public void drw_line(int x0, int x1, int x2, int n, int d, int c)	// 水平線と矢印の表示
	{
		if(c==0) gr.clearRect(x0,n*12+28,6,5);							// 矢印の消去
		else	 dsp_g(x0, n*12+28,0,d,12);								// 矢印の表示
		gr.drawLine(X+x1,Y+n*12+5,X+x2,Y+n*12+5);						// 水平線の表示
	}

	public int dsp_route(int c)											// 暗号化経路の表示
	{
		int n=Key, r;
		gr.setColor(new Color(c));
		drw_line(443,371,439,n,0,c);									// 水平線と矢印の表示
		dsp_g(X+440,Y+n*12,(c==0)?1:3,n,0);								// key board の表示
		dsp_g(X+400,Y+n*12,0,n,0);										// Lamp board の表示
		for(r=2; r>=0; r--)												// Rotor の表示(往路)
		{
			n=dsp_rotor((n+26-R[r])%26,r,c,true);						// Rotor 内部結線の表示
			drw_line(83+r*120, r*120+11, r*120+40-1, n,0,c);			// 水平線と矢印の表示
		}
		dsp_g(X,Y+n*12,(c==0)?2:4,n,0);									// Reflector 文字の表示
		n=dsp_ref(n, c);												// Reflector 内部結線の表示
		dsp_g(X,Y+n*12,(c==0)?2:4,n,0);									// Reflector 文字の表示
		for(r=0;r<3;r++)												// Rotor の表示(帰路)
		{
			drw_line(102+r*120, r*120+11, r*120+40-1, n,1,c);			// 水平線と矢印の表示
			n=dsp_rotor((n+26-R[r])%26,r,c,false);						// Rotor 内部結線の表示
		}
		drw_line(462,371,399,n,1,c);									// 水平線と矢印の表示
		dsp_g(X+400,Y+n*12,(c==0)?0:4,n,0);								// Lamp の表示
		return n;
	}
	
	public void dsp_cip(int c)											// 暗号文の表示
	{
		if(Cx<515) dsp_g(Cx,Koy-26,0,c,13);								// 暗号化文字の表示
		Cx+=(Lw[c]+1);													// 表示位置の更新
	}
	
	public void paint(Graphics g)
	{
		int i=0,j, x=0, y=0, r;
		g.setColor(new Color(224,224,240));
		g.fillRect(X-61,Y,61,311);										// Reflector の塗りつぶし
		for(r=0;r<3;r++)
		{
			g.fillRect(X+r*120+56-5,Y,69,311);							// Rotor の塗りつぶし
			dsp_g(X+r*120+ 41,0,0,0,2);									// Rotor INC ボタン
			dsp_g(X+r*120+ 73,1,0,R[r],1);								// ローター設定 No.
			dsp_g(X+r*120+104,0,0,0,3);									// Rotor DEC ボタン
		}
		g.setColor(new Color(0,0,0));
		for(i=0;i<26;i++)
		{
			for(r=0;r<3;r++) g.drawLine(X+r*120+5,Y+i*12+5,X+r*120+40+5,Y+i*12+5);	// 水平線の表示
			g.drawLine(X+365,Y+i*12+5,X+445,Y+i*12+5);					// 水平線の表示
			dsp_ref(i,0); dsp_g(X,Y+i*12,2,i,0);						// Reflector の表示
			dsp_g(X+400,Y+i*12,0,i,0);									// Lamp の表示
			dsp_g(X+440,Y+i*12,1,i,0);									// Key の表示
		}
		for(r=0;r<3;r++)												// Rotor の表示
		{
			for(i=0;i<26;i++)
			{
				j=(R[r]+i)%26;
				dsp_rotor(j,r,0,true);									// Rotor 内部配線の表示
			}
		}
		dsp_g(14,339,0,0,6);											// "Reflector" の表示
		dsp_g(365,339,0,0,7); dsp_g(238,339,0,0,8); dsp_g(125,339,0,0,9);	// Rotor 名称の表示
		dsp_g(462,339,0,0,10); dsp_g(506,339,0,0,11);					// "Lamp", "Key" の表示
		g.setColor(new Color(153,153,153));								// 暗号文表示エリアの作成
		g.drawRect(X-62,Koy-31,514,20);
		g.setColor(new Color(255,255,255));
		g.fillRect(X-61,Koy-30,512,18);
		Cx=X-55;
		for(i=0;i0)			// CLR ボタンをクリック
		{
			dsp_g(485,448,0,1,4);										// CLR ボタンを表示
			Cq=0; Cx=X-55;
			gr.setColor(new Color(255,255,255));
			gr.fillRect(X-61,Koy-30,513,18);							// 暗号文表示をクリア
		}
		return true;
	}
	
	public boolean mouseUp(Event e, int mx, int my)
	{
		int i,j=0,k,r, n=(mx-(X+35))/120, x=(mx-(X+35))%120;
		if(inside(n,0,2) && inside(my,0,21))							// Rotor
		{
			if(inside(x, 6,32)) dsp_g(X+n*120+ 41,0,0,0,2);				// Rotor のボタンの表示を元に戻す
			if(inside(x,69,95)) dsp_g(X+n*120+104,0,0,0,3);				// 同上
		}
		if(inside(Key,0,25))											// Key がクリックされたときの処理
		{
			dsp_route(0x000000);										// 暗号化経路を元に戻す
			k=inc_roter();												// Rotor を回転させる
			for(r=2;r>=k;r--)											// その結果を表示
			{
				clr_rotor(r);
				for(i=0;i<26;i++) dsp_rotor(i,r,0,true);				// Rotor 内部配線の表示
				dsp_g(X+r*120+73,1,0,R[r],1);							// Rotor の No. の表示
			}
			dsp_key(Rewq[Key],0); dsp_key(Rewq[Crp],0);					// キーの表示を元に戻す
			Ac2.play();
		}
		if(inside(mx,485,511) && inside(my,448,470)) dsp_g(485,448,0,(Cq==0)?2:0,4);	// クリアボタンの表示
		return true;
	}
}
//
戻る