「Hello World あたたたた」とは
「Hello World あたたたた」は、以下の記事で定義されている。
Hello World あたたたた 1日目 概要編 #HelloWorld - Qiita
以下の要件が定義されている。
・「あ」か「た」をランダムに出力する
・「あたたたた」が出たら「お前はもう死んでいる」を出力して終了する
また、以下の処理フローが指定されている。
変数 hako に空文字をセット 変数 running に true をセット running が true なら繰り返す 0か1をランダムに決める もし0なら 変数 char に「あ」をセット その他なら 変数 char に「た」をセット 画面に char を出力 char を hako に追加 もし 最後の 5 文字が「あたたたた」なら "お前はもう死んでいる" を出力 running に false をセット
HSP3 (Hot Soup Processor) とは
HSP3 は、「おにたま」氏によって開発されているプログラミング言語である。
何も書かずに実行するだけでウィンドウが表示され、BASIC 的な平易な文法でスクリプトを記述できる。
文字コードは SJIS を用いる。
今回は、執筆時点で最新の HSP3.7 を用いる。
UTF-8 を用いるバージョンのランタイムもあるが、今回は用いない。
最近、インタビュー記事が公開された。
だって最高のホビーだから。プログラミング言語「HSP3」を30年開発している理由【フォーカス】 | レバテックラボ(レバテックLAB)
今回用いた機能
式と変数
HSP3 プログラミング・マニュアル → 3.6.式
HSP3 プログラミング・マニュアル → 3.8.変数
変数名 = 値
の形式で、変数に値を代入できる。
式の中で変数名を用いることで、変数の値を参照できる。
式では、以下の演算子を用いることができる。(今回用いたものだけを紹介)
| 演算子 | 意味 |
|---|---|
値1 == 値2 |
値1と値2が等しいかを判定する |
値1 < 値2 |
値1が値2未満かを判定する |
数値1 + 数値2 |
数値1と数値2の和を求める |
文字列1 + 文字列2 |
文字列1の後ろに文字列2を結合した文字列を求める |
== だけでなく、= も等しいかを判定する演算子として使用できる。
変数名 演算子= 値
と書くことで、
変数名 = 変数名 演算子 値
と書くのと同様の処理を行うことができる。
すなわち、たとえば以下の2行は同じ処理を行う。
a += 72
a = a + 72
コメント
文字列以外で ; を書くと、その行のそれ以降の部分がコメントになる。
マクロ定義
HSP3 プログラミング・マニュアル → 4.7.#defineマクロについて
#define 名前 置き換え先
と書くことで、「名前」を「置き換え先」に置き換えるマクロを定義できる。
より複雑なマクロ定義も可能だが、今回は用いない。
条件分岐
HSP3 プログラミング・マニュアル → 3.12.条件判断
if 式 : 式が真のとき行う処理
の形式で、条件分岐を行うことができる。
式と処理の間は : で区切る。
処理も : で区切ることで、複数の処理を記述できる。
else を用いると、式が偽のとき行う処理も記述できる。
処理と else の間も : で区切る。
if 式 : 式が真のとき行う処理 : else : 式が偽のとき行う処理
処理を {} で囲むことで、複数行に分けて記述できる。
if 式 {
式が真のとき行う処理1
式が真のとき行う処理2
}
条件を指定しての繰り返し
HSP3 プログラミング・マニュアル → 4.8.標準マクロ定義ファイル
while~wend マクロを用いることで、条件を指定し、その条件が満たされる間繰り返しを行うことができる。
while 式
式が真の間繰り返す処理
wend
データの出力
HSP3 プログラミング・マニュアル → 5.3.フォントと文字表示
mes 命令でデータをウィンドウに出力できる。
mes 値
デフォルトでは、次に出力する位置は出力したデータの下に移動する。
第2引数に 1 を指定することで、次の出力を出力したデータの右にすることができる。
mes 値, 1
デフォルトの動作は「改行する」(出力位置を次の行の一番左にする) ではなく、「次の出力位置を出力したデータの下にする」である。
次のデータを一番左から出力するには、別途出力位置を左に戻さなければならない。
コンソール版のランタイムでは、出力先は標準出力となり、第2引数に 1 を指定するかどうかの差は単純な「改行する/しない」になるようである。
pos 命令で、次にデータを出力する位置を指定できる。
pos x座標, y座標
乱数の生成
rnd 関数で、整数の乱数を生成できる。
この関数は1個の引数をとり、0以上指定した値未満の乱数を生成する。
randomize 命令で、rnd 関数で生成する乱数を不定な系列にできる。
逆に、randomzie 命令を実行しない場合、実行開始時から毎回同じ乱数が生成される。
randomize
mes rnd(10) ; 0~9の乱数を生成して表示する
ウィンドウ情報の取得
HSP3 プログラミング・マニュアル → 3.16.システム変数
ginfo 関数で、ウィンドウに関する情報を取得できる。
この関数は1個の引数をとり、取得する情報を指定する。
また、この関数で取得できる情報を取得するマクロもある。
今回は、以下のマクロを使用した。
| マクロ | 内容 |
|---|---|
ginfo_winx |
ウィンドウのクライアント領域の横幅 |
ginfo_mesx |
前回出力したデータの横幅 |
ginfo_cx |
次にデータを出力する位置のx座標 |
ginfo_cy |
次にデータを出力する位置のy座標 |
部分文字列の取得
strmid 関数を用いて、文字列から部分文字列を取得できる。
この関数は、以下の形式で用いる。
strmid(抜き出し元の文字列を格納した変数, 抜き出しを開始する位置, 抜き出すバイト数)
第1引数は変数でなければならず、文字列を直接指定するとエラーになった。
第2引数は、0-origin で抜き出しを開始する位置を指定することができ、-1 を指定すると文字列の右端から第3引数で指定したバイト数を抜き出す。
第3引数は、文字数ではなくバイト数を指定する。標準では SJIS を使用するので、全角文字は2バイトである。
プログラム
標準ランタイム版
#define true 1
#define false 0
randomize
hako = ""
running = true
while running == true
if rnd(2) == 0 : char = "あ" : else : char = "た"
mes char, 1
if ginfo_winx < ginfo_cx + ginfo_mesx : mes "" : pos 0, ginfo_cy
hako += char
if strmid(hako, -1, 10) == "あたたたた" {
mes ""
pos 0, ginfo_cy
mes "お前はもう死んでいる"
running = false
}
wend
コンソール版
HSP3 プログラミング・マニュアル → 5.14.コンソール版HSP
スクリプトの先頭に
#runtime "hsp3cl"
を追加し、ウィンドウ関係の命令をコメントアウトすることで、ウィンドウのかわりにコンソールで動作させることができる。
#runtime "hsp3cl"
#define true 1
#define false 0
randomize
hako = ""
running = true
while running == true
if rnd(2) == 0 : char = "あ" : else : char = "た"
mes char, 1
;if ginfo_winx < ginfo_cx + ginfo_mesx : mes "" : pos 0, ginfo_cy
hako += char
if strmid(hako, -1, 10) == "あたたたた" {
mes ""
;pos 0, ginfo_cy
mes "お前はもう死んでいる"
running = false
}
wend
実行結果例
標準ランタイム版
HSPスクリプトエディタでスクリプトを開き、F5 キーを押すことで、スクリプトをコンパイルして実行できる。
同じスクリプトを繰り返し実行する際は、F6 キーを押すことで、コンパイルを省略して実行のみを行うことができる。
コンソール版
コンソール版も、標準ランタイム版と同様にHSPスクリプトエディタから実行できる。
このとき、自動で終了時キーが押されるのを待機してくれるようである。
「HSP → 実行ファイル自動作成」メニューで実行ファイルを作成し、コマンド プロンプトから実行することもできる。
このときは、終了時のキー押下待機は行われないようである。
プログラムのポイント
ここでは、今回作成したプログラムの中で、特に自明ではない点を紹介する。
char の出力
mes char, 1
if ginfo_winx < ginfo_cx + ginfo_mesx : mes "" : pos 0, ginfo_cy
mes 命令で、変数 char に格納した文字列を出力する。
このとき、第2引数に 1 を指定し、この後右に続けて出力できるようにする。
続いて、標準ランタイムでは自動で折り返されず、何もしないと右からはみ出してしまうことがあるので、次の出力がはみ出しそうだったら次の行に移る処理を行う。
具体的には、「次に今と同じデータを出力したら右にはみ出してしまう」場合、「出力位置を次の行の一番左にする」処理を行う。
mes で空文字列を出力することで出力位置を次の行に移し、続いて pos を用いて出力位置を一番左に移す。
接尾辞の判定と条件を満たした際の処理
if strmid(hako, -1, 10) == "あたたたた" {
mes ""
pos 0, ginfo_cy
mes "お前はもう死んでいる"
running = false
}
strmid を用いて hako の右の文字列を取り出し、「あたたたた」と比較する。
処理フローでは「5文字」との指定だが、今回は全角文字のみを扱うので、SJIS ではこれは「10バイト」となる。
接尾辞が指定のものだったら、改行し、「お前はもう死んでいる」を出力する。
この「改行する」というのは要件や処理フローには書かれていないが、「処理結果のイメージ」で改行されているのでそれに合わせる。
この改行処理は、右端での折り返し処理と同様に「次の行に移る」「一番左に移る」処理からなる。
おわりに
HSP3 で「Hello World あたたたた」を実装することができた。
今回の題材では、HSP3 のGUIが簡単に作れるという強みは活かせなかった。




