18-6 ドキドキ分岐ポイント①

解説動画

解答画像

// -- 18-6 起伏のある線路を修復する ----------------------------------------------------

// 線路パターンの連想配列
let dic_railBlocks186: { [key: number]: number[] } = {
    173: [66, 66, 27, 27, 66],      // 印(石炭): 線路パターン [普通, 普通, パワード, パワード, 普通]
    896: [66, 27, 27, 66, 66],  // 印(鉄の原石): 線路パターン [普通, パワード, パワード, 普通, 普通]
    22: [66, 66, 27, 66, 28] // 印(ラピスラズリ): 線路パターン [普通, 普通, パワード, 普通, ディテクター]
};

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

// 修復した線路の配列
let array_builtRails186: number[] = [];

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

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

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

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

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

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

// 足元の印を探す関数
function findMarker186(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 = moveLeft186(agentStatus);
        if (!canMove) {
            // 左に移動できなくなった場合は、0を返します
            return 0;
        }
    }
}

// 線路を修復する関数
function buildRails186(agentStatus: { [key: string]: number }, blocks: number[]) {

    // 線路のパーツを置くときの、エージェントの位置(上下)を記録する配列
    let arr_agentUp: number[] = [];

    // 線路の各パーツを設置していきます
    for (let i = 0; i < blocks.length; i++) {
        agentStatus["block"] = blocks[i];
        placeBlock186(agentStatus);

        // エージェントが今いる位置(上下)を記録します
        arr_agentUp.push(agentStatus["up"]);

        // もし前にブロックがあれば、上へ移動します
        let forwardBlockId = agent.inspect(AgentInspection.Block, FORWARD);
        if (forwardBlockId != 0) {
            moveUp186(agentStatus);
        }
        // 前へ移動します
        moveForward186(agentStatus);
        // もし下にブロックがなければ、下へ移動します
        let belowBlockId = agent.inspect(AgentInspection.Block, DOWN);
        if (belowBlockId == 0) {
            moveDown186(agentStatus);
        }
    }

    // エージェントの位置(上下)の配列を、エージェントが歩いてきた順番と逆の順番にします
    arr_agentUp.reverse();

    // エージェントを上下に移動しながら、スタート地点まで戻します
    for (let i = 0; i < arr_agentUp.length; i++) {
        let moveUpTo = arr_agentUp[i]; // エージェントが戻る位置(上下)
        // エージェントが上へ移動する必要がある場合は、上へ移動します
        while (agentStatus["up"] < moveUpTo) {
            moveUp186(agentStatus);
        }
        // エージェントを1歩後ろに戻します
        moveBack186(agentStatus);
        // エージェントが下へ移動する必要がある場合は、下へ移動します
        while (agentStatus["up"] > moveUpTo) {
            moveDown186(agentStatus);
        }
    }
}

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

    // 線路の印を記録する配列を初期化します
    array_builtRails186 = [];

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

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

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

        // 線路の材料ブロック番号の配列を取得します
        let blocks = dic_railBlocks186[markerBlockId];

        // 線路を修復します
        buildRails186(dic_agentStatus186, blocks);

        // 右へ移動します
        moveLeft186(dic_agentStatus186);

        // すべての線路を修復し終わった場合は終了します
        if (array_builtRails186.length >= Object.keys(dic_railBlocks186).length) {
            player.say("すべての線路を修復しました");
            break;
        }
    }

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