কোন করিডোর এবং ঘরের নির্ভরতা সহ অন্ধকূপ জেনারেশন


15

আমি গেমের শুরুতে তৈরি পদ্ধতিগতভাবে উত্পন্ন বিশ্বের সাথে একটি গেম তৈরি করছি, গ্রিড দ্বারা প্রতিনিধিত্ব করা বেশ কয়েকটি অঞ্চল নিয়ে গঠিত (বলুন, 8x8, 9x6, মাপগুলি আদর্শভাবে নির্বিচারে হবে)। নির্ভরতা তালিকার মাধ্যমে এই অঞ্চলগুলি একে অপরের সাথে সংযুক্ত হওয়ার কথা।

যখন এই গ্রিডের কমপক্ষে 3 স্পেসগুলি দুটি অঞ্চলগুলির মধ্যে প্রকাশিত হয় তখন একটি সংযোগ বিদ্যমান। সেই 3 স্পেস সংযোগ অঞ্চলের মাঝের কক্ষে অঞ্চলগুলির মধ্যে দ্বার way

আমি তাদের সংযোগ করার একটি উপায় বের করার চেষ্টা করেছি, তবে একই সময়ে আপনাকে আরও বেশি ক্ষেত্র বিবেচনা করা এটি ক্রমশ জটিল হয়ে উঠছে।

আমি কিছু কাগজ প্রোটোটাইপিং চেষ্টা করেছি এবং এটি খুব সহজ প্রক্রিয়াটি যখন দৃষ্টিভঙ্গি করে এটি করার সময়, আমি গাণিতিক এক্সপ্রেশনগুলির একটি ভাল সেট খুঁজে পাইনি যা আমাকে কোড অনুসারে একই দক্ষতার সাথে কক্ষগুলি স্থাপন করতে দেয়।

এই মুহুর্তে আমি লড়াই করছি এমন একটি "সাধারণ" উদাহরণ:

  • অঞ্চল 'ক' কে 'বি' এবং 'সি' এর সাথে সংযুক্ত করা দরকার
  • অঞ্চল 'খ' 'এ' এবং 'ডি' এর সাথে সংযুক্ত হওয়া দরকার
  • অঞ্চল 'সি' 'এ' এবং 'ডি' এর সাথে সংযুক্ত হওয়া দরকার
  • অঞ্চল 'ডি' 'বি' এবং 'সি' এর সাথে সংযুক্ত হওয়া দরকার

সরলতার জন্য বিবেচনা করুন, আমরা তালিকায় তাদের উপস্থিতির ক্রম অনুসারে কক্ষগুলি রাখছি (আমি অন্যদের চেষ্টা করেছি)। তাই আমি এটি আপনার প্রমিত প্রক্রিয়াজাত ডানজিওন জেনারেশন অ্যালগরিদম হিসাবে পৌঁছে যাচ্ছি।

আমরা বোর্ডে যে কোনও জায়গায় 'এ' রাখি কারণ এটি প্রথম অঞ্চল। এর পরে, আমরা এলোমেলোভাবে একটি প্রাচীর বাছাই করি এবং যেহেতু কিছুই সেই দেয়ালের সাথে সংযুক্ত না থাকে, আমরা সেখানে 'বি' রাখতে পারি:

এখন আমাদের 'সি' স্থাপন করা দরকার, তবে 'এ' বোর্ডে ইতিমধ্যে রয়েছে এবং এর একটি দখল প্রাচীর রয়েছে, তাই আমরা এটিকে অন্য কোনও দেয়ালে রাখার সিদ্ধান্ত নিই। তবে প্রত্যেকটি প্লেসমেন্টটি করবে না, কারণ 'ডি' আসছে এবং এটি 'বি' এবং 'সি' এর সাথেও সংযুক্ত হওয়া দরকার:

আমি একটি সম্ভাব্য সীমাবদ্ধতার চেষ্টা করেছি যে একই রকম নির্ভরতা থাকা 2 টি কক্ষগুলি বিপরীত দেয়ালে থাকতে পারে না, এমনকি এটি সাফল্যের গ্যারান্টি দেয় না:

