การทำให้ยุ่งเหยิงกับล็อคและคีย์?


22

ผมทำงานในเกมกับแผนที่ที่มีลักษณะคล้ายกับการล็อคและคีย์ปริศนา AI ต้องการนำทางไปยังเป้าหมายที่อาจอยู่หลังประตูสีแดงที่ถูกล็อค แต่กุญแจสีแดงอาจอยู่ด้านหลังประตูสีน้ำเงินที่ถูกล็อคและอื่น ๆ ...

ปริศนานี้คล้ายกับดันเจี้ยนสไตล์เซลด้าเหมือนภาพนี้:

Zelda dungeon

ในการไปถึงเป้าหมายคุณจะต้องเอาชนะบอสซึ่งต้องผ่านหลุมซึ่งต้องใช้การรวบรวมขนนกซึ่งต้องใช้การรวบรวมคีย์

คุกใต้ดินเซลด้ามีแนวโน้มที่จะเป็นเส้นตรง อย่างไรก็ตามฉันต้องแก้ปัญหาในกรณีทั่วไป ดังนั้น:

  • เป้าหมายอาจต้องใช้หนึ่งในชุดของคีย์ ดังนั้นคุณอาจจำเป็นต้องได้รับทั้งคีย์สีแดงหรือสีน้ำเงิน หรืออาจมีประตูที่ปลดล็อคได้ทางไกล!
  • อาจมีประตูและกุญแจหลายชนิด เช่นอาจมีปุ่มสีแดงหลายปุ่มในแผนที่และการรวบรวมปุ่มหนึ่งจะอนุญาตให้เข้าถึงประตูสีแดงทั้งหมด
  • เป้าหมายไม่สามารถเข้าถึงได้เนื่องจากปุ่มขวาอยู่ด้านหลังประตูที่ถูกล็อค

ฉันจะแสดงเส้นทางบนแผนที่ดังกล่าวได้อย่างไร กราฟการค้นหามีลักษณะอย่างไร

หมายเหตุ: จุดสุดท้ายเกี่ยวกับการตรวจจับเป้าหมายที่ไม่สามารถเข้าถึงได้เป็นสิ่งสำคัญ ตัวอย่างเช่น A * นั้นไม่มีประสิทธิภาพอย่างมากหากไม่สามารถเข้าถึงเป้าหมายได้ ฉันต้องการจัดการกับสิ่งนี้อย่างมีประสิทธิภาพ

สมมติว่า AI รู้ว่าทุกอย่างอยู่บนแผนที่


4
AI รู้และค้นพบสิ่งต่าง ๆ เมื่อมันปลดล็อคหรือไม่ เช่นรู้ว่าขนอยู่ด้านหลังประตูล็อคหรือไม่ AI เข้าใจแนวคิดเช่น "นั่นคือล็อคดังนั้นฉันต้องการกุญแจ" หรือเป็นอะไรที่เรียบง่ายกว่าเช่น "ฉันมีบางสิ่งบางอย่างขวางทางของฉันดังนั้นลองทำทุกสิ่งที่พบในนั้นขนบนประตูใช่ไหม กุญแจประตูใช่มั้ย! "
Tim Holt

1
มีการสนทนาก่อนหน้านี้ของปัญหานี้ในคำถามนี้เกี่ยวกับการส่งต่อการส่งต่อและย้อนกลับซึ่งอาจเป็นประโยชน์สำหรับคุณ
DMGregory

1
ดังนั้นคุณไม่ได้พยายามจำลองผู้เล่น แต่พยายามสร้างดันเจี้ยนที่ดีที่สุด คำตอบของฉันคือการจำลองพฤติกรรมผู้เล่น
Tim Holt

