DQ1の「ふっかつのじゅもん」の仕組みを全解説

この記事では、ドラクエ1のふっかつのじゅもんの仕組みを完全解説しています。
全て読めばプログラムを組んだりできるように、順を追って丁寧に説明しました。
需要があるかどうかは分かりませんが、参考になればうれしいです。

:::note warn
（注）本記事は、ドラクエ1のネタバレを含みます。
:::

▼YouTube動画できました！じっくり学習したい人はどうぞ！

https://youtu.be/a15mmjJqQKo 

Python を使ったサンプルプログラムも用意しています。より詳細に知りたい場合は参考にしてもらえればと思います。

:::note info
サンプルプログラム（Google Colaboratory）
[ドラクエ1 ステータス→じゅもん ](https://colab.research.google.com/drive/1EhM2As0eWuGw-EfjVgBFidhKvQp3vWnm?usp=sharing)
[ ドラクエ1 じゅもん→ステータス ](https://colab.research.google.com/drive/1T84BOO1lyjp7T_CHOVucBQQjPniH7sBH?usp=sharing)
:::


参考サイト（元ネタ）はこちらです。

https://qiita.com/yoshi389111/items/29ade2f62483e9c095d9

じゅもんを解析した日記や、C言語やTypeScriptでのソースコードを公開されています。


## ドラクエ1に存在するステータス

ドラクエ1は普通にプレイすると10～20時間くらいかかる、そこそこやりごたえのあるゲームですが、使用できるデータ量は64KBと非常に少なかったです。なので、レベルは経験値から計算する、HPはレベルから計算する…などといったように、保存しておくべきステータスをなるべく削減するという工夫がなされていました。

よって、主人公の状態を決めるステータスも数が絞られ、下の項目に示す分しかありません。

- 名前（6bit×4文字）
- 経験値（16bit）
- 所持金（16bit）
- ぶき（3bit）
- よろい（3bit）
- たて（2bit）
- アイテム（4bit×8）
- やくそうの数（4bit）
- かぎの数（4bit）
- りゅうのうろこを装備したか（1bit）
- せんしのゆびわを装備したか（1bit）
- しのくびかざりを装備したか（1bit）
- ドラゴンを倒したか（1bit）
- ゴーレムを倒したか（1bit）
- パターン（3bit）



bitというのは **二進数に直したとき何桁になるか** ということです。例えばやくそうの数なら0～6個のどれかですが、6は二進数で110なので、000～110でやくそうの数は表現できます。つまり、3ケタぶんの二進数があれば足りるということです。なので3bitになっています。

合計すると全部で112bitあり、ここから8bitのチェックコードというのを計算するので、全データをずらーっと並べると120bitになります。つまり120個の1または0が並んでいるというイメージです。これがふっかつのじゅもんで表されている全情報になります。

それぞれの項目を一つずつ確認します。

### 名前

ゲームスタート時に入力する名前です。最大でひらがな4文字で、一文字当たり6bitなので計6×4=24bitの情報量となります。

文字に割り当たっている番号は次のようになっています。

```python
#名前に使われる文字と番号との関係
nameDict = {0:"０", 1:"１", 2:"２", 3:"３", 4:"４", 5:"５", 6:"６", 7:"７", 8:"８", 9:"９",
            10:"あ", 11:"い", 12:"う", 13:"え", 14:"お", 15:"か", 16:"き", 17:"く", 18:"け", 19:"こ",
            20:"さ", 21:"し", 22:"す", 23:"せ", 24:"そ", 25:"た", 26:"ち", 27:"つ", 28:"て", 29:"と",
            30:"な", 31:"に", 32:"ぬ", 33:"ね", 34:"の", 35:"は", 36:"ひ", 37:"ふ", 38:"へ", 39:"ほ",
            40:"ま", 41:"み", 42:"む", 43:"め", 44:"も", 45:"や", 46:"ゆ", 47:"よ", 48:"ら", 49:"り",
            50:"る", 51:"れ", 52:"ろ", 53:"わ", 54:"を", 55:"ん", 56:"っ", 57:"ゃ", 58:"ゅ", 59:"ょ",
            60:"゛", 61:"゜", 62:"ー", 63:"　"}
```

3文字以下の場合は「空白」用の二進数（111111）が挿入されます。上の図で言うと「空白」は63番に当たります。例えば「ろと　　」は二文字分のデータではなく、空白も一文字6bit分の扱いなので、結局、四文字分のデータ量24bitとなります。

また、0～9番には「0」から「9」の文字が割り当たっています。本来は名前に数字を使うことはできないはずですが、ふっかつのじゅもんを調整することで、数字をつけることもできます。

:::note info
例えば、「ふるいけやかわずとびこむみずのおとばしや」では、「4ひえた」という名前になります
:::

### 経験値

ステータスのEに書かれている値（EXP）です。0～65535の値を取り、二進数では16桁で表せます。
レベルは経験値から計算されます。

### 所持金

いわゆるゴールドで、ステータスのGに書かれている値です。
0～65535の値を取り、16bitです。

### ぶき

装備している武器です。0～7の8種類あります。

```
0. なし
1. たけざお
2. こんぼう
3. どうのつるぎ
4. てつのおの
5. はがねのつるぎ
6. ほのおのつるぎ
7. ロトのつるぎ
```


それぞれの番号を2進数になおした値が3bitであらわされます。例えば、てつのおのは4番なので100です。

### よろい

装備しているよろいです。ぶきと同様、0～7の8種類あります。

```
0. なし
1. ぬののふく
2. かわのふく
3. くさりかたびら
4. てつのよろい
5. はがねのよろい
6. まほうのよろい
7. ロトのよろい
```


### たて

たてです。こちらは、0～3の4種類しかありません。

```
0. なし
1. かわのたて
2. てつのたて
3. みかがみのたて
```


なんで「たて」の最強装備だけ「ロトのたて」じゃなくて「みかがみのたて」なんでしょうね。

### アイテム

アイテムは全14種類あり、8つ持つことができます。
なので、4bit分のデータが8種類あり、合計32bitであらわせます。

アイテムの種類は次の通り。

```
0. なし
1. たいまつ
2. せいすい
3. キメラのつばさ
4. りゅうのうろこ
5. ようせいのふえ
6. せんしのゆびわ
7. ロトのしるし
8. おうじょのあい
9. のろいのベルト
10. ぎんのたてごと
11. しのくびかざり
12. たいようのいし
13. あまぐものつえ
14. にじのしずく
```


重要アイテムが多いので、普段使いするアイテムはそんなに種類がない印象です。

「のろいのベルト」と「しのくびかざり」は、どちらも装備する（つかう）と呪いがかかってラダトーム城に入れなくなります。

### やくそうの数

やくそうはアイテムと別枠で所持できます。0～6個まで持てるので、3bitの2進数であらわせますが、先頭に0をつけて4bitで表します。

### かぎの数

かぎもやくそうと同じく、アイテムと別枠になっています。0～6個まで持て、その数を4bitで表します。

### 各種フラグ

イベントをクリアしたかどうかを表すフラグが5つ存在します。

- りゅうのうろこを装備したか（1bit）
- せんしのゆびわを装備したか（1bit）
- しのくびかざりを装備したか（1bit）
- ドラゴンを倒したか（1bit）
- ゴーレムを倒したか（1bit）



上の3つは ```装備したことがあれば1、装備したことがなければ0```
下の2つは ```倒していれば1、倒していなければ0```
であらわされます。

装備がなぜフラグ扱いなのかというと、例えばりゅうのうろこは**一度でも**装備すれば、永久的に守備力が2ポイント上昇するという仕様だからです。一度装備すると外せませんし、2個以上使っても意味はありません。よって「装備したか」「装備してないか」の2択しかないので、フラグで管理されています。
詳しい説明などは[ドラゴンクエスト大辞典](https://wikiwiki.jp/dqdic3rd/%E3%80%90%E3%82%8A%E3%82%85%E3%81%86%E3%81%AE%E3%81%86%E3%82%8D%E3%81%93%E3%80%91)を参照。

### パターン

通常プレイでは気にすることはないと思いますが、パターンという項目もあります。

実は、同じステータスでも、8パターンの異なるふっかつのじゅもんを聞くことができます。
それが、このパターンという項目の数字によって決まります。

0～7までの8種類あるので、3bitです。

### チェックコード

これが何者なのかはあとで示します。とりあえず8bitです。
最初は暫定的にすべて0としておきます。（00000000）



## ドラクエ1ふっかつのじゅもんの仕組み

上の節で、ふっかつのじゅもんに組み込まれているステータスを確認しました。
すべての値はコンピュータ上で2進数として保存されていますので、これからは各項目が2進数であらわされていると思ってください。

ここからふっかつのじゅもんができるまでのザックリした流れを示します。非常に複雑です。

ふっかつのじゅもん作成フロー

- Step1 ふっかつのじゅもんのベースをつくる
- Step2 チェックコードを計算
- Step3 チェックコードを置き換える
- Step4 並べ替える
- Step5 4と一つ前のコードを足す
- Step6 ひらがなになおして完成



何言ってるかわからないと思いますので、それぞれをもう少し詳しく見てみましょう。

### Step1 ふっかつのじゅもんのベースをつくる

「経験値」「ゴールド」「アイテム」などの情報すべてを一列に並べます。全部で120bitの長い2進数となるはずです。
〈イメージ〉
000000000011110100010001…01101000

これを、ここでは「**ふっかつのじゅもんのベース**」と呼びます。

並べ方は次の通り。下に書かれているものをすべて2進数になおして、上から下まで並べると、120bitの2進数になるはずです。

分かりやすいように、8bitごとに区切って書いていきます。つまり、一行が8bit分に対応します。
後ろの（）の中にbit数を記載しています。

```
チェックコード（8bit）
経験値の後ろ半分（8bit）
パターンの3bit目 ＋ しのくびかざり装備した？ ＋ 名前の3文字目（1bit + 1bit + 6bit）

4つ目のアイテム ＋ 3つ目のアイテム（4bit + 4bit）
ゴールドの後ろ半分（8bit）
名前の1文字目 ＋ ゴーレム倒した？ ＋ パターンの2bit目（6bit + 1bit + 1bit）

8つ目のアイテム ＋ 7つ目のアイテム（4bit + 4bit）
パターンの1bit目 ＋ ドラゴン倒した？ ＋ 名前の4文字目（1bit + 1bit + 6bit）
ぶき ＋ よろい ＋ たて（3bit + 3bit + 2bit）

ゴールドの前半分（8bit）
かぎの数 ＋ やくそうの数（4bit + 4bit）
6つ目のアイテム ＋ 5つ目のアイテム（4bit + 4bit）

経験値の前半分（8bit）
りゅうのうろこ装備した？ ＋ 名前の2文字目 ＋ せんしのゆびわ装備した？（1bit + 6bit + 1bit）
2つ目のアイテム ＋ 1つ目のアイテム（4bit + 4bit）
```


つまり、さっきの〈イメージ〉の2進数を使えば、（8bitごとにスペースを入れました）
00000000 00111101 00010001 00001101 … 01101000
となり、

```
最初の「00000000」はチェックコード
次の8bit「00111101」は経験値の後ろ半分
その次の8bit「00010001」は、0がパターンの3bit目、0がしのくびかざりを装備したかのフラグ、001101が名前の3文字目
```



などのように対応しています。分かりにくくてすみません。
（パターンの3bit目というのは、もしパターンが001だった場合、左から数えて3番目の1のことです）

ちなみに、チェックコードは次のステップで計算するので、今の段階では 00000000 とします。

でき上がった2進数は。「チェックコード、経験値、パターン、しのくびかざり…」というように、ぐちゃぐちゃに並んでいます。このように並び替えることで、解読されにくいじゅもんを作ることができるんですね。しかし、アイテムは必ず2連続で配置されてるなど、若干の規則性も見られます。


### Step2 チェックコードを計算

Step1でつくった120bitの2進数「ふっかつのじゅもんのベース」を使って、「**チェックコード**」というものを計算します。
チェックコードというのは、じゅもんが有効かどうかを確認するための数字です（チェックサム？）。120bitすべてを使って計算されるので、例えばやくそうの数が1個→2個になったりするだけで、チェックコードは全然違う数字になります。なので、ほとんどステータスが同じであっても、全く異なるじゅもんが生成されるのです。

厳密に言うと、ここで計算されるチェックコードは **CRC-16-CCITT、生成多項式は 0x1021** らしいです。これはどういうものかというと、ふっかつのじゅもんのベース
000000000011110100010001…01101000
を生成多項式「0x1021（2進数でいうと、0001 0000 0010 0001）」でわり算し、その余りをチェックコードとする計算方式です。

実装は [参考サイト](https://qiita.com/yoshi389111/items/29ade2f62483e9c095d9)のほうを引用すると、

```C
//yoshi389111(2022)「[ネタ]復活の呪文を解析してみたよ」,<https://qiita.com/yoshi389111/items/29ade2f62483e9c095d9>(参照2022-10-11) より引用。
   int cd = 0x8000;
   for (int i = 0; i < 15 * 8; i++) {
       if (cd & 0x8000) {
           cd = (cd << 1) ^ 0x1021;
       } else {
           cd <<= 1;
       }
       printf("0x%.2x\n", cd & 0xff);
   }
```

最終的にcdに代入される値の下8ケタがチェックコードになります。

ちなみに、<<という記号は「シフト演算子」（2進数を左や右に一つずらす）、^は「XOR演算」を表す記号です。

### Step3 チェックコードを置き換える

ふっかつのじゅもんのベース
000000000011110100010001…01101000

の先頭8bitを、Step2で計算したチェックコードに置き換えます。
チェックコードが11101111になった場合は、

111011110011110100010001…01101000

とします。

### Step4 並び替える

ふっかつのじゅもんの2進数を並び替えます。
まず、120bitを、24bitずつ区切って、5つのかたまりを作ります。

```111011110011110100010001…01101000（120bit）```

↓

```24bit``` ```24bit``` ```24bit``` ```24bit``` ```24bit```




5つに分けたかたまりのそれぞれの内部で、数字の並べ替えを行います。

左の24bitのかたまりについてみていきます。

111011110011110100010001（24bit）

24bitを、さらに8bitずつ、三つのかたまりに分け、

<font color="red">11101111 <font color="blue">00111101 <font color="green">00010001

左と右を入れ替えます。

<font color="green">00010001 <font color="blue">00111101 <font color="red">11101111

一旦くっつけた後、今度は6bitずつ分けて、

<font color="purple">000100 <font color="dirt">010011 <font color="SeaGreen">110111 <font color="DimGray">101111

後ろのものから順に並べます。

<font color="DimGray">101111 <font color="SeaGreen">110111 <font color="dirt">010011 <font color="purple">000100



これで一つ目のかたまりは入れ替え完了です。
あとは、残りの4つのかたまりについても同じ操作を行います。

101111 110111 010011 000100 … 011010（120bit）

### Step5 4と一つ前のコードを足す

Step4で並べ替えた120bitの2進数が並び替えられて、最終的に6bit×20の2進数になったはずです。

101111 110111 010011 000100 … 011010（120bit）

分かれた6bitが、最終的なじゅもんのひらがな一文字分に対応します。
20個に区切れたので、ひらがな20文字分ということですが、これはふっかつのじゅもんが20文字であることとつながります。

```
ほりいゆう　じえにつくすど　らごくえす　とだよ
```

では、その6bitをそれぞれひらがなに変換したら終わりか…？というと、そうでもありません。最後に「**4と一つ前のコードを足す**」ということをします。と言われても、何のことかさっぱりだと思います。なので、例をみて理解してください。

まず、一番左の6bit（つまり、じゅもんのひらがな一文字目に対応）に <font color="red">000100（4）</font> を足します。今回の場合でいえば、一文字目に対応する6bitは **101111** なので、

(一文字目) = **101111** + <font color="red">000100</font> = <font color="blue">110011</font>

が、最終的なじゅもんのひらがな一文字目に変換されます。さらに、ここで計算された <font color="blue">110011</font> を覚えておきます。

次の6bit（7bit目から12bit目）は <font color="green">110111</font> です。これはじゅもんのひらがな二文字目に対応しますが、これには<font color="red">000100</font>と、<font color="blue">**一文字目の2進数**</font>を足します。つまり、

(二文字目) = <font color="green">110111</font> + <font color="red">000100</font> + <font color="blue">110011</font> = <font color="purple">101110</font>（7ケタ目は無視）

が、じゅもんの二文字目に変換されます。
同じように三文字目は、また次のとなりの6bitに000100と二文字目の2進数を足して、<font color="gray">010011</font> + <font color="red">000100</font> + <font color="purple">101110</font> を計算します。
このように、6bitをとって、「000100」と「**一つ前の文字の2進数**」を足す、という操作を繰り返します。

四文字目以降の2進数についても、まったく同じように操作をくり返します。

### Step6 ひらがなになおして完成

Step5までで、6bitの2進数（110011など）が20個できたはずです。これらの6bitひとつひとつを、下の対応表を使ってひらがなになおします。

```python
#ふっかつのじゅもんに使われる文字と番号との関係
passDict = {0:"あ", 1:"い", 2:"う", 3:"え", 4:"お", 5:"か", 6:"き", 7:"く", 8:"け", 9:"こ",
            10:"さ", 11:"し", 12:"す", 13:"せ", 14:"そ", 15:"た", 16:"ち", 17:"つ", 18:"て", 19:"と",
            20:"な", 21:"に", 22:"ぬ", 23:"ね", 24:"の", 25:"は", 26:"ひ", 27:"ふ", 28:"へ", 29:"ほ",
            30:"ま", 31:"み", 32:"む", 33:"め", 34:"も", 35:"や", 36:"ゆ", 37:"よ", 38:"ら", 39:"り",
            40:"る", 41:"れ", 42:"ろ", 43:"わ", 44:"が", 45:"ぎ", 46:"ぐ", 47:"げ", 48:"ご", 49:"ざ",
            50:"じ", 51:"ず", 52:"ぜ", 53:"ぞ", 54:"だ", 55:"ぢ", 56:"づ", 57:"で", 58:"ど", 59:"ば",
            60:"び", 61:"ぶ", 62:"べ", 63:"ぼ"}
```

例えば、一文字目はStep5で計算した値をみると 110011 でした。上の対応表は10進数で番号が示されていますので、110011 を10進数になおすと「51」です。つまり、51番の「ず」がじゅもんの一文字目だということです。

この調子で、すべての2進数をひらがなになおしたら、晴れてじゅもんの完成です！

ちなみに、この2進数⇔ひらがなの対応表は、名前の方ででてきた対応表と異なるものになっています。

```python
#名前に使われる文字と番号との関係
nameDict = {0:"０", 1:"１", 2:"２", 3:"３", 4:"４", 5:"５", 6:"６", 7:"７", 8:"８", 9:"９",
            10:"あ", 11:"い", 12:"う", 13:"え", 14:"お", 15:"か", 16:"き", 17:"く", 18:"け", 19:"こ",
            20:"さ", 21:"し", 22:"す", 23:"せ", 24:"そ", 25:"た", 26:"ち", 27:"つ", 28:"て", 29:"と",
            30:"な", 31:"に", 32:"ぬ", 33:"ね", 34:"の", 35:"は", 36:"ひ", 37:"ふ", 38:"へ", 39:"ほ",
            40:"ま", 41:"み", 42:"む", 43:"め", 44:"も", 45:"や", 46:"ゆ", 47:"よ", 48:"ら", 49:"り",
            50:"る", 51:"れ", 52:"ろ", 53:"わ", 54:"を", 55:"ん", 56:"っ", 57:"ゃ", 58:"ゅ", 59:"ょ",
            60:"゛", 61:"゜", 62:"ー", 63:"　"}
```

名前の場合は、「0、1」などの数字や「っ、ゃ、ゅ、ょ」などが使える一方、「が」「ば」などの濁点付きのひらがなは使用できませんでした。逆に、ふっかつのじゅもんでは数字などが使えない代わりに、濁点付きのひらがなが使われています。なので、名前のときは「あ」は10番だったのに、じゅもんのときは「あ」は0番に対応する、などのズレが生じています。

## おわりに

以上が、ふっかつのじゅもんの仕組みです。

実装するなど、より深い仕組みまで知りたい場合は、冒頭でも示したPythonのサンプルプログラムや、[元ネタのサイト](https://qiita.com/yoshi389111/items/29ade2f62483e9c095d9)なども確認してみてください。

:::note info
サンプルプログラム（Google Colaboratory）
[ドラクエ1 ステータス→じゅもん ](https://colab.research.google.com/drive/1EhM2As0eWuGw-EfjVgBFidhKvQp3vWnm?usp=sharing)
[ ドラクエ1 じゅもん→ステータス ](https://colab.research.google.com/drive/1T84BOO1lyjp7T_CHOVucBQQjPniH7sBH?usp=sharing)
:::