ぷよぷよのアルゴリズムとMSX BASIC

この記事はMSX Advent Calendar 2015の4日目の記事(にでっち上げた記事)です。

今から20年ほど前、長谷川少年はコンパイルから発売された「ぷよぷよ」というゲームに大ハマりしていました。
目をつぶると上から「ぷよ」が落ちてくるのが見えるレベルに。

そして、当時「物理部」という部活でプログラミングや電子工作をしていた長谷川少年は部活の場で大手を振って「ぷよぷよ」で対戦がしたく、当時使っていたパソコンMSX2+で対戦ぷよぷよを作ろうと思い立ちました。

MSX BASIC

使用言語はMSX BASICです。Visualとか付かないBASIC。
知らない方はなかなか想像が付かないと思いますがMSX BASICは以下の様な言語でした。

  • プログラムは1行ごとに行番号を付ける。行番号を指定してジャンプが可能。
  • 関数という概念は無い。GOSUBという特殊なジャンプをするとRETURN命令で元の場所に戻ってこられる。GOSUBの”SUB”はサブルーチン。今だとサブルーティンって言いそうだけど当時はサブルーチンと言っていた。
  • 変数はすべてグローバルスコープ。なので変数を使って関数みたいなことは可能。
  • forループやif構造は(現在の言語と比べると少し構造が違うものの)存在する。

こんなのです。

10 FOR I = 0 TO 100
20 IF I MOD 3 = 0 THEN GOSUB 110 ELSE GOSUB 100
30 NEXT
100 PRINT "Ping ":RETURN
110 PRINT "Pong "+CHR$(I):RETURN

命令を : でつないで1行に複数命令を書くことも可能でこの例の100行、110行ではそんな風にしています。
プログラム表示しても色も付かずカーソルも自由に動かず、恐ろしく可読性が低いですが当時はそんなもんだと思っていました。

「ぷよぷよ」のルール

皆さんご存じかと思いますが「ぷよぷよ」ってこんなゲームです。(細かいルールは省いています。)

  • 何色かの「ぷよ」が上から落下し、それをフィールドに積み上げる。
  • 同色の「ぷよ」が4つ以上つながるとその「ぷよ」は消える。4つ以上つながっていさえすれば形を問わずすべて消える。
  • 「ぷよ」が消えて空白ができるととその上の「ぷよ」はそれぞれ空白が無くなるまで落下する。
  • 「ぷよ」が落下した時に複数色の「ぷよ」が同時に4つ以上つながった場合その全てが消える。

参考: メガドライブ版「ぷよぷよ」(のWiiバーチャルコンソール)

01
(画像は上記URLより)

BASICで「盤面が与えられた時にどのぷよが消えるか」を計算するアルゴリズムが当時どうしても思いつかず「ぷよぷよ」にハマった時からずっと考えていました。
そしてある授業中に突然アルゴリズムがひらめきました。

以下がそのアルゴリズムのご紹介です。

ぷよぷよのアルゴリズム

フィールドが以下の様になっていると想定します。形だけ見ると「連鎖を作ろうとしてたけどやらかしちゃった」形ですね。
この場合、赤い「ぷよ」が消えることになります。

puyo-01

基本的な方針としては「左上から注目する場所(セル)を右下まで走査する」「注目したセルにある「ぷよ」がいくつつながっているか調べる」です。

1. まず、左上のセルに注目します。

puyo-02

2. 左上のセルには何も無かったので次のセルに注目します。

puyo-03

このセルには赤い「ぷよ」が居ました。
これ以降はこの赤い「ぷよ」がいくつつながっているか(=消せるか)をチェックします。

3.「この「ぷよ」のまわりをチェックするよ」という意味で1とフラグを立てます。

puyo-04

4. 1のフラグの上下左右を見て同じ色があればそこに1とフラグを立てます。

puyo-05

5. 上下左右を全部見たら「この「ぷよ」のまわりのチェックは完了したよ」の意味で自分自身に2とフラグを立てます。