4
น่าเสียดายที่การตรวจจับเป้าหมายที่ไม่สามารถเข้าถึงได้นั้นค่อนข้างยาก วิธีเดียวที่จะตรวจสอบให้แน่ใจว่าไม่มีทางไปถึงเป้าหมายได้คือสำรวจพื้นที่ทั้งหมดที่เข้าถึงได้เพื่อให้แน่ใจว่าไม่มีเป้าหมายอยู่ - ซึ่งเป็นสิ่งที่ A * ทำซึ่งทำให้ขั้นตอนพิเศษมากมายหากเป้าหมายคือ ไม่สามารถเข้าถึงได้ อัลกอริทึมใด ๆ ที่ค้นหาพื้นที่น้อยลงนั้นไม่มีความเสี่ยงที่จะขาดเส้นทางที่มีไปยังเป้าหมายเพราะเส้นทางนั้นซ่อนอยู่ในพื้นที่ที่ข้ามการค้นหา คุณสามารถเร่งความเร็วได้โดยทำงานในระดับที่สูงขึ้นค้นหากราฟของการเชื่อมต่อห้องแทนที่จะเป็นทุกรูปหลายเหลี่ยม
DMGregory

1
Offtopic ฉันคิดสัญชาตญาณของChip's Challengeแทน Zelda :)
Flater

คำตอบ:


22

การค้นหาเส้นทางแบบมาตรฐานดีพอ - สถานะของคุณคือที่ตั้งปัจจุบันของคุณ + สินค้าคงคลังปัจจุบันของคุณ "ย้าย" เป็นห้องเปลี่ยนเสื้อผ้าหรือเปลี่ยนสินค้าคงคลัง ไม่ครอบคลุมในคำตอบนี้ แต่ไม่ใช่ความพยายามเพิ่มเติมมากเกินไปคือการเขียนฮิวริสติกที่ดีสำหรับ A * - สามารถเพิ่มความเร็วในการค้นหาได้โดยเลือกที่จะหยิบสิ่งต่าง ๆ ออกไปแทนที่จะเลือกประตูที่อยู่ใกล้เป้าหมาย การค้นหาทางไกล ฯลฯ

คำตอบนี้ได้รับ upvotes มากมายตั้งแต่ครั้งแรกและมีการสาธิต แต่สำหรับโซลูชันที่ได้รับการปรับปรุงและพิเศษกว่านั้นคุณควรอ่านคำตอบ "การทำแบบย้อนหลังนั้นเร็วกว่ามาก" /gamedev/ / a / 150155/2624


การใช้งาน Javascript อย่างสมบูรณ์ในการพิสูจน์แนวคิดด้านล่าง ขออภัยสำหรับคำตอบในรูปแบบการถ่ายโอนข้อมูล - ฉันใช้งานจริงก่อนที่จะเชื่อมั่นว่าเป็นคำตอบที่ดี แต่ดูเหมือนยืดหยุ่นสำหรับฉัน

ในการเริ่มต้นเมื่อคิดเกี่ยวกับการหาเส้นทางโปรดจำไว้ว่าลำดับขั้นตอนวิธีการหาเส้นทางแบบง่ายคือ:

  • การค้นหาครั้งแรกของ Breadth นั้นเกี่ยวกับเรียบง่ายอย่างที่คุณจะได้รับ
  • อัลกอริทึมของ Djikstra เหมือนกับการค้นหาแบบกว้างครั้งแรก แต่ด้วย "ระยะทาง" ที่แตกต่างกันระหว่างรัฐ
  • A * เป็น Djikstras ที่คุณมี 'ความรู้สึกทั่วไปเกี่ยวกับทิศทางที่ถูกต้อง' ซึ่งมีอยู่ในรูปแบบฮิวริสติก

ในกรณีของเราเพียงแค่เข้ารหัส "สถานะ" เป็น "ตำแหน่ง + สินค้าคงคลัง" และ "ระยะทาง" เป็น "การเคลื่อนไหวหรือการใช้รายการ" ช่วยให้เราสามารถใช้ Djikstra หรือ A * เพื่อแก้ปัญหาของเรา

นี่คือรหัสจริงที่แสดงระดับตัวอย่างของคุณ ตัวอย่างแรกนั้นใช้สำหรับการเปรียบเทียบ - ข้ามไปยังส่วนที่สองหากคุณต้องการดูคำตอบสุดท้าย เราเริ่มต้นด้วยการใช้งานของ Djikstra ซึ่งค้นหาเส้นทางที่ถูกต้อง แต่เราไม่สนใจสิ่งกีดขวางและกุญแจทั้งหมด (ลองดูสิคุณจะเห็นว่ามันเป็นแค่เส้นแบ่งสำหรับการจบจากห้อง 0 -> 2 -> 3-> 4-> 6-> 5)

