異次元ワープロ2号機

他のブログに当てはまらない「その他」カテゴリ用ブログです。

『STN-BASIC』を公開しました

令和8年8月8日午後8時から88時間限定*1で公開します。
初回アクセス時にややくどい表示が出ますので一応読んでください。命令一覧等へのリンクはページ内にあります。

https://waaimyroom2.at-ninja.jp/STNBASIC.html

21:00以降の追記

完全な動作にはパソコンを推奨します。
スマートフォンでも動作しますが、キー入力およびマウスボタン入力が取れないため*2実質的に使えません。ご注意ください。
また、ゲーム機内蔵ブラウザーでは、ほとんどの場合動作しません*3。

*1:常時公開するにはまだ不完全なので一度公開を中断して完成度を上げる予定

*2:USB端子等でキーボードとマウスを接続すれば可能

*3:JavaScriptの比較的新しい機能を使用しているため、アップデートが提供されていないブラウザーはほぼ全て不可

STN-BASIC:サンプルゲーム1

穴掘り法による迷路ゲームで、毎回固定の全8フロアです。
右下のマスがゴール。

※そこまでボリュームはないですが、セーブ機能はないため暇なときに遊んでください。

'--------------------------------------------
'@#NAME:SAMPLE GAME NO.1
'--------------------------------------------

'<<[!USE STDLIB]>>
'↑この行のみ、動作に影響しますので省かないでください。ほかのコメント行は省略OK
SETBTREPEAT 16

VAR B,I,R,X,Y
VAR BX,BY
VAR GX,GY
VAR OX,OY
VAR PX,PY
VAR SX,SY
VAR NOW_FLOOR
'********************************************
VAR KR

DEF KRANDOMIZE SEED
 KR=SEED
END

DEF KRND() 'クロサワ式乱数
 KR=KR XOR &H9630
 KR=KR-&H6553 AND &HFFFF
 KR=((KR<<2) OR (KR>>14)) AND &HFFFF
 RETURN KR
END

DEF SRND(M)
 RETURN KRND() MOD M
END
'********************************************
ACLS
SPSET 64,304:SPOFS 64,23*16,13*16
DIM MYSP,WALL,ANIMCNT=0,ANIMCHR=0
DIM MVX,MVY
DIM ANIMX=0,ANIMY=0
RESTORE @CHARACTER
READ MYSP,WALL

FOR NOW_FLOOR=1 TO 8
 SX=13:SY=8
 GOSUB @MAZE
 CLS
 ?NOW_FLOOR;"F"

 PX=16:PY=16
 SPSET 0,MYSP
 SPOFS 0,PX,PY,-1'実際はZ座標は無視

 'BGMは未実装なので略

 WHILE !GOALCHK()
  VSYNC 1
  B=BTRIG()

  IF ANIMCNT>0 THEN
   SPCHR 0,ANIMCHR
   INC ANIMX,MVX:INC ANIMY,MVY
   SPOFS 0,ANIMX,ANIMY
   DEC ANIMCNT
   IF ANIMCNT MOD 4==0 THEN INC ANIMCHR
   CONTINUE
  ENDIF
  IF B==0 || ANIMCHK() THEN CONTINUE
  OX=PX:PX=PX+(!(4AND B)-!(8AND B))*16
  OY=PY:PY=PY+(!(1AND B)-!(2AND B))*16
  IF BGGET(1,PX/16,PY/16) THEN PX=OX:PY=OY
  IF BGGET(1,OX/16,PY/16) THEN PX=OX:PY=OY
  IF BGGET(1,PX/16,OY/16) THEN PX=OX:PY=OY
  IF PX==OX && PY==OY THEN CONTINUE
  MVX=SGN(PX-OX):MVY=SGN(PY-OY)
  IF B AND 2THEN SPCHR 0,MYSP+4
  IF B AND 4THEN SPCHR 0,MYSP+8
  IF B AND 8THEN SPCHR 0,MYSP
  IF B AND 1THEN SPCHR 0,MYSP+12
  IF B AND 15 THEN
   ANIMCNT=15
   ANIMCHR=SPCHR(0)
   ANIMX=OX+MVX:ANIMY=OY+MVY'初回分移動量
   SPOFS 0,ANIMX,ANIMY
  ENDIF
 WEND
 'BGM(ジングル)は未実装なので略
