シレン6 武器盾の値段と呪い状態に法則性があるのか検証する


## 事の発端

https://note.com/shiny_llama970/n/n8469520feb5f

上の記事を読んでいて興味深い記述を見つけました。
それを引用します。

>値段から呪いの判定は、以下のようにすればいい（間違っていたら教えてください）
>* 買値：下1桁が0であれば呪いではない
>* 売値：下1桁が0か5であれば呪いではない

（現在、打ち消し線が入っているが、例外パターンがあったのか、それともただ単に予防線を張っているだけなのかが分からない。）

もし、これが本当だとしたら非常に値段識別が楽になる大発見です。

私はこれの真偽が知りたい。と思いました。

## 検証する

しかし、私は数学が苦手なのでこれが正しいかどうかを論理的に求めることができません。
という訳でテキトーな武器盾を生成してぱいぷ氏の非呪い判定が正しいのかを検証したいと思います。
とりあえず1億回検証します。

```javascript:main.js
/*
【参考元】
風来のシレン６　武器・盾の値段計算式
https://note.com/shiny_llama970/n/n8469520feb5f

武器 - 風来のシレン6 とぐろ島探検録 Wiki
https://shiren6.game-info.wiki/d/%C9%F0%B4%EF

盾 - 風来のシレン6 とぐろ島探検録 Wiki
https://shiren6.game-info.wiki/d/%bd%e2
*/

function 値段の計算(値段の種類, アイテム, 神器か, 修正値, 印リスト, 呪いか) {
    const 神器補正 = 神器か ? 2 : 1;
    const 修正値補正 = 値段の種類 === '買値' ? 100 : 40;
    const 印の値段の和 = 印リスト.reduce((和, 印) => 和 + 印[値段の種類], 0);
    const 呪い補正 = 呪いか ? 0.87 : 1;
    return Math.floor((アイテム[値段の種類] * 神器補正 + 修正値 * 修正値補正 + 印の値段の和) * 呪い補正);
}

function 値段の計算式(値段の種類, アイテム, 神器か, 修正値, 印リスト, 呪いか) {
    const 神器補正 = 神器か ? 2 : 1;
    const 修正値補正 = 値段の種類 === '買値' ? 100 : 40;
    const 印の値段の和の計算式 = 印リスト.map(印 => 印[値段の種類]).join(' + ');
    const 呪い補正 = 呪いか ? 0.87 : 1;
    if (印リスト.length === 0) {
        return `(${アイテム[値段の種類]} * ${神器補正} + ${修正値} * ${修正値補正}) * ${呪い補正}`;
    }
    else {
        return `(${アイテム[値段の種類]} * ${神器補正} + ${修正値} * ${修正値補正} + (${印の値段の和の計算式})) * ${呪い補正}`;
    }
}

const 武器一覧 = [
    {名前: '木刀', 買値: 250, 売値: 100},
    {名前: '青銅の太刀', 買値: 550, 売値: 220},
    {名前: 'カタナ', 買値: 1000, 売値: 400},
    {名前: 'どうたぬき', 買値: 2200, 売値: 880},
    {名前: '剛剣マンジカブラ', 買値: 5500, 売値: 2200},
    {名前: '火迅風魔刀', 買値: 16000, 売値: 6400},
    {名前: '秘剣カブラステギ', 買値: 25000, 売値: 10000},
    {名前: '金の剣', 買値: 3000, 売値: 1200},
    {名前: '妖刀かまいたち', 買値: 8400, 売値: 3360},
    {名前: 'ミノタウロスの斧', 買値: 6500, 売値: 2600},
    {名前: '必中の剣', 買値: 20000, 売値: 8000},
    {名前: '連撃刀', 買値: 10000, 売値: 4000},
    {名前: '水斬りの剣', 買値: 3300, 売値: 1320},
    {名前: '原始の斧', 買値: 5000, 売値: 2000},
    {名前: 'ドラゴンキラー', 買値: 4000, 売値: 1600},
    {名前: '三日月刀', 買値: 3500, 売値: 1400},
    {名前: '空の刃', 買値: 3700, 売値: 1480},
    {名前: '成仏のカマ', 買値: 4200, 売値: 1680},
    {名前: 'ドレインバスター', 買値: 3600, 売値: 1440},
    {名前: '一ツ目殺し', 買値: 3200, 売値: 1280},
    {名前: '斬鉄剣', 買値: 3100, 売値: 1240},
    {名前: '巨大ハリセン', 買値: 4200, 売値: 1680},
    {名前: '回復の剣', 買値: 4300, 売値: 1720},
    {名前: '桃まん棒', 買値: 4500, 売値: 1800},
    {名前: '金食い虫こん棒', 買値: 6000, 売値: 2400},
    {名前: '鉄塊の大剣', 買値: 5300, 売値: 2120},
    {名前: 'ステーキナイフ', 買値: 5400, 売値: 2160},
    {名前: 'スパークソード', 買値: 5500, 売値: 2200},
    {名前: '四ツ叉', 買値: 5600, 売値: 2240},
    {名前: 'めでたい熊手', 買値: 5700, 売値: 2280},
    {名前: 'つるはし', 買値: 1000, 売値: 400},
    {名前: '黄金のつるはし', 買値: 18000, 売値: 7200},
    {名前: '木づち', 買値: 1000, 売値: 400},
    {名前: '最強ハンマー', 買値: 15000, 売値: 6000},
    {名前: '罠探りの棒', 買値: 4400, 売値: 1760},
    {名前: 'かつおぶし', 買値: 1800, 売値: 720},
    {名前: '山姥包丁', 買値: 4000, 売値: 1600},
    {名前: '使い捨て刀', 買値: 3000, 売値: 1200},
];

const 盾一覧 = [
    {名前: '木甲の盾', 買値: 500, 売値: 200},
    {名前: '青銅甲の盾', 買値: 800, 売値: 320},
    {名前: '鉄甲の盾', 買値: 1200, 売値: 480},
    {名前: 'おにおおかみ', 買値: 1500, 売値: 600},
    {名前: '風魔の盾', 買値: 6000, 売値: 2400},
    {名前: '螺旋風魔の盾', 買値: 15000, 売値: 6000},
    {名前: '金の盾', 買値: 2500, 売値: 1000},
    {名前: 'バトルカウンター', 買値: 2200, 売値: 880},
    {名前: '見切りの盾', 買値: 4000, 売値: 1600},
    {名前: 'ドラゴンシールド', 買値: 3000, 売値: 1200},
    {名前: '爆発隠の盾', 買値: 3300, 売値: 1320},
    {名前: 'ミノタウロスの盾', 買値: 2500, 売値: 1000},
    {名前: 'トドよけの盾', 買値: 2600, 売値: 1040},
    {名前: 'ガマラよけの盾', 買値: 2700, 売値: 1080},
    {名前: 'いたずらよけの盾', 買値: 2800, 売値: 1120},
    {名前: 'にぎりよけの盾', 買値: 3600, 売値: 1440},
    {名前: 'オトトの盾', 買値: 2000, 売値: 800},
    {名前: 'カッパのお皿', 買値: 5000, 売値: 2000},
    {名前: 'ゲイズの盾', 買値: 4000, 売値: 1600},
    {名前: '魔法よけの盾', 買値: 7500, 売値: 3000},
    {名前: '不動の盾', 買値: 2500, 売値: 1000},
    {名前: 'ざぶとん', 買値: 3000, 売値: 1200},
    {名前: '金食い虫の盾', 買値: 6000, 売値: 2400},
    {名前: '鉄塊の大盾', 買値: 4400, 売値: 1760},
    {名前: 'ステーキプレート', 買値: 4500, 売値: 1800},
    {名前: '根性の盾', 買値: 4600, 売値: 1840},
    {名前: '絶好調の盾', 買値: 5000, 売値: 2000},
    {名前: 'サトリの盾', 買値: 10000, 売値: 4000},
    {名前: 'ハラモチの盾', 買値: 2000, 売値: 800},
    {名前: 'めでたい御守', 買値: 5500, 売値: 2200},
    {名前: 'お告げの盾', 買値: 7000, 売値: 2800},
    {名前: '山姥の鍋ぶた', 買値: 4100, 売値: 1640},
    {名前: '使い捨ての盾', 買値: 3400, 売値: 1360},
];

const 武器印一覧 = [
    {名前: 'サビ', 買値: 500, 売値: 175},
    {名前: '三', 買値: 3000, 売値: 1050},
    {名前: '後', 買値: 3000, 売値: 1050},
    {名前: '左右', 買値: 3000, 売値: 1050},
    {名前: '会', 買値: 1000, 売値: 350},
    {名前: '必', 買値: 5000, 売値: 1750},
    {名前: '連', 買値: 5000, 売値: 1750},
    {名前: '水', 買値: 500, 売値: 175},
    {名前: '獣', 買値: 500, 売値: 175},
    {名前: '竜', 買値: 500, 売値: 175},
    {名前: '爆', 買値: 500, 売値: 175},
    {名前: '仏', 買値: 500, 売値: 175},
    {名前: 'ド', 買値: 500, 売値: 175},
    {名前: '目', 買値: 500, 売値: 175},
    {名前: '斬', 買値: 1000, 売値: 350},
    {名前: '浮', 買値: 500, 売値: 175},
    {名前: 'デ', 買値: 500, 売値: 175},
    {名前: '乱', 買値: 1000, 売値: 350},
    {名前: '眠', 買値: 1000, 売値: 350},
    {名前: '封', 買値: 1000, 売値: 350},
    {名前: '暗', 買値: 1000, 売値: 350},
    {名前: '縛', 買値: 1000, 売値: 350},
    {名前: '炎', 買値: 2000, 売値: 700},
    {名前: '電', 買値: 1000, 売値: 350},
    {名前: '突', 買値: 1000, 売値: 350},
    {名前: '回', 買値: 1000, 売値: 350},
    {名前: '桃', 買値: 1000, 売値: 350},
    {名前: '金', 買値: 1000, 売値: 350},
    {名前: '腹力', 買値: 1000, 売値: 350},
    {名前: '飢', 買値: 1000, 売値: 350},
    {名前: 'ス', 買値: 500, 売値: 175},
    {名前: '溜4', 買値: 500, 売値: 175},
    {名前: '0', 買値: 500, 売値: 175},
    {名前: '1', 買値: 500, 売値: 175},
    {名前: '2', 買値: 500, 売値: 175},
    {名前: '3', 買値: 500, 売値: 175},
    {名前: '4', 買値: 500, 売値: 175},
    {名前: '5', 買値: 500, 売値: 175},
    {名前: '6', 買値: 500, 売値: 175},
    {名前: '7', 買値: 500, 売値: 175},
    {名前: '8', 買値: 500, 売値: 175},
    {名前: '9', 買値: 500, 売値: 175},
    {名前: '堀', 買値: 500, 売値: 175},
    {名前: '堀∞', 買値: 5000, 売値: 1750},
    {名前: '壊', 買値: 500, 売値: 175},
    {名前: '壊∞', 買値: 5000, 売値: 1750},
    {名前: '探', 買値: 500, 売値: 175},
    {名前: '鰹', 買値: 500, 売値: 175},
    {名前: '呪', 買値: 500, 売値: 175},
    {名前: '劣', 買値: 500, 売値: 175},
    {名前: '薬', 買値: 2000, 売値: 700},
    {名前: '弟', 買値: 1000, 売値: 350},
    {名前: '癒', 買値: 3000, 売値: 1050},
    {名前: '命', 買値: 3000, 売値: 1050},
];

// 魔反の値段が分からないため抜けている。
const 盾印一覧 = [
    {名前: 'サビ', 買値: 500, 売値: 175},
    {名前: '反', 買値: 1000, 売値: 350},
    {名前: '影', 買値: 1000, 売値: 350},
    {名前: 'ゾ', 買値: 1000, 売値: 350},
    {名前: '暴', 買値: 1000, 売値: 350},
    {名前: '惑', 買値: 1000, 売値: 350},
    {名前: '米', 買値: 1000, 売値: 350},
    {名前: '飛', 買値: 8000, 売値: 2800},
    {名前: '見', 買値: 2000, 売値: 700},
    {名前: '竜', 買値: 8000, 売値: 2800},
    {名前: '爆', 買値: 1000, 売値: 350},
    {名前: '痛', 買値: 8000, 売値: 2800},
    {名前: '鱗', 買値: 1000, 売値: 350},
    {名前: 'ト', 買値: 1000, 売値: 350},
    {名前: 'ガ', 買値: 1000, 売値: 350},
    {名前: '戯', 買値: 1000, 売値: 350},
    {名前: '握', 買値: 8000, 売値: 2800},
    {名前: '投', 買値: 1000, 売値: 350},
    {名前: '催', 買値: 1000, 売値: 350},
    {名前: '魔よ', 買値: 1000, 売値: 350},
    // {名前: '魔反', 買値: , 売値: },
    {名前: '不', 買値: 2000, 売値: 700},
    {名前: '受', 買値: 1000, 売値: 350},
    {名前: '金', 買値: 8000, 売値: 2800},
    {名前: '腹力', 買値: 1000, 売値: 350},
    {名前: '飢', 買値: 1000, 売値: 350},
    {名前: '根', 買値: 1000, 売値: 350},
    {名前: '満', 買値: 1000, 売値: 350},
    {名前: 'ハラ', 買値: 500, 売値: 175},
    {名前: 'サ', 買値: 5000, 売値: 1750},
    {名前: '罠', 買値: 1000, 売値: 350},
    {名前: '0', 買値: 1000, 売値: 350},
    {名前: '1', 買値: 1000, 売値: 350},
    {名前: '2', 買値: 1000, 売値: 350},
    {名前: '3', 買値: 1000, 売値: 350},
    {名前: '4', 買値: 1000, 売値: 350},
    {名前: '5', 買値: 1000, 売値: 350},
    {名前: '6', 買値: 1000, 売値: 350},
    {名前: '7', 買値: 1000, 売値: 350},
    {名前: '8', 買値: 1000, 売値: 350},
    {名前: '9', 買値: 1000, 売値: 350},
    {名前: '告', 買値: 1000, 売値: 350},
    {名前: '呪', 買値: 1000, 売値: 350},
    {名前: '劣', 買値: 1000, 売値: 350},
    {名前: '薬', 買値: 2000, 売値: 700},
    {名前: '弟', 買値: 1000, 売値: 350},
    {名前: '癒', 買値: 3000, 売値: 1050},
    {名前: '命', 買値: 3000, 売値: 1050},
];

// 0以上{個数}未満の整数をランダムで返す。
function 乱数(個数) {
    return Math.floor(Math.random() * 個数);
}

function 武器盾ランダム検証() {
    let アイテム = null;
    let 印一覧 = [];
    if (乱数(2) === 0) {
        アイテム = 武器一覧[乱数(武器一覧.length)];
        印一覧 = 武器印一覧;
    }
    else {
        アイテム = 盾一覧[乱数(盾一覧.length)];
        印一覧 = 盾印一覧;
    }
    const 印数 = 乱数(6); // 最大5個まで印が入っていると仮定する。数値に深い意味はなくテキトーに決めた。
    const 印リスト = [];
    while (印リスト.length < 印数) {
        const 印 = 印一覧[乱数(印一覧.length)];
        if (!印リスト.includes(印)) {
            印リスト.push(印);
        }
    }
    const 神器か = 乱数(2) === 0;
    const 呪いか = true; // 例外パターンを探したいので、ここはtrueで固定する。
    const 値段の種類 = 乱数(2) === 0 ? '買値' : '売値';
    const 修正値 = -1 + 乱数(5); // -1以上3以下の修正値だと仮定する。数値に深い意味はなくテキトーに決めた。

    const 値段 = 値段の計算(値段の種類, アイテム, 神器か, 修正値, 印リスト, 呪いか);

    const 下1桁 = 値段 % 10;

    /*
    値段から呪いの判定は、以下のようにすればいい（間違っていたら教えてください）
    ・買値：下1桁が0であれば呪いではない
    ・売値：下1桁が0か5であれば呪いではない
    (引用元: https://note.com/shiny_llama970/n/n8469520feb5f)
    */
    if (値段の種類 === '買値' && 下1桁 === 0 || 値段の種類 === '売値' && (下1桁 === 0 || 下1桁 === 5)) {
        if (呪いか) {
            console.error('【例外パターン発生】');
            console.error(`${値段の種類}, ${アイテム.名前}, 神器か = ${神器か}, 修正値 = ${修正値}, 印リスト = [${印リスト.map(印 => 印.名前).join(', ')}], 呪いか = ${呪いか}`);
            console.error(`${値段の計算式(値段の種類, アイテム, 神器か, 修正値, 印リスト, 呪いか)} = ${値段}`);
            return false;
        }
        else { // 呪いで固定しているため、ここに来ることはないが、意味論的に残している。
            console.log('【問題なし】');
            console.log(`${値段の種類}, ${アイテム.名前}, 神器か = ${神器か}, 修正値 = ${修正値}, 印リスト = [${印リスト.map(印 => 印.名前).join(', ')}], 呪いか = ${呪いか}`);
            console.log(`${値段の計算式(値段の種類, アイテム, 神器か, 修正値, 印リスト, 呪いか)} = ${値段}`);
            console.log("");
        }
    }
    return true;
}

let 異常なしか = true;
for (let i = 0; i < 1_0000_0000; i++) {
    異常なしか = 武器盾ランダム検証();
    if (!異常なしか) {
        break;
    }
}

if (異常なしか) {
    console.log('問題なく検証が終わりました。');
}
```

## 結果

```
【例外パターン発生】
売値, 山姥包丁, 神器か = true, 修正値 = 1, 印リスト = [回, 探], 呪いか = true
(1600 * 2 + 1 * 40 + (350 + 175)) * 0.87 = 3275
```

なんと例外パターンがありました。

ちなみに床落ち呪い装備は修正値は-1されているので、そこを固定して調べてみましたが、やはり例外がありました。

（簡単は反例はカタナの呪いでしょう。）

## 終わりに

値段から楽に呪い判定が出来ないという結果になり残念でした。

しかし、計算式が分からなければ検証をすることもできませんでした。
noteのアカウントがないのでここに書きますが、
ぱいぷさん調査ありがとうございます。