function Transition(cost, state) { this.cost = cost, this.state = state; }
// given a current room, return a room of next rooms we can go to. it costs 
// 1 action to move to another room.
function next(n) {
    var moves = []
    // simulate moving to a room
    var move = room => new Transition(1, room)
    if (n == 0) moves.push(move(2))
    else if ( n == 1) moves.push(move(2))
    else if ( n == 2) moves.push(move(0), move(1), move(3))
    else if ( n == 3) moves.push(move(2), move(4), move(6))
    else if ( n == 4) moves.push(move(3))
    else if ( n == 5) moves.push(move(6))
    else if ( n == 6) moves.push(move(5), move(3))
    return moves
}

// Standard Djikstra's algorithm. keep a list of visited and unvisited nodes
// and iteratively find the "cheapest" next node to visit.
function calc_Djikstra(cost, goal, history, nextStates, visited) {

    if (!nextStates.length) return ['did not find goal', history]

    var action = nextStates.pop()
    cost += action.cost
    var cur = action.state

    if (cur == goal) return ['found!', history.concat([cur])]
    if (history.length > 15) return ['we got lost', history]

    var notVisited = (visit) => {
        return visited.filter(v => JSON.stringify(v) == JSON.stringify(visit.state)).length === 0;
    };
    nextStates = nextStates.concat(next(cur).filter(notVisited))
    nextStates.sort()

    visited.push(cur)
    return calc_Djikstra(cost, goal, history.concat([cur]), nextStates, visited)
}

console.log(calc_Djikstra(0, 5, [], [new Transition(0, 0)], []))

ดังนั้นเราจะเพิ่มรายการและกุญแจในรหัสนี้ได้อย่างไร ! ง่าย แทนที่จะเป็น "สถานะ" ทุกรายการเริ่มต้นเพียงหมายเลขห้องพักตอนนี้มันเป็นสิ่งอันดับห้องและสถานะสินค้าคงคลังของเรา:

 // Now, each state is a [room, haskey, hasfeather, killedboss] tuple
function State(room, k, f, b) { this.room = room; this.k = k; this.f = f; this.b = b }

การเปลี่ยนตอนนี้เปลี่ยนจากการเป็น tuple (ราคาห้อง) เป็น tuple (ราคา, สถานะ) ดังนั้นจึงสามารถเข้ารหัสได้ทั้ง "ย้ายไปที่ห้องอื่น" และ "เก็บรายการ"

// move(3) keeps inventory but sets the room to 3
var move = room => new Transition(1, new State(room, cur.k, cur.f, cur.b))
// pickup("k") keeps room number but increments the key count
var pickup = (cost, item) => {
    var n = Object.assign({}, cur)
    n[item]++;
    return new Transition(cost, new State(cur.room, n.k, n.f, n.b));
};

ในที่สุดเราทำการเปลี่ยนแปลงเล็กน้อยที่เกี่ยวข้องกับประเภทฟังก์ชั่นของ Djikstra (ตัวอย่างเช่นมันยังคงเป็นเพียงการจับคู่กับหมายเลขห้องเป้าหมายแทนสถานะเต็ม) และเราได้รับคำตอบทั้งหมดของเรา! สังเกตผลลัพธ์ที่พิมพ์ออกมาก่อนไปที่ห้องที่ 4 เพื่อรับกุญแจจากนั้นไปที่ห้อง 1 เพื่อรับขนจากนั้นไปที่ห้อง 6 ฆ่าเจ้านายจากนั้นไปที่ห้อง 5)

// Now, each state is a [room, haskey, hasfeather, killedboss] tuple
function State(room, k, f, b) { this.room = room; this.k = k; this.f = f; this.b = b }
function Transition(cost, state, msg) { this.cost = cost, this.state = state; this.msg = msg; }