এবং অন্যান্য ক্ষেত্রে, যেখানে অঞ্চলগুলির বিভিন্ন আকার রয়েছে, বিপরীতে প্রাচীরের থাকা কাজ করতে পারে:

এছাড়াও, ব্যবহৃত প্রাচীর বিবেচনা না করা একটি ত্রুটিযুক্ত অনুমিতি কারণ এটি বৈধ সমাধানগুলি বাতিল করে দেয়:

আমি অন্যান্য প্রসিডেরাল জেনারেশন অ্যালগরিদম বা অনুরূপ যেমন: অনুকূল আয়তক্ষেত্রাকার প্যাকিং এবং গ্রাফ লেআউট আলগোরিদিমগুলির বিষয়ে গবেষণার চেষ্টা করেছি, তবে সাধারণত সেই অ্যালগোরিদমগুলি এই সমস্যার প্রতিটি প্রতিবন্ধকে বিবেচনা করে না এবং একসাথে মিশ্রিত হওয়া শক্ত।

আমি উপযুক্ত প্লেসমেন্ট না পাওয়া পর্যন্ত একটি অঞ্চল এবং ব্যাকট্র্যাক স্থাপন সহ একাধিক পদ্ধতির কথা ভেবেছিলাম, তবে তারা পরীক্ষার এবং ত্রুটির উপর খুব নির্ভরশীল এবং গণনার ক্ষেত্রে ব্যয়বহুল বলে মনে হয়। তবে, আমি উল্লেখ করা শেষ দুটি সমস্যার উপর ব্যাপক গবেষণা দেওয়া, এটিই কি কেবলমাত্র / সেরা সমাধান হতে পারে?

আমি কেবল দেখতে চেয়েছিলাম যে অতীতেও কারওর একইরকম সমস্যা আছে কিনা বা আমাকে এটি নির্ধারণ করতে এবং আমাকে অ্যালগরিদম দিয়ে কোথায় শুরু করা উচিত সে সম্পর্কে কয়েকটি পয়েন্টার দিতে সাহায্য করতে ইচ্ছুক কিনা। অথবা, এটি ব্যর্থ হয়ে, আমি আমার যে সীমাবদ্ধতাগুলি স্থির করেছি তা শিথিল করতে হবে।


ঘরগুলি কি পুরো বর্গক্ষেত্র হতে হবে?
উলফডন

যদি আপনার অর্থ যদি তাদের 4 টি দেয়াল থাকতে হয় এবং তার চেয়ে বেশি না হয় তবে হ্যাঁ, তবে আমি বিশ্ব স্পেসকে সহজ করার জন্য এটি করেছি। প্রতিটি অঞ্চল যে জায়গা দখল করে আছে তা আমাকে খুব সহজেই গণনা করতে হবে যাতে আমি জানি যে আমি এতে যা চাই তার সবই রাখতে সক্ষম হবো কিনা।
জোয়ানা আলমেইদা

উত্তর:


6

এটি একটি দুর্দান্ত সমস্যা। আমি বিশ্বাস করি যে রুম বসানো জায়গার ক্রিয়া পরিকল্পনা ব্যবহার করে এটি সমাধান করা যেতে পারে।

নিম্নলিখিত হিসাবে বিশ্বের রাষ্ট্র সংজ্ঞায়িত :

//State:
//    A list of room states.
//    Room state:
//      - Does room exist?
//      - Where is room's location?
//      - What is the room's size?

একটি নির্ধারণ কনস্ট্রেইন্ট অর্থাৎ হিসাবে:

 // Constraint(<1>, <2>):
 //  - If room <1> and <2> exist, Room <1> is adjacent to Room <2>

"সংলগ্ন" যেখানে আপনি বর্ণিত হিসাবে রয়েছে (কমপক্ষে 3 প্রতিবেশী ভাগ করে নেওয়া)

একটি কনস্ট্রেইন্ট অর্থাৎ করা হয়েছে invalidated যখনই দুই কক্ষ আছে না সংলগ্ন, এবং উভয় কক্ষ বিদ্যমান।

কোনও রাষ্ট্রকে বৈধ হওয়ার জন্য সংজ্ঞা দিন যখন:

// foreach Constraint:
//        The Constraint is "not invalidated".
// foreach Room:
//       The room does not intersect another room.

একটি বর্তমান স্থিতি দেওয়া, একটি কক্ষের স্থান হিসাবে একটি ক্রিয়া সংজ্ঞায়িত করুন । অ্যাকশন হয় বৈধ যখনই কর্ম ফলে রাষ্ট্র বৈধ। অতএব, আমরা প্রতিটি রাজ্যের জন্য ক্রিয়াগুলির একটি তালিকা তৈরি করতে পারি:

// Returns a list of valid actions from the current state
function List<Action> GetValidActions(State current, List<Constraint> constraints):
    List<Action> actions = new List<Action>();
    // For each non-existent room..
    foreach Room room in current.Rooms:
        if(!room.Exists)
            // Try to put it at every possible location
            foreach Position position in Dungeon:
                 State next = current.PlaceRoom(room, position)
                 // If the next state is valid, we add that action to the list.
                 if(next.IsValid(constraints))
                     actions.Add(new Action(room, position));

এখন, আপনি কি অবশিষ্ট করছি একটি হল গ্রাফ , যেখানে যুক্তরাষ্ট্র নোড আছে, এবং পদক্ষেপ লিঙ্ক দেওয়া হয়েছে। লক্ষ্যটি এমন একটি রাজ্য সন্ধান করা যা উভয়ই বৈধ, এবং সমস্ত কক্ষই রাখা হয়েছে। আমরা গ্রাফটি একটি স্বেচ্ছাসেবী ভাবে অনুসন্ধান করে একটি বৈধ স্থান নির্ধারণ করতে পারি, সম্ভবত গভীরতার প্রথম অনুসন্ধান ব্যবহার করে। অনুসন্ধানে এরকম কিছু দেখাবে:

// Given a start state (with all rooms set to *not exist*), and a set of
// constraints, finds a valid end state where all the constraints are met,
// using a depth-first search.
// Notice that this gives you the power to pre-define the starting conditions
// of the search, to for instance define some key areas of your dungeon by hand.
function State GetFinalState(State start, List<Constraint> constraints)
    Stack<State> stateStack = new Stack<State>();
    State current = start;
    stateStack.push(start);
    while not stateStack.IsEmpty():
        current = stateStack.pop();
        // Consider a new state to expand from.
        if not current.checked:
            current.checked = true;
            // If the state meets all the constraints, we found a solution!
            if(current.IsValid(constraints) and current.AllRoomsExist()):
                return current;

            // Otherwise, get all the valid actions
            List<Action> actions = GetValidActions(current, constraints);

            // Add the resulting state to the stack.
            foreach Action action in actions:
                State next = current.PlaceRoom(action.room, action.position);
                stateStack.push(next);

    // If the stack is completely empty, there is no solution!
    return NO_SOLUTION;

এখন উত্পন্ন অন্ধকূপটির গুণমান কক্ষ এবং ক্রিয়াগুলি বিবেচনা করা হয় সেই ক্রমের উপর নির্ভর করবে। প্রতিটি পর্যায়ে আপনি যে ক্রিয়া করেন তা কেবল এলোমেলোভাবে অনুমতি দিয়ে আপনি আকর্ষণীয় এবং বিভিন্ন ফলাফল পেতে পারেন, যার ফলে স্টেট-অ্যাকশন গ্রাফের মাধ্যমে এলোমেলো হাঁটাচলা করে। আপনি কীভাবে অবৈধ অবস্থা প্রত্যাখ্যান করতে পারবেন তার উপর অনুসন্ধান দক্ষতা ব্যাপকভাবে নির্ভর করবে। আপনি যখনই বৈধ ক্রিয়াগুলি সন্ধান করতে চান এটি সীমাবদ্ধতা থেকে বৈধ রাজ্যগুলি তৈরি করতে সহায়তা করতে পারে ।


