18-3 ぐらぐらレール③

解説動画

解答画像

// -- 18-3 2本ずつ柱を立てる ----------------------------------------------------

// 封印柱と光源の柱の連想配列
// キー:柱を立てる場所の印のブロック番号
// 値:2本の柱の材料ブロック番号の二次元配列
let dic_pillerBlocks183: { [key: number]: number[][] } = {
    173: [                  // 印(石炭):
        [4, 1, 98],     //     右の柱 [丸石, 石, 石レンガ]
        [169, 766, 89]  //     左の柱 [グロウストーン, シュルームライト, シーランタン]
    ],
    896: [                  // 印(鉄の原石):
        [945, 48, 98],  //     右の柱 [模様入りの凝灰岩, 苔むした丸石, 石レンガ]
        [89, 169, 766]  //     左の柱 [シーランタン, グロウストーン, シュルームライト]
    ],
    22: [                   // 印(ラピスラズリ):
        [98, 98, 4],    //     右の柱 [石レンガ, 石レンガ, 丸石]
        [766, 89, 169]  //     左の柱 [シュルームライト, シーランタン, グロウストーン]
    ]
};

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

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

// 立てた封印柱の配列
let arr_builtPillars183: number[] = [];

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

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

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

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

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

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

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

// 封印柱の印を探す関数
function findMarker183(agentStatus: { [key: string]: number }, pillarBlocks: { [key: number]: number[][] }): number {
    while (true) {
        // 足元のブロックを調べます
        let belowBlock = agent.inspect(AgentInspection.Block, DOWN);

        // 封印柱の印が見つかった場合、そのブロックIDを返します
        if (pillarBlocks[belowBlock] != undefined) {
            player.say(`印を発見しました:ID ${belowBlock}`);
            return belowBlock;
        }
        // 見つからなかった場合、右に移動します
        let canMove = moveRight183(agentStatus);
        if (!canMove) {
            // 右に移動できなくなった場合は、0を返します
            return 0;
        }
    }
}

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

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

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

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

    // 封印柱の印を記録する配列を初期化します
    arr_builtPillars183 = [];

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

    while (true) {
        // 地面の印を探します
        let markerBlockId = findMarker183(dic_agentStatus183, dic_pillerBlocks183);
        if (markerBlockId <= 0) {
            // 印が見つけられないまま移動できなくなった場合は、終了します
            player.say("エラー:移動できなくなりました");
            break;
        }

        // 発見した印を配列に記録します
        arr_builtPillars183.push(markerBlockId);

        // 前へ1歩移動します
        moveForward183(dic_agentStatus183);

        // 右の封印柱を立てます
        let rightBlocks = dic_pillerBlocks183[markerBlockId][0];
        dic_agentStatus183["placeDirection"] = RIGHT;
        buildPillar183(dic_agentStatus183, rightBlocks);

        // 左の封印柱を立てます
        let leftBlocks = dic_pillerBlocks183[markerBlockId][1];
        dic_agentStatus183["placeDirection"] = LEFT;
        buildPillar183(dic_agentStatus183, leftBlocks);

        // 後ろへ1歩移動します
        moveBack183(dic_agentStatus183);

        // 右へ移動します
        moveRight183(dic_agentStatus183);

        // すべての封印柱を立て終わった場合は終了します
        if (arr_builtPillars183.length >= Object.keys(dic_pillerBlocks183).length) {
            player.say("すべての封印柱を立て終わりました");
            break;
        }
    }

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