function next(cur) {
var moves = []
// simulate moving to a room
var n = cur.room
var move = room => new Transition(1, new State(room, cur.k, cur.f, cur.b), "move to " + room)
var pickup = (cost, item) => {
	var n = Object.assign({}, cur)
	n[item]++;
	return new Transition(cost, new State(cur.room, n.k, n.f, n.b), {
		"k": "pick up key",
		"f": "pick up feather",
		"b": "SLAY BOSS!!!!"}[item]);
};

if (n == 0) moves.push(move(2))
else if ( n == 1) { }
else if ( n == 2) moves.push(move(0), move(3))
else if ( n == 3) moves.push(move(2), move(4))
else if ( n == 4) moves.push(move(3))
else if ( n == 5) { }
else if ( n == 6) { }

// if we have a key, then we can move between rooms 1 and 2
if (cur.k && n == 1) moves.push(move(2));
if (cur.k && n == 2) moves.push(move(1));

// if we have a feather, then we can move between rooms 3 and 6
if (cur.f && n == 3) moves.push(move(6));
if (cur.f && n == 6) moves.push(move(3));

// if killed the boss, then we can move between rooms 5 and 6
if (cur.b && n == 5) moves.push(move(6));
if (cur.b && n == 6) moves.push(move(5));

if (n == 4 && !cur.k) moves.push(pickup(0, 'k'))
if (n == 1 && !cur.f) moves.push(pickup(0, 'f'))
if (n == 6 && !cur.b) moves.push(pickup(100, 'b'))	
return moves
}

var notVisited = (visitedList) => (visit) => {
return visitedList.filter(v => JSON.stringify(v) == JSON.stringify(visit.state)).length === 0;
};

// Standard Djikstra's algorithm. keep a list of visited and unvisited nodes
// and iteratively find the "cheapest" next node to visit.
function calc_Djikstra(cost, goal, history, nextStates, visited) {

if (!nextStates.length) return ['No path exists', history]

var action = nextStates.pop()
cost += action.cost
var cur = action.state

if (cur.room == goal) return history.concat([action.msg])
if (history.length > 15) return ['we got lost', history]

nextStates = nextStates.concat(next(cur).filter(notVisited(visited)))
nextStates.sort()

visited.push(cur)
return calc_Djikstra(cost, goal, history.concat([action.msg]), nextStates, visited)
o}

console.log(calc_Djikstra(0, 5, [], [new Transition(0, new State(0, 0, 0, 0), 'start')], []))

ในทางทฤษฎีมันใช้งานได้กับ BFS และเราไม่ต้องการฟังก์ชั่นค่าใช้จ่ายสำหรับ Djikstra's แต่การมีค่าใช้จ่ายทำให้เราสามารถพูดได้ว่า "การหยิบกุญแจมีความสะดวก 100 ขั้นตอนแทนที่จะต่อสู้กับเจ้านายถ้าเรามีตัวเลือก ":

if (n == 4 && !cur.k) moves.push(pickup(0, 'k'))
if (n == 1 && !cur.f) moves.push(pickup(0, 'f'))
if (n == 6 && !cur.b) moves.push(pickup(100, 'b'))

ใช่รวมถึงสินค้าคงคลัง / สถานะที่สำคัญในกราฟการค้นหาเป็นทางออกหนึ่ง ฉันกังวลเกี่ยวกับความต้องการพื้นที่ที่เพิ่มขึ้น - แผนที่ที่มี 4 ปุ่มต้องการ 16 ครั้งของพื้นที่ของกราฟที่ไม่มีคีย์
congusbongus

8
@congusbongus ยินดีต้อนรับสู่ปัญหาพนักงานขายการเดินทางที่สมบูรณ์แบบ ไม่มีวิธีแก้ปัญหาทั่วไปที่จะแก้ปัญหานั้นในเวลาพหุนาม
วงล้อประหลาดใน

1
@congusbongus ฉันไม่คิดว่าโดยทั่วไปแล้วกราฟการค้นหาของคุณจะมีค่าใช้จ่ายมาก แต่ถ้าคุณกังวลเรื่องพื้นที่เพียงแค่แพ็คข้อมูลของคุณ - คุณสามารถใช้ 24 บิตสำหรับตัวบ่งชี้ห้อง (16 ล้านห้องควร เพียงพอสำหรับทุกคน) และรายการแต่ละรายการสำหรับการใช้เป็นประตู (มากถึง 8 รายการที่ไม่ซ้ำกัน) หากคุณต้องการได้รับแฟนซีคุณสามารถใช้การอ้างอิงเพื่อแพ็ครายการลงในบิตที่เล็กลงเช่นใช้บิตเดียวกันสำหรับ "คีย์" และ "เจ้านาย" เนื่องจากมีการถ่ายทอดทางอ้อมโดยอ้อม
จิมมี่

