1 คะแนน โดย GN⁺ 2024-10-12 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • กล่าวถึงแนวทางการออกแบบกลไกหลักของเกมด้วย ความสัมพันธ์เชิงตรรกะและเพรดิเคต แทนฟังก์ชัน คลาส หรือสเตตตัวแปร
  • เหตุผลที่ 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 ความคิดเห็น

 
GN⁺ 2024-10-12
ความคิดเห็นจาก 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)
    และยังมีต่อไปอีก

    • เห็นว่าต่อเนื่องไปจนถึง Part 13 คงต้องใช้เวลาอ่านให้ครบ แต่ชอบมากจริง ๆ และตั้งใจจะลองตาม Scryer Prolog ที่เขียนด้วย Rust ที่ https://github.com/mthom/scryer-prolog
      น่าจะสามารถนำเทคนิคเหล่านี้ไปใช้กับการเขียนเกมด้วย Rust ได้
    • อาจจะดีกว่าถ้าเปลี่ยนลิงก์เป็นสารบัญ: https://thingspool.net/morsels/list.html
    • หรือในทางกลับกัน ถ้าอยากช่วยโปรโมตเว็บไซต์ของผู้เขียนและทำให้เขาเขียนต่อไปเรื่อย ๆ ก็อาจต้องทำตรงกันข้าม
  • ในการออกแบบเกม 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 นี้เองได้” แล้ว

    • Noita เป็นเกมที่วางอยู่บนแนวคิด เคมีเอนจินระดับพิกเซล และใช้เอนจินกฎแบบทำเองที่เขียนด้วย C++
      เป็นหนึ่งในเกมที่ค่อนข้างน่าสนใจมากในบรรดาเกมที่เคยเล่นมา
      https://store.steampowered.com/app/881100/Noita/
      https://www.youtube.com/watch?v=prXuyMCgbTc
    • ระบบอ็อบเจกต์นั้นโดยเนื้อแท้แล้วเหมือนกับการออกแบบของ ZMachine อ็อบเจกต์สามารถมีคุณสมบัติได้ และทำงานเหมือนอ็อบเจกต์กับเมธอดใน object-oriented programming
      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 ก็คล้ายกัน
    • นึกถึง Dwarf Fortress ค้อนเงินสร้างความเสียหายได้มากกว่าเพราะเงินหนักกว่า และเฟอร์นิเจอร์ไม้ก็ติดไฟได้ เสื้อผ้าเปียกของเหลวจากฝนหรือเลือด และยังดื่มสิ่งนั้นได้ด้วย
      จากกฎเรียบง่าย เกิด ความซับซ้อน ที่น่าสนใจขึ้นมามากจริง ๆ
    • ขอพูดโดยมีสมมติฐานว่ายังไม่ได้อ่านต้นฉบับ แต่ตลอดหลายปีที่ผ่านมาผมหลงใหลกับการใช้ relational programming ในเอนจินเกม ท้ายที่สุดก็สรุปได้ว่า แทนที่จะสร้างทั้งเกมด้วยภาษาเชิงสัมพันธ์แบบทั่วไป เขียนเอนจินด้วย C++ แล้วใช้ตัวแก้ปัญหาแบบเฉพาะสำหรับบางด้านที่อยากจัดการเชิงสัมพันธ์จะดีกว่า
      ไม่ใช่ว่ามีแต่อัลกอริทึมแก้ปัญหาที่ภาษาเชิงตรรกะ/เชิงสัมพันธ์ทั่วไป 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

    • ใน Common Lisp หนังสือ Land of Lisp ให้ผู้เริ่มต้นฝึกเขียนเกมแบบนี้จริง ๆ
      แต่ใน Inform6 ด้วยแนวทางที่จัดการความสัมพันธ์ของอ็อบเจ็กต์ในเกมโดยตรง เช่น object-oriented ที่นำมาใช้กับการออกแบบเกมและ ZMachine ความยากจึงลดลงมากจนแทบเป็นเรื่องเล็กน้อย
    • https://amzi.com/AdventureInProlog/ ก็สอน Prolog ด้วยแนวทางเดียวกัน
    • บน Chrome/Firefox เวอร์ชันล่าสุดของ macOS ปริศนาที่ลิงก์จากหน้าระดับบนสุดทำให้เกิด ข้อผิดพลาด JavaScript ในเทอร์มินัล อยากเห็นตอนที่มันทำงานจริง
      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

    • ผมก็กำลังจะพูดถึงหนังสือเล่มนั้นเหมือนกัน ที่ทำงานเคยสำรวจแนวทางใช้ CLIPS หรือสิ่งคล้าย ๆ กันกับระบบบางอย่าง ผมอ่านเอกสารฟรีคร่าว ๆ แล้วซื้อมา เป็นหนังสือที่อ่านเพลิน
      https://www.clipsrules.net/
    • https://ryjo.codes/ มีทรัพยากรดี ๆ เกี่ยวกับ CLIPS อยู่มาก
    • ดูน่าสนใจ อยากรู้ว่าเวอร์ชัน Kindle ใช้ได้ดีไหม
      หนังสือโปรแกรมมิงบน Kindle มักแย่บ่อย ๆ แต่ถ้าดูบนแท็บเล็ต Fire อาจพอใช้ได้
  • มีส่วนทับซ้อนที่น่าสนใจระหว่างมุมมองที่มองสถานะเกมเป็นชุดของข้อเท็จจริงและความสัมพันธ์ (Prolog) กับแก่นของ ECS ที่ว่า “นี่คือฐานข้อมูล”[1]
    ส่วนตัวกำลังทดลองใช้ Datascript เป็นฐานข้อมูลสถานะเกม แต่ยังเร็วเกินไปที่จะตัดสินว่าสำเร็จหรือไม่ ดีที่ได้เห็นไอเดียในทูโทเรียลนี้แมปกับมุมมองนั้นแบบ 1:1

    1. https://www.gamedevs.org/uploads/data-driven-game-object-sys...
    • จุดที่น่าสนใจคือส่วนทับซ้อนระหว่าง กฎ ใน logic programming กับกฎของเกม เมื่อวานได้รับแรงบันดาลใจจากงาน Game Description Language [1] ของ Stanford ที่อิง logic programming แล้วลองอิมพลีเมนต์ tic-tac-toe ด้วย Datascript: https://github.com/kasbah/datascript-games/blob/e06a37025bf9...
      ยังไม่แน่ใจว่ามีวิธีกำหนดกฎให้กระชับกว่าที่เขียนตอนนี้ได้หรือไม่ ในเปเปอร์ของ Stanford สามารถเขียนกฎแบบ (<= (column ?n ?x) ...) ได้ แต่ใน Datascript มีงานรอบข้างที่ต้องย้ายข้อมูลมากกว่ามาก
      ไม่รู้ว่านี่เป็นข้อจำกัดของ Datascript/Datomic Datalog หรือเพราะผมยังเข้าใจไม่พอ
      อยากรู้ว่าคุณเข้าใกล้การทดลองนี้อย่างไร ถ้ามีงานที่แชร์ได้หรือมีคำแนะนำเกี่ยวกับวิธีที่ผมกำลังทำอยู่ตอนนี้ ผมสนใจมาก
      [1]: https://www.cs.uic.edu/~hinrichs/papers/love2006general.pdf
    • ถ้ายังไม่เคยดู แนวทางนี้ที่ เชื่อมกฎ DataScript เพื่อคำนวณเฟรมถัดไปน่าจะน่าสนใจ: https://frankiesardo.github.io/minikusari/#!/minikusari.tuto...
  • เป็นแนวทางที่สดใหม่ในการจัดการปัญหา state machine ในเกมที่มีตรรกะเยอะ เช่น ซิมูเลชันเมือง ไม่เคยคิดมาก่อนว่าจะใช้ Prolog แบบนี้ได้

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

  • ไม่เคยคิดมาก่อนว่าโมเดล actor-world/entity-trait ที่พบได้บ่อยจะเข้ากันได้ดีกับแนวทางเชิงความสัมพันธ์ของ Prolog
    แต่เวลารันที่คาดการณ์ได้และมีประสิทธิภาพก็สำคัญเช่นกัน โดยทั่วไป Prolog มักมีแนวโน้มจะทำ การค้นหาแบบ brute force โดยจับคู่ term ไปเรื่อย ๆ เพื่อให้ query เป็นจริง ยังไม่ได้อ่านซีรีส์นี้ทั้งหมด เลยสงสัยว่ามีการพูดถึงปัญหานี้หรือไม่

    • การค้นหาแบบ brute force เป็นเพียงวิธีแบบตรงไปตรงมาในการหาคำตอบเท่านั้น เช่นเดียวกับที่สามารถทำดัชนีให้ตาราง SQL ได้ ก็สามารถทำ ดัชนี ให้ predicate ของ Prolog เพื่อเพิ่มประสิทธิภาพได้เช่นกัน
    • เป็นคำถามแบบมือใหม่ แต่ปริมาณการค้นหาแบบ brute force ไม่ได้ขึ้นอยู่กับ solver ที่ใช้หรือ? พอรู้คร่าว ๆ เรื่อง finite domain constraints อยู่บ้าง เลยสงสัยว่า Prolog เปิดช่องให้ใช้ solver ที่ต่างกันในส่วนต่าง ๆ ของ codebase ได้แค่ไหน
      เดาในเบื้องต้นว่าน่าจะเป็นรูปแบบการเขียนข้อจำกัดที่รู้เกี่ยวกับคำตอบไว้คล้ายกับ “การประกาศชนิด” บางอย่าง