18-9 ドキドキ分岐ポイント④

解説動画

解答画像

 // -- 18-9 魔法陣を修復する ----------------------------------------------------

// 読み取り範囲の連想配列
let dic_scanAreaStatus189: { [key: string]: number } = {
    "width": 5, // 幅
    "depth": 5 // 奥行き
};

// 魔法陣のブロック番号の連想配列
// キー:奥行き(前)方向の移動距離
// 値:連想配列(キー:幅(右)方向の移動距離、値:ブロック番号)
let dic_sigilBlocks189: { [key: number]: { [key: number]: number } } = {
    // 初期状態は空です
};

let airBlockId189 = 0; // 空気ブロックのID

// エージェントの状態の連想配列
let dic_agentStatus189: { [key: string]: number } = {
    "block": 0, // 持つブロック番号
    "forward": 0, // 前の移動距離
    "right": 0, // 右の移動距離
    "placeDirection": DOWN // ブロックを置く方向
};

// エージェントを前へ移動させる関数
function moveForward189(agentStatus: { [key: string]: number }): boolean {
    let canMove = agent.move(FORWARD, 1);
    if (!canMove) {
        player.say("エージェントが前へ移動できません!");
        return false;
    }
    agentStatus["forward"] += 1;
    return true;
}

// エージェントを後ろ移動させる関数
function moveBack189(agentStatus: { [key: string]: number }): boolean {
    let canMove = agent.move(BACK, 1);
    if (!canMove) {
        player.say("エージェントが後ろへ移動できません!");
        return false;
    }
    agentStatus["forward"] -= 1;
    return true;
}

// エージェントを右に移動させる関数
function moveRight189(agentStatus: { [key: string]: number }): boolean {
    let canMove = agent.move(RIGHT, 1);
    if (!canMove) {
        player.say("エージェントが右に移動できません!");
        return false;
    }
    agentStatus["right"] += 1;
    return true;
}

// エージェントを左に移動させる関数
function moveLeft189(agentStatus: { [key: string]: number }): boolean {
    let canMove = agent.move(LEFT, 1);
    if (!canMove) {
        player.say("エージェントが左に移動できません!");
        return false;
    }
    agentStatus["right"] -= 1;
    return true;
}

// エージェントにブロックを設置させる関数
function placeBlock189(agentStatus: { [key: string]: number }): boolean {
    // 空のブロックを置く場合は何もせず true を返して終了します
    if (agentStatus["block"] == airBlockId189) {
        return true;
    }
    agent.setItem(agentStatus["block"], 1, 1);
    let canPlace = agent.place(agentStatus["placeDirection"]);
    if (!canPlace) {
        player.say("エージェントがブロックを設置できません!");
    }
    return canPlace;
}

// エージェントに魔法陣の範囲のブロックを読みとらせる関数
function scanBlockInArea189(agentStatus: { [key: string]: number },
    scanAreaStatus: { [key: string]: number },
    sigilBlocks: { [key: number]: { [key: number]: number } }) {
    // 今のエージェントの位置を記録します
    let forward = agentStatus["forward"];
    let right = agentStatus["right"];
    // 魔法陣の奥行きサイズ分の繰り返し
    while (agentStatus["forward"] - forward < scanAreaStatus["depth"]) {
        // 魔法陣の幅サイズ分の繰り返し
        while (agentStatus["right"] - right < scanAreaStatus["width"]) {
            // ブロックを読み取ります
            let blockId = agent.inspect(AgentInspection.Block, agentStatus["placeDirection"]);
            player.say(`ブロックID: ${blockId}`);

            // 空気ブロックでなければ、魔法陣の連想配列へ登録します
            if (blockId != airBlockId189) {
                // 魔法陣の連想配列の、奥行き(前)方向の位置に、連想配列が未登録の場合:空の連想配列を登録します
                if (sigilBlocks[agentStatus["forward"]] == undefined) {
                    sigilBlocks[agentStatus["forward"]] = {};
                }
                // 魔法陣の連想配列へ、現在のエージェントの位置をキーとして、ブロック番号を登録します
                sigilBlocks[agentStatus["forward"]][agentStatus["right"]] = blockId;
            }

            // 右へ1歩移動します
            moveRight189(agentStatus);
        }
        // 右端まで移動したら、左端まで戻って、前へ1歩移動します
        while (agentStatus["right"] > 0) {
            moveLeft189(agentStatus);
        }
        moveForward189(agentStatus);
    }
}

// 魔法陣を修復する関数
function buildSigil189(agentStatus: { [key: string]: number },
    sigilBlocks: { [key: number]: { [key: number]: number } }) {
    // 魔法陣の奥行き方向の移動距離の配列を取得します
    let forwards = Object.keys(sigilBlocks);
    for (let i = 0; i < forwards.length; i++) {
        // 魔法陣の奥行き方向の移動距離を取得します
        let forward = parseInt(forwards[i]);
        // エージェントを魔法陣の奥行き方向の移動距離だけ前または後ろに移動させます
        while (agentStatus["forward"] < forward) {
            moveForward189(agentStatus);
        }
        while (agentStatus["forward"] > forward) {
            moveBack189(agentStatus);
        }
        // 魔法陣の幅方向の移動距離の配列を取得します
        let rights = Object.keys(sigilBlocks[forward]);
        for (let j = 0; j < rights.length; j++) {
            // 魔法陣の幅方向の移動距離を取得します
            let right = parseInt(rights[j]);
            // エージェントを魔法陣の幅方向の移動距離だけ右または左に移動させます
            while (agentStatus["right"] < right) {
                moveRight189(agentStatus);
            }
            while (agentStatus["right"] > right) {
                moveLeft189(agentStatus);
            }
            // 魔法陣のブロック番号を取得します
            let blockId = sigilBlocks[forward][right];
            // エージェントにブロックを設置させます
            agentStatus["block"] = blockId;
            placeBlock189(agentStatus);
        }
    }
}

// エージェントに魔法陣の範囲のブロックを読みとらせるコマンド
player.onChat("18-9scan", function () {
    // エージェント状態を初期化します
    dic_agentStatus189["block"] = 0;
    dic_agentStatus189["forward"] = 0;
    dic_agentStatus189["right"] = 0;
    dic_agentStatus189["placeDirection"] = DOWN;

    // エージェントを1歩前に移動させます
    moveForward189(dic_agentStatus189);

    // エージェントの位置にあるブロックを調べて、魔法陣パターンの連想配列へ登録します
    scanBlockInArea189(dic_agentStatus189, dic_scanAreaStatus189, dic_sigilBlocks189);

    player.say("魔法陣のパターンをすべて読み取りました");
});

// チャットコマンドで線路を修復する処理を開始します
player.onChat("18-9build", function () {
    // エージェント状態を初期化します
    dic_agentStatus189["block"] = 0;
    dic_agentStatus189["forward"] = 0;
    dic_agentStatus189["right"] = 0;
    dic_agentStatus189["placeDirection"] = DOWN;

    // エージェントを1歩前に移動させます
    moveForward189(dic_agentStatus189);

    // 魔法陣のパターンの連想配列をもとに、エージェントに魔法陣を修復させます
    buildSigil189(dic_agentStatus189, dic_sigilBlocks189);

    player.say("作業を終了します");
});