プチコンで遊ぼう! (はてなブログ版)

任天堂3DSのプチコンで遊ぼう! [twitter:@eida_s]

はてなダイアリーから移行しました。 はてなダイアリーのURLを開いても自動的にこちらにリダイレクトされますのでご了承ください。

別スロットの関数名/命令名

■ライブラリの直接呼びされることを想定しないDEFは、COMMON DEFにしないようにしよう

ライブラリとして呼び出したプログラムに、自分のプログラムと同じ関数名/命令名があると、Duplicate functionエラーになる。

SLOT 0

USE 1
?"A=";A()
?"B=";B()

DEF B()
 RETURN 1
END

SLOT 1

COMMON DEF A()
 RETURN B()
END

DEF B()
 RETURN 2
END

この結果は次のように表示される。(当然だが...)

A=2
B=1


仮にSLOT 1のDEF B()が、COMMON DEF B()になっていると、Duplication functionエラーになる。
ちなみにSLOT 0のDEF B()をCOMMON DEF B()にした場合もなぜか同様。
(SLOT 1からSLOT 0はUSEしていないので本来はエラーにならなくてもよさそうだが...)

結論としては、USEされたスロットは全部で一つの名前空間になり、COMMON DEFがある時、その名前と同じDEFが存在してはいけない、ということになる。

これを踏まえてライブラリプログラム作成時の注意事項を以下に書いておく。
以下では、ライブラリプログラムを呼び出すプログラムを「ホストプログラム」と呼ぶことにする。

ほしけんさんのプチコン漢字ライブラリ(KNJLIB)が広く使われるようになり、ライブラリプログラムの中に埋め込んで使うケースも出てきた。
さらにライブラリプログラムを利用したホストプログラムがあり、そのホストプログラムにもKNJLIBを埋め込んであるとする。

すると、ホストプログラム、ライブラリプログラムの両方にKNJLIBが埋め込まれていることになり、名前の衝突が起こってしまう。

この場合、ホストプログラム、ライブラリプログラム双方のKNJLIB部分のCOMMON DEFをDEFに変えることで名前の衝突を回避できる。

もちろんホストプログラム側の対応も必要だが、ライブラリプログラムを公開している方は上記を検討してみていただけると大変助かる。

3号プログラミング 覚え書き(7) クリップボード編

プチコン3号のエディターでアンドゥできなくなるのは4103文字以上の文字列をペーストしようとした時

 クリップボードに入っている文字列が4102文字までの時は、ペーストしてもアンドゥできる。

 

 

計算式評価ライブラリEVALLIB

計算式を評価するいわいるEVALを実現するライブラリを作成中です。

ファイル名: EVALLIB

公開キー: S2NXCNKE C3E8N4JP 434X4X2D

公開日: 2016/07/05 2016/07/03 2016/07/02

バージョン: 0.03 0.02 0.01

v0.03 ()を含めたバグ修正、前置の+-を使えるようにした
v0.02 演算優先度のバグ修正、デバッグ機能の強化
v0.01 初公開

現在のV0.03は、カッコありの四則演算のみ。
関数を含む式の評価ができることが目標。
そのためには、構文解析部分を再帰下降パーサーに書き換えないとダメなようです。

最初は見ないで作ってみようと思ったけど、ちょっと無理だったので以下を参考にした。
http://www.gg.e-mansion.com/~kkatoh/program/novel2/novel208.html

BGMCHKの挙動

旧3DSLLかつプチコン3号 Ver3.3.1で以下を確認。

134番のBGMが終わってから、135番のBGMを流すつもりで以下のように処理を書くと、

BGMPLAY 134
WHILE BGMCHK():WEND
BGMPLAY 135

なぜかループがすぐ終了し、135番は演奏されない。

BGMPLAYを発行してからタイムラグがあるのかもしれない。

BGMPLAY 134
WHILE BGMCHK():VSYNC 1:WEND
BGMPLAY 135

だと大丈夫。134番の演奏が終わってから135番が演奏された。

BGMPLAY 134
WHILE BGMCHK():FOR I=1 TO 29:NEXT:WEND
BGMPLAY 135

でも大体問題ない。

BGMPLAY 134
WHILE BGMCHK():FOR I=1 TO 28:NEXT:WEND
BGMPLAY 135

だと大体ダメで135番が演奏されない。


しかし、WHILEループを除いて、

BGMPLAY 134
BGMPLAY 135

とすると、人間の耳には135番だけ演奏されているように聞こえる。

謎である。

パズル 7650 (パックマンDLC必要)

パックマンDLCを使ったパズル7650。
なんか見たことあるような?いや気のせいですw

ファイル名: ED7650

公開キー: QDAJR3B3 C33NY3AP E23N33D4

公開日: 2016/12/18 2016/06/27 2016/06/12

バージョン: 1.11 1.10 1.00

v1.11 WiiUでエラーになる問題を修正
v1.10 DLCがない場合の対応を少し修正
v1.00 初公開

必要DLCPACMAN
DLCがない場合は、スプライト等が代用品に置き換わります)

【遊び方】

1)十字キーでタイルをスライドし、同じ絵柄同士を合体させていきます。

2)同じ絵柄同士を合体させると得点になり、より得点の高い絵柄に変わります。

3)これを繰り返して7650点のタイル作成を目指してください。
(7650点を獲得してもゲームは続きます。)

4)A,B,X,Yボタンのいずれかを押すとメニューを表示し、リトライを選ぶと最初からやり直すことができます。

