類似処理の自動反復化1
下記スクリプトをご覧ください。

 1
 2
 3
 4
	mes "気合だぁ〜!"
	mes "気合だぁ〜!"
	mes "気合だぁ〜!"
	mes "某アニマルより。"
1〜3行目に同じメッセージを3回、4行目に異なるメッセージを1回出力していますね。 今回のようにメッセージ表示の一文だけだとマシですが、このように同じプログラムを繰り返す場合、 同じ内容をずらずらと書いていたのでは1回の処理が増えるほど見にくくなってしまいます。 有限(終わりのある)回数であればまだしも、例えばキーを押すまで等のなにかしらのイベントが発生するまで 処理を繰り返したい場合等は繰り返し数が未定である為に先程のスクリプトのような書き方はできません。
repeat 繰り返す回数, カウンタ初期値
繰り返す回数省略時は-1。マイナス時は無限ループとなる。
カウンタ初期値システム変数cntの初期値を決定する。
条件を満たすまで一定の処理を繰り返す命令としてrepeat命令が用意されています。 ループを抜ける条件は3つあります。 指定回繰り返すか、脱する命令を通過させるか、外部要因(エラーや強制終了)が発生するかのいずれかです。 repeat命令の第一パラメータには処理する回数を数値もしくは数値の入った変数で指定します。 小数の入った数値を渡すと、小数点以下を切り捨てた回数となります。 ループ回数が0の場合は、ループ内に書かれた処理は一切実行されません。 また、省略かマイナス値を指定した場合は、repeat命令では終了する回数条件を指定しないこととなり、 内部的に終了させる条件を設定しなければ無限ループになってしまいます。 現在の状態で無限ループにさせてしまうと、HSP以前にOS自体が不安定になり大変危険です。 絶対に興味本位で実行しないようにしてください。 まぁ、上で紹介しましたrepeat命令だけではエラーとなり動作させることができないわけですが…。 第二パラメータにはシステム変数と呼ばれるHSPが内部的に設定している変数cntの初期値をセットします。 この変数はカウンタの意味で存在し、ループの度に特定の条件を除きカウンタ値が自動的に更新されるように なっているため、自分がプログラムにカウンタ値の更新処理を組み込む必要はありません。 更新の必要がない以前に、システム変数は通常変数のように値の代入はできませんけどね…。 ループ開始時に初期値が設定されていなければcntには0がセットされます。 カウンタの増加値は1のみで、例えば「repeat 4, 3」なら、カウンタは「3,4,5,6」と推移します。 ループ外に抜けるとcntは再び0がセットされるようになります。
loop
[パラメータなし]処理をrepeatまで戻すだけの為、パラメータは必要ない。
repeat命令の紹介をしましたが、サンプルスクリプトを載せていないのは正常に動作しない為です。 repeat命令がループの開始点となるわけなのですが、どこまでが1つのループとするのか ループの終了点も決めif命令によるブロック同様、repeat命令のブロックを形成しなければなりません。 ループの終了点にはループ開始点へ処理を戻す意味の上記loop命令を使用してください。 repeat命令とloop命令は常に1対1の関係(ニコイチ)です。 1つのrepeat命令に対し、複数または0個のloop命令は設定できません。 この命令はループ先頭まで戻すだけである為、必要なパラメータは1つもありません。 試しに初めの反復処理で行ってみましょう。
 1
 2
 3
 4
	repeat 3
		mes "気合だぁ〜!" // メッセージを3度処理する
	loop
	mes "某アニマルより。"
システム変数cntを使ったサンプルも書いておきましょう。
 1
 2
 3
 4
 5
	// カウンタ初期値を1として3回繰り返す
	repeat 3, 1
		mes "" + cnt + "…"
	loop
	mes "ダー!!"
mes命令を分けると勝手に縦に並んでしまいます。横に並べたい場合は、
 1
 2
 3
 4
 5
 6
	repeat 3, 1
		pos cnt * 25, 0
		mes "" + cnt + "…"
	loop
	pos 100, 0
	mes "ダー!!"