@Jimmy แม้ว่ามันจะไม่ได้ส่วนตัวผมชื่นชมการกล่าวถึงคำตอบของฉัน :)
Jibb สมาร์ท

13

ย้อนกลับ A * จะทำการหลอกลวง

ตามที่กล่าวไว้ในคำตอบนี้ คำถามเกี่ยวกับการส่งต่อการย้อนกลับกับการย้อนกลับการย้อนกลับการค้นหาเส้นทางเป็นการตอบกลับที่ค่อนข้างง่ายสำหรับปัญหานี้ สิ่งนี้ทำงานคล้ายกับ GOAP (การวางแผนปฏิบัติการที่มุ่งเน้นเป้าหมาย) การวางแผนโซลูชันที่มีประสิทธิภาพในขณะที่ลดความสงสัยอย่างไร้จุดหมาย

ที่ด้านล่างของคำตอบนี้ฉันมีรายละเอียดของวิธีจัดการตัวอย่างที่คุณให้

ในรายละเอียด

ค้นหาเส้นทางจากปลายทางไปยังจุดเริ่มต้น หากในการค้นหาเส้นทางของคุณคุณเจอประตูล็อคคุณมีสาขาใหม่สำหรับการค้นหาเส้นทางที่ดำเนินการผ่านประตูราวกับว่ามันถูกปลดล็อกโดยมีสาขาหลักดำเนินการต่อเพื่อค้นหาเส้นทางอื่น สาขาที่ดำเนินการผ่านประตูราวกับว่าปลดล็อคไม่ได้มองหาตัวแทน AI อีกต่อไป - ตอนนี้กำลังมองหากุญแจที่สามารถใช้เพื่อผ่านประตู ด้วย A * ฮิวริสติกใหม่ของมันคือระยะทางถึงคีย์ + ระยะทางถึงตัวแทน AI แทนที่จะเป็นระยะทางจากตัวแทน AI

หากสาขาที่ปลดล็อคพบกุญแจแล้วมันยังคงค้นหาตัวแทน AI

โซลูชันนี้มีความซับซ้อนเพิ่มขึ้นเล็กน้อยเมื่อมีคีย์ที่ทำงานได้หลายแบบ แต่คุณสามารถแยกสาขาได้ เนื่องจากกิ่งไม้มีปลายทางที่แน่นอนมันยังช่วยให้คุณใช้ฮิวริสติกเพื่อเพิ่มประสิทธิภาพการค้นหาเส้นทาง (A *) และเส้นทางที่เป็นไปไม่ได้จะหวังว่าจะถูกตัดออกอย่างรวดเร็ว - ถ้าไม่มีทางรอบ ๆ ประตูล็อคสาขาที่ไม่ ไม่ผ่านประตูหมดตัวเลือกอย่างรวดเร็วและสาขาที่ผ่านประตูและมองหากุญแจยังคงดำเนินต่อไปด้วยตนเอง

แน่นอนที่มีความหลากหลายของตัวเลือกที่ทำงานได้ (หลายปุ่มรายการอื่น ๆ เพื่อหลีกเลี่ยงประตูเส้นทางยาวรอบประตู) สาขาหลายจะได้รับการบำรุงรักษาส่งผลกระทบต่อประสิทธิภาพการทำงาน แต่คุณจะพบตัวเลือกที่เร็วที่สุดและสามารถใช้งานได้


ในการดำเนินการ