NEXT
BGCLR 0:BGCLR 1:SPCLR 64:CLS
?"GAME CLEAR!"
?"THANK YOU FOR YOUR PLAYING!"
END

DEF ANIMCHK()
 RETURN ANIMCNT!=0
END

DEF GOALCHK()
 RETURN !ANIMCHK() && PX==23*16 && PY==13*16
END

DIM TPX,TPY
@MAZE
 KRANDOMIZE 17*NOW_FLOOR+16
 DIM T[SX*2,SY*2]
 DIM P[0]

 BX=SRND(8)*2+5
 BY=SRND(5)*2+5

 FILL T,1

 BGCLR 0:BGCLR 1

 WHILE 1
  IF GET(BX-2,BY)!=1 && GET(BX+2,BY)!=1 && GET(BX,BY-2)!=1 && GET(BX,BY+2)!=1 THEN
   IF MAX(P)<0 THEN BREAK
   REPEAT
   '乱数生成で次アドレス
    I=SRND(LEN(P)/2 OR 0)
   UNTIL P[I*2]>=0
   BX=P[I*2]
   BY=P[I*2+1]
   P[I*2]=-1
   P[I*2+1]=-1
   CONTINUE
  ENDIF

  R=SRND(4)'ほうこうせってい
  IF R==0 THEN GX=-1:GY=0
  IF R==1 THEN GX=1:GY=0
  IF R==2 THEN GX=0:GY=-1
  IF R==3 THEN GX=0:GY=1

  IF BX+GX<1||BY+GY<1 THEN CONTINUE
  IF BX+GX>SX*2-3||BY+GY>SY*2-3 THEN CONTINUE

  '注:二次元配列の添字は式を認識しないので変数に代入する
  'また、二次元の添字は 宣言 if 代入のどれか以外では認識しない
  TPX=BX+GX*2:TPY=BY+GY*2
  IF T[TPX,TPY]==1 THEN
   T[BX,BY]=0'移動前のマス
   INC BX,GX:INC BY,GY:T[BX,BY]=0'途中のマス
   INC BX,GX:INC BY,GY:T[BX,BY]=0'移動完了
   PUSH P,BX
   PUSH P,BY
  ENDIF

 WEND

 FOR Y=0 TO SY*2-2
  FOR X=0 TO SX*2-2
   B=T[X,Y]
   BGPUT 0,X,Y,103
   BGPUT 1,X,Y,B*WALL
  NEXT
 NEXT

RETURN

@CHARACTER
DATA 756 'MY SPRITE
DATA 107 'WALL BG : 163に変えると木になります

DEF GET(X,Y)
 IF X>=0 && X<SX*2-1 && Y>=0 && Y<SY*2-1 THEN
   RETURN T[X,Y]
  ELSE
   RETURN 0
  ENDIF
END

※THENやANDの前後で詰めているのは、そう書いても動くことを確かめる意図的なものです。
特定のキーワードのみピンポイントで省略されたスペースを補うので、基本的にアルファベットの演算子の前後は空けてください。

STN-BASICの作例

こんなものが動く予定、というサンプルを載せていきます

※素材バンク変更のため、一部修正しました(8/7)
※マウス入力のサンプルを追加(8/7)
※名称が決まったため記事タイトル変更(8/7)
※スプライトのテンプレート番号が標準ライブラリと被るので変更(8/8)

スプライト歩行テスト

操作に関係なくスプライトが下→右→下→右…と歩き、画面下端まで行くと終了します。

ACLS
DIM Q=4,PY=0
GOSUB @SUB

Q=0:PY=32
GOSUB @SUB

SPSET 2,&H100+4
DIM I,W,X=128,Y=0
WHILE Y<240
	?Y
	FOR I=0 TO 3
		SPCHR 2,&H100+4+I
		FOR W=1 TO 16
			IF W MOD 4==0 THEN INC Y:SPOFS 2,X,Y
			VSYNC 1
		NEXT
	NEXT
	FOR I=0 TO 3
		SPCHR 2,&H100+I
		FOR W=1 TO 16
			IF W MOD 4==0 THEN INC X:SPOFS 2,X,Y
			VSYNC 1
		NEXT
	NEXT
WEND
END