このようにcntpos命令にうまく形を換えて与えてあげるとよいでしょう。 上の例の2行目で、左端を基点に「繰り返し回数×25」位置にメッセージを表示するように設定しています。 1回目に「1×25=25」、2回目に「2×25=50」、3回目に「3×25=75」を それぞれX座標に指定してるというわけです。 カウントダウンさせたい場合は下記のようにすればよいでしょう。
 1
 2
 3
 4
 5
 6
	repeat 3
		pos cnt * 25, 0
		mes "" + (3 - cnt) + "…"
	loop
	pos 100, 0
	mes "ハッスル!ハッスル!"
何気なく紹介していますが、実は3行目の書き方はHSP3から記述できるようになりました。 バージョン3からあらゆる処理順序が、括弧を使用した場合に内部から計算されるようになったのです。 それまでは計算式のみ括弧が内部から処理され、それ以外は括弧をつけても効果ありませんでした。 簡単な話、文字列内でも括弧をつけると括弧内の計算結果を文字列として使用できるようになったわけです。 入っていて当たり前とも言える仕様ですが、以前から使っている人にとってこの変更はありがたいですね。 バージョン2以前は下記のようなアセンブラっぽい書き方をしなければならなかったのです。
 1
 2
 3
 4
 5
 6
 7
	repeat 3
		pos cnt * 25, 0
		counter = 3 - cnt // 一旦別の変数に演算結果を代入
		mes "" + counter + "…" // 表示処理に演算させることはできない
	loop
	pos 100, 0
	mes "ハッスル!ハッスル!"
repeat命令はループ回数を指定できますが、次の命令を使うと指定回数よりも早く終わらせられます。 また、回数指定のないループの場合はこの命令を使用しなければ正常にループを抜けられなくなります。
break
[パラメータなし]処理をloopの次に移すだけの為、パラメータは必要ない。
使い方は至って簡単。抜けたいところでbreak命令を記述するだけです。 break命令を通過すると、回数が何回であろうと、break命令以下にも別命令があろうとも 強制的にループを抜けるようになっています。 通常はそのままポンと置くのではなく、5章で紹介した条件分岐命令と組み合わせて 「ある条件」に該当した場合のみbreak命令を実行させるようにすることでしょう。
 1
 2
 3
 4
 5
	repeat 10, 1
		if cnt = 8 : break
		mes "繰り返し数:" + cnt + "回"
	loop
	mes "指定回数以下で抜けました。"
2行目にブレイク条件を置いている為、繰り返し回数1〜7回は正常にループしメッセージを表示しますが、 8回目には条件に該当しbreak命令を処理する為、3行目のメッセージ表示をせずloop命令の次行に進みます。 ループの度にシステム変数cntは1ずつカウントアップするわけですが、 continue命令を使用することでcntを指定回数から再実行することができるようになります。
continue 変更後のカウンタ値
変更後のカウンタ値cntを指定数に変更してrepeat位置に戻る。
continue命令を処理すると現在のcntを指定回数に変更しrepeat命令位置に移動します。 パラメータを省略すると、「cnt+1」を指定したことと同じものを意味する為、 実質、ループ内に配置するloop命令の役割にすることが可能です。 変更後のカウンタ値は今よりも小さい値だけでなく、大きい値や同じ値も設定可能です。 ループさせる回数よりも大きい値を指定すると、break命令と同じ役割を果たすこととなります。 continue命令に通過しない条件分岐なしに現在値と同じ回数か少ない回数を指定すると、 例えループ回数を1回に設定しても無限ループとなるので、注意してください。
 1
 2
 3
 4
	repeat 30
		mes "現在「" + cnt + "」回目。"
		if cnt \ 6 = 5 : continue cnt + 7
	loop
