解説動画
解答画像
// -- 18-8 線路を読み取り、修復する ----------------------------------------------------
// 線路パターンの連想配列
let dic_railBlocks188: { [key: number]: number[] } = {
// 初期状態は、空です
};
// エージェントの状態の連想配列
let dic_agentStatus188: { [key: string]: number } = {
"block": 0, // 持つブロック番号
"forward": 0, // 前の移動距離
"right": 0, // 右の移動距離
"placeDirection": DOWN, // ブロックを置く方向
"moveDirection": RIGHT // 印を探すときの移動方向
};
let airBlockId188 = 0; // 空気ブロックのID
let fenceBlockId188 = 262229; // フェンスのブロックID
// 反対方向の連想配列
let dic_oppositeDirection: { [key: number]: number } = {
[FORWARD]: BACK,
[BACK]: FORWARD,
[RIGHT]: LEFT,
[LEFT]: RIGHT,
[UP]: DOWN,
[DOWN]: UP
};
// エージェントを前へ移動させる関数
function moveForward188(agentStatus: { [key: string]: number }): boolean {
let canMove = agent.move(FORWARD, 1);
if (!canMove) {
player.say("エージェントが前へ移動できません!");
return false;
}
agentStatus["forward"] += 1;
return true;
}
// エージェントを後ろ移動させる関数
function moveBack188(agentStatus: { [key: string]: number }): boolean {
let canMove = agent.move(BACK, 1);
if (!canMove) {
player.say("エージェントが後ろへ移動できません!");
return false;
}
agentStatus["forward"] -= 1;
return true;
}
// エージェントを右に移動させる関数
function moveRight188(agentStatus: { [key: string]: number }): boolean {
let canMove = agent.move(RIGHT, 1);
if (!canMove) {
player.say("エージェントが右に移動できません!");
return false;
}
agentStatus["right"] += 1;
return true;
}
// エージェントを左に移動させる関数
function moveLeft188(agentStatus: { [key: string]: number }): boolean {
let canMove = agent.move(LEFT, 1);
if (!canMove) {
player.say("エージェントが左に移動できません!");
return false;
}
agentStatus["right"] -= 1;
return true;
}
// エージェントにブロックを設置させる関数
function placeBlock188(agentStatus: { [key: string]: number }): boolean {
// 空のブロックを置く場合は何もせず true を返して終了します
if (agentStatus["block"] == airBlockId188) {
return true;
}
agent.setItem(agentStatus["block"], 1, 1);
let canPlace = agent.place(agentStatus["placeDirection"]);
if (!canPlace) {
player.say("エージェントがブロックを設置できません!");
}
return canPlace;
}
// エージェントにレールのブロックを読みとらせる関数
function scanBlock188(agentStatus: { [key: string]: number }, railBlocks: { [key: number]: number[] }) {
while (true) {
// 足元のブロックと、レールのブロックを読み取ります
let downBlockId = agent.inspect(AgentInspection.Block, DOWN);
player.say(`足元のブロックID: ${downBlockId}`);
let railBlockId = agent.inspect(AgentInspection.Block, LEFT);
player.say(`レールのブロックID: ${railBlockId}`);
// 足元のブロック番号をキーとして、線路パターンの連想配列へレールのブロック番号を登録します
if (railBlocks[downBlockId] == undefined) {
railBlocks[downBlockId] = [railBlockId];
} else {
railBlocks[downBlockId].push(railBlockId);
}
// 前へ進むかどうかを判定します
let forwardBlockId = agent.inspect(AgentInspection.Block, agentStatus["moveDirection"]);
if (forwardBlockId == fenceBlockId188) {
// 前にフェンスがある場合は、前へ進まずにループを抜けます
player.say("前にフェンスがあるので、これ以上進みません");
break;
}
// 次のレールを読み取るために、前へ進みます(前以外には進みません)
if (agentStatus["moveDirection"] == FORWARD) {
moveForward188(agentStatus);
}
}
}
// フェンスに囲まれたエリアで足元の印を探し回る関数
function searchMarkerInArea188(agentStatus: { [key: string]: number }, railBlocks: { [key: number]: number[] }): number {
while (true) {
// 足元のブロックを調べます
let belowBlock = agent.inspect(AgentInspection.Block, DOWN);
// 印が見つかった場合、そのブロックIDを返します
if (railBlocks[belowBlock] != undefined) {
player.say(`印を発見しました:ID ${belowBlock}`);
return belowBlock;
}
// 見つからなかった場合、次の場所へ移動します
let canMove = moveNextInArea188(agentStatus);
if (!canMove) {
// 次の場所へ移動できなくなった場合は、0を返します
return 0;
}
}
}
// フェンスに囲まれたエリアで次の場所へ移動する関数
function moveNextInArea188(agentStatus: { [key: string]: number }): boolean {
// 移動が成功したかどうかの変数(この関数から返す戻り値)
let canMove = false;
// もし、次の印を探す方向にフェンスがあれば、前へ移動して、印を探す方向を反対にします
let blockId = agent.inspect(AgentInspection.Block, agentStatus["moveDirection"]);
if (blockId == fenceBlockId188) {
// もし、前にフェンスがあれば、移動できないので、false を返します
let forwardBlockId = agent.inspect(AgentInspection.Block, FORWARD);
if (forwardBlockId == fenceBlockId188) {
return false;
}
moveForward188(agentStatus); // 前へ移動します
agentStatus["moveDirection"] = dic_oppositeDirection[agentStatus["moveDirection"]]; // 印を探す方向を反対にします
return true; // 移動したので、true を返します
} else {
// 次の印を探す方向にブロックがない場合は、移動します
if (agentStatus["moveDirection"] == RIGHT) {
canMove = moveRight188(agentStatus);
} else if (agentStatus["moveDirection"] == LEFT) {
canMove = moveLeft188(agentStatus);
}
}
return canMove;
}
// 線路を修復する関数
function buildRails188(agentStatus: { [key: string]: number }, blocks: number[]) {
let startForward = agentStatus["forward"]; // エージェントが線路修復を開始したときの前の移動距離を記録します
// レールを設置していきます
for (let i = 0; i < blocks.length; i++) {
agentStatus["block"] = blocks[i];
placeBlock188(agentStatus);
// 前へ移動します
moveForward188(agentStatus);
}
// 線路を修復し終わったら、エージェントを線路修復を開始したときの位置まで戻します
while (agentStatus["forward"] > startForward) {
moveBack188(agentStatus);
}
}
// チャットコマンドで線路パターンを読み取る処理を開始します
player.onChat("18-8scan", function () {
// 線路パターンの連想配列を初期化します
dic_railBlocks188 = {};
// エージェント状態を初期化します
dic_agentStatus188["block"] = 0;
dic_agentStatus188["forward"] = 0;
dic_agentStatus188["right"] = 0;
dic_agentStatus188["up"] = 0;
dic_agentStatus188["placeDirection"] = DOWN;
dic_agentStatus188["moveDirection"] = FORWARD; // 読み取り時の移動方向は、前です
// エージェントを1歩前に移動させます
moveForward188(dic_agentStatus188);
// エージェントの位置にあるブロックを調べて、線路パターンの連想配列へ登録します
scanBlock188(dic_agentStatus188, dic_railBlocks188);
player.say("線路のパターンをすべて読み取りました");
});
// チャットコマンドで線路を修復する処理を開始します
player.onChat("18-8build", function () {
// エージェント状態を初期化します
dic_agentStatus188["block"] = 0;
dic_agentStatus188["forward"] = 0;
dic_agentStatus188["right"] = 0;
dic_agentStatus188["up"] = 0;
dic_agentStatus188["placeDirection"] = DOWN;
dic_agentStatus188["moveDirection"] = RIGHT; // 修復時の移動方向は、初期状態では右です
// エージェントを1歩前に移動させます
moveForward188(dic_agentStatus188);
while (true) {
// 地面の印を探します
let markerBlockId = searchMarkerInArea188(dic_agentStatus188, dic_railBlocks188);
if (markerBlockId <= 0) {
// 印が見つけられないまま移動できなくなった場合は、エリアを探索し終えたので、終了します
break;
}
// 線路の材料ブロック番号の配列を取得します
let blocks = dic_railBlocks188[markerBlockId];
// 線路を修復します
buildRails188(dic_agentStatus188, blocks);
// 次の場所へ移動します
let canMove = moveNextInArea188(dic_agentStatus188);
// 次の場所へ移動できなくなった場合は、終了します
if (!canMove) {
break;
}
}
player.say("作業を終了します");
});