puyo-06

6. 左上から右下まで走査して1のフラグが立った「ぷよ」を探し、見つかれば上下左右をチェックします。(「ぷよ」のつながっている形によっては1のフラグが立った「ぷよ」は複数存在します。)

puyo-07

上下左右に同色がありフラグが立っていなければ1を立てます。

7. 1が無くなるまで処理を繰り返します。

puyo-08

このとき、盤面で2のフラグが立っている「ぷよ」の個数をチェックし、それが4個以上であればそれを全て消します。
今回の例では赤「ぷよ」が消せます。

8. 注目するセルを次のセルに変更し、同じことを繰り返します。

puyo-09

puyo-10

puyo-11

この緑の「ぷよ」は1つしか無いので消すことが出来ませんでした。

という様に注目するセルをずらしていって右下まで完了したら1回のチェックが完了です。

「ぷよぷよ」の盤面は横6x縦12ほどですが、これを2プレイヤー分処理してもMSX2+のBASIC(+ BASICコンパイラ)で処理が十分間に合いました。
(当時のCPUはZ80 3.58MHzです。BASICが使えるメモリは16KBぐらい。今だと電子工作で使う数百円の「マイコン」以下ですね。)

こうして解説を書いてみるとなんてことないですが後にも先にもあの瞬間が一番「自分天才!」と思った瞬間でした。

そしてこうやって生み出された「ぷよぷよ」で思う存分(学校で)対戦し、友人も「ぷよぷよ」にハマり、しばらくみんなで「ぷよぷよ」ばっかりやって過ごしていました。

これがそのスクリーンショットです。
相殺の無いルールなのでプレイヤー2、優勢ですね。
タイトルではプレイヤー1と2のスピードや色数を設定できる様になっています。(LEVELって何だったかな…)

A1

A0


「ぷよ」の絵は雑誌などのスクリーンショットを見ながらグラフィックエディタでぽちぽち作っていました。
左のスクリーンショットがその素材です。「ぷよ」って上下左右に同じ色がいるかいないかで形が違ったり目がそっち見てたりするのですがその全パターンを作っています。

右はタイトルやゲーム中で使う「ぷよ」以外の素材たちです。中ほどの数字のフォントが当時大好きだったコナミっぽい作りになっています。

PUYO

TITLE-2


MSXは画面が4枚あったので画面0を表示してゲーム進行、非表示の画面1と画面2にこの2枚を置いて画面0に随時コピーして使っています。もしかしたらもう1枚を使ってオフスクリーン描画していた可能性もありますが…。記憶ナシです。読解力のある方、後述のソースからどうなっているか調べてみてください。(笑)

プログラム

そして出来たものがこれ。
いやあガチですねえ。
当時は10000行以降に再利用するサブルーチンを置いて、行番号とサブルーチンの対応をノートにメモしながら作っていました。
同様に変数もMSXの場合2文字までしか変数名が付けられなかったのでメモ必須。

