作者: Yさ
日時: 2002/5/29(17:37)
続々awkでPGその4

4.1.1 サンプル(1/2)
 では、今回の参考用Yさ版スクリプトです。
 長くなりますので、2つに分けてUPします。

 <<重要>> 今回のスクリプトだけでは動作しません。
          第二回の1/2のスクリプト(MAZE3DM1.000)および
          今回の2/2のスクリプト(MAZE3DS3.003)を
          編集して追加してください。

 (maze3d.002 と言う名前で編集した場合)
    jgawk -f maze3d.002 -v _DISP3D_TEST=1[ENTER]
   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 などとして、実行してください。

-----^ MAZE3DS2.002 ( date:02-05-01 time:00:00:00 ) --------------< cut here
# 3D迷路脱出Game Sub#2 - Disp 3D maze -  written by Yさ
function setDT(x,y,s,len,  r,l)
{ l=(x<2)?"":substr(DispTbl[y],1,x);
  r=(x+len>=31)?"":substr(DispTbl[y],x+len+1);
  DispTbl[y]=l s r;}
function setLine(x1,y1,x2,y2,s,  x,y,dx,dy)
{ dx=(x1<x2)?1:((x1>x2)?-1:0);  dy=(y1<y2)?1:((y1>y2)?-1:0);
  x=x1; y=y1; while(!(x==x2 && y==y2)){ setDT(x*2,y,s,2); x+=dx; y+=dy;}
  setDT(x*2,y,s,2);}
function put3D(  i,c,rdir,ldir)
{ # 表示テーブルを空白で埋める    0....5....0....5....0....5....0.
  for(i=0; i<16; ++i) DispTbl[i]="                                ";
  # 表示テーブルにセット
  if(NowDir==3)  rdir=0;  else  rdir=NowDir+1;  # 向かって右方向set
  if(NowDir==0)  ldir=3;  else  ldir=NowDir-1;  # 向かって左方向set
  xParam=NowXPos;  yParam=NowYPos;  c=put3Dsub(ldir,rdir,0);
  if(c!=1 && c!=2 && c!=3)          c=put3Dsub(ldir,rdir,1);
  if(c!=1 && c!=2 && c!=3)          c=put3Dsub(ldir,rdir,2);
  if(c!=1 && c!=2 && c!=3)          c=put3Dsub(ldir,rdir,3);
  # 表示
  system("cls");  # clear screen--if cls does not work, try "clear"
  for(i=0; i<16; ++i) print DispTbl[i];}
function put3Dsub(ldir,rdir,r,  c,lc,rc,lc2,rc2)
{ lc=Mtbl[xParam+XMove[ldir],yParam+YMove[ldir]]; writeLEFT(lc, r);  # 左側
  rc=Mtbl[xParam+XMove[rdir],yParam+YMove[rdir]]; writeRIGHT(rc, r); # 右側
  xParam+=XMove[NowDir]; yParam+=YMove[NowDir];     # 一歩前
  lc2=Mtbl[xParam+XMove[ldir],yParam+YMove[ldir]];  #       左側
  rc2=Mtbl[xParam+XMove[rdir],yParam+YMove[rdir]];  #       右側
  c=Mtbl[xParam,yParam];  writeFORWARD(c,lc,rc,lc2,rc2, r);          # 正面
  if(c==4)  writeKEY(r);  # 鍵
  if(c==3)  writeEXIT(r); # 出口
  return c;}
function writeKEY(r)
{ if(r==0) setDT(8*2,12,"$",2);
  if(r==1) setDT(8*2, 9,"・",2);}
function writeEXIT(r)
{ if(r==0){ setDT(4*2,2,"__",2); setDT(10*2,2,"_____ ",2*3);
    setDT(3*2,3," |__  \/  |   | ",2*9);
    setDT(3*2,4," |__  /\  |   | ",2*9);}
  if(r==1) setDT(6*2,5,"EXIT",2*4);
  if(r==2) setDT(7*2,7,"''''",4);}
function writeLEFT(lc,r)
{ if(lc==1 || lc==2){ set3D(LTW[r+1],sLTW); set3D(LBW[r+1],sLBW);} # 左側は 壁
  else{               set3D(LTR[r+1],sLTR); set3D(LBR[r+1],sLBR);}}#        道
