การเขียนโปรแกรมใช้งานและการผจญภัยข้อความ


14

นี่เป็นคำถามเชิงทฤษฎีส่วนใหญ่เกี่ยวกับ FP แต่ฉันจะผจญภัยข้อความ (เช่น Zork โรงเรียนเก่า) เพื่อแสดงจุดของฉัน ฉันต้องการทราบความคิดเห็นของคุณเกี่ยวกับวิธีจำลองสถานการณ์จำลองด้วย FP

การผจญภัยข้อความดูเหมือนจะเรียก OOP ตัวอย่างเช่น "ห้อง" ทั้งหมดเป็นอินสแตนซ์ของRoomคลาสคุณสามารถมีItemคลาสพื้นฐานและอินเทอร์เฟซที่เหมือนกับItem<Pickable>สิ่งที่คุณสามารถพกพาไปเรื่อย ๆ

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

ฉันคิดว่าวิธีการที่บริสุทธิ์จะส่งวัตถุขนาดใหญ่นี้ไปยังฟังก์ชันใด ๆ และให้พวกเขาส่งคืน (อาจแก้ไข) ตัวอย่างเช่นฉันมีmoveToRoomฟังก์ชั่นที่รับWorldและส่งคืนพร้อมWorld.player.locationเปลี่ยนเป็นห้องใหม่World.rooms[new_room].visited = Trueและอื่น ๆ

แม้ว่านี่จะเป็นวิธีที่ "ถูกต้อง" มากกว่า แต่ก็ดูเหมือนว่าจะมีการบังคับใช้ความบริสุทธิ์เพื่อประโยชน์ของมัน ขึ้นอยู่กับภาษาการเขียนโปรแกรมการส่งผ่านWorldวัตถุที่มีขนาดใหญ่มากไปมาอาจมีราคาแพง นอกจากนี้ทุกฟังก์ชั่นอาจต้องมีการเข้าถึงWorldวัตถุใด ๆ ตัวอย่างเช่นห้องอาจเข้าถึงได้หรือไม่ขึ้นอยู่กับคันโยกที่ถูกเรียกในห้องอื่นเพราะอาจถูกน้ำท่วม แต่หากผู้เล่นมีเสื้อชูชีพก็สามารถเข้าได้ สัตว์ประหลาดอาจก้าวร้าวหรือไม่ขึ้นอยู่กับว่าผู้เล่นสังหารญาติของเขาในห้องอื่น ซึ่งหมายความว่าroomCanBeEnteredฟังก์ชั่นความต้องการที่จะเข้าถึงWorld.player.invetoryและWorld.rooms, describeMonsterความต้องการในการเข้าถึงWorld.monstersและอื่น ๆ (โดยทั่วไปคุณต้องผ่านภาระทั้งหมดไปรอบ ๆ ) นี่ดูเหมือนว่าฉันจะเรียกตัวแปรทั่วโลกถึงแม้ว่านี่จะเป็นรูปแบบการเขียนโปรแกรมที่ดีโดยเฉพาะใน FP

คุณจะแก้ปัญหานี้อย่างไร


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

2
ฉันคิดว่างานวิจัยของ Chris Marten น่าสนใจโดยมีจุดประสงค์เพื่อแสดงวิธีสร้างนวนิยายเชิงโต้ตอบในภาษาที่ประกาศ github.com/chrisamaphone/interactive-lp
Daniel Gratzer

2
คุณอาจต้องการดูบล็อกนี้อธิบายวิธีการเขียนโปรแกรมเกมดังกล่าวในลักษณะการทำงาน โพสต์นี้โดยเฉพาะค่อนข้างตรงประเด็น
gallais

3
ฉันต้องสงสัยว่าคำถามนี้มีผลต่อการตัดสินใจในภายหลังของ @ EricLippert หรือไม่ในการเขียนบทความเกี่ยวกับการใช้งานเครื่อง Z ใน Ocaml ...
จูลส์

1
@Jules ลิงก์ไปยังจุดเริ่มต้นของซีรี่ส์นั้นสำหรับผู้ที่สนใจ: ericlippert.com/2016/02/01/west-of-house
KChaloux

คำตอบ:


4

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

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

ภาษาที่ใช้งานได้จริงส่วนใหญ่มีวิธีที่ทำให้ตระหนักถึงการกลายพันธุ์โดยตรง (พูดว่า ST monad ใน Haskell หรือ transients ใน Clojure) หรือจำลองมันอย่างมีประสิทธิภาพ (บ่อยครั้งโดยการนำส่วนที่ไม่เปลี่ยนแปลงของโครงสร้างข้อมูลมาใช้ใหม่ ) วิธีการรักษาความบริสุทธิ์อย่างใดอย่างหนึ่ง

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

ตัวเลือกอื่นที่ฉันได้เห็นจะกลับมาเป็นเพียงคำแนะนำในการเปลี่ยนแปลงบางส่วนของโลกจากฟังก์ชั่นส่วนตัวของคุณแล้วอัปเดตโลกของคุณตามสิ่งเหล่านี้ ชุดของการโพสต์บล็อกอธิบายนี้สามารถใช้ได้ที่http://prog21.dadgum.com/23.html

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


0

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

ด้วยเหตุนี้ลูกค้าปัจจุบันจึงจำเป็นต้องรับรู้ถึงRoomวัตถุและสิ่งที่ส่งผลกระทบโดยตรงเท่านั้น noticableEventsOutsideRoomอาจเป็นเพียงคลาสย่อยที่Roomได้รับผลกระทบจากการเปลี่ยนแปลงล่าสุดของฐานข้อมูลและวัตถุในเกมของคุณมีขนาดเล็กลงมาก


ผมเข้าใจว่าวิธีการนี้ไม่ได้ทำมากสำหรับ pathfinding หรือเรียกกิจกรรมในท้องถิ่น (เช่นเกษตรใน mobs ใกล้เคียง) แต่ฉันได้รับทราบเพื่อฐานข้อมูลการละเมิดในอดีตที่ผ่านมา ... ฉันอาจต้องการเพียงแค่ส่งสายไปupdate mobs set agro=1 where distance<5และ ทำกับมัน อาจไม่ใช่วิธีปฏิบัติที่ดีที่สุด แต่มันเหมาะกับวัตถุประสงค์ของฉัน สำหรับ pathfinding ผ่านฐานข้อมูลหนึ่งก็สามารถใช้ขั้นตอนวิธีเส้นทางที่สั้นที่สุดของ Dijkstra ...
Ayelis

0

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

BAD:
   f :: (World, Int) -> World

Good:
   f :: (Int,Int,Int,Int) -> World

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

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