ในตัวอย่างเฉพาะของคุณให้ค้นหาจากเป้าหมายไปยังจุดเริ่มต้น:

  1. เราพบประตูเจ้านายอย่างรวดเร็ว สาขา A เดินผ่านประตูไปหาเจ้านายเพื่อต่อสู้ สาขา B ยังค้างอยู่ในห้องและจะหมดอายุในไม่ช้าเมื่อพบว่าไม่มีทางออก

  2. สาขา A ค้นหาเจ้านายและกำลังมองหาจุดเริ่มต้น แต่พบกับหลุม

  3. สาขา A ยังคงอยู่เหนือหลุม แต่ตอนนี้มันกำลังมองหาขนนกและจะทำให้สายผึ้งไปทางขนนกตามลำดับ Branch C ถูกสร้างขึ้นซึ่งพยายามหาทางรอบ ๆ หลุม แต่จะหมดอายุในไม่ช้า นั่นหรือมันจะถูกเพิกเฉยไปซักพักถ้าฮิวริสติก A * ของคุณพบว่าสาขา A ยังคงดูมีแนวโน้มมากที่สุด

  4. สาขา A พบประตูที่ถูกล็อคและดำเนินการต่อผ่านประตูที่ถูกล็อคราวกับว่ามันถูกปลดล็อค แต่ตอนนี้มันกำลังมองหากุญแจ Branch D ยังคงผ่านประตูที่ถูกล็อคเช่นกันยังคงมองหาขนนก แต่จากนั้นมันจะมองหากุญแจ นี่เป็นเพราะเราไม่ทราบว่าเราต้องหากุญแจหรือขนนกก่อนหรือไม่และถ้าเท่าที่เกี่ยวข้องกับการหาเส้นทางการเริ่มต้นอาจอยู่อีกด้านหนึ่งของประตูนี้ สาขา E พยายามหาทางรอบ ๆ ประตูล็อคและล้มเหลว

  5. Branch D พบขนอย่างรวดเร็วและหากุญแจต่อไป มันได้รับอนุญาตให้ผ่านประตูล็อคอีกครั้งเนื่องจากมันยังคงมองหากุญแจ (และมันทำงานย้อนเวลากลับไป) แต่เมื่อมันมีกุญแจมันจะไม่สามารถผ่านประตูล็อคได้ (เนื่องจากมันไม่สามารถผ่านประตูล็อคก่อนที่มันจะพบกุญแจ)

  6. สาขา A และ D ยังคงแข่งขันกันอยู่ แต่เมื่อสาขา A ถึงกุญแจมันกำลังมองหาขนนกและมันจะล้มเหลวในการเข้าถึงขนเพราะมันจะต้องผ่านประตูล็อคอีกครั้ง สาขา D ในทางกลับกันเมื่อไปถึงกุญแจก็หันไปสนใจการเริ่มต้นและพบว่ามันไม่มีความยุ่งยาก

  7. สาขา D ชนะ พบเส้นทางย้อนกลับ เส้นทางสุดท้ายคือ: Start -> Key -> Feather -> Boss -> Goal


6

แก้ไข : สิ่งนี้เขียนขึ้นจากมุมมองของ AI ที่ออกไปสำรวจและค้นหาเป้าหมายและไม่ทราบตำแหน่งของกุญแจล็อคหรือจุดหมายปลายทางล่วงหน้า

ก่อนอื่นสมมติว่า AI มีเป้าหมายโดยรวมอยู่บ้าง เช่น "ค้นหาเจ้านาย" ในตัวอย่างของคุณ ใช่คุณต้องการเอาชนะมัน แต่จริงๆแล้วมันเกี่ยวกับการค้นหามัน สมมติว่าไม่รู้ว่าจะไปถึงเป้าหมายได้อย่างไร และมันจะรู้เมื่อพบ เมื่อบรรลุเป้าหมายแล้ว AI สามารถหยุดการทำงานเพื่อแก้ไขปัญหาได้

นอกจากนี้ฉันจะใช้คำว่า "ล็อค" และ "กุญแจ" ทั่วไปที่นี่แม้ว่ามันจะเป็นช่องว่างและขนก็ตาม คือขน "ปลดล็อค" ช่องว่าง "ล็อค"

แนวทางการแก้ปัญหา

ดูเหมือนว่าคุณจะเริ่มต้นด้วย AI ที่เป็นนักสำรวจเขาวงกต (ถ้าคุณคิดว่าแผนที่ของเขาเป็นเขาวงกต) การสำรวจและทำแผนที่สถานที่ทั้งหมดที่สามารถไปได้นั้นเป็นจุดสนใจหลักของ AI มันอาจอ้างอิงจากสิ่งที่เรียบง่ายอย่างหมดจดเช่น "ไปที่เส้นทางที่ใกล้ที่สุดที่ฉันเคยเห็น แต่ยังไม่เคยไป"

