17-9 廃坑から覗く闇④

解説動画

解答コード

// 反対方向の連想配列は、17-8と同じものを使います
// let dic_opposite: { [key: number]: number } = {
//     [RIGHT]: LEFT,    // 右の反対:左
//     [LEFT]: RIGHT,    // 左の反対:右
//     [UP]: DOWN,       // 上の反対:下
//     [DOWN]: UP,       // 下の反対:上
//     [FORWARD]: BACK,  // 前の反対:後ろ
//     [BACK]: FORWARD   // 後ろの反対:前
// };

// エージェントの状態を保持する連想配列
let dic_agentStatus179: { [key: string]: number } = {
    "col": 0,               // エージェントの現在の列位置
    "row": 0,               // エージェントの現在の行位置
    "item": 0,              // エージェントが修理に使うアイテムのID
    "moveDirection": RIGHT, // エージェントの移動方向
    "fixDirection": FORWARD // エージェントが修復する方向
};

// 壁エリアの状態を保持する連想配列
let dic_wallAreaStatus179: { [key: string]: number } = {
    "item": 935,                   // 壁の材料
    "maxCol": 8,                   // 列の最大値
    "maxRow": 4,                   // 行の最大値
    "fixDirection": FORWARD,       // 修復する方向
    "positiveColDirection": RIGHT, // 列の順方向
    "positiveRowDirection": UP     // 行の順方向
};

// 床エリアの状態を保持する連想配列
let dic_floorAreaStatus179: { [key: string]: number } = {
    "item": 5,                     // 床の材料
    "maxCol": 8,                   // 列の最大値
    "maxRow": 9,                   // 行の最大値
    "fixDirection": DOWN,          // 修復する方向
    "positiveColDirection": RIGHT, // 列の順方向
    "positiveRowDirection": BACK   // 行の順方向
};

// エージェントをエリア内で移動させる関数
function move179(agentStatus: { [key: string]: number }, areaStatus: { [key: string]: number }) {
    // エージェントの現在の位置と移動方向を取得します
    let row = agentStatus["row"];                     // エージェントの現在の行位置
    let col = agentStatus["col"];                     // エージェントの現在の列位置
    let moveDirection = agentStatus["moveDirection"]; // エージェントの移動方向

    // 列の順方向を取得します
    let positiveColDirection = areaStatus["positiveColDirection"];
    // 列の逆方向を取得します
    let negativeColDirection = dic_opposite[positiveColDirection];

    // 方向転換が必要かどうかを判定します
    let shouldTurn = false;

    // エージェントが列を順方向に進んでいて、エリアの列の最後にいる場合は、方向転換が必要です
    if (moveDirection == positiveColDirection && col == areaStatus["maxCol"]) {
        shouldTurn = true;
    }
    // エージェントが列を逆方向に進んでいて、エリアの列の最初にいる場合は、方向転換が必要です
    if (moveDirection == negativeColDirection && col == 0) {
        shouldTurn = true;
    }

    // 移動を続けるかどうかを判定します
    let shouldContinue = true;

    // エージェントがエリアの行の最後にいる場合
    if (row == areaStatus["maxRow"]) {
        // かつ、方向転換が必要の場合は、移動してもエリア外に出てしまうので、ここで移動を終了します
        if (shouldTurn) {
            shouldContinue = false;
        }
    }

    // 移動終了の場合は、false を返して終了します
    if (shouldContinue == false) {
        return false;
    }

    // エージェントを移動します
    if (shouldTurn) {
        // 方向転換をする場合の移動方法:

        // 行を移動します
        agent.move(areaStatus["positiveRowDirection"], 1);
        row += 1;
        // エージェントが移動する向きを反対にします
        moveDirection = dic_opposite[moveDirection];
    } else {
        // 方向転換をしない場合の移動方法:

        // 列を移動します
        agent.move(moveDirection, 1);
        if (moveDirection == positiveColDirection) {
            // 列の順方向へ移動する場合はエージェントの列位置に 1 を加えます
            col += 1;
        } else {
            // 列の逆方向へ移動する場合はエージェントの列位置から 1 を除きます
            col -= 1;
        }
    }

    // エージェントの状態を更新します
    agentStatus["row"] = row;
    agentStatus["col"] = col;
    agentStatus["moveDirection"] = moveDirection;

    // 移動したので、true を返して終了します
    return true;
}

// エージェント状態の初期化を行う関数
function initialize179(agentStatus: { [key: string]: number }, areaStatus: { [key: string]: number }) {
    agentStatus["col"] = 0;
    agentStatus["row"] = 0;
    agentStatus["item"] = areaStatus["item"];
    agentStatus["moveDirection"] = areaStatus["positiveColDirection"];
    agentStatus["fixDirection"] = areaStatus["fixDirection"];
}

// エージェントをスタート地点に戻す関数
function returnToOrigin179(agentStatus: { [key: string]: number }, areaStatus: { [key: string]: number }) {
    let backColDirection = dic_opposite[areaStatus["positiveColDirection"]];
    let backRowDirection = dic_opposite[areaStatus["positiveRowDirection"]];

    while (true) {
        let shouldContinue = false;
        if (agentStatus["col"] > 0) {
            agent.move(backColDirection, 1);
            agentStatus["col"] -= 1;
            shouldContinue = true;
        }
        if (agentStatus["row"] > 0) {
            agent.move(backRowDirection, 1);
            agentStatus["row"] -= 1;
            shouldContinue = true;
        }
        if (shouldContinue == false) {
            break;
        }
    }
}

// エージェントが注目する方向のブロックを修復する関数
function fix179(agentStatus: { [key: string]: number }) {
    // エージェントが注目する方向のブロックを調べて、穴が開いていなければ、何もしません
    let blockId = agent.inspect(AgentInspection.Block, agentStatus["fixDirection"]);
    if (blockId > 0) {
        // 何もしないときは false を返します
        return false;
    }
    // 穴が開いているときは、その方向にブロックを置きます
    agent.setItem(agentStatus["item"], 1, 1);
    agent.place(agentStatus["fixDirection"]);
    // ブロックを置いたときは true を返します
    return true;
}

// エージェントがエリア内を移動しながら修復を行う関数
function fixArea179(agentStatus: { [key: string]: number }, areaStatus: { [key: string]: number }) {
    // 修復した箇所の数を数える変数
    let fixedCount = 0;

    // エリア内を移動しながら修復を行います
    while (true) {
        let fixed = fix179(agentStatus);
        if (fixed) {
            fixedCount += 1;
        }
        let shouldContinue = move179(agentStatus, areaStatus);
        if (shouldContinue == false) {
            break;
        }
    }
    // 修復した箇所の数を返します
    return fixedCount;
}

// チャットコマンド「17-9」で壁と床の修復を開始します
player.onChat("17-9", function () {
    player.say("=== 壁と床の修復開始 ===");
    let wallFixed = 0;
    let floorFixed = 0;

    // 壁を直します
    initialize179(dic_agentStatus179, dic_wallAreaStatus179);
    wallFixed = fixArea179(dic_agentStatus179, dic_wallAreaStatus179);

    // スタート地点へ戻ります
    returnToOrigin179(dic_agentStatus179, dic_wallAreaStatus179);

    // 床を直します
    initialize179(dic_agentStatus179, dic_floorAreaStatus179);
    floorFixed = fixArea179(dic_agentStatus179, dic_floorAreaStatus179);

    // 修復した箇所の数を表示します
    player.say("壁の穴: " + wallFixed + "箇所");
    player.say("床の穴: " + floorFixed + "箇所");
    player.say("修復完了");
});