@SUB
	SPDEF &H100+Q,"SPU0",48*2+16,PY,16,16
	SPDEF 1+&H100+Q,"SPU0",48*2+16*0,PY,16,16
	SPDEF 2+&H100+Q,"SPU0",48*2+16,PY,16,16
	SPDEF 3+&H100+Q,"SPU0",48*2+16*2,PY,16,16
RETURN

動作例:

マウス入力のサンプル(超簡易ペイント)

Tabキーで終了。色は白とピンクとマゼンタで、マウスの押すボタンで決まります。

ACLS
REPEAT
 VSYNC
 CLS
 ?TCHX
 ?TCHY
 ?TCHST
 IF TCHST>0 THEN GPSET TCHX,TCHY,RGB(255,255-255*(TCHST-1)/2,255) 
UNTIL BUTTON(0)==32
スクリーンショットに使用した著作物に関する表示

スプライトは著作権者「Lanea Zimmerman」による素材「Tiny 16: Basic」(ライセンスCC-BY 3.0ほか)のcharacters.pngを使用
入手元:opengameart.org

フォントは「美咲フォント」を使用。ライセンスは下記ページ内を参照
入手元:littlelimit.net

独自圧縮フォーマット(ADE:ArrayDictionaryEncode)に関するメモ

説明は飛ばして、バリエーションを一通りまとめるだけ。
具体的な仕様はプログラムが全て(いつものやつ)

用語

分割数:配列1要素(32bit)をいくつに区切って使うかの数
塊:配列1要素を指定した分割数で区切った値1個のこと。4分割ならちょうど1byteになる
追加圧縮:ADEの別名。もとはSRD画像フォーマットの一部なのでそう呼んでいたが、後にADE単独で使うようにもなった
バージョン値:『SRD画像圧縮ライブラリ』のwiki記事を参照。&h23→&h20という変な順番なのは、ASCII文字として解釈した時それぞれ『#』、スペースになる値を付けたから

初期版ADE(バージョン値:&h23)

参照が成立しない値をそれぞれ1塊として記録していたので、ランダムに近いデータはとても肥大する。

NEW_ADE(バージョン値:&h20)

初期版から「参照が成立しない値」が連続した数を記録するように変えたため、ランダムに近いデータがほとんど肥大しなくなった。
『SRD画像圧縮ライブラリ』の2022/06/01の更新記録にある「PackBits的なロジックを加える」というのはこの変更のこと。
細かいことをいうと2バージョン存在する(参考:2022/06/10の更新記録)

ADC

手元には存在するが非公開の模様。
NEW_ADEとの違いは参照不成立連続数の表現が違う(参照成立時の参照位置が常に1塊の代わりに、0,連続数の2塊で記録)ことらしい。
おそらくNEW_ADEと比べて圧縮率の差が少ない以前に、デコーダのバグを発見できず修正ができなかったので没になった。

XADE

NEW_ADEデコーダをJavaScriptへ移植するにあたり、計算過程で出る値が必ず非負になるようにビット演算を乗除算に変更したもの。
ついでに、2の冪でない分割数*1を指定できるよう手を加えて実験したものの、圧縮率がほとんど優れていないのでこの変更点は没になった。
分割数が2の冪であるときの圧縮データはNEW_ADEと全く同じ。


ところで、初期の頃は月に複数回規格が変わるような有様なので、おちおち使えない感じでしたね。
今はめったに改定しないので安心して使えますね(?)

更新(大きな変更のみ)

  • 4/10…ADCとXADEの制作経緯がほとんど嘘なことが分かったので修正。

*1:この場合、プログラムの簡略化のため端数のbitは使わない(たとえば3分割だと10bit×3ごとに、あまりの2bitは未使用)

ATAMA_EXPLORERで使っている独自符号化の解説

確か、プチコン3号まとめwikiに掲載した記憶があるのだが
アーカイブをいくら探しても見つからないので、今後のアップデートで追加する符号種類を含めて軽くまとめておく

現在の最新の規格は2026-01-20に発効したバージョン『3.5(2026.1)』です

符号の種類

AC…ASCII Character

名前のまま。U+0000からU+007Fまでの文字は、シンプルに1オクテットで符号化する。
ただし、ETC・TTC・RLCで符号化できる文字列は、ACとして符号化してはならない。

NAC…Non ASCII Character