3行目で「\」を使用していますが、コレはHSPで使用する余りを求めるときに使用する演算子です。 「cnt \ 6」で「0,1,2,3,4,5,0,1,2,3,4,5,0,1,2…」と繰り返しますが、5になった時に「+7」します。 演算子についてもう少し掘り下げてみましょう。 加算「+」やビットシフト「>>」は言語が変われど共通の記号ですが、 なぜか余算演算子だけは統一されず言語により微妙にバラバラです。 「%」を用いるものが多いようですが、HSPでは余算演算子に「\」を使ってください。 余算とは何かということまではコチラでは説明しません。わからない方は調べてくださいませ。 他の演算子は同じであるように書きましたが、何があるのかわからなければ同じでも使えませんね。
+加算「1 + 2」で「3」
-減算「2 - 1」で「1」
*乗算「1 * 2」で「2」
/除算「2 / 1」で「2」
\余算「1 \ 2」で「1」
>>右ビットシフト「2 >> 1」で「1」
<<左ビットシフト「1 << 2」で「4」
|,||,or論理和「2 | 1」で「3」
&,&&,and論理積「1 & 2」で「0」
^,xor排他的論理和「1 ^ 2」で「3」
=,==等価「2 = 1」で「0」
!,!=,not不等価「1 != 2」で「1」
>「1 > 1」で「0」
>=以上「2 >= 2」で「1」
<未満「1 < 1」で「0」
<=以下「2 <= 2」で「1」
加減乗除余算については演算式の中に何個あっても普通ですが、等価や以上・以下等はあまり見かけません。 しかし、ビット演算や論理演算と呼ばれるものの中ではごく自然に使われるものです。 覚えておくと別々に分けなければできなさそうな公式でも1つにすることができるかもしれません。
 1
 2
	mes (X * 2 > 9) * 100 + 200
	v = ((X > 3) = (Y - 5 <= 1)) + 4
例えば、1行目では変数Xに2を乗じた数値が10以上なら300、9以下なら200を表示するものです。 2行目は、変数Xが4以上でかつ変数Yに5引いたものが1以下となるか、 変数Xが3以下でかつ変数Yに5引いたものが2以上なら5、宗でないなら4を変数vに代入します。 様々な用途で利用できると思いますので是非とも覚えておきたいものです。 最後になりますが、システム変数をもう一点だけ紹介してきます。 ループに使用できるシステム変数はcntの他にlooplevというものがあります。 このlooplevcntに比べ、使用する機会が少ないものと思われます。 知っていなくてもほとんど差しさわりがないものでしょうが、紹介だけはしておきます。 どんなものかは名前からなんとなく想像出来るかもしれませんが、 ループのレベル(ネスト)回数を知るために用意されています。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
	y = 1
	repeat 9
		x = 1
		repeat 9
			pos x * 60, y * 30
			mes "" + x + "*" + y + "=" + (x * y)
			x++
		loop
		y++
	loop
ループは一重だけではなく、上記の様に何重かに入れ子にすることが可能となっています。 一重のループではlooplevが1、サンプルのように二重ではlooplevが2、ループ外では0となります。 このネスト回数はループ外に抜けることでマイナスされますが、ネスト回数には上限があります。 しかし、下記8重のループでも、エラーにはなりません。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
	repeat 1
		mes "ネスト回数:" + looplev
		repeat 1
			mes "ネスト回数:" + looplev
			repeat 1
				mes "ネスト回数:" + looplev
				repeat 1
					mes "ネスト回数:" + looplev
					repeat 1
						mes "ネスト回数:" + looplev
						repeat 1
							mes "ネスト回数:" + looplev
							repeat 1
								mes "ネスト回数:" + looplev
								repeat 1
									mes "ネスト回数:" + looplev
								loop
							loop
						loop
					loop
				loop
			loop
		loop
	loop
ネスト回数でエラーとなってしまうのは32重以上ネストさせた場合となります。 そんなネストさせることなんてないから自分は大丈夫、と思うアナタは危険かもしれません。 なぜなら、知らぬ間にネスト回数が増えてエラーになってしまうことがよくあるからです。 どういう時かと申しますと、 後々紹介する「スクリプトの処理位置を変更する命令」をループ内で使用した場合に ループは抜けているのだけど、正常には抜けてないと判断されてネスト回数が増えてしまい、 再びループに突入、不正に抜ける…というのを繰り返してネストがどんどん溜まっていくわけです。 この話は、その処理位置を変更する命令が出て来た時に再度お話します。 とりあえず今はそんなこともあるのかと頭の片隅に入れておいてください。