/*:
 * @target MZ
 * @plugindesc 最大値に近いほど抽選されにくい変数抽選プラグイン（カーブ調整付き） 
 * @author ChatGPT
 *
 * @param VariableID
 * @text 対象変数
 * @type variable
 * @desc 抽選結果を入れる変数
 * @default 1
 *
 * @param SwitchID
 * @text 抽選スイッチ
 * @type switch
 * @desc このスイッチがONになると抽選が実行され、自動でOFFになります
 * @default 1
 *
 * @param MinValue
 * @text 最小値
 * @type number
 * @desc 抽選範囲の最小値
 * @default 0
 *
 * @param MaxValue
 * @text 最大値
 * @type number
 * @desc 抽選範囲の最大値
 * @default 100
 *
 * @param Curve
 * @text カーブ係数
 * @type number
 * @decimals 2
 * @desc 大きいほど最大値に近い数字が出にくい（1=直線的, 2=急激, 0.5=緩やか）
 * @default 1
 *
 * @help
 * 【使い方】
 * 1. プラグインパラメータで変数ID、スイッチID、最小値、最大値、カーブ係数を設定してください。
 * 2. ゲーム内で指定スイッチをONにすると抽選が行われ、変数に値が代入されます。
 * 3. 抽選後はスイッチが自動でOFFになります。
 *
 * 【カーブ係数の例】
 * - 1 → 直線的に最大値が出にくい
 * - 2 → 最大値付近はかなり出にくい
 * - 0.5 → 最大値付近もそこそこ出やすい
 */

(() => {
    const pluginName = "WeightedRandomVariableCurve";

    const parameters = PluginManager.parameters(pluginName);
    const variableId = Number(parameters["VariableID"] || 1);
    const switchId   = Number(parameters["SwitchID"] || 1);
    const minValue   = Number(parameters["MinValue"] || 0);
    const maxValue   = Number(parameters["MaxValue"] || 100);
    const curve      = Number(parameters["Curve"] || 1);

    // 重み付き乱数
    function weightedRandom(min, max, curve) {
        let range = max - min + 1;
        let weights = [];

        for (let i = 0; i < range; i++) {
            let value = min + i;
            // (距離) ^ curve で調整
            let weight = Math.pow(max - value + 1, curve);
            weights.push(weight);
        }

        let totalWeight = weights.reduce((a, b) => a + b, 0);
        let rnd = Math.random() * totalWeight;
        let cumulative = 0;

        for (let i = 0; i < range; i++) {
            cumulative += weights[i];
            if (rnd < cumulative) {
                return min + i;
            }
        }
        return max; // フォールバック
    }

    const _Game_Map_update = Game_Map.prototype.update;
    Game_Map.prototype.update = function(sceneActive) {
        _Game_Map_update.call(this, sceneActive);

        if ($gameSwitches.value(switchId)) {
            let result = weightedRandom(minValue, maxValue, curve);
            $gameVariables.setValue(variableId, result);
            $gameSwitches.setValue(switchId, false);
        }
    };

})();
