//
/* --------------------------------------------------------------------------------------------------------
turing.java チューリングマシン ver. 1.00 (JDK 1.02)
ueyama@infonet.co.jp 2009.03.14
-------------------------------------------------------------------------------------------------------- */
import java.applet.*;
import java.awt.*;
import java.util.*;
public class turing extends Applet implements Runnable
{
int Hx; // ヘッド表示X座標
int Ty=38; // テープ表示Y座標
int Bx[]={18,278,308,338,398,428,458,518,748,660,660}; // ボタン表示X座標
int By[]={90, 90, 90, 90, 90, 90, 90, 90, 90,344,370}; // ボタン表示Y座標
int Kx=405; // キー表示X座標
int Ky[]={154,204,240,266,292}; // キー表示Y座標
int Kq[]={26,8,8,2,26}; // 入力キーの数
int Kn=-1; // 入力可能キー列No.
int Kc=-1; // クリックされたキーNo.
int Tape[]=new int[512]; // テープのデータ
int Rt[][]=new int[256][5]; // ルール
int Rq=0; // ルール数
int Rx=-1, Ry=-1; // ルール表編集位置
int Rm=-1, Rn=-1; // ルール表旧編集位置
int Td=239; // テープの表示開始No.
int Rd=0; // ルールの表示開始No.
int Hp; // ヘッドの位置
int Hs=0; // ヘッドの状態
int Ra; // 適用されるルール No.
int Pn=0; // プログラム No.
int Sp=0; // 実行ステップ数
int Te=-1; // 編集テープNo.
int Dx=-1,Dy=-1; // ドラッグの処理用
int Mc=-1; // 0:Head, 1:Tape, 2:Btn, 3:Tbl, 4:Rule
int Mx=0;
int Wait=256;
int Bgc;
Thread th=null;
boolean Run=false;
boolean Err=false;
TextArea Rtxt=new TextArea(3,30);
Image Img;
// Ar[n][0]: ルールNo. [1]: ルール表示開始No. [2]: テープ表示開始No. [3]: ヘッド位置 [4]: テープデータ
int Ar[][]=new int[256][5]; // 履歴データ
// Rule[0]: テープデータ件数 (8bit), テープの表示開始位置 (8bit), ヘッドの位置 (8bit), 状態 (8bit)
// Rule[1]〜 テープデータ: テープ位置 (任意), データ (8bit)
// Rule[] 以後ルールデータ: 状態 (8), 入力 (4), 出力 (4), 移動 (4), 次の状態 (8bit)
// Rule[] 最後 負の数
int Rule[][]=new int[5][256];
String Rstr[]={"03efff00,fd01,fe00,ff01,0061101,0001101,0010000,0166019,0100101,0111101", // インクリメント
"04efff00,fc01,fd00,fe01,ff01,0001000,0010000,0066101,0166019,0177101", // 否定
"0ce9ff00,f301,f401,f500,f601,f701,f800,fa00,fb01,fc00,fd01,fe01,ff01,0066108,0002001,0013003,0077108,0166002,0100001,0111001,0262106,0202106,0213106,0222002,0233002,0366004,0300003,0311003,0463106,0403106,0412005,0422004,0433004,0561106,0501106,0510005,0666107,0677106,0700107,0711107,0722000,0733000,0866009,0877108,096600a,0900109,0911109,0926009,0936009,0a6610b,0a0010b,0a1110b,0a2000a,0a3100a,0b66019,0b7710b", // 加算
"08eafc00,f401,f501,f600,f701,f900,fa01,fb01,fc00,0001000,0010000,0066101,0166002,0177101,0261103,0201103,0210002,0300103,0311103,0366004,046610c,0402005,0413007,047710c,0566006,0500005,0511005,066210a,060210a,061310a,0622006,0633006,0766008,0700007,0711007,086310a,080310a,0812009,0822008,0833008,096110a,090110a,0910009,0a6610b,0a7710a,0b0010b,0b1110b,0b22004,0b33004,0c6600d,0c7710c,0d6600e,0d0010d,0d1110d,0d2600d,0d3600d,0e6610f,0e0010f,0e1110f,0e2000e,0e3100e,0f66010,0f7710f,1066111,1077010,1116112,1266019,1277112"}; // 減算
public void init() // 初期設定
{
int i,j;
String q;
String bg=getParameter("bgcolor");
Bgc=Integer.valueOf(bg,16).intValue();
setBackground(new Color(Bgc));
MediaTracker mt=new MediaTracker(this);
Img=getImage(getCodeBase(), getParameter("figure"));
setLayout(null);
add(Rtxt);
Rtxt.reshape(405,345,240,48);
mt.addImage(Img, 0);
try
{
mt.waitForID(0);
}
catch(InterruptedException e){};
for(i=0;i<4;i++) // ルールデータの設定
{
StringTokenizer st=new StringTokenizer(Rstr[i],",");
for(j=0; st.hasMoreTokens(); j++)
{
q=st.nextToken();
Rule[i][j]=Integer.valueOf(q,16).intValue(); // ルール
}
}
rule_init(Pn);
}
public void rule_init(int c) // ルールの初期化
{
int i,m,n;
m=Rule[c][0];
Hs=m%256; m/=256; // ヘッドの初期状態
Hp=m%256; m/=256; // ヘッドの位置
Td=m%256; // テープの表示開始位置
n=m/=256; // テープデータ件数
for(i=0; i<512;i++) Tape[i]=6; // テープのクリア
for(i=0; i<256;i++) Rt[i][0]=-1; // ルールのクリア
for(i=0;i0; i++) // ルールデータの読み込み
{
m=Rule[c][i+n+1];
Rt[i][4]=m%256; m/=256;
Rt[i][3]=m%16; m/=16;
Rt[i][2]=m%16; m/=16;
Rt[i][1]=m%16; m/=16;
Rt[i][0]=m%256;
}
Rq=i; // ルール数
Sp=0; Err=false;
}
public void start()
{
if(th==null)
{
th=new Thread(this);
th.start();
}
}
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 m, int n, int e, int c) // 画像の表示
{
int w=0, h=0, ox=0, oy=0;
Graphics gx=getGraphics();
switch(c)
{
case 0: w= 15; h= 11; ox= 66; oy= 24; break; // キー 状態用数字
case 1: w= 8; h= 13; ox= 456; oy= 24; break; // キー テープ用記号
case 2: w= 26; h= 20; ox= 0; oy= 38; break; // キー
case 4: w= 33; h= 38; ox= 0; oy= 0; break; // ヘッド
case 5: w= 25; h= 22; ox= 520; oy= 70; break; // テープ
case 6: w= 18; h= 12; ox= 66; oy= 0; break; // 状態用数字
case 7: w= 60; h= 13; ox= 52; oy= 57; break; // "状態 入力 出力 移動 次の状態"
case 8: w= 26; h= 23; ox= 52; oy= 70; break; // ボタン
case 9: w= 59; h= 16; ox= 52; oy=116; break; // ルール表の編集表示
case 10: w= 24; h= 4; ox= 351; oy= 63; break; // 速度表示用ドット
case 11: w=104; h= 15; ox= 757; oy= 0; break; // ポップアップメニュー選択項目
case 12: w= 83; h= 15; ox= 757; oy= 0; break; // ポップアップメニュー選択項目
case 13: w=106; h= 98; ox= 545; oy= 0; break; // ポップアップメニュー
case 14: w= 33; h= 9; ox= 0; oy=116; break; // ボタン説明
}
gx.clipRect(x, y, w, h);
if(e>0) gx.clearRect(x, y, w, h);
gx.drawImage(Img,x-(ox+m*w),y-(oy+n*h),this);
gx.dispose();
}
public void paint(Graphics g) // 画面の表示
{
int i,j,m;
g.clearRect(0, 0, size().width, size().height);
g.setColor(new Color (0x000000));
for(i=0; i<34; i++) g.drawRect(i*24-12,Ty,24,21); // テープの表示
dsp_tape(); // テープデータの表示
dsp_head(); // ヘッドの表示
dsp_g(70,93,0,0,1,13); // ポップアップメニューの表示
dsp_g(72,96,0,Pn,1,12); // メニュー選択項目の表示
dsp_tbl(); // 表の罫線の表示
dsp_rules(); // ルール表 の表示
for(i=0;i<11;i++) dsp_btn(i,0); // ボタンの表示
for(i=0;i<9;i++) dsp_g(Bx[i]-4,118,(i==6)?9:i,0,0,14); // ボタンの説明表示
dsp_g(Bx[1]+Mx*10+32,84,0,0,1,10); // 実行速度表示用ドットの表示
for(i=0;i<5;i++) dsp_g(Kx-85+((i==4 || i==0)?15:0),Ky[i]+4,i,0,1,7); // キーの説明の表示
for(i=0;i<5;i++) dsp_keys(i,0); // キーの表示
}
public void dsp_head() // ヘッドの表示
{
Hx=(Hp-Td)*24+8; // ヘッド表示座標
dsp_g(Hx,0,0,0,1,4); // ヘッドの表示
dsp_g(Hx+7,8,Hs,0,1,6); // ヘッドの状態の表示
}
public void dsp_tape() // テープデータの表示
{
int i,m;
for(i=0;i<32;i++) // テープデータの表示
{
dsp_g(i*24+12,Ty,0,0,1,5); // テープの表示
m=Tape[Td+i];
dsp_g(i*24+20,Ty+5,(m==6)?8:m,1,1,1); // (m==6)?8:m は空白の処理
}
}
public void dsp_rule(int m, int n) // ルールの表示
{
int j=Rt[m][n], k=(Ra==m)?2:1; // ルールNo.
if(Rt[m][0]>=0)
{
if(m>Rq) dsp_g(23+n*60,172+(m-Rd)*17+1,8,k,1,1); // 状態
else
{
if(n==0 || n==4) dsp_g(23+n*60,172+(m-Rd)*17+1,j,k,1,0); // 状態
else if(n==3) dsp_g(26+n*60,172+(m-Rd)*17,j+9,k,1,1); // 移動
else dsp_g(26+n*60,172+(m-Rd)*17,j,k,1,1); // 入出力
}
}
}
public void dsp_rules() // ルール表 の表示
{
int i,j;
Ra=-1;
Err=false;
for(i=0;i12)?Ra-6:0;
for(i=0;i<13;i++) for(j=0;j<5;j++) if(i+Rd0 && Hs<25)?2:0; break; // Rule Clear
case 1: m=6; n=1; k=(Wait<4096)?0:2; break; // Slow
case 2: m=3; n=(Run)?1:0; k=(Hs==25 || Err)?2:0; break; // Run
case 3: m=9; n=1; k=(Wait>16)?0:2; break; // Fast
case 4: m=0; n=0; k=(Sp==0)?2:0; break; // Back
case 5: m=6; n=0; k=(Hs==25 || Err)?2:0; break; // Step
// case 6: m=12; n=1; k=(Sp==0)?2:0; break; // Reset
case 6: m=0; n=1; k=(Sp==0)?2:0; break; // Reset
case 7: m=9; n=0; k=(Sp==0)?2:0; break; // Clear
case 8: m=12; n=0; k=(Sp>0 && Hs<25)?2:0; break; // Tape Clear
case 9: m=15; n=1; k=(Sp>0 && Hs<25)?2:0; break; // Write
case 10: m=15; n=0; k=(Sp>0 && Hs<25)?2:0; break; // Read
}
dsp_g(Bx[i],By[i],m+((c==0)?k:c),n,1,8); // ボタンの表示
}
public void dsp_key(int m, int n, int c) // キー(1個)の表示
{
int j=n%13, k=n/13;
switch(m)
{
case 0: dsp_g(Kx+j*30,Ky[0]+k*24,1,c,1,2); // 状態キーの表示
dsp_g(Kx+j*30+6,Ky[0]+k*24+4,n,0,0,0); break; // 文字の表示
case 1: dsp_g(Kx+n*30,Ky[1],1,c,1,2); // 入力キーの表示
dsp_g(Kx+n*30+10,Ky[1]+3,n,0,0,1); break; // 文字の表示
case 2: dsp_g(Kx+n*30,Ky[2],0,c,1,2); // 出力キーの表示
dsp_g(Kx+n*30+10,Ky[2]+3,n,0,0,1); break; // 文字の表示
case 3: dsp_g(Kx+n*30,Ky[3],0,c,1,2); // 移動キーの表示
dsp_g(Kx+n*30+10,Ky[3]+3,n+9,0,0,1); break; // 文字の表示
case 4: dsp_g(Kx+j*30,Ky[4]+k*24,0,c,1,2); // 状態キーの表示
dsp_g(Kx+j*30+6,Ky[4]+k*24+4,n,0,0,0); break; // 文字の表示
}
}
public void dsp_keys(int m, int c) // キー(一組)の表示
{
int i;
switch(m)
{
case 0: for(i=0;i<26;i++) dsp_key(m,i,c); break; // 状態キーの表示
case 1: for(i=0;i<8;i++) dsp_key(m,i,c); break; // 入力キーの表示
case 2: for(i=0;i<8;i++) dsp_key(m,i,c); break; // 出力キーの表示
case 3: for(i=0;i<2;i++) dsp_key(m,i,c); break; // 移動キーの表示
case 4: for(i=0;i<26;i++) dsp_key(m,i,c); break; // 状態キーの表示
}
}
public void dsp_tbl() // ルール表 (罫線) の表示
{
int i;
for(i=0;i<5;i++) dsp_g(i*60, 152,i,0,1,7); // 表の見出しの表示
Graphics gx=getGraphics();
gx.clearRect(0,169,300,221);
gx.setColor(new Color(0xcccccc)); // 表 (罫線) を描く
for(i=0;i<12;i++) gx.drawLine(0,186+i*17,300,186+i*17);
for(i=1;i<5;i++)
{
gx.setColor(new Color((i==2)?0:0xcccccc));
gx.drawLine(i*60,170,i*60,390);
}
gx.setColor(new Color(0x000000));
gx.drawRect(0,169,300,221);
gx.dispose();
}
public void draw_rect(int x, int y, int m, int c) // テープ、ルール表入力位置の表示
{
Graphics gx=getGraphics();
gx.setColor(new Color((c==0)?Bgc:0xff9999)); //
switch(m)
{
case 0: gx.drawRect(x,y,22,19); break; // テープ
case 1: gx.drawRect(x,y,58,15); break; // ルール表
}
gx.dispose();
}
public void run()
{
int i;
while(true)
{
try
{
th.sleep(Wait);
}
catch (InterruptedException e){}
if(Run)
{
tur_calc();
dsp_g(Hx,0,1,0,1,4); // ヘッドの消去
dsp_head();
dsp_tape(); // テープデータの表示
dsp_rules(); // ルール表 の表示
if(Hs==25) // 停止 (H)
{
Run=false;
for(i=0;i<11;i++) dsp_btn(i,0); // ボタンの表示
}
}
}
}
public void stop()
{
if(th!=null)
{
th.stop();
th=null;
}
}
public void tur_calc() // 計算の実行
{
int i, m=-1;
Ar[Sp][0]=Ra; // 履歴:ルール No.
Ar[Sp][1]=Rd; // ルールの表示開始位置
Ar[Sp][2]=Td; // テープの表示開始位置
Ar[Sp][3]=Hp; // ヘッドの位置
Ar[Sp][4]=Tape[Hp]; // テープのデータ
for(i=0; i=0) Tape[Hp]=Rt[Ra][2]; // テープデータ
Hs=Rt[Ra][4]; // ヘッドの状態
Hp+=(Rt[Ra][3]==0)?-1:1; // ヘッドの位置
Sp++;
}
public boolean mouseDown(Event e, int mx, int my) // マウスがクリックされたときの処理
{
int i, j, k, l, m=-1, n=0;
String p,q,s;
boolean f=false;
Kc=-1;
Dx=mx; Dy=my;
if(Mc==1 && Te>=0) // テープクリック後であれば…
{
draw_rect((Te-Td)*24+13,Ty+1,0,0); // テープの編集位置表示を消す
}
if(Mc==3) draw_rect(Rm*60+1,170+Rn*17,1,0); // ルール編集位置赤表示を元に戻す
for(i=0;i<5;i++) dsp_keys(i,(i==Rx)?1:0); // 入力キーを元に戻す
if(inside(my,38,58)) // テープをクリック
{
Mc=1;
Te=(mx+12)/24+Td-1; // テープ編集位置
draw_rect((Te-Td)*24+13,Ty+1,0,1); // テープの編集位置表示
Rx=1;
}
if(inside(mx,Hx,Hx+33) && my<38) Mc=0; // ヘッドをクリック
if(inside(mx,70,176) && inside(my,93,114)) // ポップアップメニューをクリック
{
Mc=4;
Dy=my;
dsp_g(70,93,1,0,1,13); // ポップアップメニューの表示
dsp_g(72,96,0,Pn,1,12); // メニュー選択項目の表示
for(i=0; i<5; i++) dsp_g(71,115+i*15,(i==Pn)?1:0,i,1,11); // メニューリストの表示
}
if(inside(mx,71,175) && inside(my,115,190)) // メニューリストをクリック
{
Mc=-1;
Pn=(my-115)/15;
dsp_g(70,93,0,0,1,13); // ポップアップメニューの表示
dsp_g(72,96,0,Pn,1,12); // メニュー選択項目の表示
rule_init(Pn);
dsp_g(Hx,0,1,0,1,4); // ヘッドの消去
dsp_head();
dsp_tape(); // テープデータの表示
dsp_tbl();
dsp_rules(); // ルール表 の表示
for(i=0;i<11;i++) dsp_btn(i,0); // ボタンの表示
}
for(m=0;m<11;m++) if(inside(mx,Bx[m],Bx[m]+26) && inside(my,By[m],By[m]+23)) // ボタンをクリック?
{
Mc=2;
Rx=-1;
switch(m)
{
case 0: // ルールのクリア
dsp_btn(m,1);
for(i=0;i<256;i++) Rt[i][0]=-1; // ルールのクリア
dsp_rules();
break;
case 1: if(Wait<4096) { // Slow ボタンをクリック
Wait*=2; Mx--;
dsp_btn(m,1);
dsp_g(Bx[1]+Mx*10+32,84,0,0,1,10);} break; // ドットの表示
case 2: if(Hs<25 && !Err) { // RUN ボタンをクリック
dsp_g(Bx[2],By[2],4,(Run)?1:0,1,8); // ボタンの表示
Run=!Run;} break;
case 3: if(Wait>16) { // Fast ボタンをクリック
Wait/=2; Mx++;
dsp_btn(m,1);
dsp_g(Bx[1]+Mx*10+32,84,0,0,1,10);} break; // ドットの表示
case 4: if(Sp>0) {Sp--; // 戻るボタンをクリック
Ra=Ar[Sp][0]; // 履歴:ルール No.
Rd=Ar[Sp][1]; // ルールの表示開始位置
Td=Ar[Sp][2]; // テープの表示開始位置
Hp=Ar[Sp][3]; // ヘッドの位置
Hs=Rt[Ra][0]; // ヘッドの状態
Tape[Hp]=Ar[Sp][4]; // テープのデータ
Err=false;
f=true;} break;
case 5: if(Hs<25 && !Err) { // ステップボタンをクリック
tur_calc(); // 計算の実行
f=true;} break;
/*
case 6: if(Sp>0) { // リセットボタンをクリック
for(i=0;i<34;i++) dsp_g(i*24-12,Ty,0,0,1,3); // テープの表示
for(i=0;i<24;i++) dsp_g(i*33,0,1,0,1,4); // ヘッドの消去
Sp=0;
Err=false;
f=true;} break;
*/
case 7: if(Sp>0) { // クリアボタンをクリック
rule_init(Pn);
for(i=0; i<24; i++) dsp_g(i*33,0,1,0,1,4); // ヘッドの消去
Sp=0;
Err=false;
f=true;} break;
case 8:
dsp_btn(m,1);
for(i=0; i<512;i++) Tape[i]=6; // テープのクリア
dsp_tape(); // テープデータの表示
break;
case 9:
dsp_btn(m,1);
for(i=0,j=0;i<512;i++) if(Tape[i]!=6) j++;
s=Integer.toString(Hs+Hp*0x100+Td*0x10000+j*0x1000000,16);
for(j=s.length();j<8;j++) s="0"+s;
Rtxt.appendText(s+"\n");
for(i=0;i<512;i++)
{
if(Tape[i]!=6)
{
s=Integer.toString(i*0x100+Tape[i],16);
for(j=s.length();j<5;j++) s="0"+s;
Rtxt.appendText(s+"\n");
}
}
for(i=0;i170) // ルール表をクリック
{
Mc=3; // ルール表をクリック
Rx=mx/60; Ry=(my-170)/17;
draw_rect(Rx*60+1,170+Ry*17,1,1); // 編集位置を赤表示
for(i=0;i<5;i++) dsp_keys(i,(i==Rx)?1:0); // キーの表示
}
if(mx>Kx && my>Ky[0] && Rx>=0) // キーをクリック
{
for(i=0;i=0)
{
Rx++; Rx%=5;
if(Rx==0) Ry++;
if(Ry==13)
{
Rd++;
Ry--;
for(i=0;i<13;i++) for(j=0;j<5;j++) if(i+Rd戻る