- กล่าวถึงแนวทางการออกแบบกลไกหลักของเกมด้วย ความสัมพันธ์เชิงตรรกะและเพรดิเคต แทนฟังก์ชัน คลาส หรือสเตตตัวแปร
- เหตุผลที่ Prolog รู้สึกแปลกกว่า LISP ไม่ใช่เพราะไวยากรณ์ แต่เป็นเพราะมันจัดการโครงสร้างข้อมูลและอัลกอริทึมโดยยึด ความสัมพันธ์ทางคณิตศาสตร์ เป็นศูนย์กลาง
- เมื่อมองแถวของฐานข้อมูลเชิงสัมพันธ์ อินพุต/เอาต์พุตของวงจรดิจิทัล และอ็อบเจ็กต์ในเกมเป็น ความสัมพันธ์ n-ary ทั้งหมด ก็จะเห็นความเชื่อมโยงระหว่างโมเดลเชิงประกาศของ Prolog กับการออกแบบแบบขับเคลื่อนด้วยข้อมูล
- แม้จะยากที่จะทำกราฟิก เสียง ฟิสิกส์ หรือ I/O พื้นฐานด้วย Prolog แต่ก็ยังมีความเป็นไปได้ในการนำไปใช้กับ กลไกการเล่นเกม
- ภาค 1 อธิบายการแท็กและความสัมพันธ์ระหว่าง actor โดยอิงจาก world และ actor ส่วนการเปลี่ยนแปลงตามเวลาและ game loop จะไปต่อในตอนถัดไป
มุมมองปัญหาในการนำ Prolog มาใช้กับกลไกเกม
- LISP และ Prolog อยู่ในกระบวนทัศน์การเขียนโปรแกรมที่ต่างจากภาษาเชิงวัตถุทั่วไปอย่าง C# หรือ Java
- LISP เด่นด้านการเขียนโปรแกรมเชิงฟังก์ชันและแพตเทิร์นแบบเมตาภาษา ส่วน Prolog มักถูกยกให้เป็นภาษาตัวแทนของ logical programming
- LISP เข้าถึงได้ง่ายกว่าที่คิด เพราะมีแนวคิดอย่าง lambda expression และ higher-order function ใน C# รวมถึงพื้นฐานด้านวิศวกรรมไฟฟ้าและการประมวลผลสัญญาณ
- ในทางกลับกัน Prolog แม้ไวยากรณ์จะดูเรียบง่าย แต่ความยากสำคัญคือการจัดการโครงสร้างข้อมูลและอัลกอริทึมในรูปของ ความสัมพันธ์ทางคณิตศาสตร์
- แนวทางของ Prolog เชื่อมโยงกับโมเดลทางวิศวกรรมหลายแบบ
- แต่ละแถวของฐานข้อมูลเชิงสัมพันธ์สามารถมองเป็น n-ary predicate ในไวยากรณ์ของ Prolog ได้
- พฤติกรรมอินพุต/เอาต์พุตขององค์ประกอบในวงจรดิจิทัลสามารถนิยามเป็นความสัมพันธ์ n-ary ที่รวมพอร์ตอินพุตและเอาต์พุตเข้าด้วยกันได้
- แม้แต่อ็อบเจ็กต์อย่างชิ้นส่วนฮาร์ดแวร์หรือข้อมูลล้วน ๆ ในหน่วยความจำ ก็สามารถนิยามเป็นความสัมพันธ์ได้ในการเขียนโปรแกรมเชิงตรรกะ
- เช่นเดียวกับที่การเขียนโปรแกรมเชิงฟังก์ชันสามารถมองอ็อบเจ็กต์เหมือนฟังก์ชันได้ การเขียนโปรแกรมเชิงตรรกะก็สามารถมองอ็อบเจ็กต์เป็นความสัมพันธ์ได้เช่นกัน
กลไกหลักของเกมและการออกแบบเชิงประกาศ
- การเขียนโปรแกรมเชิงตรรกะสามารถนำไปใช้ในการออกแบบและพัฒนาระบบที่ซับซ้อน เช่น กลไกการเล่นหลักของวิดีโอเกม
- การสร้างเกมทั้งเกมด้วย Prolog เป็นความท้าทายอย่างมากสำหรับนักพัฒนาเกมทั่วไป หากไม่ได้ทำเพื่อการทดลอง
- ไม่ใช่องค์ประกอบของเกมทุกส่วนที่จะเหมาะกับ Prolog
- โมดูล I/O พื้นฐาน
- โมดูลกราฟิก
- โมดูลเสียง
- โมดูลฟิสิกส์
- เป้าหมายที่เหมาะสมจึงใกล้เคียงกับ กลไกหลัก มากกว่าตัวเกมทั้งหมด
- หากสร้างระบบ gameplay เป็นชุดของข้อความเชิงประกาศ มันอาจ แข็งแรงและแยกโมดูลได้ดี กว่าระบบเชิงคำสั่ง และอาจปลอดจาก edge case ที่ชวนสับสนอย่าง race condition ได้มากกว่า
- ในวิธีคิดนี้ ระบบต้องถูกออกแบบด้วยความสัมพันธ์เชิงตรรกะและเพรดิเคตเท่านั้น
- ไม่มีฟังก์ชัน
- ไม่มี struct
- ไม่มี class
- ไม่มี interface
- ไม่มีสเตตตัวแปร
โมเดล World และ Actor
- หัวใจของการเขียนโปรแกรมเกมด้วย Prolog คือการใช้ ความสัมพันธ์ เป็นหน่วยประกอบพื้นฐานที่สุด คล้ายกับตัวต้านทาน ทรานซิสเตอร์ ตัวเก็บประจุ และตัวเหนี่ยวนำในวงจรไฟฟ้า
- เกมแบ่งคร่าว ๆ ได้เป็น world และ actor
- world คือฉากที่ทุกอย่างเกิดขึ้น
- actor คืออ็อบเจ็กต์ที่อยู่ภายใน world
- actor หมายถึงเอนทิตีรายตัวที่มีชื่อและคุณสมบัติ เช่น player, enemy, obstacle หรือ item
- actor สามารถโต้ตอบกับ actor อื่นหรือกับตัวเองได้ และในกระบวนการนั้นก็จะเกิดเหตุการณ์หลากหลายขึ้น
- gameplay สามารถมองเป็นลำดับต่อเนื่องของเหตุการณ์เหล่านี้ได้
- ในโมเดลนี้ world จะประกอบด้วย actor หลายตัว และ actor แต่ละตัวมีสถานะและพฤติกรรมของตัวเอง
การแท็กด้วย unary predicate
- actor แต่ละตัวถูกระบุด้วยชื่อเฉพาะ
- ในตัวอย่าง
actor1, actor2 หมายถึง actor ตัวที่หนึ่งและตัวที่สอง
- tag คือคีย์เวิร์ดที่ติดอยู่กับ actor เพื่อบอกว่า actor นั้นคืออะไร
bread(actor1). และ bread(actor2). หมายความว่า actor1 และ actor2 ต่างก็เป็นขนมปัง
bread(actor1).
bread(actor2).
- ใน Prolog คำว่า
bread คือ ความสัมพันธ์เอกภาค และ bread(actor1) กับ bread(actor2) คืออินสแตนซ์แต่ละรายการของความสัมพันธ์นั้น
- actor หนึ่งตัวสามารถมีได้หลาย tag
- ถ้าขนมปังทุกชิ้นควรเป็น
flammable และ decomposable การติด tag ให้ actor ทีละตัวด้วยมือจะทั้งยุ่งยากและเสี่ยงต่อความผิดพลาด
- หากใช้ Horn clause เมื่อ
bread(X) เป็นจริง ก็จะอนุมานได้โดยอัตโนมัติว่า flammable(X) และ decomposable(X) เป็นจริงด้วย
flammable(X) :- bread(X).
decomposable(X) :- bread(X).
- Horn clause เหล่านี้ทำงานคล้าย ข้อมูลการตั้งค่า ของเกม
- ใกล้เคียงกับการนิยามคุณสมบัติของ character type, skill type หรือ mission type ในเอกสารออกแบบทางเทคนิคหรือสเปรดชีต
- เป็นโครงสร้างที่คุณสมบัติ
flammable, decomposable ถูกรวมอยู่ใน type-specifier ชื่อ bread
- หากเทียบกับ Unity ก็คล้ายกับการใส่คอมโพเนนต์
Flammable, Decomposable ลงใน prefab Bread
- ในสภาพแวดล้อมเชิงวัตถุ ก็คล้ายกับที่คลาส
Bread implements อินเทอร์เฟซ IFlammable, IDecomposable
- ในบริบทนี้ Horn clause ของ Prolog ทำหน้าที่คล้าย การนิยามชนิดข้อมูล
custom tag สำหรับ actor รายตัว
- นอกจาก tag ที่นิยามไว้ล่วงหน้าแล้ว ยังสามารถใส่ custom tag ให้กับ actor บางตัวโดยเฉพาะได้
- ในตัวอย่าง พ่อมดได้ร่ายเวทใส่ขนมปังก้อนที่สอง
actor2 จึงต้องมี tag enchanted
enchanted(actor2).
flammable และ decomposable เป็นคุณสมบัติที่มีร่วมกันในขนมปังทุกชิ้น
enchanted เป็นคุณสมบัติที่มีเฉพาะขนมปังพิเศษที่ถูกมนตร์สะกดเท่านั้น
การแสดงความสัมพันธ์ระหว่าง Actor ด้วย binary predicate
- ระบบ gameplay ต้องแสดงได้ไม่เพียงคุณสมบัติของ actor แต่ละตัวเท่านั้น แต่รวมถึงความสัมพันธ์ระหว่าง actor ด้วย
- ตัวอย่างของความสัมพันธ์มีดังนี้
- ในระบบนิเวศ predator จะล่า prey และ prey จะหนี predator
- ใน dating simulator ผู้ชายจะพยายาม flirt กับผู้หญิง และผู้หญิงจะปฏิเสธ
- ใน social simulator แบบ The Sims ผู้คนอาจเป็นเพื่อนกัน เป็นศัตรูกัน หรืออยู่ระหว่างนั้น
- ในหมากรุก bishop กิน rook ตามแนวทแยง ส่วน rook กิน bishop ตามแนวตั้งฉาก
- ใน Prolog เช่นเดียวกับที่ unary predicate ใช้แทนคุณสมบัติของ actor เดี่ยว ๆ binary predicate ก็ใช้แทนความสัมพันธ์ระหว่าง actor สองตัวได้
- เมื่อใช้ Horn clause ก็สามารถอนุมานความสัมพันธ์แบบไดนามิกจากชุดเงื่อนไขที่ต้องการได้
ตัวอย่าง canEat และ canSpoil
- หาก
actor3 เป็นมนุษย์ และมนุษย์กินขนมปังได้ ก็สามารถนิยามความสัมพันธ์ว่า “ถ้า X เป็น human และ Y เป็น bread แล้ว X สามารถกิน Y ได้”
human(actor3).
canEat(X, Y) :- human(X), bread(Y).
- ในที่นี้
canEat(X, Y) คือ ความสัมพันธ์ ที่เกิดขึ้นระหว่าง X กับ Y
- หาก
actor4 เป็น fungus และขนมปังเป็น decomposable ก็จะนิยามได้ว่า fungus สามารถ spoil actor ที่ decomposable ได้
fungus(actor4).
canSpoil(X, Y) :- fungus(X), decomposable(Y).
canSpoil(X, Y) คือความสัมพันธ์ที่ว่า “ถ้า X เป็น fungus และ Y เป็น decomposable แล้ว X สามารถ spoil Y ได้”
decomposable(Y) สามารถถูกอนุมานจาก bread(Y) ผ่าน Horn clause ที่กล่าวไว้ก่อนหน้าได้
ปัญหาที่ยังเหลือ: การเปลี่ยนแปลงตามเวลาและ game loop
- ตัวอย่างทั้งหมดจนถึงตอนนี้แสดงคุณสมบัติและความสัมพันธ์ของ actor แต่ยังเป็นแบบ คงที่ ทั้งหมด
- เกมไม่ใช่ฉากที่หยุดนิ่ง แต่เป็นสิ่งที่ actor ต้องเคลื่อนไหวและโต้ตอบกันไปตามกาลเวลา
- ด้วยธรรมชาติเชิงประกาศของ Prolog เพียงอย่างเดียว ดูเหมือนจะไม่ง่ายนักในการจัดการปัญหาที่คุณสมบัติเปลี่ยนไปเมื่อเวลาผ่านไป
- การทำความเข้าใจว่า game loop จะถูกทำให้เป็นแนวคิดใน Prolog อย่างไร จะต่อใน Part 2
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
ปกติบทความที่มีแค่ Part 1 แล้วหยุดไป ผมจะมองไม่ค่อยดีนัก แต่บทความนี้มี ตอนต่อ ออกมาเรื่อย ๆ จริง ๆ
https://thingspool.net/morsels/page-11.html (part 2)
https://thingspool.net/morsels/page-12.html (part 3)
https://thingspool.net/morsels/page-13.html (part 4)
https://thingspool.net/morsels/page-14.html (part 5)
และยังมีต่อไปอีก
น่าจะสามารถนำเทคนิคเหล่านี้ไปใช้กับการเขียนเกมด้วย Rust ได้
ในการออกแบบเกม Breath of the Wild มีแนวคิดที่เรียกว่า เคมีเอนจิน โดยปกติเอนจินเกมจะมีฟิสิกส์เอนจินที่คำนวณว่าวัตถุต่าง ๆ โต้ตอบกันอย่างไรในแง่การเคลื่อนที่ แต่เคมีเอนจินจะจัดการว่าวัสดุต่าง ๆ โต้ตอบกันอย่างไรในความหมายเชิงเล่นแร่แปรธาตุ
มันคำนวณปฏิสัมพันธ์ระหว่างสสารต่างชนิดกันเหมือนเอนจินแบบอิงกฎ จึงเกิดปฏิสัมพันธ์น่าทึ่ง เช่น ลูกธนูติดไฟได้เพราะทำจากไม้
ลิงก์ YouTube: https://www.youtube.com/watch?v=QyMsF31NdNc&t=2354s
องค์ประกอบแบบอิงกฎในเกมมักค่อนข้างเรียบง่ายและไม่จำเป็นต้องใช้งานได้ทั่วไป จึงดูเหมือนจะเขียนโค้ดด้วยมือ เมื่อถามผู้สร้าง Baba is You ว่าได้สร้าง Datalog engine หรือไม่ เขาก็บอกว่าไม่ และ Breath of the Wild ก็น่าจะคล้ายกัน
ถึงอย่างนั้น ผมมักคิดว่าเคมีเอนจินแบบนี้น่าจะเหมาะที่สุดหากทำด้วย ภาษาเชิงตรรกะ อย่าง Prolog หรือ Datalog เพื่อให้ทดลองได้เร็ว SQL เองก็ถูกใช้เพื่อรักษาความยืดหยุ่นของ query และสุดท้ายก็ถูกนำไป deploy ทั้งอย่างนั้น ในอดีตคงมีคนบ่นกันมากว่า query ของ SQL ช้า แต่ความยืดหยุ่นนั้นมีประโยชน์พอจนคนทุ่มเวลามหาศาลทำให้มันเร็วขึ้น ทุกวันนี้แทบไม่มีใครคิดว่า “ฉันเขียนโค้ด imperative ที่เร็วกว่า query นี้เองได้” แล้ว
เป็นหนึ่งในเกมที่ค่อนข้างน่าสนใจมากในบรรดาเกมที่เคยเล่นมา
https://store.steampowered.com/app/881100/Noita/
https://www.youtube.com/watch?v=prXuyMCgbTc
MUD ก็น่าจะคล้ายกัน
สิ่งที่เกมกราฟิกพยายามทำให้เป็นนวัตกรรม เป็นสิ่งที่เกมข้อความเมื่อ 40 ปีก่อน โดยเฉพาะ interactive fiction เคยทำไปแล้ว เรื่องนี้เด่นชัดยิ่งกว่างานยุคแรกของ Infocom ในยุคฟื้นฟูของเกมสมัครเล่นชั้นเยี่ยมช่วงทศวรรษ 90 เช่น Curses, Jigsaw, Anchorhead, Devours, Spider and Web รวมถึง roguelike อย่าง NetHack/Slash'EM, CDDA: Bright Nights และ MUD ออนไลน์ที่จัดการวัสดุแปลก ๆ กับปฏิสัมพันธ์ต่าง ๆ ไม่ใช่แค่ในฉากแฟนตาซี แต่รวมถึงไซเบอร์พังก์หรือ SF ด้วย
นักสร้างเกมชั้นยอดอย่าง Warren Spector ก็น่าจะเล่นเกม free software เกมอินดี้ และเกมแปลก ๆ เพื่อหยิบไอเดีย gameplay ใหม่ ๆ มาใช้
ผมมองว่าการกล่าวถึง NetHack ใน Deus Ex ต้นฉบับไม่ใช่แค่ easter egg แต่คงเป็นการคารวะต่อ emergent gameplay ที่อาจได้รับแรงบันดาลใจจาก NetHack
จุดแข็งของ Deus Ex ไม่ใช่กราฟิกหรือโลกทัศน์ แต่คือสิ่งที่ผู้เล่นทำได้ภายในเกม และการทำลายโครงสร้างเชิงเส้นของ FPS ในขณะที่ยังเข้าถึงง่ายกว่า System Shock 1 และ 2 ฝั่ง System Shock มีด้านที่ล้มเหลวในเรื่องการปรับระดับความยากและความสมบูรณ์ของ gameplay Arx Fatalis (ปัจจุบันคือ Libertatis) และ Ultima Underworld ก็คล้ายกัน
จากกฎเรียบง่าย เกิด ความซับซ้อน ที่น่าสนใจขึ้นมามากจริง ๆ
ไม่ใช่ว่ามีแต่อัลกอริทึมแก้ปัญหาที่ภาษาเชิงตรรกะ/เชิงสัมพันธ์ทั่วไป implement ไว้เท่านั้นที่ใช้ได้ และยิ่งมันทั่วไปมากเท่าไร ก็อาจยิ่งไม่มีประสิทธิภาพกับปัญหาที่เอนจินเกมต้องแก้อย่างมีประสิทธิภาพมากขึ้นเท่านั้น ในทางกลับกัน หากขยายภาษาเชิงตรรกะให้มีฟังก์ชันแบบนั้นแบบ native ก็อาจต้องทำลายสมมติฐานที่ทำให้มันเรียบง่าย หรือเปลี่ยนลำดับการประเมินผล จนทำให้ implement ภาษาให้เรียบง่ายและมีประสิทธิภาพได้ยาก
ตัวอย่างเช่น ผมเคยอยากใช้ความสัมพันธ์เชิงตรรกะร่วมกับข้อจำกัดเชิงเส้น เช่น
A <= (B-10.0) .OR. B <= (A-10.0)เพื่อจำกัดตำแหน่งศูนย์กลางของวัตถุเกมสองชิ้นที่มีความกว้าง 10.0 ไม่ให้ขอบซ้อนกัน โดยไม่ต้องสนใจว่าชิ้นไหนอยู่ด้านหน้า ด้วยประโยคแบบนี้ เราสามารถประกอบฉากหรืออ็อบเจกต์เกมที่ซับซ้อนในเชิงคุณภาพ แล้วให้ linear constraint solver เลือกพิกัดที่แน่นอนได้ปัญหาคือ เมื่อแก้ข้อจำกัดเชิงเส้นอย่าง
f(A) <= g(B)มันอาจส่งผลต่อทุกตัวแปรที่เกี่ยวข้องได้ เนื่องจาก A หรือ B อาจมีข้อจำกัดกับ C, D, E, F ด้วย ดังนั้นหากเลือกฝั่งซ้ายหรือฝั่งขวาของนิพจน์ตรรกะprop(X) .OR. prop(Y)แล้วรันทันที ก็อาจทำให้ประพจน์อื่นที่ตัดสินไปแล้วกลายเป็นใช้ไม่ได้ดังนั้น แทนที่จะตีความ
<=ของตัวแปรเชิงเส้นเป็นการทดสอบที่ให้ผลลัพธ์บูลีน ควรตีความว่าเป็นคำสั่งเพิ่มf(A) <= g(B)เข้าไปในที่เก็บข้อจำกัดเชิงเส้นส่วนกลาง แล้วค่อยรันตัวแก้ปัญหากับเมทริกซ์ตัวแปรเชิงเส้นทั้งหมดภายหลังจะดีกว่าจากนั้นก็เกิดคำถามด้านการออกแบบตามมา เช่น ภาษาจะรู้ได้อย่างไรว่าการเพิ่มข้อจำกัดเสร็จแล้วและถึงเวลาแก้แล้ว หรือจะทำอย่างไรกับอนุประโยคเชิงตรรกะที่ต้องทดสอบค่าจริง ๆ ไม่ใช่ไปตั้งเป็นข้อจำกัด แต่ประเด็นสำคัญคือ ในบริบทของเอนจินเกม เราต้องควบคุมให้มากขึ้นว่าการคำนวณยาว ๆ ทั้งในการแก้ข้อจำกัดเชิงเส้นและใน logic programming จะถูกรันเมื่อไรและนานแค่ไหน
กล่าวคือ แม้จะออกแบบให้ส่วนขยายทำงานได้ดีจากมุมมองของภาษาเชิงตรรกะ แต่จากมุมมองของระบบภายนอกก็ยังมีปัญหาอยู่ดีว่าเวลาในการค้นหาเพื่อแก้บางส่วนของโปรแกรมเชิงตรรกะอาจพุ่งขึ้นอย่างกะทันหัน และโปรแกรมเมอร์คาดเดาได้ไม่เสมอว่าจะเกิดขึ้นเมื่อไรที่ไหน ในความหมายนี้ โค้ด imperative ที่เขียนเองไม่จำเป็นต้องเร็วกว่าเลยด้วยซ้ำ ต่อให้ช้ากว่า ขอแค่มี ความคาดการณ์ได้ ก็พอ
ในทางปฏิบัติ ก็ไม่จำเป็นต้องเขียนเองทั้งหมดเสมอไป แก่นสำคัญคือ rules engine เป็น solver ที่โค้ดเกมแบบ imperative ขับจากภายนอกและแทรกแซงได้ หรือว่าทั้งเกมรันอยู่ภายใน solver หรือก็คือภาษาสัมพันธ์กันแน่ การจินตนาการว่าถ้าทั้งเกมเป็น relational จะทำอะไรได้บ้างนั้นน่าดึงดูด แต่ถ้าจะใช้เทคโนโลยีนั้นกับทั้งเกมจริง ๆ ก็ต้องมี relational solver วิเศษบางอย่างที่ในความเป็นจริงยังไม่มี
เป็นบทนำสู่การเขียนโปรแกรมเกมด้วย Prolog แต่จุดที่น่าสนใจคือไปที่ เกมแอ็กชัน ทันที ครอบคลุมแง่มุมแบบเรียลไทม์, ไทม์ไลน์, 3D, ECS และอีเวนต์
ปกติหนังสือเบื้องต้นเกี่ยวกับการพัฒนาเกมด้วย Prolog จะเริ่มจากเกมผจญภัย โดยเฉพาะ text adventure แบบคลาสสิก เพราะเขาวงกตและปริศนาอินเวนทอรีเข้ากันพอดีกับข้อเท็จจริงและกฎของ Prolog รวมถึง DSL
เกมไพ่หรือเกมกระดานก็สามารถแสดงกฎด้วย Prolog ได้สะดวกมาก และสามารถขยายคู่ต่อสู้เกมทั่วไปเชิงจัดหมู่พื้นฐานได้แทบจะง่าย ๆ คล้ายกับตัววางแผน Prolog ที่ใช้ในหุ่นยนต์ โลจิสติกส์ การเงิน อุตสาหกรรม ฯลฯ
ตอนเรียนวิชา AI สิ่งแรกที่ได้เรียนคือ Prolog และงานที่ต้องส่งคือทุกคนต้องเขียน เกมสไตล์ adventure/colossal cave Prolog เหมาะกับงานนั้นมาก และความหลากหลายของเกมง่าย ๆ ที่สร้างกันในชั้นเรียนก็น่าทึ่ง
คิดว่าน่าจะเก็บเกมทั้งหมดที่นักศึกษาคนอื่นทำไว้ด้วย หลังจากเรียนเรื่องนี้ไม่กี่สัปดาห์ก็ย้ายไปหัวข้ออื่นอย่าง CLIPS และ Lisp
ในงานของผม ผมทำ Bureaucratic Maze [1] ซึ่งใน Prolog ก็ถือว่าค่อนข้างตรงไปตรงมา
[1]. http://logicmazes.com/bureau/index.htm
แต่ใน Inform6 ด้วยแนวทางที่จัดการความสัมพันธ์ของอ็อบเจ็กต์ในเกมโดยตรง เช่น object-oriented ที่นำมาใช้กับการออกแบบเกมและ ZMachine ความยากจึงลดลงมากจนแทบเป็นเรื่องเล็กน้อย
http://logicmazes.com/alice.html
alice.html:353 Uncaught TypeError: Cannot read properties of undefined (reading 'play')at playSound (alice.html:353:30)at finalize2 (alice.html:347:1)at :1:1ลองกวาดตาดูบทความ 12 ตอนแล้ว สำหรับบทนำการใช้ Prolog ดูเหมือนจะดี แต่ยังดูฝืนอยู่ถ้าจะบอกว่าสิ่งนี้เกี่ยวข้องกับ การเขียนโปรแกรมเกม
ต่อไปอาจพัฒนาไปได้ แต่จนถึงบทที่ 12 เนื้อหาส่วนใหญ่เป็นการพยายามโมเดลแนวคิดเชิงวัตถุบางอย่างใน Prolog
ไม่แน่ใจว่าผมพลาดอะไรไปหรือเปล่า แต่ยังไม่ได้พูดถึงการโต้ตอบกับผู้ใช้ซึ่งดูเหมือนเป็นเงื่อนไขตั้งต้นของเกม มีช่วงที่พูดถึงการส่งข้อความแบบสั้น ๆ อยู่ อาจตั้งใจหมายถึงส่วนนั้นก็ได้
ในบริบทคล้ายกัน ผมอ่านหนังสือเขียนโปรแกรมเกมแบบ logic programming ที่ใช้ CLIPS แทน Prolog แล้วสนุกดี
Adventures in Rule-Based Programming: A CLIPS Tutorial https://a.co/d/7wVOcZp
https://www.clipsrules.net/
หนังสือโปรแกรมมิงบน Kindle มักแย่บ่อย ๆ แต่ถ้าดูบนแท็บเล็ต Fire อาจพอใช้ได้
มีส่วนทับซ้อนที่น่าสนใจระหว่างมุมมองที่มองสถานะเกมเป็นชุดของข้อเท็จจริงและความสัมพันธ์ (Prolog) กับแก่นของ ECS ที่ว่า “นี่คือฐานข้อมูล”[1]
ส่วนตัวกำลังทดลองใช้ Datascript เป็นฐานข้อมูลสถานะเกม แต่ยังเร็วเกินไปที่จะตัดสินว่าสำเร็จหรือไม่ ดีที่ได้เห็นไอเดียในทูโทเรียลนี้แมปกับมุมมองนั้นแบบ 1:1
ยังไม่แน่ใจว่ามีวิธีกำหนดกฎให้กระชับกว่าที่เขียนตอนนี้ได้หรือไม่ ในเปเปอร์ของ Stanford สามารถเขียนกฎแบบ
(<= (column ?n ?x) ...)ได้ แต่ใน Datascript มีงานรอบข้างที่ต้องย้ายข้อมูลมากกว่ามากไม่รู้ว่านี่เป็นข้อจำกัดของ Datascript/Datomic Datalog หรือเพราะผมยังเข้าใจไม่พอ
อยากรู้ว่าคุณเข้าใกล้การทดลองนี้อย่างไร ถ้ามีงานที่แชร์ได้หรือมีคำแนะนำเกี่ยวกับวิธีที่ผมกำลังทำอยู่ตอนนี้ ผมสนใจมาก
[1]: https://www.cs.uic.edu/~hinrichs/papers/love2006general.pdf
เป็นแนวทางที่สดใหม่ในการจัดการปัญหา state machine ในเกมที่มีตรรกะเยอะ เช่น ซิมูเลชันเมือง ไม่เคยคิดมาก่อนว่าจะใช้ Prolog แบบนี้ได้
ดูเหมือนว่าสามารถทำสิ่งที่เจ๋งมากได้ในประเด็นเรื่องเหตุและผลกับสัมพัทธภาพ เช่น ขณะสร้างการเผชิญหน้าแบบสุ่มกับ NPC ก็สามารถสร้างประวัติเหตุการณ์ของ NPC นั้นที่รวม ห่วงโซ่เหตุและผล ที่ผู้เล่นเคยเริ่มไว้ในอดีตได้
ทุกอย่างเป็นความสัมพันธ์ และเมื่อมีข้อเท็จจริงว่า NPC มีอยู่ตอนนี้ รวมถึงสถานะโลกและประวัติการกระทำทั้งหมดที่ถูกสังเกตไว้ ก็สามารถไล่ย้อนกลับเพื่อมอบอดีตที่สอดคล้องกันอย่างสมบูรณ์ให้ NPC ได้ โดยไม่ต้องจำลองไว้ล่วงหน้า
ไม่เคยคิดมาก่อนว่าโมเดล actor-world/entity-trait ที่พบได้บ่อยจะเข้ากันได้ดีกับแนวทางเชิงความสัมพันธ์ของ Prolog
แต่เวลารันที่คาดการณ์ได้และมีประสิทธิภาพก็สำคัญเช่นกัน โดยทั่วไป Prolog มักมีแนวโน้มจะทำ การค้นหาแบบ brute force โดยจับคู่ term ไปเรื่อย ๆ เพื่อให้ query เป็นจริง ยังไม่ได้อ่านซีรีส์นี้ทั้งหมด เลยสงสัยว่ามีการพูดถึงปัญหานี้หรือไม่
เดาในเบื้องต้นว่าน่าจะเป็นรูปแบบการเขียนข้อจำกัดที่รู้เกี่ยวกับคำตอบไว้คล้ายกับ “การประกาศชนิด” บางอย่าง