5)ハイスコアは、メニューからEXIT GAMEを選んだ時に保存されます。


【その他】

「7650」という数字にこじつけたかっただけなので、「パックマンの内容とかけはなれている」などの批判は受け付けませんw

ちなみにmkIIの時も似た(w)ゲームを作っていました。
http://d.hatena.ne.jp/eidaht/20140608/1402249061

SMILE BASIC 小技(9)

PRGINSで動的にコードを追加する方法。

PRGINSで他のスロットにコードを追加した後にUSEを実行すると、追加したコードを実行することができる。
PRGINS毎にUSEを使えば、何度でもコードを追加できる。

例:

VAR DQ$=CHR$(34)
PRGEDIT 3
PRGDEL -1

PRGINS "DEF A"
PRGINS " ?"+DQ$+"A"+DQ$
PRGINS "END"

USE 3
CALL "3:A"

PRGINS "DEF B"
PRGINS " ?"+DQ$+"B"+DQ$
PRGINS "END"

USE 3
CALL "3:B"

USEが2度現れているが、問題なく実行できる。

これを応用する例としては、ツール系のプログラムで設定ファイルにコードを書いて追加するとか、ユーザーに入力させたコードを実行する等が考えられる。

ただし、一般的な注意として、最初にプログラムを実行したスロットをPRG系命令で編集することはできないので気を付ける必要がある。

SMILE BASIC 小技(8)

BGのキャラ定義の一部がキャラクターコードに対応していることと、BGGETを使うと非常に簡単に自作キーボードを作ることができる。

具体的には、

TOUCH OUT STTM, TX, TY
G=BGGET(レイヤー番号,TX,TY,1)

とすると、GにBGのキャラ番号がとれる。
BGの32〜95番には、同一アスキーコードの英数字記号が割り当てられているので、これを使って処理する。

簡易キーボードの例:

前半部分で文字を並べているが、この文字のレイアウトを変えても、判定部分は一切変える必要がない。


実用例としては、この小技を使って、拙作のゲームブックドルアーガの塔アドベンチャーシートで、数値入力用パネルを実装している。
ゲームブック「ドルアーガの塔」アドベンチャーシート for プチコン3号 (β2版)


また、上記の小技を使って簡単なゲームを作ってみた。
OSE! Catch The Gyoku
キー【EBNECE3E】
遊び方:
 「玉」をタッチでつかまえてください。
 ただし、人質になっているキングとクイーンを間違えてタッチしたり、画面外に逃げられると負けになります。

バイナリファイル調査その(2)

型変換調査
(1)

VAR A#[10]
A#[0]=1.5
A#[1]=2.5
SAVE "DAT:BINDATA",A#
VAR B%[0]
LOAD "DAT:BINDATA",B%
?"LEN=";LEN(B%)
?B%[0]
?B%[1]
?B%[2]
?B%[3]

とすると、

LEN=10
1
2
0
0

と表示される。

(2)

VAR A%[10]
A%[0]=1
A%[1]=2
SAVE "DAT:BINDATA",A%
VAR B#[0]
LOAD "DAT:BINDATA",B#
?"LEN=";LEN(B#)
?B#[0]
?B#[1]
?B#[2]
?B#[3]

とすると、

LEN=10
1
2
0
0

と表示される。

つまり、直接的にバイナリとして読み込まれるわけではなく、
LOAD時に、SAVE時の型として一度読み込まれてから、その後に変数に代入されていることがわかる。

バイナリファイル調査その(1)

バイナリファイルサイズ調査
(1)

VAR A[1]
a[0]=1
SAVE "DAT:BINTEST",A

とすると、36バイトのファイルが作成された。

(2)

VAR A#[2]
A#[0]=1
A#[1]=2
SAVE "DAT:BINTEST",A#

だと44バイト。

(3)

VAR A%[1]
A%[0]=1
SAVE "DAT:BINTEST",A%

だと32バイト。

(4)

VAR A%[2]
A%[0]=1
A%[1]=2
SAVE "DAT:BINTEST",A%

だと36バイト。

よって、
ヘッダー28バイト+(倍精度小数なら8バイト、整数なら4バイト)*個数
の大きさと思われる。


#ヘッダーが読み取れたら、GRPファイルかそうじゃないか判別できると思って調査しはじめたけど、今のところヘッダーを読み取る方法はない。

PRGINSしたコードを呼び出すことができるか

昨日、いろいろ試していた結果。
あるスロットから他のスロットにPRGINSでコードを追加して、追加したコードを呼び出すことができるか、という研究。

PRGEDIT 3
FUNCNM$="_ABC"
IF !CHKCALL(FUNCNM$) THEN
 PRGINS "COMMON DEF "+FUNCNM$+"()"
 PRGINS " RETURN 1"
 PRGINS "END"
ENDIF
USE 3

PRINT CALL(FUNCNM$)  '1が表示される

ポイントは、PRGINSをした後でUSEを実行していること。
おそらく、USEでそのスロットがコンパイルされるようだ。
(その証拠にUSE 3をPRGINSより前に入れると、Undefined functionエラーになる)

第4回大喜利で入賞したLOWERDASHもこの考え方で、起動時にコードを追加している。
が、USEは何回でも呼び出せるので、プログラム中で必要な時にどんどんコードを追加するという使い方ができると思う。
現在作成中の構造体ライブラリには一部にこの考え方を使おうかと思う。