18-7 ドキドキ分岐ポイント②

解説動画

解答画像

 // -- 18-7 落石を取り除いて線路を修復する ----------------------------------------------------

// 線路パターンの連想配列
let dic_railBlocks187: { [key: number]: number[] } = {
    896: [66, 66, 66, 27, 66, 66, 66],  // 鉄の原石 → 線路パターンの配列
    22: [66, 27, 66, 66, 66]            // ラピスラズリ → 線路パターンの配列
};

let airBlockId187 = 0; // 空気のブロックID(前方確認用)

let coalBlockId187 = 173; // 石炭のブロックID(終了条件用)

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

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

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

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

// がれきを取り除く関数
function doGrading187(agentStatus: { [key: string]: number }) {
    // 修復を開始する地点の位置を記録します
    let startForward = agentStatus["forward"];

    // 終了条件まで繰り返します
    while (true) {

        // 前方のブロック番号を取得します
        let forwardBlockId = agent.inspect(AgentInspection.Block, FORWARD);
        if (forwardBlockId === coalBlockId187) {
            // 終了条件を満たした場合は、終了します
            player.say("石炭ブロックが見つかったので、終了します。");
            break;
        }
        if (forwardBlockId !== airBlockId187) {
            // がれきがある場合は、がれきを除去します
            agent.destroy(FORWARD);
        }

        // 上方のブロック番号を取得します
        let topBlockId = agent.inspect(AgentInspection.Block, UP);
        if (topBlockId !== airBlockId187) {
            // がれきがある場合は、がれきを除去します
            agent.destroy(UP);
        }

        moveForward187(agentStatus);
    }

    // エージェントを修復開始地点まで戻します
    while (agentStatus["forward"] > startForward) {
        moveBack187(agentStatus);
    }
}

// 足元の印を探す関数
function findMarker187(agentStatus: { [key: string]: number }, railBlocks: { [key: number]: number[] }): number {
    // 終了条件まで繰り返します
    while (true) {
        // 前方のブロック番号を取得します
        let forwardBlockId = agent.inspect(AgentInspection.Block, FORWARD);
        if (forwardBlockId === coalBlockId187) {
            // 終了条件を満たした場合は、終了します
            player.say("石炭ブロックが見つかったので、終了します。");
            return 0;
        }

        // 足元のブロックを調べます
        let belowBlock = agent.inspect(AgentInspection.Block, DOWN);

        // 印が見つかった場合、そのブロックIDを返します
        if (railBlocks[belowBlock] != undefined) {
            player.say(`印を発見しました:ID ${belowBlock}`);
            return belowBlock;
        }

        // 見つからなかった場合、前に移動します
        let canMove = moveForward187(agentStatus);
        if (!canMove) {
            // 前に移動できなくなった場合は、0を返します
            return 0;
        }
    }
}

// 線路を修復する関数
function buildRails187(agentStatus: { [key: string]: number }, blocks: number[]) {
    // 線路パターンでレールを設置していきます
    for (let i = 0; i < blocks.length; i++) {
        agentStatus["block"] = blocks[i];
        placeBlock187(agentStatus);
        // 前にブロックが無い時だけ、前へ移動します
        let forwardBlockId = agent.inspect(AgentInspection.Block, FORWARD);
        if (forwardBlockId == airBlockId187) {
            moveForward187(agentStatus);
        }
    }
}

// チャットコマンド "18-7" を入力したときの処理
player.onChat("18-7", function () {
    // エージェント状態を初期化します
    dic_agentStatus187["block"] = 0;
    dic_agentStatus187["forward"] = 0;
    dic_agentStatus187["placeDirection"] = DOWN;

    // エージェントに落石を取り除かせます
    doGrading187(dic_agentStatus187);

    // 印を探しながら、線路を修復します
    while (true) {
        let markerBlockId = findMarker187(dic_agentStatus187, dic_railBlocks187);
        if (markerBlockId == 0) {
            // 印が見つからないまま移動できなくなった場合は、終了します
            break;
        }
        // 線路の材料ブロック番号の配列を取得します
        let blocks = dic_railBlocks187[markerBlockId];
        // 線路を修復します
        buildRails187(dic_agentStatus187, blocks);
    }

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