function writeRIGHT(rc,r)
{ if(rc==1 || rc==2){ set3D(RTW[r+1],sRTW); set3D(RBW[r+1],sRBW);} # 右側は 壁
  else{               set3D(RTR[r+1],sRTR); set3D(RBR[r+1],sRBR);}}#        道
function writeFORWARD(c,lc,rc,lc2,rc2,r)
{ if(c==1 || c==2){  # 正面は壁?
    set3D(FTW[r+1],sFW);  set3D(FBW[r+1],sFW);
    if(lc==1 || lc==2){ set3D(LFW[r+1],sLFW);}              # 左は壁
    else{ set3D(LFTR[r+1],sLFTR);  set3D(LFBR[r+1],sLFBR);} #     道
    if(rc==1 || rc==2){ set3D(RFW[r+1],sRFW);}              # 右は壁
    else{ set3D(RFTR[r+1],sRFTR);  set3D(RFBR[r+1],sRFBR);} #     道
  }else{             # 正面は道
    # 左側に壁があれば描く
    if(lc!=1 && lc!=2 || lc2!=1 && lc2!=2 || c==3) set3D(LFW[r+1],sLFW);
    # すぐ左が壁ではないなら道を描く
    if(lc!=1 && lc!=2){ set3D(LFTR[r+1],sLFT2R); set3D(LFB2R[r+1],sLFB2R);}
    # 右側に壁があれば描く
    if(rc!=1 && rc!=2 || rc2!=1 && rc2!=2 || c==3) set3D(RFW[r+1],sRFW);
    # すぐ右が壁ではないなら道を描く
    if(rc!=1 && rc!=2){ set3D(RFTR[r+1],sRFT2R); set3D(RFB2R[r+1],sRFB2R);}
} }
-----$ MAZE3DS2.002 ( lines:64 words:274 bytes:3124 ) ------------< cut here


4.1.2 サンプル(2/2)

-----^ MAZE3DS3.003 ( date:02-05-01 time:00:00:00 ) --------------< cut here
# 3D迷路脱出Game Sub#3 - 3D maze data & sub -  written by Yさ
function init3Ddata()
{ # (road/wall) Left = L+Top/Bottom+Road/Wall[range +1]
  split("-1, 2, 0, 1@ 2, 4, 3, 4@-1, 2, 5, 6@-1, 2, 7, 7",LTR,"@");
  split("-1, 2, 0,13@ 2,10, 3,10@-1, 2, 5, 8@",           LBR,"@");
  split(" 0, 0, 1, 1@ 2, 2, 4, 4@ 5, 5, 6, 6@-1, 2, 7, 7",LTW,"@");
  split(" 0,15, 1,14@ 2,13, 4,11@ 5,10, 6, 9@-1, 2, 7, 8",LBW,"@");
  sLTR=sLBR="__"; sLTW="\"; sLBW="/";
  # (road/wall) Right = R+Top/Bottom+Road/Wall[range +1]
  split("-1, 2,15, 1@..., 4,13, 4@-1, 2,10, 6@-1, 2, 8, 7",RTR,"@");
  split("-1, 2,15,13@...,10,13,10@-1, 2,10, 8@",           RBR,"@");
  split("14, 1,15, 0@..., 4,13, 2@ 9, 6,10, 5@-1, 2, 8, 7",RTW,"@");
  split("14,14,15,15@...,11,13,13@ 9, 9,10,10@-1, 2, 8, 8",RBW,"@");
  sRTR=sRBR="__"; sRTW="/"; sRBW="\";
  # wall Forward = F+Top/Bottom+Wall[range +1]
  split(" 2, 1,13, 1@ 5, 4,10, 4@ 7, 6, 8, 6@",FTW,"@");
  split(" 2,13,13,13@ 5,10,10,10@ 7, 8, 8, 8@",FBW,"@");
  sFW="__";
  # wall Left - (road/wall) Forward = LF+Wall[range +1]
  split(" 1, 2, 1,13@ 4, 5, 4,10@ 6, 7, 6, 8@",LFW,"@");
  sLFW=" |";
  # road Left - (wall/road) Forward = LF+Top/Bottom/Bottom#2+Road[range +1]
  split("-1, 2, 1, 1@-1, 2, 4, 4@-1, 2, 6, 6@",LFTR,"@");
  split("-1, 2, 1,13@-1, 2, 4,10@-1, 2, 6, 8@",LFBR,"@");
# split("-1, 2, 1, 1@-1, 2, 4, 4@-1, 2, 6, 6@",LFT2R,"@");
  split("-1,-1, 1,13@-1,-1, 4,10@-1,-1, 6, 8@",LFB2R,"@");
  sLFTR=sLFBR="__"; sLFT2R="_ "; sLFB2R="_";
  # wall Right - (road/wall) Forward = RFW[range +1]
  split("14, 2,14,13@..., 5,11,10@ 9, 7, 9, 8@",RFW,"@");
  sRFW="| ";
  # road Right - (road/wall) Forward = RF+Top/Bottom/Bottom#2+Road[range +1]
  split("-1, 2,14, 1@-1, 2,11, 4@-1, 2, 9, 6@",RFTR,"@");
  split("-1, 2,14,13@-1, 2,11,10@-1, 2, 9, 8@",RFBR,"@");
# split("-1, 2,14, 1@-1, 2,11, 4@-1, 2, 9, 6@",RFT2R,"@");
  split("-1, 1,14,13@-1, 1,11,10@-1, 1, 9, 8@",RFB2R,"@");
  sRFTR=sRFBR="__"; sRFT2R=" _"; sRFB2R="_";}
