hrxdev
العربية

#1 نواة حتمية يفرضها المترجم

· Nick

لا يوجد ما يُرى بعد، لذا فهذا الإدخال الأول عن الجزء الذي لن يراه أحد: نواة المحاكاة. يُفترض أن تشغّل اللعبة ما يصل إلى 1000 سجين وموظف بمعدل 20 نبضة في الثانية، وأن تشرح لماذا فعل أيٌّ منهم ما فعل. ولا ينجح ذلك إلا إذا كانت المدخلات نفسها تعطي دائمًا العالم نفسه. قررت أن أجعل ذلك خاصية تتحقق منها الآلة، منذ اليوم الأول.

أين وصلت

أنا في المَعلم الأول، هيكل النواة. المحاكاة مكتبة .NET خالصة لا تحوي أي شيفرة من Godot، وعميل Godot 4 لا يفتح حتى الآن سوى مشهد ثلاثي الأبعاد فارغ. لا يوجد نموذج للعالم، ولا مربعات، ولا شخصيات، ولا حفظ. ميزانية الألف شخصية هدف؛ لم أقس شيئًا بهذا الحجم بعد.

النبضة

الزمن في النواة عدد صحيح من النبضات، 20 في الثانية. لا يوجد زمن بأعداد عشرية. تمر النبضة بثلاث مراحل: تطبيق الأوامر الخارجية، وتشغيل الأنظمة بترتيب مكتوب في مكان واحد، ثم اعتماد التغييرات المؤجلة وزيادة العدّاد. إذا أفلت خطأ من النبضة، يُوسم العالم بأنه معطوب ويتوقف. قائمة الأنظمة اليوم فارغة؛ الحلقة موجودة كي يكون للنظام الأول مكان يذهب إليه.

الأوامر والسجل

لا يتغير العالم إلا عبر الأوامر. الأمر سجلّ صغير له معرّف نوع ثابت وترميز ثنائي مكتوب يدويًا. لكل أمر، يرمّزه العالم، ويختمه بالنبضة ورقم تسلسلي، ويتحقق منه (قراءةً فقط)، ويكتبه في السجل، وعندها فقط يطبّقه. تُسجَّل الأوامر المرفوضة أيضًا، وهذا يُفترض أن يساعد في تقارير الأخطاء. البذرة مع السجل يُفترض أن تعيد إنتاج الجولة بدقة. صيغة ملف إعادة التشغيل لم تُكتب بعد.

الأعداد العشوائية

كتبت مولّدات الأعداد العشوائية بنفسي (SplitMix64 وxoshiro256**) وحظرت Random من المكتبة القياسية داخل النواة. للعالم أربعة تدفقات مسمّاة (الأوامر، والاحتياجات، والذكاء الاصطناعي، والأحداث)، مشتقة من البذرة ومخزنة في حالة العالم، فتُحفظ وتدخل في البصمة. وللأعمال التي يجب ألا يؤثر فيها الترتيب، هناك مولّد عديم الحالة يعتمد على مفتاح من النطاق والكيان والنبضة. مخرجات البذرة 42 مثبّتة، لأنها فعليًا صيغة إعادة التشغيل: غيّر المولّد فتتعطل كل إعادة تشغيل قديمة.

بصمة العالم

دالة بصمة صغيرة حساسة للترتيب تطوي البذرة والنبضة والتدفقات العشوائية وملخصًا لسجل الأوامر في 64 بت. يمكن مقارنة جولتين يُفترض أن تتطابقا برقم واحد. حاليًا تغطي هذه الأجزاء فقط، لأن العالم لا يحوي غيرها. الخطوة التالية مقارنة البصمات كل N نبضة أثناء الجولة.

جعل اللاحتمية خطأً في البناء

لم أرد أن أعتمد على تذكّر القواعد. تُبنى النواة مع محللات للواجهات المحظورة: وقت الساعة الفعلي، والأعداد العشوائية بلا بذرة، والمعرّفات GUID العشوائية، وبصمات النصوص العشوائية، والخيوط وأدوات التوازي، وSIMD، وواجهات النصوص المعتمدة على الإعدادات الإقليمية، كلها تُفشل البناء. وتتحقق فحوص أخرى من عدم وجود حالة ساكنة قابلة للتغيير، وتمسح الشيفرة المترجمة بحثًا عن أي شيء تسلل. يستخدم جهازي إعدادات إقليمية روسية بفاصلة عشرية، وهذا سبب وجيه لحظر الواجهات المعتمدة على الإعدادات الإقليمية.

ثم ذهبت أبعد وحظرت مجموعات التجزئة القياسية (Dictionary وHashSet وأخواتها) من النواة، لأن ترتيب المرور عليها مصدر كلاسيكي للانحراف. تحصل النواة على مصفوفات وقوائم ومجموعتين صغيرتين خاصتين بها بترتيب موثّق. ليس ذلك محكمًا تمامًا: واجهة تعيد مجموعة تجزئة عبر واجهة عامة قد تتسلل، وجزء من الحماية لا يعمل إلا في الاختبارات.

كيف تُبنى

الأدوات المحيطة بالشيفرة مؤتمتة أيضًا، والسكربتات نفسها تعمل على Windows وmacOS. النهج العام موصوف في كيف تُصنع.

التالي

ما زال مفتوحًا في هذا المَعلم: نموذج العالم بطوابقه، وملفات الحفظ وإعادة التشغيل، واختبار الحتمية، ومشغّل سيناريوهات بلا واجهة مع خط أساس لاختبار الأداء. بعد ذلك تأتي واجهة البناء في Godot. انظر خريطة الطريق.

→ كل إدخالات اليوميات