মজার বিষয় আপনি এই সমাধান উল্লেখ করা উচিত। আমি আগে একটি বন্ধুর সাথে কথা বলেছিলাম এবং তিনি উল্লেখ করেছিলেন যে আমার সম্ভবত ট্রি ভিত্তিক অনুসন্ধান অ্যালগরিদমগুলি খতিয়ে দেখা উচিত, তবে এই প্রসঙ্গে কীভাবে সেগুলি ব্যবহার করবেন তা নিশ্চিত ছিলাম না। আপনার পোস্ট চোখ খোলা ছিল! এটি সম্ভবত একটি সম্ভাব্য সমাধান হিসাবে মনে হয় যদি আপনি শাখা প্রজন্ম পরিচালনা করেন এবং যত তাড়াতাড়ি সম্ভব খারাপ শাখা কাটাতে কয়েকটি অনুকূলিতকরণ করেন।
জোয়ানা আলমেইদা

7

আপনার প্রজন্মের অগ্রাধিকারগুলি দ্বন্দ্বের মধ্যে রয়েছে। স্তর উত্পাদন করার সময়, আপনার প্রথম লক্ষ্যটি স্ক্যান নির্বিশেষে প্ল্যানারের ওয়েব (অ-ওভারল্যাপিং), সংযুক্ত পয়েন্ট হওয়া উচিত । তারপরে সেই ওয়েবের মধ্যে থাকা পয়েন্টগুলি থেকে কক্ষগুলি তৈরি করতে এগিয়ে যান। প্রথমে ঘরের আকার তৈরি করা একটি ভুল, সাধারণভাবে বলা। প্রথমে কানেক্টিভিটি তৈরি করুন এবং তারপরে দেখুন কী কী ঘরগুলির ফর্মগুলি এর মধ্যে অন্তর্ভুক্ত করা যায়।

জেনারেল অ্যালগরিদম

  1. আপনার স্তরের সমর্থন করতে 2 ডি অ্যারে বা চিত্র ব্যবহার করে পর্যাপ্ত আকারের একটি পরিমাণযুক্ত তল গ্রিড তৈরি করুন।

  2. এই ফাঁকা তল স্থান জুড়ে এলোমেলোভাবে স্ক্যাটার পয়েন্টস। এটি প্রতিটি পয়েন্টে একটি পয়েন্ট পাওয়া যায় কিনা তা দেখতে আপনি সরল এলোমেলো চেক ব্যবহার করতে পারেন, বা স্ক্যাটার পয়েন্টগুলিতে স্ট্যান্ডার্ড / গাউসীয় বিতরণ ব্যবহার করতে পারেন। প্রতিটি এবং প্রতিটি বিন্দুর জন্য একটি অনন্য রঙ / সংখ্যাসূচক মান নির্ধারণ করুন। এগুলি আইডি। (পিএস যদি এই পদক্ষেপের পরে আপনি মনে করেন যে আপনার স্থানটি সমস্ত উপায়ে বাড়িয়ে তোলা দরকার, তাই করুন))

  3. প্রতিটি যেমন উত্পন্ন পয়েন্টের জন্য, ক্রমানুসারে, অতিরিক্ত হিসাবে সীমা বৃত্ত হত্তয়া বা সীমা একটি একক পদক্ষেপ (সাধারণত 0.5-1.0 কোষ পদক্ষেপ প্রতি / পিক্সেল রেট) দ্বারা আউট আয়তক্ষেত্র xএবং y। আপনি হয় একই ধাপে আকারের শূন্য থেকে শুরু করে সমান্তরালভাবে সমস্ত সীমানা বৃদ্ধি করতে পারেন, বা আপনি বিভিন্ন সময়ে এবং বিভিন্ন হারে তাদের বাড়ানো শুরু করতে পারেন, যেগুলি শুরু হয় তাদের আকারকে পক্ষপাত প্রদান করে (চারা বাড়ার কল্পনা করুন, যেখানে কিছু দেরীতে শুরু)। "বৃদ্ধি" বলতে আমার অর্থ সীমাবদ্ধতার জন্য প্রারম্ভিক পয়েন্টের সাথে রঙ / আইডিটির সাথে সদ্য-বর্ধিত সীমাগুলি পূরণ করুন। এর রূপকটিতে কাগজের টুকরোটির পিছনে মার্কার কলম ধারণ করা হবে এবং তারা মিলিত হওয়া অবধি বিভিন্ন বর্ণের কালি ব্লকগুলি বৃদ্ধি পেতে দেখবে।

  4. এক পর্যায়ে কিছু বিন্দুর সীমা এবং অন্য একটি বিন্দু সংঘর্ষে চলেছে, বৃদ্ধির পদক্ষেপের সময়। এটি সেই বিন্দু যেখানে আপনার সেই দুটি পয়েন্টের সীমানা বাড়ানো বন্ধ করা উচিত - অন্তত ৩ য় ধাপে বর্ণিত অভিন্ন অর্থে।

  5. একবার আপনি যতদূর সম্ভব সমস্ত পয়েন্টের সীমানা বাড়িয়ে নিলেন এবং সমস্ত বৃদ্ধির প্রক্রিয়া বন্ধ করে দেবেন, আপনার কাছে এমন একটি মানচিত্র থাকবে যা বেশিরভাগ ক্ষেত্রে হওয়া উচিত, তবে সম্পূর্ণরূপে ভরাট হবে না। আপনি এখন সেই শূন্য স্থানটি প্যাক আপ করতে চাইতে পারেন, যা আমি সাদা বলে ধরে নেব, যেন কাগজের কোনও শীটে রঙ করা হয়।