function set3D(fmt,s,  i,wk,x1,y1,x2,y2)
{ if(""==fmt) return; else split(fmt,wk,",");
  x1=wk[1]+0; y1=wk[2]+0; x2=wk[3]+0; y2=wk[4]+0; for(i in wk) delete wk[i];
  if(x1>=0) setLine(x1,y1,x2,y2,s);
  else      setDT(x2*2+((y1==1)?1:0),y2,s,((y1<0)?-y1:y1));}
_DISP3D_TEST{ NowDir=0; NowXPos=2; NowYPos=4; split($1,wk,",");
  Mtbl[1,1]=int(wk[1]/100); Mtbl[2,1]=int(wk[1]/10)%10; Mtbl[3,1]=wk[1]%10;
  Mtbl[1,2]=int(wk[2]/100); Mtbl[2,2]=int(wk[2]/10)%10; Mtbl[3,2]=wk[2]%10;
  Mtbl[1,3]=int(wk[3]/100); Mtbl[2,3]=int(wk[3]/10)%10; Mtbl[3,3]=wk[3]%10;
  Mtbl[1,4]=int(wk[4]/100); Mtbl[2,4]=int(wk[4]/10)%10; Mtbl[3,4]=wk[4]%10;
  for(i=1; i<=4; ++i){ for(j=1; j<=3; ++j) printf Mtbl[j,i];  printf "\n";}
  for(i in wk) delete wk[i]; put3D(); printf("\nCOMMAND?>"); }
-----$ MAZE3DS3.003 ( lines:48 words:326 bytes:2676 ) ------------< cut here

 実行し、3*4 の大きさで表示したい迷路を、例えば 101,000,101,001 の
形式で指定してください。 指定例の意味は、
   101  - 3つ先:左右は壁
   000  - 2つ先:全て道
   101  - 1つ先:左右は壁
   001  - 自分がいる場所の左は道、右は壁
です。指定の迷路を(疑似)三次元表示します。
 なお 2バイト文字表示ができない環境の場合は、"\"や"/"を"-_"や"_-"
などとしてください。ただし、  \/    が   -__-  と表示されますので
                              /\         _--_
いまいちですが d(^^;)


4.2 プログラムの説明など
 表示は DispTbl[] を 1byte*32文字で16行分用意して、一度配列にセット
したものを表示するようにしています。 セットは次の順番に行ないます。
   1)自分のいる場所の左右と1つ先の正面の壁の有無をセット
   2)1つ先が道なら、その左右と、2つ先の正面の壁の有無をセット
   3)2つ先が道なら、その左右と、3つ先の正面の壁の有無をセット
   4)3つ先が道なら、その左右の壁の有無をセット

 (疑似)三次元表示用のデータは、関数 init3Ddata() で、表示用の文字、
場所(左右、正面)と距離(いくつ先か)でパターン化して準備してます。
 配列に格納する所の split() を使ったコンパクト化がミソです(^_^)b


 次回はいよいよ「(疑似)三次元迷路脱出ゲームでも作ろうかい?」講座の
最終回です。m(_ _)m Yさ