これも名前のまま。U+0080以降かつETC・TTC・RLCで符号化できない文字を符号化する。3オクテット。
当然のことながら、ACで符号化できる文字は、NACとして符号化してはならない。

ETC…Extra Token Character

特徴的な符号の種類で、プチコンのプログラムによく出現する"DIALOG"や"DISPLAY"などの単語を1文字であるかのように符号化することで、圧縮効果を発揮する。2オクテット。
頻出する英単語のほか、ひらがな・カタカナ*1と句読点も含まれる。

TTC…Triple-1 Token Character【バージョン3.5(2026.1)で追加】

ETC同様、頻出する単語を1文字のように表現するが、元が2文字の"IF"などがETCでは圧縮できないため効率向上を意図して作られた符号の種類。ETCの空き符号に無理やりねじ込んで1オクテットで符号化する。
名前は、2進数で表記した時に左の3桁が1になることに由来する。

変更履歴(符号の種類について)

2026-01-15

  • エンコード処理に課題*2があるため、RLCを追加する時期を未定に変更。

2026-01-20

  • RLC(Run-Length Character)を完全に規格から削除した。

勝手にFAQ

独自符号全体に名前は無いのですか?

初期から存在した符号の種類の頭を取って"ANETコード"という名前を考えているが、同じ読みの単語が既に存在するため正式には「名前がない」状態
プログラム名の一部を冠した『AT-ANETコード』を正式な名前に決定。

*1:このうち、半濁音とや行を除いた小文字を含んでいない

*2:たとえばETC定義済みの"BUTTON"という文字列が、BUT(2回繰返し)ONと表現できてしまうなど

プチコン3号用OSMレンダラもどきの開発を緩くまとめる

この記事は『OpenStreetMap - Qiita Advent Calendar 2025 - Qiita』の14日目の記事です

前提:プチコン3号とは

公式サイトを見る方が早いので(投げやり)
一言でいえば3DS用のプログラム開発環境(とても合法*1)です
smilebasic.com

4月 - 6月

4月30日。プチコン作品でおそらく*2初めて、osmファイルからウェイとノードの座標を取り出して地物の輪郭を表示した

若葉駅東口付近
座標の解釈に誤りがあるので、実は鏡映し(左右反転になっている)
Map data © OpenStreetMap contributors | Copyright and License | OpenStreetMap

※以下の各スクリーンショットは同ライセンスの地図データによる

なんやかんやありまして(開発中のつぶやきのツリー)

こんな感じになりました

6月6日に「SVG EDITOR」ver.1.0として公開
petitcom.mitsutan.dev

12月 - 記事投稿

6月時点では地物の表示だけで満足していたが、どうせなら表示だけじゃなくてマッピング機能を付けようという機運が出てきたので開発を再開

まずはPOIをマークで表示し、選択すると何であるかを確認できる機能を実装

画面座標から経緯度へ換算する式をあり得ない方法で求めながら(開発中のつぶやきのツリー)

タッチした座標に新しいPOIを作成する機能を実装

詳細の入力は、3DSという端末でやるにはヘビー*3なので、よくあるブランドをプリセットから選ぶ形にしました

コンビニ、スーパー、飲食店に加えて自動販売機のプリセットを作りました

ただし、これは手元のOSMファイルに書き込むだけの機能。プチコンの制約*4のため、OSMのサーバーにデータをアップロードすることはできない
そこで、変更点をLevel0L形式*5に整え、二次元コードとして表示。それをスマートフォンなどの他端末で読み取る、という少し面倒なやり方でサーバーへのアップロードを実装する予定です(記事投稿時点で、Level0L出力の手前まで実装完了)

実際のアップロードができたら、新しい記事で続報を書く…かもしれない

*1:カスタムファームウェアみたいなことをしないでいいので自信をもって他人と話題にできる

*2:日本語圏以外の情報は一部しか把握できていないので、海外に先駆者がいる可能性は否定できない

*3:処理能力的な問題ではなく、プチコンではまず日本語入力自体を自作・搭載する必要があり、プログラムの肥大に繋がるため

*4:任天堂機という環境の都合上、インターネットへのアクセスは専用の作品共有サーバーを除き不可能

*5:おそらくosc形式でも可能だが、先に知っていたのがl0lなのでそうした