প্রক্রিয়া-পরবর্তী স্থান-ফিলিং

ধাপ ৫ অনুযায়ী প্রতি শূন্য / শূন্যস্থান পূরণ করতে বিভিন্ন কৌশল ব্যবহার করা যেতে পারে:

  • একটি একক প্রতিবেশী, ইতিমধ্যে বর্ণযুক্ত অঞ্চলটি জায়গাটি দাবি করুন, বন্যার মাধ্যমে সেই রঙটি পূরণ করুন যাতে এটি সমস্ত অংশে যোগ দেয়।
  • নতুন, এখনও-অব্যবহৃত রং / নম্বর / আইডি সহ বন্যা যেমন তারা সম্পূর্ণ নতুন অঞ্চল গঠন করে।
  • রাউন্ড রবিন এমনভাবে পৌঁছায় যে প্রতি ইতিমধ্যে ভরা প্রতিবেশী অঞ্চলটি খালি জায়গায় সামান্য কিছুটা "বৃদ্ধি" করে। কোনও জলের গর্তের আশপাশে প্রাণীদের পান করার কথা ভাবুন: তারা সকলেই কিছুটা জল পান।
  • খালি জায়গাটি পুরোপুরি পূরণ করবেন না, সরাসরি উত্তরণগুলি ব্যবহার করে বিদ্যমান অঞ্চলগুলিকে সংযুক্ত করতে কেবল এটি অতিক্রম করুন।

ব্যাকুলতা

জিনিসগুলিকে আরও জৈবিক দেখানোর চূড়ান্ত পদক্ষেপ হিসাবে, আপনি বিভিন্ন প্রান্তে বিভিন্ন প্রান্তে প্রান্ত-ব্যঙ্গাত্মক করতে পারেন। গুরুত্বপূর্ণ গতিময় চলমান রুটগুলি অবরুদ্ধ না করার বিষয়ে নিশ্চিত হন।

তত্ত্ব, আগ্রহের জন্য

এটি ভোরোনাই ডায়াগ্রাম / ডেলাউন ট্রায়াঙ্গুলেশনে গৃহীত পদ্ধতির অনুরূপ , উপরের অংশে আপনি স্পষ্টভাবে প্রান্ত তৈরি করছেন না - পরিবর্তে, যখন সীমাবদ্ধ অঞ্চলগুলি সংঘর্ষিত হয়, বৃদ্ধি বন্ধ হয়ে যায়। আপনি লক্ষ্য করবেন যে ভোরোনাই ডায়াগ্রামগুলি স্থান পূরণ করছে; এটি কারণ কেবলমাত্র স্পর্শ করেই নয়, বরং কিছুটা ওভারল্যাপের নামমাত্র ডিগ্রি নিয়ে তারা বৃদ্ধি বন্ধ করে না। আপনি অনুরূপ চেষ্টা করতে পারে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.