18-10 その先へダイブ!

解説動画

解答画像

// -- 18-10 5本の封印柱を立てる ----------------------------------------------------

// 封印柱の連想配列
// キー:柱を立てる場所の印のブロック番号
// 値:柱の材料ブロック番号の配列
let dic_pillarBlocks1810: { [key: number]: number[] } = {
    173: [4, 1, 98],     // 印(石炭):        柱 [丸石, 石, 石レンガ]
    896: [945, 48, 98],  // 印(鉄の原石):    柱 [模様入りの凝灰岩, 苔むした丸石, 石レンガ]
    22: [98, 98, 4]     // 印(ラピスラズリ): 柱 [石レンガ, 石レンガ, 丸石] 
};

//let torchBlockId = 50; // 松明のブロック番号

// 失われた印の位置を示す連想配列の配列
let arr_markerPositions1810: { [key: string]: number }[] = [
    { "marker": 173, "forward": 1, "right": 2 }, // [0] 印(石炭)の位置
    { "marker": 173, "forward": 7, "right": 8 }, // [1] 印(石炭)の位置
    { "marker": 22, "forward": 1, "right": 8 }, // [2] 印(ラピスラズリ)の位置
    { "marker": 22, "forward": 7, "right": 2 }, // [3] 印(ラピスラズリ)の位置
    { "marker": 896, "forward": 4, "right": 5 }  // [4] 印(鉄の原石)の位置
];

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

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

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

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

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

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

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

// エージェントにブロックを設置させる関数
function placeBlock1810(agentStatus: { [key: string]: number }): boolean {
    agent.setItem(agentStatus["block"], 1, 1);
    let canPlace = agent.place(agentStatus["placeDirection"]);
    if (!canPlace) {
        player.say("エージェントがブロックを設置できません!");
    }
    return canPlace;
}

// エージェントを床まで移動させる関数
function moveToFloor1810(agentStatus: { [key: string]: number }) {
    let canMove = true;
    while (canMove && agentStatus["up"] > 0) {
        canMove = moveDown1810(agentStatus);
    }
}

// 封印柱を立てる関数
function buildPillar1810(agentStatus: { [key: string]: number }, blocks: number[]) {
    // 封印柱の各ブロックを設置していきます
    for (let i = 0; i < blocks.length; i++) {
        agentStatus["block"] = blocks[i];
        placeBlock1810(agentStatus);
        moveUp1810(agentStatus);
    }

    // 柱の上に松明を設置します
    agentStatus["block"] = torchBlockId;
    placeBlock1810(agentStatus);

    // エージェントを床まで戻します
    moveToFloor1810(agentStatus);
}

// エージェントを印の位置まで移動させる関数
function moveToMarker1810(agentStatus: { [key: string]: number },
    markerPosition: { [key: string]: number }): boolean {
    let canMove = true;
    while (canMove) {
        // エージェントの位置と、マーカーの位置が一致したとき、移動は正常に終了します。
        if (agentStatus["forward"] == markerPosition["forward"] &&
            agentStatus["right"] == markerPosition["right"]) {
            // 同じ位置に移動できた場合、true を返します
            return true;
        }
        // まだ位置が一致しないときは、移動を行います。
        let canMoveLeft = false;
        if (agentStatus["right"] > markerPosition["right"]) {
            canMoveLeft = moveLeft1810(agentStatus);
            if (canMoveLeft == false) {
                player.say("左に移動しようとしましたが、失敗しました");
            }
        }
        let canMoveRight = false;
        if (agentStatus["right"] < markerPosition["right"]) {
            canMoveRight = moveRight1810(agentStatus);
            if (canMoveRight == false) {
                player.say("右に移動しようとしましたが、失敗しました");
            }
        }
        let canMoveBack = false;
        if (agentStatus["forward"] > markerPosition["forward"]) {
            canMoveBack = moveBack1810(agentStatus);
            if (canMoveBack == false) {
                player.say("後ろに移動しようとしましたが、失敗しました");
            }
        }
        let canMoveForward = false;
        if (agentStatus["forward"] < markerPosition["forward"]) {
            canMoveForward = moveForward1810(agentStatus);
            if (canMoveForward == false) {
                player.say("前に移動しようとしましたが、失敗しました");
            }
        }
        // いずれかの方向に移動できた場合は、移動を続けます
        canMove = canMoveBack || canMoveForward || canMoveLeft || canMoveRight;
    }
    // 同じ位置に移動できないまま中断した場合、false を返します
    return false;
}

// チャットコマンドで封印柱を立てる処理を開始します
player.onChat("18-10", function () {
    // エージェント状態を初期化します
    dic_agentStatus1810["block"] = 0;
    dic_agentStatus1810["forward"] = 0;
    dic_agentStatus1810["right"] = 0;
    dic_agentStatus1810["up"] = 0;
    dic_agentStatus1810["placeDirection"] = FORWARD;

    // 印の位置の数だけ繰り返します
    for (let i = 0; i < arr_markerPositions1810.length; i++) {
        // 印の位置の連想配列を取得します
        let markerPosition = arr_markerPositions1810[i];

        // 印の位置まで移動します
        let canMoveToMarker = moveToMarker1810(dic_agentStatus1810, markerPosition);
        if (!canMoveToMarker) {
            // エラーで移動できなかった場合、メッセージを表示してプログラムを終了します
            player.say("印への移動に失敗しました。終了します");
            return;
        }

        // 印のブロック番号
        let markerBlockId = markerPosition["marker"];

        // 柱のブロック番号の配列
        let blocks = dic_pillarBlocks1810[markerBlockId];

        // 柱を立てます
        buildPillar1810(dic_agentStatus1810, blocks);
    }

    // 柱を立て終わったのでプログラムを終了します
    player.say("作業を終了します");

});