100 SAVE"PUYO.BAS
110 POKE&HFBB0,1:SCREEN5:CLEAR20:MAXFILES=0
120 SETPAGE0,1:COLOR15,0,0:BLOAD"PUYO.SC5",S
130 SETPAGE0,2:COLOR15,0,0:BLOAD"TITLE-2.SC5",S
140 SETPAGE0,3:COLOR15,0,0:BLOAD"MAIN.SC5",S
150 SETPAGE0,1:COLOR=RESTORE:SETPAGE0,0
160 _TURBO ON
170 DEFINTA-Z:DIMSC(1,7,13),JO(1,5,11),P(1,1,1),K(3,1),PI(1,1),P2(1,1),TT(1,1,1,1),OF(1),C(1),J(1),V(1),OT(1),OP(1),SH(5,11),RN(18),DK(5),NA(11),PT(1),X(2),PR(1),PS(5),PK(1),ST(1,2),S2(1,5,11),KC(1)
175 DIM KK(1),KF(1),R(1),D(1),N(1),T(1),A(1),B(1),CC(1)
180 PS=1:R=RND(-TIME):FORI=0TO1:ST(I,0)=0:ST(I,1)=10:ST(I,2)=4:NEXTI
190 FORI=0TO3:READK(I,0),K(I,1):NEXTI:DATA1,-1,1,1,-1,1,-1,-1
200 FORD=0TO1:FORC=0TO1:FORB=0TO1:FORA=0TO1:READTT(A,B,C,D):NEXTA,B,C,D:DATA0,1,2,6,3,8,10,15,4,7,9,12,5,14,13,11
210 FORI=1TO16:READRN(I):NEXTI:DATA0,8,16,32,64,128,256,512,999,999,999,999,999,999,999,999,999,999
220 FORI=1TO5:READDK(I):NEXTI:DATA0,3,6,12,24:FORI=1TO11:READNA(I):NEXTI:DATA0,0,0,0,2,3,4,5,6,7,10
230 '
240 SETPAGE0,0:COLOR1,15,1:CLS:Y=0:COPY(0,96)-(255,122),2TO(60,160),0
250 FORJ=0TO1:FORI=JTO44STEP2:COPY(0,48+I)-(255,48+I),2TO(0,30+I),0:FORT=0TO500:NEXTT,I,J:FORI=0TO3:COPY(0,130+10*I)-(255,130+10*I+9),2TO(55,90+I*16),0:NEXTI
260 FORI=0TO3:IFI=YTHENCOPY(0,0)-(15,15),1TO(35,87+I*16),0,TPSET:NEXTIELSELINE(35,87+I*16)-(50,102+I*16),15,BF:NEXTI
270 FORJ=0TO1:FORI=0TO2:COPY(ST(J,I)*11,170)-(ST(J,I)*11+10,179),2TO(147+J*45,106+I*16),0:NEXTI,J
280 FORT=0TO300:IFSTRIG(0)ORSTRIG(1)ORSTRIG(2)THENV(0)=0:V(1)=0:T=300:NEXTT:GOTO350ELSENEXTT
290 S0=STICK(0)ORSTICK(2):S1=STICK(1):Y=Y+((S0ORS1)=1)-((S0ORS1)=5):IFY<0THENY=0ELSEIFY>3THENY=3
300 IFY<>0THENST(0,Y-1)=ST(0,Y-1)+(S0=7)-(S0=3):ST(1,Y-1)=ST(1,Y-1)+(S1=7)-(S1=3)
310 FORJ=0TO1:FORI=0TO1
320 IFY=1ORY=2THENIFST(J,I)<0THENST(J,I)=0ELSEIFST(J,I)>11+I*9THENST(J,I)=11+I*9
325 IFY=3THENIFST(J,2)<2THENST(J,2)=2ELSEIFST(J,2)>5THENST(J,2)=5
330 NEXTI,J
340 GOTO 260
350 '●
360 FORI=0TO1:FORY=1TO12:SC(I,0,Y)=7:SC(I,7,Y)=7:FORX=1TO6:SC(I,X,Y)=6:JO(I,X-1,Y-1)=0:NEXTX,Y,I
370 FORI=0TO1:FORX=0TO7:SC(I,X,13)=7:NEXTX,I
380 COLOR15,0,0:CLS:FORJ=0TO9:FORI=JTO212STEP9:COPY(0,I)-(255,I),3TO(0,I),0:NEXTI,J:FORPL=0TO1:A=0:B=0:PT(PL)=0:OT(PL)=0:PK(PL)=0:GOSUB10070:NEXTPL
390 FORPL=0TO1:IFST(PL,0)=0THEN410
400 FORYY=0TOST(PL,0):FORXX=0TO5:SC(PL,XX+1,0)=5:NEXTXX:GOSUB10000:NEXTYY
410 NEXTPL:PL=1
420 GOSUB10050:FORI=0TO1:P(I,0,0)=3:P(I,0,1)=-1:P(I,1,0)=3:P(I,1,1)=0:NEXTI
430 P2(0,0)=RND(1)*ST(0,2):P2(0,1)=RND(1)*ST(0,2):P2(1,0)=RND(1)*ST(1,2):P2(1,1)=RND(1)*ST(1,2)
440 FORJ=0TO1:FORI=0TO1:COPY(0,P2(J,I)*16)-(15,P2(J,I)*16+15),1TO(108+J*24,16*I+15),0:NEXTI,J
450 '●NEXT
460 GOSUB1230:GOSUB1470:PK(PL)=PK(PL)+2
470 IFPT(PL)=>70THENPR(PL)=1ELSEPR(PL)=0
480 J(PL)=0:C(PL)=0:OF(PL)=0:PI(PL,0)=P2(PL,0):PI(PL,1)=P2(PL,1):P2(PL,0)=RND(1)*ST(PL,2):P2(PL,1)=RND(1)*ST(PL,2):P(PL,0,0)=3:P(PL,0,1)=-1:P(PL,1,0)=3:P(PL,1,1)=0
490 FORI=0TO1:COPY(0,P2(PL,I)*16)-(15,P2(PL,I)*16+15),1TO(108+PL*24,16*I+15),0:NEXTI:IFSC(PL,3,1)<>6THEN1340
500 '●めいん
510 IFPS=1THENPL=PLXOR1
515 ONKF(PL)GOTO1470,2000,1470
520 IFPT(PL)<70THENPR(PL)=0
530 IFPR(PL)=1THEN10120
540 IFOT(PL)=1THEN1210
550 IFPL=0THENS=STICK(0)ORSTICK(2):ST=STRIG(0)ORSTRIG(2)ELSES=STICK(1):ST=STRIG(1)
560 IFC(PL)=0OR(S=4ORS=5ORS=6)THENIFOF(PL)=0THENFORI=0TO1:P(PL,I,1)=P(PL,I,1)+1:NEXTI
570 A=(S=6ORS=7ORS=8):B=(S=2ORS=3ORS=4):X=A-B
580 FORI=0TO1:IFSC(PL,P(PL,I,0)+X,P(PL,I,1))<>6THENI=1:NEXTI:GOTO600ELSENEXTI
590 P(PL,0,0)=P(PL,0,0)+X:P(PL,1,0)=P(PL,1,0)+X
600 IFSTTHENGOSUB1380
610 FORI=0TO1:SC(PL,P(PL,I,0),P(PL,I,1))=PI(PL,I):NEXTI
620 GOSUB1040:GOTO1110
630 FORI=0TO1:SC(PL,P(PL,I,0),P(PL,I,1))=6:NEXTI
640 C(PL)=(C(PL)+1)MODST(PL,1):GOTO 500
1000 '
1010 FORY=0TO11:FORX=0TO5
1020 COPY(JO(PL,X,Y)*16,SC(PL,X+1,Y+1)*16)-(JO(PL,X,Y)*16+15,SC(PL,X+1,Y+1)*16+15),1TO(X*16+PL*152+4,Y*16+12),0
1030 NEXTX,Y:RETURN
1040 '
1050 FORY=-3TO1:FORX=-3TO3
1060 IFP(PL,1,0)+X<0ORP(PL,1,1)+Y<0THEN1100
1070 SX=P(PL,1,0)+X:SY=P(PL,1,1)+Y
1080 IFSX<0ORSX>5ORSY>11THEN1100
1090 COPY(JO(PL,SX,SY)*16,SC(PL,SX+1,SY+1)*16)-(JO(PL,SX,SY)*16+15,SC(PL,SX+1,SY+1)*16+15),1TO(SX*16+PL*152+4,SY*16+12),0
1100 NEXT X,Y:RETURN
1110 '●おちる?
1120 ONJ(PL)+1GOTO1130,1140,1150,1140
1130 IFSC(PL,P(PL,1,0),P(PL,1,1)+1)<>6THEN1160ELSEOF(PL)=0:GOTO 630
1140 IFSC(PL,P(PL,0,0),P(PL,0,1)+1)=6ANDSC(PL,P(PL,1,0),P(PL,1,1)+1)=6THENOF(PL)=0:GOTO630ELSE1170
1150 IFSC(PL,P(PL,0,0),P(PL,0,1)+1)<>6THENELSEOF(PL)=0:GOTO630
1160 IFOF(PL)=0THEN OF(PL)=1:GOTO630ELSEIFOF(PL)>3THEN450ELSEOF(PL)=OF(PL)+1:GOTO630
1170 '●ぽと
1180 IFOF(PL)=0THENOF(PL)=1:GOTO500ELSEIFOF(PL)<6THENOF(PL)=OF(PL)+1:GOTO500
1190 IFSC(PL,P(PL,0,0),P(PL,0,1)+1)<>6ANDSC(PL,P(PL,1,0),P(PL,1,1)+1)<>6THEN450
1200 FORI=0TO1:IFSC(PL,P(PL,I,0),P(PL,I,1)+1)=6THENOP(PL)=I:OT(PL)=1:NEXTIELSENEXTI
1210 SC(PL,P(PL,OP(PL),0),P(PL,OP(PL),1))=6:P(PL,OP(PL),1)=P(PL,OP(PL),1)+1:SC(PL,P(PL,OP(PL),0),P(PL,OP(PL),1))=PI(PL,OP(PL))
1220 GOSUB1000:IF SC(PL,P(PL,OP(PL),0),P(PL,OP(PL),1)+1)=6THEN500ELSEOT(PL)=0:GOTO450
1230 '●ぺと
1240 FORI=1TO6:SC(PL,I,0)=6:NEXTI
1250 FORY=0TO11:FORX=0TO5:CK=SC(PL,X+1,Y+1)
1260 A0=0:A1=0:A2=0:A3=0
1270 IFCK=6ORCK=5THEN1320
1280 IFSC(PL,X+1,Y)=CKTHENA0=1
1290 IFSC(PL,X+1,Y+2)=CKTHENA1=1
1300 IFSC(PL,X,Y+1)=CKTHENA2=1
1310 IFSC(PL,X+2,Y+1)=CKTHENA3=1
1320 JO(PL,X,Y)=TT(A0,A1,A2,A3):A=JO(PL,X,Y):COPY(A*16,SC(PL,X+1,Y+1)*16)-(A*16+15,SC(PL,X+1,Y+1)*16+15),1TO(X*16+PL*152+4,Y*16+12),0
1330 NEXTX,Y:RETURN
1340 '●END
1350 FORY=0TO11:FORX=0TO5:JO(PL,X,Y)=0:NEXTX,Y:FORI=0TO11:FORY=11TO0STEP-1:FORX=1TO6:SC(PL,X,Y+2)=SC(PL,X,Y+1):SC(PL,X,Y+1)=6:NEXTX,Y:GOSUB1000:NEXTI
1360 V(PLXOR1)=V(PLXOR1)+1:GOSUB10050
1370 IFSTRIG(0)ORSTRIG(1)THEN350ELSE1370
1380 '●カイテン
1390 AA=(J(PL)+1)MOD4:IFSC(PL,P(PL,0,0)+K(AA,0),P(PL,0,1)+K(AA,1))<>6THEN1410
1400 FORI=0TO1:P(PL,0,I)=P(PL,0,I)+K(AA,I):NEXTI:GOTO1460
1410 IFSC(PL,P(PL,0,0)+1,P(PL,0,1))<>6ANDSC(PL,P(PL,0,0)-1,P(PL,0,1)-1)<>6THENRETURN
1420 ONJ(PL)+1GOTO 1430,1440,1450,1460
1430 IFSC(PL,P(PL,1,0)-1,P(PL,0,1)+1)=6THENP(PL,0,1)=P(PL,0,1)+1:P(PL,1,0)=P(PL,1,0)-1:GOTO1460ELSERETURN
1440 IFSC(PL,P(PL,0,0)-1,P(PL,1,1)-1)=6THENP(PL,0,0)=P(PL,0,0)-1:P(PL,1,1)=P(PL,1,1)-1:GOTO1460ELSERETURN
1450 IFSC(PL,P(PL,1,0)+1,P(PL,1,1)+1)=6THENP(PL,1,0)=P(PL,1,0)+1:P(PL,1,1)=P(PL,1,1)+1:GOTO1460ELSERETURN
1460 J(PL)=AA:RETURN
1470 '●きえる
1480 IFKF(PL)=0ORKF(PL)=3THENKF(PL)=1:KC(PL)=0:D(PL)=0:KK(PL)=0:N(PL)=0:FORY=0TO11:FORX=0TO5:S2(PL,X,Y)=0:NEXTX,Y
1490 C2=KC(PL)
1500 FORY=0TO11:FORX=0TO5:SH(X,Y)=0:NEXTX,Y
1510 X=KC(PL)MOD6:Y=KC(PL)\6:P=1:SH(X,Y)=1:C=SC(PL,X+1,Y+1)
1520 FORY2=0TO11:FORX2=0TO5
1530 IFSH(X2,Y2)=1THENSH(X2,Y2)=2:GOSUB1640:GOTO1520
1540 NEXTX2,Y2
1550 IFP<4THEN1590ELSEKK(PL)=1
1560 FORY2=0TO11:FORX2=0TO5
1570 IFSH(X2,Y2)=2THENS2(PL,X2,Y2)=1
1580 NEXTX2,Y2:T(PL)=T(PL)+P:D(PL)=D(PL)+1:B(PL)=NA(P)
1590 KC(PL)=KC(PL)+1:IFKC(PL)>72THEN1610
1600 IF(KC(PL)-C2)< =0THEN1500ELSE500
1610 KC(PL)=0:KF(PL)=KK(PL):IFKK(PL)=0THENR(PL)=0:GOTO500ELSER(PL)=R(PL)+1:KF(PL)=2:KC(PL)=0:GOTO500
1640 IFY2-1=>0THENIFSC(PL,X2+1,Y2)=CANDSH(X2,Y2-1)=0THENSH(X2,Y2-1)=1:P=P+1
1650 IFX2+1=<5THENIFSC(PL,X2+2,Y2+1)=CANDSH(X2+1,Y2)=0THENSH(X2+1,Y2)=1:P=P+1
1660 IFY2+1=<11THENIFSC(PL,X2+1,Y2+2)=CANDSH(X2,Y2+1)=0THENSH(X2,Y2+1)=1:P=P+1
1670 IFX2-1=>0THENIFSC(PL,X2,Y2+1)=CANDSH(X2-1,Y2)=0THENSH(X2-1,Y2)=1:P=P+1
1680 RETURN
1690 '
1700 FORY=0TO11:FORX=0TO5
1710 IFS2(PL,X,Y)=1THENGOSUB1730
1720 NEXTX,Y:RETURN
1730 IFY2-1=>0THENXX=X2+1:YY=Y2:IFSC(PL,XX,YY)=5THENSC(PL,XX,YY)=6:S2(PL,XX-1,YY-1)=1
1740 IFX2+1=<5THENXX=X2+2:YY=Y2+1:IFSC(PL,XX,YY)=5THENSC(PL,XX,YY)=6:S2(PL,XX-1,YY-1)=1
1750 IFY2+1=<11THENXX=X2+1:YY=Y2+2:IFSC(PL,XX,YY)=5THENSC(PL,XX,YY)=6:S2(PL,XX-1,YY-1)=1
1760 IFX2-1=>0THENXX=X2:YY=Y2+1:IFSC(PL,XX,YY)=5THENSC(PL,XX,YY)=6:S2(PL,XX-1,YY-1)=1
1770 RETURN
1771 '
1772 FORY=0TO11:FORX=0TO5
1773 IFS2(PL,X,Y)=1THENCOPY(16+CC(PL)*16,80+SC(PL,X+1,Y+1)*16)-(16+CC(PL)*16+15,80+SC(PL,X+1,Y+1)*16+15),1TO(X*16+PL*152+4,Y*16+12),0
1774 NEXTX,Y:CC(PL)=CC(PL)+1:IFCC(PL)=3THENKF(PL)=2
1775 GOTO500
2000 '
2010 A=T(PL)*10:B=RN(R(PL))+B(PL)+DK(D(PL)):IFB=0THENB=1
2020 PT(PLXOR1)=PT(PLXOR1)+A*B:GOSUB10070
2030 GOSUB1690:FORY=0TO11:FORX=0TO5
2040 IFS2(PL,X,Y)=1THENCOPY(16+KC(PL)*16,80+S*16)-(31+KC(PL)*16,95+S*16),1TO(X*16+PL*152+4,Y*16+12),0
2050 NEXTX,Y:KC(PL)=KC(PL)+1
2060 IFKC(PL)<3THEN500ELSEKF(PL)=3:GOTO500
10000 '●おちる
10010 FORY=11TO0STEP-1:FORX=1TO6:S=1:IFSC(PL,X,Y)=6ORSC(PL,X,Y+1)<>6THEN10030
10020 IFSC(PL,X,Y+S)=6THENS=S+1:GOTO10020ELSESC(PL,X,Y+S-1)=SC(PL,X,Y):SC(PL,X,Y)=6
10030 NEXTX,Y
10040 GOSUB1230:RETURN
10050 '●WIN
10060 FORI=0TO1:V$=RIGHT$("00"+MID$(STR$(V(I)),2),2):FORJ=0TO1:A=VAL(MID$(V$,J+1,1)):COPY(88+A*8,0)-(88+A*8+7,15),2TO(113+J*10+I*12,70+I*30),0:NEXTJ,I:RETURN
10070 '●P
10080 A$=RIGHT$("000"+MID$(STR$(A),2),3):FORI=0TO2:A=VAL(MID$(A$,I+1,1)):COPY(88+A*8,0)-(88+A*8+7,15),2TO(109+I*10,140),0:NEXTI
10090 A$=RIGHT$("0000"+MID$(STR$(B),2),4):FORI=0TO3:A=VAL(MID$(A$,I+1,1)):COPY(88+A*8,0)-(88+A*8+7,15),2TO(109+I*10,170),0:NEXTI
10100 FORPP=0TO1:A=PT(PP)\70:X(0)=A\30:A=AMOD30:X(1)=A\6:X(2)=AMOD6
10110 FORI=0TO2:COPY(10*I,32)-(10*I+9,39),2TO(6+PP*152+25*I,0),0:COPY(X(I)*10,40)-(X(I)*10+9,47),2TO(6+PP*152+25*I+11,0),0:NEXTI,PP:RETURN
10120 '●T
10130 A=PT(PL)\70:IFA>=6THENFORI=0TO5:SC(PL,I+1,0)=5:NEXTI:PT(PL)=PT(PL)-420:GOTO10150
10140 FORI=0TO5:PS(I)=I:NEXTI:FORI=0TO10:P1=RND(1)*6:P2=RND(1)*6:SWAPPS(P1),PS(P2):NEXTI:A=(PT(PL)\70):FORI=0TOA-1:SC(PL,PS(I)+1,0)=5:NEXTI:PT(PL)=0
10150 GOSUB10000:GOSUB10070:GOTO500

そんなこんなでここ数年ずっと書きたかった懐古ネタでした。