学研の4ビットマイコン GMC-4 で、一見じゃんけんのようなゲームを作ってみた。
遊び方
0 (グー)、1 (チョキ)、2 (パー) のいずれかのキーを押して自分の手を選択する。
自分の手を選択すると、選択した手を表す2進LEDが光り、7セグメントLEDに相手の手が表示される。
相手の手は、6 (グー)、A (チョキ)、0 (パー) のいずれかで表示される。(手の形をイメージした設計)
仕様
2人で行う通常のじゃんけんでは、1回手を出すと、1/3の確率で勝ち、1/3の確率で負け、1/3の確率であいこになる。
しかし、今回のプログラムでは、プレイヤーは1/8の確率で勝ち、7/8の確率で負け、あいこになる確率は0である。
勝つか負けるかをランダムで決め、プレイヤーの手を見てから後出しで手を出すのである。
Tモールの「CMじゃんけん」で全然あいこが出ないことから思いついた。
プログラム
以下のプログラムは、MikeAssembler でアセンブルできる。
target gmc4
; プレイヤーの操作
; グー : 0
; チョキ : 1
; パー : 2
; プレイヤーの出す手 (2進LED)
; グー : 2ビット目
; チョキ : 1ビット目
; パー : 0ビット目
; 相手の出す手 (7セグメントLED)
; グー : 6
; チョキ : A
; パー : 0
TIA 0
TIY 0xE
AM
TIY 0xF
AM
main_loop:
CAL RSTO
CAL DSPR
; Zレジスタ : 勝敗制御用ルーレット
TIY 0
CH
key_wait:
CH
AIY 2
CH
KA
JUMP key_wait
; 3以上の値が入力された場合は、戻る
AIA 0x10 - 3
JUMP key_wait
; 押された手を2進LEDに表示する
CAL CMPL
CY
CAL SETR
CY
; さらに、勝てる手に変換する
CAL CMPL
AIA 5
; ルーレットが0だった場合、1を引いて負ける手にする
CH
CIY 0
JUMP no_win
CH
AIA -1
CH
no_win:
CH
; mod 3 をとる (3以上だったら3を引く)
AIA 0x10 - 3
JUMP mod_no_rollback
AIA 3
mod_no_rollback:
; 出す手を7セグメントLEDに表示する数字に変換する
TIY 0xD
AM
M+
AM
M+
AIA 8
JUMP hand_decided
AIA -2
hand_decided:
AO
CAL SHTS
key_release_wait:
KA
JUMP main_loop
JUMP key_release_wait
以下は、このプログラムの機械語表現である。
| 0 1 2 3 4 5 6 7 8 9 A B C D E F
--+-----------------------------------
0 | 8 0 A E 4 A F 4 E 0 E D A 0 2 2
1 | B 2 2 0 F 0 F 9 D F 0 F E 4 3 E
2 | 1 3 E 4 9 5 2 D 0 F 3 0 2 9 F 2
3 | 2 9 D F 3 8 9 3 A D 4 6 4 6 9 8
4 | F 4 5 9 E 1 E 9 0 F 0 8 F 4 8
解説
まず、キーから0~2の入力を受け付ける。
これに-3を足すと、それぞれ -3 (0b1101)、-2 (0b1110)、-1 (0b1111) となる。
これをビット反転すると、2 (0b0010)、1(0b0001)、0 (0b0000) となり、2進LEDの点灯位置が求まる。
もう一度ビット反転して元に戻し、5を足すと、2~4になる。
これは、0 (グー) に対して 2 (パー) などのように、3で割った余りがプレイヤーの出した手に勝てる手になっている。
プレイヤーの出した手に勝てる手にするには、さらに1を引けばよい。
すると、例えば 0 (グー) に対して 1 (チョキ) のようになる。
これらの計算で求まった値は3以上にはなり得るが6以上にはならないので、3以上であれば3を引くことで3で割った余りが求まる。
これは、まず3を引いてみて、0未満になったら3を足して取り消す、という処理で実現できる。
3を引いて0未満になるかは、例えば0に-3を足すことを考えるとわかるように、キャリーが無いかで判定できる。
最後に、求まった0~3の手を、7セグメントLEDに表示する数字に変換する。
今回は、0を6、1をA、2を0に変換することにした。
6とAの差は4なので、まず数値を4倍する。
すると、0は0、1は4、2は8になる。
これに8を足すと、それぞれ 8、C、0 となり、変換前が2のときは変換したい0となった。
さらに、このとき変換前が2のときはキャリーがあり、それ以外のときはキャリーが無い。
よって、キャリーが無ければさらに2を引くことで、求めたい 6、A、0 を求めることができる。