อย่างไรก็ตามกฎเล็กน้อยจะเตะในขณะสำรวจที่อาจเปลี่ยนลำดับความสำคัญ ...

  • มันจะใช้รหัสใด ๆ ที่พบเว้นแต่จะมีรหัสเดิมอยู่แล้ว
  • หากพบล็อคที่ไม่เคยเห็นมาก่อนมันจะลองใช้ทุกปุ่มที่พบบนล็อคนั้น
  • ถ้าคีย์ทำงานกับล็อคชนิดใหม่มันจะจดจำประเภทคีย์และประเภทล็อค
  • หากพบกุญแจที่เคยเห็นมาก่อนและมีกุญแจมันจะใช้ประเภทกุญแจที่จำได้ (เช่นพบล็อคสีแดงตัวที่สองกุญแจสีแดงทำงานก่อนหน้านี้บนกุญแจสีแดงดังนั้นให้ใช้กุญแจสีแดง)
  • มันจะจำตำแหน่งของการล็อคใด ๆ ที่ไม่สามารถปลดล็อกได้
  • มันไม่จำเป็นต้องจำตำแหน่งของล็อคที่ปลดล็อค
  • เมื่อใดก็ตามที่พบกุญแจและรู้เกี่ยวกับการปลดล็อคก่อนหน้านี้มันจะไปที่ล็อคที่ล็อคแต่ละอันทันทีและลองปลดล็อคด้วยกุญแจที่พบ
  • เมื่อใดก็ตามที่มันปลดล็อคเส้นทางมันก็จะย้อนกลับไปสู่เป้าหมายการสำรวจและทำแผนที่โดยให้ความสำคัญกับการก้าวเข้าสู่พื้นที่ใหม่

ข้อสังเกตในประเด็นสุดท้าย หากต้องเลือกระหว่างการตรวจสอบพื้นที่ที่ยังไม่ได้สำรวจที่เคยเห็นก่อนหน้านี้ (แต่ไม่ได้เยี่ยมชม) กับพื้นที่ที่ไม่ได้ตรวจสอบด้านหลังเส้นทางที่ปลดล็อกใหม่ควรทำให้เส้นทางที่ปลดล็อกใหม่มีความสำคัญ อาจเป็นเพราะมีกุญแจใหม่ (หรือล็อค) ที่จะเป็นประโยชน์ นี่ถือว่าเส้นทางที่ถูกล็อคอาจจะไม่ใช่จุดจบที่ไม่มีจุดหมาย

การขยายความคิดด้วยปุ่ม "ล็อคได้"

คุณอาจมีกุญแจที่ไม่สามารถรับได้หากไม่มีคีย์อื่น หรือล็อคกุญแจเหมือนเดิม หากคุณรู้จักถ้ำ Colossal เก่าของคุณคุณจะต้องมีกรงนกเพื่อจับนก - ซึ่งคุณต้องการในภายหลังสำหรับงู ดังนั้นคุณ "ปลดล็อก" นกด้วยกรง (ซึ่งไม่ได้ปิดกั้นเส้นทาง แต่ไม่สามารถหยิบขึ้นมาได้หากไม่มีกรง) จากนั้น "ปลดล็อก" งู (ซึ่งบล็อกเส้นทางของคุณ) กับนก

ดังนั้นการเพิ่มกฎบางอย่าง ...

  • หากไม่สามารถนำกุญแจได้ (มันถูกล็อคไว้) ให้ลองใช้กุญแจทุกดอกที่มีอยู่แล้ว
  • หากคุณพบกุญแจที่คุณไม่สามารถปลดล็อกได้โปรดจำไว้เป็นรหัสในภายหลัง
  • หากคุณพบกุญแจใหม่ให้ลองใช้กุญแจนั้นในทุก ๆ กุญแจที่ถูกล็อครวมถึงเส้นทางที่ถูกล็อค

ฉันจะไม่เข้าใจอะไรเกี่ยวกับการถือกุญแจบางอย่างว่าอาจลบล้างผลกระทบของกุญแจอื่น (ถ้ำขนาดมหึมา, rod rod scares bird และต้องตกหล่นก่อนที่นกจะถูกหยิบขึ้นมา แต่จำเป็นต้องสร้างภายหลังเพื่อสร้างสะพานเวทย์มนต์) .

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.