ক্ষুধা গেমিং - খাওয়া বা মরা


60

ক্ষুধা গেমিং - খাওয়া বা মরা

যদি না খায় তবে আপনি মারা যান। যদি আপনি খান তবে আপনি বেঁচে থাকুন (মারা যাওয়া অবধি) তুমি করবে মরা, তাই গত মরা করার চেষ্টা করুন।

সংক্ষিপ্ত বিবরণ

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

কিভাবে খেলতে হবে

আপনার প্যাকটি পরিচালনা করতে একটি কমান্ড লাইন প্রোগ্রাম তৈরি করুন এবং জমা দিন। এটি STDIN- এ নিয়ন্ত্রণ প্রোগ্রামের থেকে রাজ্য সম্পর্কিত তথ্য এবং STDOUT- এ আউটপুট কমান্ড প্রাপ্ত করবে। ফর্ম্যাটটি নীচে বিস্তারিতভাবে বর্ণিত হয়েছে। প্রতিটি প্রোগ্রাম কেবল একবার কার্যকর করা হবে এবং এটির প্যাক সদস্যদের জীবিত না হওয়া পর্যন্ত চলতে থাকবে। ইনপুটটি আসার সাথে সাথে আপনাকে পড়তে হবে এবং দ্রুত প্রতিক্রিয়া জানাতে হবে। প্রতিটি প্রতিক্রিয়া জন্য 200 মিমি একটি কঠোর সময়সীমা আছে। যদি আপনি ততক্ষণে প্রতিক্রিয়া না জানান তবে আপনার প্যাকটি বর্তমান টার্নের জন্য নতুন নির্দেশাবলী গ্রহণ করবে না।

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

টুর্নামেন্ট একটি bit৪ বিট লিনাক্স সিস্টেমে অনুষ্ঠিত হবে। কোনও প্রয়োজনীয় দিকনির্দেশ দেওয়ার সময় এটি মনে রাখবেন।

বিস্তারিত

  • প্রতিটি প্রাণীর অবস্থান এবং দিক যথাক্রমে doubleতাদের xএবং yস্থানাঙ্কের প্রতিনিধিত্ব করে ডাবল-স্পষ্টতা ভাসমান পয়েন্ট সংখ্যাগুলির এক জোড়া আকারে (যেমন ) ।

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

  • দ্বীপটি একটি বর্গাকার, একপাশে 500 ইউনিট। আপনি যদি এই সীমানা ছাড়িয়ে যেতে চেষ্টা করেন তবে আপনাকে প্রান্তে আটকে দেওয়া হবে। উত্সটি ডানদিকে বৃদ্ধি এবং নীচের দিকে বৃদ্ধি {0,0}সহ ওপরে-বামে রয়েছে । আবার, মানচিত্রটি মোড়ানো হয় নাxy

  • গেমটি 1500 + (প্যাককাউন্ট * 50) শিকারী প্রাণী দিয়ে শুরু হয়। তারা দ্বীপের কেন্দ্রে জড়ো হবে তবে দ্রুত চলন্ত শুরু করার সিদ্ধান্ত নিন।

  • পরিধিগুলির চারপাশে সমানভাবে ব্যবধানযুক্ত বৃত্তে প্যাকগুলি সাজানো হবে। প্যাকের অর্ডারটি বদলানো হয়েছে, সুতরাং কোনও নির্দিষ্ট স্থানে শুরু করার বিষয়টি গণনা করবেন না।

  • শিকারী প্রাণী 30 ইউনিটের ব্যাসার্ধের মধ্যে অন্যান্য সমস্ত প্রাণী দেখতে পাবে । তারা প্রতি ঘুরে সর্বোচ্চ .0.০ ইউনিট স্থানান্তর করতে পারে ।

  • শিকারিরা 50 টি ইউনিটের ব্যাসার্ধের মধ্যে অন্যান্য সমস্ত প্রাণী দেখতে পায় তারা প্রতি ঘুরে সর্বাধিক 6.1 ইউনিটে স্থানান্তর করতে পারে । এর অর্থ তারা দেখার আগে তারা শিকার দেখতে পায় এবং (সবে) তাদের ছাড়িয়ে যায়।

  • শিকারীরা তাদের ক্ষুধার্ত স্তর অনুযায়ী বাস করে এবং মারা যায় । এটি 1000 থেকে শুরু হয় এবং প্রতিটি পালা করে একটিতে কমে যায়। যদি চলাফেরার পরে কোনও শিকারী শিকারের 1 ইউনিটের মধ্যে থাকে তবে এটি স্বয়ংক্রিয়ভাবে এটি খেয়ে ফেলবে। এটি শিকারটিকে সরিয়ে দেয় এবং শিকারীর ক্ষুধার্ত 1000 করে দেয় Each প্রতিটি শিকারী প্রতি ঘুরে কেবল একটি শিকার খেতে পারে। সীমার মধ্যে যদি একের বেশি থাকে তবে লুপটি প্রথমে যেটি পায় তা খাবে (অগত্যা নিকটতম নয়)। একটি শিকারী মারা যায় যদি এর ক্ষুধা শূন্যে পৌঁছে যায়।

  • প্যাকগুলি প্রতিটি পাঁচ জন সদস্য দিয়ে শুরু হয় । প্রতি 5000 টি মোড়ে, গেমটিতে থাকা সমস্ত প্যাকগুলি একজন নতুন সদস্যকে উত্সাহিত করবে। এটি কোনও ফেলো প্যাক সদস্যের দৃশ্যমান সীমার মধ্যে স্থাপন করা হবে। আপনার এন্ট্রিগুলি পাঁচজনের বেশি সদস্যকে পরিচালনা করতে পারে তা নিশ্চিত করুন।

  • প্রতি 1000 টার্নে আরও শিকারের জন্ম হবে। নতুন শিকারের সংখ্যা জীবিত শিকারীর সংখ্যা বিয়োগ এক হবে।

  • শিকারিরা অন্য শিকারীদের আক্রমণ করতে পারে না। তারা ধরা পড়লে শিকার খায়। এটাই.

  • একটি ঘুরার মধ্যে অর্ডারটি হ'ল:

    • সমস্ত শিকার সিদ্ধান্ত নেয়
    • সমস্ত শিকারি সিদ্ধান্ত নেয়
    • সব শিকারে চলা
    • সমস্ত শিকারী সরানো / খাওয়া
  • প্রতিটি প্যাক তাদের সিদ্ধান্ত / পদক্ষেপে যে ক্রমটি করে সেগুলি প্রতিটি বারে এলোমেলো হয়ে যাবে।

প্রোটোকল (সাধারণ)

সমস্ত যোগাযোগ স্ট্রিং ফর্ম্যাটে সম্পন্ন হয় US-ASCII। নম্বরগুলি জাভা Double.toString()বা ব্যবহার করে স্ট্রিংয়ে রূপান্তরিত হয় Integer.toString()। আপনার আউটপুটটি অবশ্যই ফর্ম্যাট করা উচিত যাতে এটি জাভা দ্বারা পড়তে পারে Double.valueOf(String)(আপনি পূর্বে পূর্ণসংখ্যা হবে না)। পার্সেবল ফর্ম্যাটগুলির বিশদগুলির জন্য, এর জন্য ডকুমেন্টেশনDouble দেখুন । একটি লাইনের সমস্ত ক্ষেত্রগুলি স্ট্যান্ডার্ড \tঅক্ষর দ্বারা পৃথক করা হয় , এবং নিউলাইনগুলি হয় \n। পুরো স্ট্রিংটি বাতিল হয়ে যাবে ull\0

নীচের উদাহরণগুলিতে, আমি ব্যবহার করছি <> পঠনযোগ্যতার জন্য ক্ষেত্রগুলি চিহ্নিত করতে । এগুলি প্রকৃত স্ট্রিংগুলিতে উপস্থিত নেই।

প্রোটোকল (ইনপুট)

আপনার প্যাকটিতে কতটি প্রাণী দৃশ্যমান তা নির্ভর করে ইনপুট স্ট্রিংটির দৈর্ঘ্য পরিবর্তিত হয়। এটি 100k অক্ষর ছাড়িয়ে যেতে পারে, সুতরাং এর জন্য প্রস্তুত থাকুন। প্রাথমিক সেটআপটি হ'ল:

  • লাইন 0: গেম সম্পর্কে প্রাথমিক তথ্য turnবর্তমান টার্ন সংখ্যা, এবং গণনাগুলি মাঠে ফেলে রাখা মোট শিকার এবং শিকারী সংখ্যা। এগুলি integerস্ট্রিং আকারে।

    <turn>\t<preyCount>\t<predatorCount>\n
    
  • লাইন 1: আপনার প্যাক সদস্যদের অনন্য আইডি এবং ক্ষুধার মাত্রা। এগুলি প্রতিটি ইনপুটগুলির জন্য একই ক্রমে দেওয়া হয় না । প্রতিটি সদস্যের, ট্র্যাকের অনন্য আইডি ব্যবহার করুন না যে ক্রমে তারা ইনপুট প্রদর্শিত হয়। আবার, এই integerস্ট্রিং হিসাবে হয়। দুটি প্যাকের জন্য, এটি হবে:

    <id[0]>\t<hunger[0]>\t<id[1]>\t<hunger[1]>\n
    
  • লাইন 2: আপনার প্যাক সদস্যের অবস্থানগুলি, একই ক্রমে 1 লাইনতে দেওয়া হয়েছে । এগুলি doubleস্ট্রিং হিসাবে রয়েছে:

    <x[0]>\t<y[0]>\t<x[1]>\t<y[1]>\n
    

নিম্নলিখিত লাইনগুলি প্রতিটি প্যাক সদস্যের দৃশ্যমানতা, লাইন 1 তে প্রদত্ত একই ক্রমে । এগুলি সদস্য হিসাবে দুটি লাইন হিসাবে দেওয়া হবে।

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

প্রতিটি জীবিত সদস্যের জন্য:

<prey[0].x>\t<prey[0].y>\t<prey[1].x>\t<prey[1].y>\n
<predator[0].x>\t<predator[0].y>\t<predator[1].x>\t<predator[1].y>\n

পরিশেষে, শেষ চরিত্রটি হবে \0পরবর্তী লাইনের শুরুতে।

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

প্রোটোকল (আউটপুট)

আউটপুট সহজ। আপনি doubleপ্রতিটি লাইভ প্যাক সদস্যের জন্য এক জোড়া মান দেবেন। এগুলি আপনি যে পরিবর্তনটি চান তা এই আন্দোলনের প্রতিনিধিত্ব করে। উদাহরণস্বরূপ, যদি আপনার প্রাণীটি বর্তমানে উপস্থিত থাকে {100.0, 100.0}এবং আপনি তাদের একটি আদেশ দেন তবে {-1.0, 1.0}তারা সেখানে চলে যাবে {99.0, 101.0}। সমস্ত সংখ্যা একক লাইনে থাকবে, ট্যাব দ্বারা পৃথক করা।

উদাহরণস্বরূপ, যদি আপনার 3 প্যাক সদস্য জীবিত থাকে তবে এটি একটি কার্যকর প্রতিক্রিয়া হবে:

1.0\t-1.0\t2.0\t-2.0\t3.0\t-3.0\0

এই করে আপনার প্রাণীকে সরাতে হবে {1.0,-1.0}, {2.0,-2.0}এবং {3.0,-3.0}। অর্ডারটি ইনপুটটিতে প্রাপ্ত হিসাবে একই। শেষ ভুলবেন না \0!

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

সমস্ত দিকটি 6.1 ইউনিটের সর্বোচ্চ দূরত্বে আবদ্ধ হবে। আপনি চাইলে এর চেয়ে ধীরে ধীরে চলতে পারেন। উদাহরণস্বরূপ, {1, 0}আপনাকে একটি ইউনিট স্থানান্তরিত করবে। {6,8}(দূরত্ব 10) কেবল আপনাকে 6.1 ইউনিট স্থানান্তরিত করবে এবং প্রায় কমে যাবে {3.66, 4.88}। দিকটি স্থির থাকে।

গুরুত্বপূর্ণ: নিয়ন্ত্রণ প্রোগ্রামটি আপনার STDOUT এবং STDOUT STDERR পড়বে। আপনি যদি একটি ব্যতিক্রম ছুঁড়ে ফেলে এবং এসটিডিআরআরতে মুদ্রণ করেন তবে এই বার্তাটি একটি বৈধ প্রতিক্রিয়ার আকারে আসার খুব সম্ভাবনা নেই। এটি এড়াতে চেষ্টা করুন।

নিয়ন্ত্রণ প্রোগ্রাম / পরীক্ষা

নিয়ন্ত্রকের জন্য উত্সটি এখানে বিটবুকিট.আরজে পাওয়া যাবে । দৌড়ানোর আগে আপনার এটি সংকলন করতে হবে। মূল ক্লাসটি Gameএবং সমস্ত ক্লাস ডিফল্ট প্যাকেজে থাকে। চালানোর জন্য, প্রতিটি প্যাকের কমান্ডকে পৃথক যুক্তি হিসাবে অন্তর্ভুক্ত করুন। উদাহরণস্বরূপ, আপনি যদি জাভা চ্যাসারপ্যাক এবং পাইথন লাজিপ্যাক.পি চালাতে চান তবে আপনি এটি ব্যবহার করতে পারেন:

java Game "java ChaserPack" "python LazyPack.py"

মানচিত্রে শিকার সবুজ রঙে এবং শিকারি লাল রঙে উপস্থিত হয়। তবে যে কোনও প্যাকটিই প্রথম আর্গুমেন্ট হিসাবে দেওয়া প্যাকটি তার পরিবর্তে নীল রঙের হবে। এটি পরীক্ষার উদ্দেশ্যে তাদের আরও সহজে পার্থক্য করার উদ্দেশ্যে। শিকারীরা যখন তারা খাবে তখন পাঁচটি ফ্রেমের জন্য সাদা ফ্ল্যাশ করবে।

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

java Game -silent "java ChaserCat" "./someOtherPack"

নামযুক্ত একটি কঙ্কাল জাভা প্যাক অন্তর্ভুক্ত GenericPack । এটিতে প্রয়োজনীয় ইনপুট / আউটপুট ক্রিয়াকলাপ অন্তর্ভুক্ত রয়েছে। কীভাবে পার্স করবেন এবং জবাব দেবেন তার একটি পরিষ্কার উদাহরণ দেওয়া আছে। আপনি যদি অন্য ভাষায় কোনও টেম্পলেট যুক্ত করতে চান তবে আমাকে জানান।

এছাড়াও অন্তর্ভুক্ত হ'ল টেমপ্লেট উপর ভিত্তি করে একটি শিকারী ChaserPack,। এটি টুর্নামেন্টে অন্তর্ভুক্ত করা হবে না এবং এটি কেবল পরীক্ষার উদ্দেশ্যে অন্তর্ভুক্ত রয়েছে। ইচ্ছাকৃত লক্ষ্যবস্তু ত্রুটির কারণে এটি বেশ খারাপভাবে সম্পাদন করে। যদি আপনি এটি মারতে না পারেন তবে চেষ্টা চালিয়ে যান।

নীচে নিয়ন্ত্রণ প্রোগ্রাম চালানোর একটি উদাহরণ দেওয়া আছে (ভিডিওর জন্য ক্লিক করুন)। ভিডিওর মানটি দুর্দান্ত নয় (দুঃখিত) তবে আপনি কীভাবে শিকারটি চলেছেন সে সম্পর্কে আপনি একটি অনুভূতি পেতে পারেন। ( সাবধানতা: অডিও )

স্ক্রিনশট

স্কোরিং

প্রতিটি রাউন্ডে পয়েন্ট অর্জন করে টুর্নামেন্ট দ্বারা বিজয়ী নির্ধারিত হবে।

সমস্ত শিকারী মারা না যাওয়া পর্যন্ত প্রতিটি রাউন্ড এগিয়ে যায়। প্রতিটি প্যাক তার শেষ সদস্য অনাহারে মারা গেলে তার উপর ভিত্তি করে স্কোর করা হবে। তাদের পরে আদেশের ভিত্তিতে পয়েন্টগুলি বরাদ্দ করা হবে। পয়েন্ট দশ রাউন্ডের জন্য জমা হবে এবং বিজয়ী সর্বোচ্চ পয়েন্ট সহ প্যাক।

প্রতিটি রাউন্ডের জন্য প্রথম স্থানটি 100 পয়েন্ট পাবেন। তার পরে প্রতিটি জায়গার জন্য, পুরষ্কারটি 20% (গোলাকৃত) দ্বারা হ্রাস পাবে। পয়েন্টগুলি শূন্যে পৌঁছানো অবধি এটি চলতে থাকবে (17 তম স্থানের পরে)। 18+ স্থানগুলি রাউন্ডের জন্য কোনও পয়েন্ট পাবেন না। যারা প্যাকগুলি টাই করবে তারা সমান পয়েন্ট পাবে। উদাহরণ স্বরূপ:

1st : 100
2nd : 80
3rd : 64 (T)
3rd : 64 (T)
4th : 51
...
17th: 1
18th: 0
19th: 0

টুর্নামেন্ট চলাকালীন সর্বোচ্চ সম্ভাব্য পয়েন্টগুলি প্রথম স্থান থেকে সমস্ত দশ বার ten

যদি একাধিক প্রোগ্রাম টুর্নামেন্টটি প্রথম স্থানের সাথে শেষ করে, তবে কেবলমাত্র প্রথম স্থানের প্রবেশপত্র জমা দিয়ে আরও দশটি রাউন্ড টুর্নামেন্ট অনুষ্ঠিত হবে । একজন বিজয়ী না হওয়া পর্যন্ত এটি অব্যাহত থাকবে।

আমি প্রায় প্রতি সপ্তাহে টুর্নামেন্ট চালানোর চেষ্টা করব বা নতুন সাবমিশন আসার সাথে সাথেই চেষ্টা করব।

অতিরিক্ত নিয়ম (মেলা খেলুন!)

  • আপনি কোনও বাহ্যিক সংস্থান পড়তে বা লিখতে নাও পারেন। যেহেতু আপনি আপনার প্রোগ্রামটি বহুত্ববৃত্ত সময়ে বার করতে চান না, তাই কোনও রাজ্যের তথ্য অভ্যন্তরীণভাবে সংরক্ষণ করা যেতে পারে।

  • অন্যান্য প্রক্রিয়া / জমা দেওয়ার ক্ষেত্রে হস্তক্ষেপ করবেন না। এর অর্থ এই নয় যে তাদের শিকার চুরি করার চেষ্টা করবেন না, তাদের ছাড়িয়ে যান, ইত্যাদি etc. এটি আমার বিবেচনার ভিত্তিতে।

  • প্রতিযোগীরা সর্বোচ্চ তিনটি প্রবেশের মধ্যে সীমাবদ্ধ । আপনি যদি আরও জমা দেন তবে আমি জমা দেওয়া প্রথম তিনটিই স্কোর করব। আপনি যদি কোনওটি প্রত্যাহার করতে চান তবে এটি মুছুন।

  • এন্ট্রিগুলি কেবলমাত্র অন্য এন্ট্রিগুলিকে সমর্থন করার জন্য উপস্থিত থাকতে পারে। প্রত্যেকের নিজস্ব মেধা অর্জন করার জন্য খেলতে হবে।

  • আপনার প্রোগ্রামটি একসাথে সর্বোচ্চ একটি শিশু প্রক্রিয়া উত্সাহিত করতে পারে ( মোট বংশধর, সরাসরি নয়)। যে কোনও উপায়ে, আপনি সময়সীমা অতিক্রম করবেন না তা নিশ্চিত করুন। আপনি কোনওভাবেই Gameক্লাসটি চালাবেন না।

ফলাফল - 29 এপ্রিল 2014

সর্বশেষ দশ রাউন্ডের টুর্নামেন্টের ফলাফল এখানে:

Clairvoyant         : 1000
EcoCamels           : 752
Netcats             : 688
RubySpiders         : 436
RubyVultures        : 431
CivilizedBeasts     : 382
LazyPack            : 257

09:00 EDT 2014/04/29 এর আগে জমা দেওয়া প্যাকগুলি এই রানের অন্তর্ভুক্ত।

আপনি প্রতিটি রাউন্ডের জন্য বিশদটি দেখতে পারেন । কোনও কারণে আমি রাউন্ডগুলি পিছনের দিকে সংখ্যা নির্ধারণ করার সিদ্ধান্ত নিয়েছি, সুতরাং এটি "রাউন্ড 10" দিয়ে শুরু হয়।

আপডেট

2014/04/23 : এফগ্রিগ সময়সীমা সম্পর্কিত একটি বাগ রিপোর্ট করেছে (ধন্যবাদ!) একটি স্থিরকরণ কার্যকর করা হয়েছে, সুতরাং পরীক্ষকরা তাদের নিয়ন্ত্রণ প্রোগ্রামের কোডটি আপডেট করতে চান।


28
আমি এই রাজাদের প্রশ্ন পছন্দ করছি!
ক্রুঙ্কার

2
@ মানু আমি উইন্ডোজ on-তে উদাহরণস্বরূপ বট লিখেছি এবং জিত এবং লিনাক্স উভয় ক্ষেত্রেই পরীক্ষা করেছি। তাদের সাথে আপনার কোন সমস্যা হচ্ছে?
জিওবিটস

2
এই পাহাড়ী প্রশ্নগুলির রাজা বেশ দুর্দান্ত, এবং এটি অবশ্যই আকর্ষণীয়। আমি এখন কাজ দুটি ভিন্ন প্যাক পেয়েছি!
mackthehobbit

2
@ Githubphagocyte আমি প্রথম টাইমআউটটিতে একটি প্যাকটি বন্ধ করতে চাই না, কেবল কারণ আমি প্রতি 40 কে + টার্ন বা অনুরূপ একই সময়ে এমনকি সাধারণ প্রোগ্রামগুলিও সময় বের করে দেখেছি। আমি নিয়ামক নামকরণ পরিবর্তন প্রতিশ্রুতিবদ্ধ। টার্নগুলি এখন পুরো প্রোগ্রাম জুড়ে টার্ন হিসাবে পরিচিত, যদি আমি কোথাও একটি মিস না করি।
জিওবিটস

2
@ জিওবিটস এহ, এটি আমার দ্বারা ভাল। আপনি জানেন, এটি আমার মতো পদার্থবিজ্ঞানের একজন অধ্যাপক করছেন এমন একটি গবেষণা প্রকল্পের সাথে দেখতে সত্যিই অনুরূপ, যা আমি গ্রীষ্মে সাহায্য করতে পারি। আমি পরে যদি কিছু করতে পারি তবে সে সম্পর্কে কিছুটা ব্যাখ্যা করব।
krs013

উত্তর:


10

অলোকদৃষ্টিসংপন্ন ব্যক্তি

AbleDogs এর মুখোমুখি হতে কোড আপডেট হয়েছে

হু! শেষ পর্যন্ত সেই নেটকেটস মার! ভবিষ্যতের ভবিষ্যদ্বাণীমূলক প্যাকটি তৈরি করতে আমি কিছু ছোট পরিবর্তন করে বিদ্যমান কোডটি (জিওবিটগুলিতে ক্রেডিট!) প্রসারিত করেছি। শিকারীরা কোথায় চলে যাবে জানে এমন শিকারীদের কিছুই মারছে না!

আমি যে দুটি পরীক্ষা করেছি তা থেকে আমার প্যাকটি সর্বদা নেটক্যাটসের বিপক্ষে জিতেছিল। তবে অন্য কোনও প্যাক না থাকলে এটি ততটা ভাল পারফর্ম করবে না, আশেপাশে আরও অনেক প্রে রয়েছে তবে ভবিষ্যদ্বাণীটি এখনও ব্যর্থ হয়।

প্রথম কয়েক হাজার টার্ন চলাকালীন আমি সম্ভবত সিভিলাইজড বিস্টের কৌতুক শিকারের সংখ্যা উল্লেখযোগ্যভাবে হ্রাস করতে পারি।

5.21 মিনিটে শেষ হয়েছে
ক্লেয়ারভাইয়ান্ট (1): টার্ন 9270: স্কোর 100
ইকো ক্যামেল.পিএল (3): 8118: 80 স্কোর করুন
নেটক্যাটস (0): 6111 ঘুরুন: স্কোর 64
রুবিভলচারস.আরবি (5): টার্ন 4249: স্কোর 51
রুবিস্পাইডার্স.আরবি (4): টার্ন 3495: স্কোর 40
সভ্যতাভিত্তিগুলি (2): টার্ন 3176: স্কোর 32
চ্যাজারপ্যাক (6): 2492 করুন: স্কোর 25

আমার প্যাকের নাম থেকে আপনার জানা উচিত যে আমি কী কৌশল = D ব্যবহার করি

সম্পাদনা করুন :

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

আমি গণনা করেছি যে প্রতিটি প্যাকটি কয়টি প্রেটি খায় এবং ফলাফল এখানে:

ক্লেয়ারভাইয়ান্ট (1) 9270 টার্নগুলিতে 916 প্রে সেবন করেছে (0.099 প্রে / টার্ন)
ইকো ক্যামেল.পিএল (3) 8118 টার্নে (০.০০৯ প্রে / টার্ন) 73৩ টি প্রে সেবন করেছে
নেটক্যাটস (0) 6111 টার্নগুলিতে 563 প্রি সেবন করেছে (0.092 প্রে / টার্ন)
রুবিভলচারস.আরবি (5) 4249 টার্নে (০.০১৮ প্রে / টার্ন) 77 77 টি প্রি সেবন করেছে
রুবিস্পাইডার্স.আরবি (4) 3495 টার্নে (২৯.০৮৮ প্রে / টার্ন) 293 প্রি সেবন করেছে
সিভিলাইজড বিস্টস (২) ৩১76 turns টার্নে ১০ টি প্রে (গ্রাহক (0.003 প্রে / টার্ন) গ্রাস করেছে
চেসারপ্যাক (6) 2492 টার্নে (৪.০১17 প্রে / টার্ন) 43 টি প্রে সেবন করেছে

আমার প্যাকটি অত্যন্ত আক্রমণাত্মক এবং 916 গুনের বেশিরভাগ অংশ আমার মনে হয় এটি রুবিস্পাইডার্সের মতো নেটক্যাটসের কাছ থেকে শিকারের চুরি থেকে আসে।

ইকো ক্যামেল থেকে কেন্দ্রের উটের কারণে দুর্ভাগ্যক্রমে সভ্যতাবিদগুলি হারাচ্ছে।

এবং ইকো ক্যামেল (ক্ষুধা সমালোচনামূলক 500) সহ বেশ দক্ষ, এটি শেষ পর্যন্ত টিকে থাকার জন্য যথেষ্ট পরিমাণে খায়।

এছাড়াও এই আপডেট হওয়া ক্লেয়ারভাইয়ান্ট সহ, খেলাটি সবেমাত্র 10,000 টি পালাতে পৌঁছে।

কোড:

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.TreeSet;

public class Clairvoyant extends GenericPack {
    private static final double MAX_SPEED = 6.1;

    private TreeSet<Animal> foods = new TreeSet<Animal>(new AnimalComparator());
    private TreeSet<Animal> predators = new TreeSet<Animal>(new AnimalComparator());

    private XY abattoirCorner;
    private double abattoirRadius = 100;

    private MyMember[] myMembers = new MyMember[100];

    public class AnimalComparator implements Comparator<Animal>{

        @Override
        public int compare(Animal arg0, Animal arg1) {
            if(arg0.x < arg1.x){
                return -1;
            } else if (arg0.x > arg1.x){
                return 1;
            } else {
                if(arg0.y < arg1.y){
                    return -1;
                } else if(arg0.y > arg1.y){
                    return 1;
                } else {
                    return 0;
                }
            }
        }
    }

    public class MyMember extends Member{
        public XY target;
        public XY herdPos;
        public double herdRadius; 
        public boolean mayEat;
        public XY pos;
        public ArrayList<MyAnimal> closestPreys;
        public boolean outdated;

        public MyMember(int id) {
            super(id);
            this.pos = new XY(x, y);
            closestPreys = new ArrayList<MyAnimal>();
            mayEat = true;
            outdated = true;
        }

        public MyMember(Member member){
            super(member.id);
            this.pos = new XY(x, y);
            closestPreys = new ArrayList<MyAnimal>();
            mayEat = true;
            outdated = true;
        }

        public MyMember(Member member, Animal target){
            super(member.id);
            this.target = new XY(target.x, target.y);
            this.pos = new XY(x, y);
            closestPreys = new ArrayList<MyAnimal>();
            mayEat = true;
            outdated = true;
        }

        public void reset(Member me){
            x = me.x;
            y = me.y;
            pos = new XY(x, y);
            closestPreys.clear();
            mayEat = true;
            outdated = true;
        }
    }

    public class MyAnimal extends Animal{
        public ArrayList<MyMember> chasers;
        public XY pos;
        public boolean resolved;

        public MyAnimal(double x, double y){
            super(x, y);
            pos = new XY(x, y);
            chasers = new ArrayList<MyMember>();
            resolved = false;
        }

        public MyAnimal(Animal ani){
            super(ani.x, ani.y);
            pos = new XY(x, y);
            chasers = new ArrayList<MyMember>();
            resolved = false;
        }
    }

    public static void main(String[] args){
        new Clairvoyant().run();
    }

    public Clairvoyant(){
        for(int i=0; i<100; i++){
            nextIdx[i] = 0;
        }
        int cornerIdx = (int)Math.floor(Math.random()*4);
        switch (cornerIdx){
        case 0: abattoirCorner = new XY(0,0); break;
        case 1: abattoirCorner = new XY(500,0); break;
        case 2: abattoirCorner = new XY(500,500); break;
        case 3: abattoirCorner = new XY(0,500); break;
        }
    }

    @Override
    public void respond(){
        updateData();
        goToTarget();
    }

    private void updateData(){
        for(int i=0; i<100; i++){
            if(myMembers[i]!=null){
                myMembers[i].pos = null;
            }
        }
        foods.clear();
        predators.clear();
        for(Member me: members){
            foods.addAll(me.foods);
            predators.addAll(me.others);
            predators.add(new Animal(me.x, me.y));
            if(myMembers[me.id] != null){
                myMembers[me.id].reset(me);
            } else {
                myMembers[me.id] = new MyMember(me);
            }
        }
        for(int i=0; i<100; i++){
            if(myMembers[i]!=null && myMembers[i].pos == null){
                myMembers[i] = null;
            }
        }

        TreeSet<MyAnimal> closestPreys = new TreeSet<MyAnimal>(new AnimalComparator());
        for(int i=0; i<100; i++){
            if (myMembers[i]==null) continue;
            MyMember me = myMembers[i];
            ArrayList<Animal> animals = findClosest(foods, me.pos, members.size());
            boolean first = true;
            for(Animal ani: animals){
                MyAnimal myAni = new MyAnimal(ani);
                if(closestPreys.contains(ani)){
                    myAni = closestPreys.ceiling(myAni);
                } else {
                    closestPreys.add(myAni);
                }
                if(first){
                    myAni.chasers.add(me);
                    first = false;
                }
                me.closestPreys.add(myAni);
            }
        }
        performMatching();
        for(int i=0; i<100; i++){
            if (myMembers[i] == null) continue;
            MyMember me = myMembers[i];
            if(!me.outdated) continue;
            if(me.closestPreys.size() == 0) continue;
            MyAnimal closestPrey = me.closestPreys.get(0);
            if(closestPrey.resolved) continue;
            if(closestPrey.chasers.size() > 1){
                MyMember hungriest = me;
                MyMember closest = me;
                for(MyMember otherMe: closestPrey.chasers){
                    if(sqDist(closestPrey.pos, otherMe) < sqDist(closestPrey.pos, closest)){
                        closest = otherMe;
                    }
                    if(otherMe.hunger < hungriest.hunger){
                        hungriest = otherMe;
                    }
                }
                if(hungriest.hunger > 200){ // Nobody's critically hungry, the closest takes the prey
                    closest.target = closestPrey.pos;
                    closest.mayEat = true;
                    closest.herdPos = abattoirCorner;
                    closest.herdRadius = abattoirRadius;
                    closest.outdated = false;
                } else {
                    if(hungriest == closest){
                        closest.target = closestPrey.pos;
                        closest.mayEat = true;
                        closest.herdPos = abattoirCorner;
                        closest.herdRadius = abattoirRadius;
                        closest.outdated = false;
                    } else {
                        closest.target = closestPrey.pos;
                        closest.mayEat = false;
                        closest.herdPos = hungriest.pos;
                        closest.herdRadius = 0;
                        closest.outdated = false;
                        hungriest.target = closestPrey.pos;
                        hungriest.mayEat = true;
                        hungriest.herdPos = abattoirCorner;
                        hungriest.herdRadius = 10;
                        hungriest.outdated = false;
                    }
                }
                closestPrey.resolved = true;
            } else {
                me.target = closestPrey.pos;
                me.herdPos = abattoirCorner;
                me.herdRadius = abattoirRadius;
                me.mayEat = true;
                me.outdated = false;
            }
        }
        for(int i=0; i<100; i++){
            if (myMembers[i] == null) continue;
            MyMember me = myMembers[i];
            if(me.outdated){
                me.target = null;
                me.outdated = false;
            }
        }
    }

    private void goToTarget(){
        for(Member me: members){
            MyMember mem = myMembers[me.id];
            if(mem.target == null){
                wander(me, 2*(me.id%2)-1);
                continue;
            } else {
                nextIdx[me.id] = 0;
                XY[] nearestHostile = new XY[100];
                for(Animal other: me.others){
                    XY otherPos = new XY(other.x, other.y);
                    boolean isMember = false;
                    for(Member otherMember: members){
                        if(other.x==otherMember.x && other.y==otherMember.y){
                            isMember = true;
                            break;
                        }
                    }
                    if(!isMember){
                        if(nearestHostile[me.id] == null || XY.sqDistance(mem.pos, otherPos) < XY.sqDistance(mem.pos,  nearestHostile[me.id])){
                            nearestHostile[me.id] = otherPos;
                        }
                    }
                }

                // Go towards the target by predicting its next position
                XY target = predictNextPos(mem.target, me);

                me.dx = (target.x - me.x);
                me.dy = (target.y - me.y); 

                // Try to herd the target to our abattoir if this member is not too hungry
                // and if there is no other hostile predator who is closer to the target than us
                // This will make the other hostile predator to keep targeting this target, while
                // it is certain that we will get the target.
                // This is a win situation for us, since it will make the other predator wasting his turn.
                if((me.hunger <= 200 && XY.sqDistance(mem.target, mem.pos) > 400) || me.hunger <= 50 ||
                        (nearestHostile[me.id] != null && Math.sqrt(XY.sqDistance(mem.target, nearestHostile[me.id])) < Math.sqrt(XY.sqDistance(mem.target, mem.pos)))){
                    continue;
                }

                // Don't eat if not threatened nor hungry
                if(me.hunger > 50 && (nearestHostile[me.id] == null ||
                        Math.sqrt(XY.sqDistance(mem.target, nearestHostile[me.id])) > Math.sqrt(XY.sqDistance(mem.target, mem.pos)) + 6)){
                    mem.mayEat = false;
                }

                // Herd to abattoir corner
                double distFromHerd = Math.sqrt(XY.sqDistance(target, mem.herdPos));
                XY oppositeAbattoirCorner = new XY(500-abattoirCorner.x, 500-abattoirCorner.y);
                double distFromOpposite = Math.sqrt(XY.sqDistance(target, oppositeAbattoirCorner));
                if((me.dx*me.dx+me.dy*me.dy > 64 && distFromHerd > mem.herdRadius && distFromOpposite > abattoirRadius)
                        || (preyCount < 5*predCount)){
                    double herdDistance = 4*(distFromHerd-mem.herdRadius)/(Island.SIZE-mem.herdRadius);
                    if(!mem.mayEat) herdDistance = 4;
                    XY gradient = target.minus(abattoirCorner);
                    me.dx += gradient.x*herdDistance/distFromHerd;
                    me.dy += gradient.y*herdDistance/distFromHerd;
                }
            }
        }
    }

    private void performMatching(){
        for(int i=0; i<100; i++){
            if (myMembers[i] == null) continue;
            MyMember me = myMembers[i];
            if(me.closestPreys.size()==0) continue;
            MyAnimal closestPrey = me.closestPreys.get(0);
            if(closestPrey.chasers.size() > 1){
                resolveConflict(closestPrey);
            }
        }
    }

    private void resolveConflict(MyAnimal prey){
        ArrayList<MyMember> chasers = prey.chasers;
        MyMember winner = null;
        double closestDist = Double.MAX_VALUE;
        for(MyMember me: chasers){
            if(sqDist(prey.pos, me) < closestDist){
                closestDist = sqDist(prey.pos, me);
                winner = me;
            }
        }
        for(int i=chasers.size()-1; i>=0; i--){
            MyMember me = chasers.get(i);
            if(me!=winner){
                me.closestPreys.get(0).chasers.remove(me);
                me.closestPreys.add(me.closestPreys.remove(0));
                me.closestPreys.get(0).chasers.add(me);
            }
        }
    }

    private Animal findClosest(Collection<Animal> preys, XY me){
        Animal target = null;
        double cDist = Double.MAX_VALUE;
        double x, y, sqDist;
        for (Animal food : preys) {
            x = food.x - me.x;
            y = food.y - me.y;
            sqDist = x * x + y * y + Double.MIN_NORMAL;
            if (sqDist < cDist) {
                cDist = sqDist;
                target = food;
            }
        }
        return target;
    }

    private ArrayList<Animal> findClosest(Collection<Animal> preys, XY me, int num){
        ArrayList<Animal> result = new ArrayList<Animal>();
        for(Animal food: preys){
            int addIdx = -1;
            for(int i=0; i<num && i<result.size(); i++){
                Animal regFood = result.get(i);
                if(sqDist(me, food) < sqDist(me, regFood)){
                    addIdx = i;
                    break;
                }
            }
            if(addIdx == -1){
                result.add(food);
            } else {
                result.add(addIdx, food);
            }
            if(result.size() > num){
                result.remove(num);
            }
        }
        return result;
    }

    private Member findClosestToTarget(Collection<Member> members, Animal target){
        Member member = null;
        double cDist = Double.MAX_VALUE;
        double x, y, sqDist;
        for (Member me : members) {
            x = me.x - target.x;
            y = me.y - target.y;
            sqDist = x * x + y * y + Double.MIN_NORMAL;
            if (sqDist < cDist) {
                cDist = sqDist;
                member = me;
            }
        }
        return member;
    }

    private static final XY[] CHECKPOINTS = new XY[]{
        new XY(49.5,49.5),
        new XY(450.5,49.5),
        new XY(450.5,100),
        new XY(49.5,100),
        new XY(49.5,150),
        new XY(450.5,150),
        new XY(450.5,200),
        new XY(49.5,200),
        new XY(49.5,250),
        new XY(450.5,250),
        new XY(450.5,300),
        new XY(49.5,300),
        new XY(49.5,350),
        new XY(450.5,350),
        new XY(450.5,400),
        new XY(49.5,400),
        new XY(49.5,450.5),
        new XY(450.5,450.5)};
    private int[] nextIdx = new int[100];

    private int advanceIdx(int idx, int sign, int amount){
        return sign*(((Math.abs(idx)+CHECKPOINTS.length-1+sign*amount) % CHECKPOINTS.length) + 1);
    }

    private void wander(Member me, int sign) {
        if(preyCount > 20*predCount){
            if (me.dx == 0 && me.dy == 0) {
                me.dx = 250 - me.x;
                me.dy = 250 - me.y;
                return;
            }

            double lx, ly, px, py;
            lx = me.dx / 4;
            ly = me.dy / 4;
            boolean dir = Math.random() < 0.5 ? true : false;
            px = dir ? ly : -ly;
            py = dir ? -lx : lx;

            me.dx += px;
            me.dy += py;
        } else {
            if(nextIdx[me.id]==0){
                XY farthest = new XY(2000,2000);
                int farthestIdx = -1;
                for(int i=0; i<CHECKPOINTS.length; i++){
                    if(sign*sqDist(CHECKPOINTS[i], me) > sign*sqDist(farthest, me)){
                        farthest = CHECKPOINTS[i];
                        farthestIdx = i+1;
                    }
                }
                nextIdx[me.id] = farthestIdx*sign;
                for(Member mem: members){
                    if(mem.id == me.id) continue;
                    if(nextIdx[mem.id]==nextIdx[me.id]){
                        nextIdx[me.id] = advanceIdx(nextIdx[me.id], sign, 5); 
                    }
                }
            }
            if(sqDist(CHECKPOINTS[Math.abs(nextIdx[me.id])-1],me) < 1){
                nextIdx[me.id] = advanceIdx(nextIdx[me.id], sign, 1);
            }
            me.setDirection(CHECKPOINTS[Math.abs(nextIdx[me.id])-1].x-me.x,
                    CHECKPOINTS[Math.abs(nextIdx[me.id])-1].y-me.y);
        }
    }

    private double sqDist(XY me, Animal target){
        double dx = me.x-target.x;
        double dy = me.y-target.y;
        return dx*dx + dy*dy + Double.MIN_NORMAL;
    }

    private double sqDist(XY me, Member target){
        double dx = me.x-target.x;
        double dy = me.y-target.y;
        return dx*dx + dy*dy + Double.MIN_NORMAL;
    }

    private double sqDist(Animal target, Member me){
        double dx = me.x-target.x;
        double dy = me.y-target.y;
        return dx*dx + dy*dy + Double.MIN_NORMAL;
    }

    private List<Animal> getNeighbors(double radius, XY pos, Collection<Animal> candidates) {
        List<Animal> neighbors = new ArrayList<Animal>();
        for(Animal neighbor: candidates){
            if(sqDist(pos, neighbor) < radius * radius){
                neighbors.add(neighbor);
            }
        }
        return neighbors;
    }

    final double[] weights = { 1, 1, 0.96, 2, 4 };
    double weightSum;

    static final int ALIGN = 0;
    static final int SEPARATE = 1;
    static final int COHESION = 2;
    static final int FLEE = 3;
    static final int WALL = 4;
    static final int VISIBLE = 30;
    static final int VISIBLE_PRED = 50;

    private HashMap<Member, List<Animal>> prevPreys = new HashMap<Member, List<Animal>>();

    private XY matchPreys(List<Animal> prevs, List<Animal> curs, XY prey){
        XY result = new XY();
        double sqDist = 0;
        Animal candidate;
        XY otherPos;
        for(Animal otherPrey: curs){
            otherPos = new XY(otherPrey.x, otherPrey.y);
            sqDist = XY.sqDistance(prey, otherPos);
            if(sqDist > VISIBLE * VISIBLE)
                continue;
            candidate = findClosest(getNeighbors(6, otherPos, prevs), prey);
            if(candidate == null){
                return null;
            }
            result.add(otherPos.x-candidate.x, otherPos.y-candidate.y);
        }
        return result;
    }

    private XY predictNextPos(XY prey, Member me) {
        List<Animal> preys = getNeighbors(VISIBLE_PRED, prey, foods);
        List<Animal> preds = getNeighbors(VISIBLE, prey, predators);

        XY flock[] = new XY[weights.length];
        for (int i = 0; i < weights.length; i++)
            flock[i] = new XY();

        double dx, dy, dist, sqDist;
        for (Animal otherPrey : preys) {
            sqDist = XY.sqDistance(prey, new XY(otherPrey.x, otherPrey.y));
            if(sqDist > VISIBLE * VISIBLE)
                continue;
            dx = otherPrey.x - prey.x;
            dy = otherPrey.y - prey.y;
            flock[COHESION].add(dx*sqDist, dy*sqDist);
            flock[SEPARATE].add(-dx*(1d/sqDist), -dy*(1d/sqDist));
            flock[ALIGN].add(new XY(prey.x-me.x,prey.y-me.y));
        }

        if(sqDist(prey, me) < 400){
            if(prevPreys.get(me) == null){
                prevPreys.put(me, preys);
            } else {
                XY flockAlign = matchPreys(prevPreys.get(me), preys, prey);
                if(flockAlign == null){
                    prevPreys.put(me , null);
                } else {
                    flock[ALIGN] = flockAlign;
                    prevPreys.put(me, preys);
                }
            }
        }

        flock[ALIGN].unitize().multiply(5);
        flock[COHESION].unitize().multiply(5);
        flock[SEPARATE].unitize().multiply(5);

        for (Animal predator : preds){
            flock[FLEE].add(prey.x-predator.x, prey.y-predator.y);
        }

        dx = Island.CENTER.x - prey.x;
        dy = Island.CENTER.y - prey.y;
        dist = Math.max(Math.abs(dx), Math.abs(dy));
        if(dist > 240){
            flock[WALL].x = dx * dist;
            flock[WALL].y = dy * dist;
            flock[WALL].unitize().multiply(5);
        }

        XY vec = new XY();
        vec.x = 0;
        vec.y = 0;
        for (int i = 0; i < flock.length; i++) {
            flock[i].multiply(weights[i]);
            vec.add(flock[i]);
        }
        limitSpeed(vec);
        return vec.add(prey);
    }

    private XY limitSpeed(XY move) {
        if (move.x*move.x+move.y*move.y > MAX_SPEED*MAX_SPEED)
            move.unitize().multiply(MAX_SPEED);
        return move;
    }
}

1
দেখতে খুব ভাল লাগছে, আপনার খেলাটি আমার খেলার নেটক্যাটগুলির চেয়ে ভাল better তবে আমি এটি ঘৃণা করি যে আমি অন্যান্য শিকারিদের চালাতে পারছি না যেহেতু আমার জানোয়ারগুলি আপনার পরিসংখ্যানগুলিতে সত্যিই খারাপ কাজ করে (যখন অশুভ কামেলটি খুব ভাল কাজ করে)। হয়তো আমাকে পার্ল সংকলক বা আরও কিছু ইনস্টল করার চেষ্টা করতে হবে।
হার্জান

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

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

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

15

Netcats

আপনাকে ছেলেদের শুরু করার জন্য এখানে একটি প্যাক। এটি GenericPackনিয়ন্ত্রণ প্রোগ্রামের সাথে অন্তর্ভুক্ত শ্রেণিটি প্রসারিত করে । এটি আসল পোস্ট করার পরে থেকে উন্নত হয়েছে, এবং আর কোনও বিরল ঝাঁকের সাথে নিজেকে অনাহারে ফেলে।

নেটক্যাটগুলি কোণে শিকারের ফাঁদে ফেলার জন্য ভী আকৃতির নেট গঠন ব্যবহার করে, যেখানে তারা অবসর সময়ে এগুলি খেতে পারে। নেটটি কেন্দ্রের একজন "প্রধান" সদস্য নিয়ে গঠিত হয়। একবার মাথা খাওয়ার পরে, এটি হাংরিয়েস্ট প্যাক সদস্যের সাথে স্থানগুলি অদলবদল করে, যেহেতু মাথাটি সাধারণত খাওয়ার সুযোগ পাওয়া প্রথম হয়।

জালটি ছোট থেকে শুরু হয়, তবে ক্ষেতটি আরও দক্ষতার সাথে ট্রল করার জন্য যখন পশুর ছোট হয়ে যায় তখন প্রশস্ত হয়।

যদি কোনও শিকার দৃশ্যমান না হয় তবে গঠনটি দ্বীপের বেশিরভাগ অংশকে coveringেকে রাখা একটি নির্লজ্জ অনুসন্ধানের ধরণে প্রসারিত হয়।

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

এই সংস্করণ সাদাসিধা দেখা Netcats চেয়ে অনেক ভালো প্রাণে বেঁচে যান ভিডিও প্রশ্নে লিঙ্ক।

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

public class Netcats extends GenericPack {

    boolean seeking;
    Member head = null;
    Set<Animal> foods;

    public static void main(String[] args) {
        new Netcats().run();
    }

    @Override
    public void respond() {
        if (foods == null)
            foods = new HashSet<Animal>();
        else
            foods.clear();
        for (Member member : members)
            foods.addAll(member.foods);

        if (members.size() < 3) {
            soloRun();
        } else {
            head = setHead();
            setHeadVec();
            for (int i = 1; i < members.size(); i++) {
                setMemberVec(i);
            }
        }
    }

    Member setHead() {
        if (!members.contains(head))
            return members.get(0);

        Member hungry = head;
        int idx = 0;
        for (int i = 0; i < members.size(); i++) {
            Member me = members.get(i);
            if (me.hunger < hungry.hunger) {
                hungry = me;
                idx = i;
            }
        }

        if (hungry != head) {
            members.remove(hungry);
            members.remove(head);
            members.add(0, hungry);
            members.add(idx, head);
            return hungry;
        }
        return head;
    }

    void setHeadVec() {
        double x = 0, y = 0;

        Collection<Animal> yummy = getFoods(head);

        seeking = false;
        if (yummy.size() == 0) {
            scoutHead();
            return;
        }

        if (members.size() == 1)
            if (findFood(head))
                return;

        for (Animal food : yummy) {
            x += food.x - head.x;
            y += food.y - head.y;
        }
        x *= 10000000;
        y *= 10000000;

        head.dx = x;
        head.dy = y;
        if (members.size() > 1)
            limitSpeed(head, MAX_SPEED * HEAD_MULT);
    }

    void scoutHead() {
        seeking = true;
        head.dy = 250 - head.y;
        head.dx = round % 80 < 40 ? -head.x : 500 - head.x;
    }

    void setMemberVec(int idx) {
        Member me = members.get(idx);
        Member leader;
        leader = idx < 3 ? members.get(0) : members.get(idx - 2);
        if (findFood(me))
            return;

        double lx, ly, px, py, tx, ty, dist;
        lx = -leader.dx;
        ly = -leader.dy;
        dist = Math.sqrt(lx * lx + ly * ly) + Double.MIN_NORMAL;
        lx /= dist;
        ly /= dist;
        px = idx % 2 == 0 ? ly : -ly;
        py = idx % 2 == 0 ? -lx : lx;

        tx = leader.x + leader.dx;
        ty = leader.y + leader.dy;
        int xtrack = seeking ? COMB : preyCount > 400 ? ASIDE : MID_SIDE;
        tx += lx * BEHIND + px * xtrack;
        ty += ly * BEHIND + py * xtrack;

        me.dx = tx - me.x;
        me.dy = ty - me.y;
        limitSpeed(me, MAX_SPEED * (idx < 3 ? MID_MULT : 1));
    }

    Collection<Animal> getFoods(Member me) {
        return me.foods.size() == 0 ? foods : me.foods;
    }

    boolean findFood(Member me) {
        if (me.hunger > 500)
            return false;

        Collection<Animal> yummy = getFoods(me);
        if (yummy.size() == 0)
            return false;

        double x, y, sqDist, cDist = 10 * 10;
        Animal target = null;
        for (Animal food : me.foods) {
            x = food.x - me.x;
            y = food.y - me.y;
            sqDist = x * x + y * y + Double.MIN_NORMAL;
            if (sqDist < cDist) {
                cDist = sqDist;
                target = food;
            }
        }

        if (target == null)
            return false;

        if (cDist < 5 * 5 || me.hunger < 200) {
            me.dx = (target.x - me.x) * 10000000d;
            me.dy = (target.y - me.y) * 10000000d;
            return true;
        }
        return false;
    }

    void soloRun() {
        double x, y, sqDist, cDist;
        for (Member me : members) {
            Collection<Animal> yummy = getFoods(me);
            if (yummy.size() == 0) {
                wander(me);
                continue;
            }

            Animal target = null;
            cDist = Double.MAX_VALUE;
            for (Animal food : yummy) {
                x = food.x - me.x;
                y = food.y - me.y;
                sqDist = x * x + y * y + Double.MIN_NORMAL;
                if (sqDist < cDist) {
                    cDist = sqDist;
                    target = food;
                }
            }

            me.dx = (target.x - me.x) * 100000d;
            me.dy = (target.y - me.y) * 100000d;
        }
    }

    void wander(Member me) {
        if (me.dx == 0 && me.dy == 0) {
            me.dx = 250 - me.x;
            me.dy = 250 - me.y;
            return;
        }

        double lx, ly, px, py;
        lx = me.dx / 4;
        ly = me.dy / 4;
        boolean dir = Math.random() < 0.5 ? true : false;
        px = dir ? ly : -ly;
        py = dir ? -lx : lx;

        me.dx += px;
        me.dy += py;
    }

    void limitSpeed(Member me, double max) {
        double x = me.dx, y = me.dy;
        double dist = Math.sqrt(x * x + y * y) + Double.MIN_NORMAL;
        if (dist > max) {
            x = (x / dist) * max;
            y = (y / dist) * max;
        }
        me.dx = x;
        me.dy = y;
    }

    final static double MAX_SPEED = 6.1;
    final static double HEAD_MULT = 0.85;
    final static double MID_MULT = 0.92;
    final static int BEHIND = -25;
    final static int ASIDE = 15;
    final static int MID_SIDE = 30;
    final static int COMB = 150;
}

11

রুবি মাকড়সা

যেহেতু কখনও কখনও কম বেশি হয় এবং অনেকগুলি সমাধান সম্ভবত যে কোনওভাবে শিকারটিকে কোণঠাসা করার চেষ্টা করবে ...

আমি ভেবেছিলাম আমার প্যাকটি কেবল আলাদা হয়ে যাবে এবং অন্যেরা কাজটি করার জন্য অপেক্ষা করবে।

gets
print "3.0\t3.0\t3.0\t-3.0\t-3.0\t-3.0\t-3.0\t3.0\t0.0\t0.0\0"
STDOUT.flush

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


4
প্রথম প্যারাসাইট সমাধান +1। আমি মনে করি এই ধরণের উত্তর ধীরে ধীরে
লুফোলগুলি অপসারণ

@ Githubphagocyte আমার মনে একটি স্মার্ট পরজীবী ছিল তবে এটি লাইভ সময় / কোডের লাইনের ক্ষেত্রে আরও দক্ষ। আমি আশা করি এটি বাস্তবায়নের জন্য আমি সময় পাব।
লেগাত

সম্ভবত @ সিংহিটিকা এই মুহূর্তে আমার ধারণার কোডিং করছে। অথবা যদি তার ধারণাটি আর একটি হয় তবে শিগগিরই আমাদের আরও বেশি পরজীবী শিকারী আসতে পারে;)
লেগাত

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

3
এটি যেমনটি প্রবেশ করতে পারে, তবুও এটি কেন জানার জন্য আমার একটি সময় লাগল took আপনি আরও বেশি নেটকেট যুক্ত করবেন বলে মনে হয় (যা বোঝায়)। আমার কাছ থেকে +1, আসুন দেখুন কোন ধরণের শিকারী কোণগুলি এড়াতে বেরিয়ে আসে :)
জিওবিটস

11

CivilizedBeasts

অবশেষে, আমার জন্তুগুলি দেখানোর সময়!

আমার জাতটি মনে করে শিকার কিছুটা আদিম, তাই তারা 4 টি দলে এক সাথে কাজ করে এবং তাই তারা তাদের 5 তম মিত্রকে ছেড়ে দেয়, কারণ: কম শিকারী = নিজের জন্য আরও শিকার y তারা মূলত যা করে তারা হ'ল মানুষ যা করে, তারা শিকারকে ধরে এবং তাদের গবাদি পশুদের ভাল যত্ন করে;)

public class CivilizedBeasts extends GenericPack{

    private static int TL = 0, TR = 0, BL = 0, BR = 0; // TopLeft/BotRight
    private static int teamSize = 0, turnsWaiting = 0, turnsToWait = 20;

    private boolean out = true;
    private double maxSpeed = 6.1, mapSize = 500;

    public CivilizedBeasts(){
    }

    @Override
    public void respond(){
        if(teamSize > members.size()){

            Member check = getMemberById(TL);
            totalLoop:
            if(check == null){
                for (Member member : members) {
                    if(member.id != TR && member.id != BL && member.id != BR){
                        TL = member.id;
                        break totalLoop;
                    }
                }

                TL = 0;
            }

            check = getMemberById(TR);
            totalLoop:
            if(check == null){
                for (Member member : members) {
                    if(member.id != TL && member.id != BL && member.id != BR){
                        TR = member.id;
                        break totalLoop;
                    }
                }

                TR = 0;
            }

            check = getMemberById(BL);
            totalLoop:
            if(check == null){
                for (Member member : members) {
                    if(member.id != TL && member.id != TR && member.id != BR){
                        BL = member.id;
                        break totalLoop;
                    }
                }

                BL = 0;
            }

            check = getMemberById(BR);
            totalLoop:
            if(check == null){
                for(Member member : members) {
                    if(member.id != TL && member.id != TR && member.id != BL){
                        BR = member.id;
                        break totalLoop;
                    }
                }

                BR = 0;
            }
        }else if(teamSize < members.size()){
            for(Member member : members) {
                if(member.id != TL && member.id != TR && member.id != BL && member.id != BR){
                    if(TL == 0)
                        TL = member.id;
                    else if(TR == 0)
                        TR = member.id;
                    else if(BL == 0)
                        BL = member.id;
                    else if(BR == 0)
                        BR = member.id;
                }
            }
        }

        teamSize = members.size();

        double border = 1;
        double x, y;
        boolean reached = true;

        double distance = 16.3;

        for (Member member : members) {
            boolean doesNotCount = false;
            x = 0; y = 0;
            if(member.id == TL){
                if(out){
                    x = -(member.x - border);
                    y = -(member.y - border);
                }else{
                    x = ((mapSize/2 - distance) - member.x);
                    y = ((mapSize/2 - distance) - member.y);
                }
            }else if(member.id == TR){
                if(out){
                    x = (mapSize - member.x - border);
                    y = -(member.y - border);
                }else{
                    x = ((mapSize/2 + distance) - member.x);
                    y = ((mapSize/2 - distance) - member.y);
                }
            }else if(member.id == BL){
                if(out){
                    x = -(member.x - border);
                    y = (mapSize - member.y - border);
                }else{
                    x = ((mapSize/2 - distance) - member.x);
                    y = ((mapSize/2 + distance) - member.y);
                }
            }else if(member.id == BR){
                if(out){
                    x = (mapSize - member.x - border);
                    y = (mapSize - member.y - border);
                }else{
                    x = ((mapSize/2 + distance) - member.x);
                    y = ((mapSize/2 + distance) - member.y);
                }
            }else{
                double dist = 50, temp = 0;
                int index = -1;
                for(int i = 0; i < member.foods.size(); i++){
                    temp = (Math.abs(member.foods.get(i).x - member.x)+Math.abs(member.foods.get(i).y - member.y));
                    if(temp < dist){
                        dist = temp;
                        index = i;
                    }
                }
                if(index != -1){
                    x = (member.foods.get(index).x - member.x);
                    y = (member.foods.get(index).y - member.y);
                }
                doesNotCount = true;
            }

            if(!doesNotCount && Math.abs(x)+Math.abs(y) > maxSpeed)
                reached = false;
            member.setDirection(x,y);
        }

        if(reached){
            if(!out){ // in the middle.
                if(teamSize < 4){
                    int temp = TL;
                    TL = BR;
                    BR = temp;
                    temp = TR;
                    TR = BL;
                    BL = temp;
                    out = true;
                }else{
                    turnsWaiting++;
                }
            }else // no need to wait in the corners
                out = false;

            if(turnsWaiting >= turnsToWait){
                turnsToWait = 15;
                out = true;
                turnsWaiting = 0;
            }

        }

    }

    public static void main(String[] args){
        new CivilizedBeasts().run();
    }
}

আমার স্তনগুলির পক্ষে 200-এরও কম শিকারের সাথে বেঁচে থাকা বেশ কঠিন হয়ে যায় + -12.000 গেমটিতে কেবল শত্রু নেটকাটসের সাথে। আপনি এই জাতের সাথে খুশী হবেন যেহেতু এটি সত্যই প্রচুর পরিমাণে শিকারকে দ্রুত গতিতে গ্রাস করে, যেমনটি অন্য কোনও জাতের পারে না (তাত্ক্ষণিকভাবে এবং বড় জবাইকারীরা বিজয় দেয় না, তবে এটি পুরোপুরি পুরোপুরি যথেষ্ট সময় নেয়াকে প্রভাবিত করে)।


3
যদি " তাদের যত্নবান হন " এর অর্থ আপনি " বার বার তাদের মাঝখানে রাখেন এবং তাদের হত্যা / খাবেন ", তবে হ্যাঁ, তারা এটি ভাল করে। +1
জিওবিটস

এটি মজার বিষয়, এভিল উটগুলির পরিবর্তিত (মূল) সংস্করণ সহ, সভ্য কৌশলগুলি 'সেন্টার উট' এর কারণে সম্পূর্ণ অদক্ষ।
ব্যবহারকারী 2846289

1
@ ভাদিমআর ক্র্যাপ, আপনার উট আপডেট করার জন্য ধন্যবাদ: পিআই এটি পরীক্ষা করতে পারে না কারণ এটি জাভা নয় তবে আমি জানি আমার কৌশলটি আমার অঞ্চলের মাঝখানে শিকারীদের সাথে একরকম বেহুদা: পি
হারজান

5
আবার হেরজন! এছাড়াও " 200 টিরও কম শিকারের সাথে আমার স্তনগুলি বেঁচে রাখা বেশ কঠিন হয়ে পড়ে " (জোর যুক্ত করা হয়েছে)। আমি বুঝতে পারি নি যে আপনার স্তনের প্রাণবন্ততা কম্পিউটারের সিমুলেশনের শিকারের সংখ্যার উপর নির্ভর করে ....
জাস্টিন

5

রুবি শকুন

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

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

আমি আশা করছি:

  • তাদের দেখার ক্ষেত্রের বাইরে শিকারিদের অনুসন্ধান করতে সহায়তা করুন
  • শিকারকে বিবেচনা করুন - প্রায়শই তাদের মধ্যে একটি অন্য প্যাক এবং শিকারের মধ্যে থাকে!
  • যখন অন্য সমস্ত ভাল খাওয়ানো হয় তখন একজনের অনাহার এড়াতে তাদের ঘোরানো শুরু করুন

22 এপ্রিল 2014: যোগ করা একঘেয়েমি , যা তাদের কম আঠালো করে তোলে এবং তাদের নিজেরাই শিকারের শিকার করতে এবং শিকারীদের সন্ধানের অনুমতি দেয়

class Animal
  attr_accessor :x, :y
end

class Hunter < Animal
  attr_accessor :id, :bored

  def initialize diff
   @diff = diff
   @lastGoal = nil
   @bored = false
  end

  def move goal
    if not goal.nil? 
      if @bored or goal != @lastGoal
        @lastGoal = goal
        return [goal.first - x + @diff.first, goal.last - y + @diff.last]
      end
    end
    [250 - x + 3*@diff.first, 250.0 - y + 3*@diff.last]
  end
end

class Pack
  def initialize
    @file = File.open "pack_log", "w"
    @count = 0
    @pack = []
    @order = []
    @hunters = []
    @closest = nil
    @random_goal = [250.0, 250.0]
    @locations = []
    @timer = 0
    d = 25.0
    diffs = [[d, d], [d, -d], [-d, -d], [-d, d], [0.0, 0.0]]
    5.times do |i|
      @pack << (Hunter.new diffs[i])
    end
    line = 0
    s = gets
    loop do
      s = gets
      if not (s =~ /dead\0/).nil?
        break
      end
      if line == 0
        get_structure s
      elsif line == 1
        get_positions s
      end
      @pack.length.times do |i|
        if line == i*2 + 3
          look_for_hunters s
          if @count <= i+1
            @closest = closest_hunter
            move
          end
        end
      end
      if not (s =~ /\0/).nil?
        line = 0
        @hunters = []
      else
        line += 1
      end
    end
  end

  def member_by_id id
    member = nil
    @pack.each do |v|
      if v.id == id
        member = v
        break
      end
    end
    member
  end

  def member_by_order index
    member_by_id @order[index]
  end

  def distance a, b
    Math.sqrt((a.first - b.first)**2 + (a.last - b.last)**2)
  end

  def bored?
    bored = true
    l1 = @locations.first
    @locations.each do |l2|
      if distance(l1, l2) > 20
        bored = false
      end
    end 
    bored
  end

  def bored_move v
    if @timer <= 0
      @random_goal = [rand(1000).to_f - 250, rand(1000).to_f - 250]
      @pack.each do |m|
        m.bored = true
      end
      @timer = 250 
    else
      @timer -= 1
    end
    v.move @random_goal
  end

  def move
    first_one = true
    answer = ""
    @order.each do |id|
      v = member_by_id id
      x, y = 0, 0
      if bored?
        x, y = (bored_move v)
      elsif @timer > 0
        @location = []
        x, y = (bored_move v)
      else
        @pack.each do |m|
          m.bored = false
        end
        @timer = 0
        x, y = v.move @closest
      end
      if not first_one
        answer << "\t"
      end
      answer << "#{x.to_i}.0\t#{y.to_i}.0"
      first_one = false
    end
    answer << "\0"
    print answer
    STDOUT.flush
  end

  def get_structure line
    @order = []
    if @pack.first.id.nil? 
      @count = 0
      line.split.each_with_index do |v, i|
        if i % 2 == 0
          @order << v.to_i
          @pack[i/2].id = v.to_i
          @count += 1
        end
      end
    else
      @count = 0
      line.split.each_with_index do |v, i|
        if i % 2 == 0
          @order << v.to_i
          @count += 1
        end
      end
    end
  end

  def get_positions line
    if not @order.empty?
      line.split.each_with_index do |v, i|
        if i % 2 == 0
          member_by_order(i/2).x = v.to_f
        else
          member_by_order(i/2).y = v.to_f
        end
      end
    end
  end

  def look_for_hunters line
    line.split.each_with_index do |v, i|
      if i % 2 == 0
        @hunters << [v.to_f]
      else
        @hunters.last << v.to_f
      end
    end
  end

  def closest_hunter
    mass_center
    closest = nil
    bestDist = 500*500
    if not @hunters.nil? and not @hunters == []
      @hunters.each do |h|
        our = false
        @pack.each do |v|
          if h.first == v.x and h.last == v.y
            our = true
          end
        end
        if our
          next
        end
        sqDist = (@mass_center.first - h.first)**2 + (@mass_center.last - h.last)**2
        if sqDist < bestDist
          closest = []
          closest << h.first
          closest << h.last
        end
      end
    end
    closest
  end

  def mass_center
    center_x = 0
    center_y = 0
    @pack.each do |v|
      center_x += v.x
      center_y += v.y
    end
    @mass_center = [center_x.to_f / @count, center_y.to_f / @count]
    if @locations.length > 30
      @locations.shift
      @locations << @mass_center
    else
      @locations << @mass_center
    end
  end
end

Pack.new

আপনার অবশ্যই মিশ্রণে আরও "শিকারী" দরকার। যেমনটি হ'ল, এগুলি অন্যান্য পরজীবীদের সাথে সংযুক্ত থাকে (যেহেতু এটি মাঠে সংখ্যাগরিষ্ঠ)। যদিও আমি তাদের দেখতে পছন্দ করি এবং প্রতিযোগীদের আলাদা মিশ্রণের সাথে তারা কীভাবে কার্যকর হতে পারে তা দেখতে পাচ্ছি।
জিওবিটস

হ্যাঁ, আমার পরীক্ষার পরিবেশে আমার কাছে আরও দুটি হান্টার প্যাক রয়েছে। তাদের ছাড়া শকুন সম্ভবত সম্ভবত নিখুঁত। বিশেষত নেটকাটগুলি মাঝখানে থেকে দেখা না গিয়ে দ্রুত কোণে কাজ করতে পারে।
লেগাত

আমি মনে করি, আমি জানি যে তাদের বিশেষত কী হতে পারে। দুষ্ট উটের যুদ্ধের নৃত্য। @ জিওবিটস ইউটিউবে মারামারি চালাবেন কীভাবে? 10 রাউন্ডে দেখতে পারা যায় এমন বেশি নয়। অবশ্যই, সদর দপ্তরের প্রয়োজন হবে। লক্ষ লক্ষ দর্শকের প্রত্যাশা না করে তবে আপনার প্যাকগুলি কীভাবে সম্পাদন করে এবং সম্ভবত তাদের জন্য কিছুটা উত্সাহিত হবে তা দেখে মনোরঞ্জন হবে :)
লেগাত

1
মনোযোগ আকর্ষণ করতে পুরো ট্যুরনিটি কিছুটা দীর্ঘ (এখন প্রতি রাউন্ডে 8 মিনিট) দীর্ঘ হতে পারে, তবে একটি "দর্শক" রাউন্ড রেকর্ডিং কাজ করতে পারে। আমি এটি ভবিষ্যতের রানগুলির জন্য একটি চিন্তাভাবনা করব।
জিওবিটস

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

5

দুষ্ট ইকো উট

সম্পাদনা: রূপান্তর # 2। ওহ, না, নেটচ্যাটসকে পরাজিত করার জন্য আমি প্রথম শিকারী আন্দোলনের পূর্বাভাসটি বাস্তবায়নে দেরি করেছি। ঠিক আছে, তাই এটি।

এই রূপান্তরটির $hunger_criticalপরিবর্তনশীল (ধ্রুবক) রয়েছে। এটির উপরে 1000 এর মান পরিবর্তন করা উটকে সর্বদা শিকারী হিসাবে তৈরি করে, যেমন ক্লেয়ারভাইয়েন্টস। তারপর:

Done in 11.93 minutes
camels1.pl(0)                   : Turn 23112    : Score 100
Netcats(1)                      : Turn 22508    : Score 80

যদি $hunger_criticalউদাহরণস্বরূপ 500 হিসাবে সেট করা থাকে (নীচে হিসাবে), তবে আমার উটগুলি ( সভ্যতার ভয়াবহতা দেখে) ) পরিবেশ বান্ধব পদ্ধতিতে আচরণ করার চেষ্টা করে (তাই তারা তাদের জাতের নাম পরিবর্তন করেছে) অর্থাৎ তারা ক্ষুধার্ত হলেই হত্যা করে। ক্ষুধার্ত না হলে, তারা অন্য কিছু শিকারিদের অর্থহীন কসাই প্রতিরোধ করতে, কেন্দ্র এবং কোণগুলি, সমালোচনামূলক দ্বীপ অঞ্চলগুলিতে টহল দেয়। ভাল, কেন্দ্রের সাথে, এটি কমবেশি কাজ করে। কোণে চক্কর দেওয়ার ধারণাটি ছিল শিকারটিকে দূরে রাখতে এবং বিড়ালদের ও পরজীবীদের জীবনকে আরও কঠিন করে তোলা। ভাল, এটি কাজ করে না। বোকা শিকার যাইহোক কোণে যায়।

এটি আকর্ষণীয়, এছাড়াও, যে flock[ALIGN]উপাদানটি কেবল শিকারি দ্বারা অনুমান করা যায়, এবং আমার বাস্তবায়ন জাস্টহল্ফের চেয়ে আলাদা। আমি সেখানে আমার মধ্যে কিছু ক্ষুদ্র বাগ এর ভয় চেরা বন্ধ Geobits 'কোড বাস্তবায়নের পর্যবেক্ষক / বনাম clairvoyants উটের পৃথক শিকার তুলনা।

এবং প্রোগ্রাম এখন অনেক ধরণের, দুঃখিত।


সম্পাদনা: রূপান্তর # 1। দ্বীপটি বেশ তেজস্ক্রিয় হয়ে উঠেছে (যা উদ্ভিদের অভাব এবং 'শিকার' প্রাণীগুলির অব্যক্ত প্রকৃতির বর্ণনা দেয়), সুতরাং এখানে আমার উটের প্রথম রূপান্তর। এদের মধ্যে যে কোনও একক শিকারী হয়ে উঠতে পারে, ক্ষুধার্ত হলে বা যদি সবার জন্য কোনও মুক্ত কোণ নেই। শিকারি সক্রিয়ভাবে কাছের শিকারটিকে অনুসরণ করার চেষ্টা করে। যদি কিছুই না থাকে তবে এটি দ্বীপের কেন্দ্রের চারপাশে প্রশস্ত চক্রে টহল দেয়, তারপরে কাছের প্রাণীটিকে এটি খুঁজে পেলে তা তাড়া করে। দুর্ভাগ্যক্রমে, শিকারের দিকটি যখন তার জঞ্জাল (তদন্তের পক্ষে ...) এর কাছাকাছি থাকে তখন অনাকাঙ্ক্ষিত হয়ে যায়, সুতরাং একক তাড়া খুব কার্যকর নয়। তবে যদি এটি সফল হয় তবে উটটি নিকটতম মুক্ত কোণে হজম করতে চলেছে (যদি থাকে)। যখন ক্ষুধার মাত্রা নির্দিষ্ট স্তরের নীচে থাকে, তখন যে কোনও উট তার কোণটি ছেড়ে দেয় (সম্ভবত নেটক্যাটসকে অভিশাপ দেয় ('খাবার কোথায়?' )) এবং নিজে থেকে বিনামূল্যে রোমিংয়ে যায়। ইত্যাদি।


একই রসিকতা দু'বার বলেছিল মজার বিষয় নয়, তবে (১) আমাকে কোথাও শুরু করতে হবে এবং আমি এই বিষয়গুলিতে নতুন, (২) সত্য, আমি রুবির আগে নেটকাটগুলি দেখার জন্য কর্নার কৌশল (এবং কে না?) নিয়ে ভাবলাম মাকড়শা দ্বীপে হাজির।

তাহলে কি কখনও মাংসাশী উট সম্পর্কে শুনেছেন? দরিদ্র প্রাণী একদিন এই godশ্বর-বিসর্জন দ্বীপে জেগে ওঠে যে কোনও ঘাস বা গাছ নেই, তবে ভোজ্য দ্রুত চলমান (বেশ বিরক্তিকর) ছোট ছোট জিনিস যদিও প্রচুর আজব সবুজ। শিকারের অভ্যাস না থাকলেও (তবে তারা শীঘ্রই পরিবর্তিত হবে, আমি আশা করি), আমার উটগুলি বেঁচে থাকার জন্য খুব খারাপ পরিকল্পনা তৈরি করেছিল: তারা বিভক্ত হয়ে প্রতিটি 4 টির 1 টির মধ্যে চলে যায়, এবং 5 তম একটি কেন্দ্রে যায় (সেখানে প্রথমে মারা যেতে হবে) এটি পরিণত হয়)। তাদের গন্তব্যগুলিতে তারা ধৈর্য সহকারে অপেক্ষা করে, এক ধরণের উট যুদ্ধের নৃত্য পরিবেশন করে, বা সম্ভবত তারা ইতিমধ্যে সেখানে অন্যান্য প্রাণী, মাকড়সা এবং সমস্ত কিছুই না চালানোর চেষ্টা করে ...

#!/usr/bin/env perl
use strict;
use warnings;

binmode STDOUT;
binmode STDIN;
$| = 1;
$, = "\t";

my $hunger_critical = 500;
my %pack;
my ($turn, $prey_count, $predators_count);
my $patrol_radius_hunt = 150;
my $patrol_radius_corner = 16;
my $patrol_radius_center = 1;
my @roles = qw/C LL LR UL UR/; # or P (patrol if > 5), H (hunt)
my %places = (
    UL => {x =>   1 + $patrol_radius_corner, y =>   1 + $patrol_radius_corner},
    UR => {x => 499 - $patrol_radius_corner, y =>   1 + $patrol_radius_corner},
    LR => {x => 499 - $patrol_radius_corner, y => 499 - $patrol_radius_corner},
    LL => {x =>   1 + $patrol_radius_corner, y => 499 - $patrol_radius_corner},
    C  => {x => 250, y => 250},
);

sub sq_dist {
    my ($x1, $y1, $x2, $y2) = @_;
    return ($x1 - $x2)**2 + ($y1 - $y2)**2
}

sub distance {
    return sqrt(&sq_dist)
}

sub assign_role {
    my $camel = shift;
    if (@roles) {
        my %choice = (d => 1000, i => 0);
        for my $i (0..$#roles) {
            my $r = $roles[$i];
            if ($r eq 'C') {
                if ($prey_count > 700) {
                    $choice{i} = $i;
                    last
                }
                else {
                    next
                }
            }
            my $d = distance($camel->{x}, $camel->{y}, $places{$r}{x}, $places{$r}{y});
            if ($d < $choice{d}) {
                @choice{qw/d i/} = ($d, $i)
            }
        }
        return splice @roles, $choice{i}, 1
    }
    else {
        return 'P'
    }
}

sub xy_average {
    my $xy = shift;
    my $x = my $y = 0;
    if ($xy && @$xy) {
        for my $item (@$xy) {
            $x += $item ->{x};
            $y += $item->{y}
        }
        $x /= @$xy;
        $y /= @$xy
    }
    return $x, $y
}

sub patrol {
    my ($xc, $yc, $radius, $camel) = @_;
    my ($x, $y) = ($camel->{x} - $xc, $camel->{y} - $yc);
    my $d = distance(0, 0, $x, $y);
    my $a = atan2($y, $x);
    if (abs($d - $radius) < 3) {
        $a += 6 / $radius
    }
    return $radius * cos($a) - $x, $radius * sin($a) - $y
}

while (1) {

    # Get input

    my @in;
    # Line 0 - turn, counts
    $_ = <>;
    die if /dead/;
    ($turn, $prey_count, $predators_count) = /\0?(\S+)\t(\S+)\t(\S+)/;
    # Line 1 - pack's ids and hunger
    $_ = <>;
    while (/(\S+)\t(\S+)/g) {
        push @in, {id => $1, hunger => $2}
    };
    # Line 2 - positions
    $_ = <>;
    for my $animal (@in) {
        /(\S+)\t(\S+)/g;
        ($animal->{x}, $animal->{y}) = ($1, $2);
    }
    # 2 lines per member, visible prey and predators
    for my $animal (@in) {
        $_ = <>;
        my @prey;
        while (/(\S+)\t(\S+)/g) {
            push @prey, {x => $1, y => $2}
        };
        $animal->{prey} = \@prey;
        $_ = <>;
        my @beasts;
        while (/(\S+)\t(\S+)/g) {
            push @beasts, {x => $1, y => $2}
        };
        $animal->{beasts} = \@beasts
    }
    # trailing \0 zero will be prepended to next turn input

    # Update my pack

    for my $n (0..$#in) {
        my $animal = $in[$n];
        my $id = $animal->{id};
        # old average prey position
        my @opp = xy_average($pack{$id}{prey});
        # new average prey position
        my @npp = xy_average($animal->{prey});
        # average prey displacement
        my %apd = (x => $npp[0] - $opp[0], y => $npp[1] - $opp[1]);
        $pack{$id}{apd}    = \%apd;
        $pack{$id}{hunger} = $animal->{hunger};
        $pack{$id}{x}      = $animal->{x};
        $pack{$id}{y}      = $animal->{y};
        $pack{$id}{prey}   = $animal->{prey};
        $pack{$id}{beasts} = $animal->{beasts};
        $pack{$id}{num}    = $n;
        $pack{$id}{dead}   = 0
    }

    # Bury dead animals, retrieve their roles

    while (my ($id, $camel) = each %pack) {
        if ($camel->{dead}) {
            my $role = $camel->{role};
            push @roles, $role if $role ne 'P' and $role ne 'H';
            delete $pack{$id};
        }
        else {
            $camel->{dead} = 1
        }
    }

    # See that everyone has a role and lives accordingly

    my @out;
    for my $camel (values %pack) {
        my $role = $camel->{role} ||= assign_role($camel);
        if ($camel->{hunger} < $hunger_critical and $role ne 'H') {
            push @roles, $role if $role ne 'P';
            $role = $camel->{role} = 'H'
        }
        if ($camel->{hunger} > $hunger_critical and ($role eq 'H' or $role eq 'P') and $prey_count > 400) {
            $role = $camel->{role} = assign_role($camel)
        }
        my @vector = (0, 0);
        if ($role eq 'H') {
            my @prey = @{$camel->{prey}};
            if (@prey) {
                my %nearest = (p => undef, dd => 2500);
                for my $prey (@prey) {
                    my $dd = sq_dist($camel->{x}, $camel->{y}, $prey->{x}, $prey->{y});
                    if ($dd <= $nearest{dd}) {
                        @nearest{qw/p dd/} = ($prey, $dd)
                    }
                }
                my $target = $nearest{p};
                if ($nearest{dd} > 900) {
                    @vector = ($target->{x} - $camel->{x}, $target->{y} - $camel->{y})
                }
                else {
                    my @vect = map{{x => 0, y => 0}}1..5;
                    my $n = 0;
                    for my $prey (@prey) {
                        next if $prey eq $target;
                        my $dd = sq_dist($target->{x}, $target->{y}, $prey->{x}, $prey->{y}) + 1/(~0);
                        next if $dd > 900;
                        $n ++;
                        my $dx = $prey->{x} - $target->{x};
                        my $dy = $prey->{y} - $target->{y};
                        $vect[1]{x} -= $dx / $dd;
                        $vect[1]{y} -= $dy / $dd;
                        $vect[2]{x} += $dx * $dd;
                        $vect[2]{y} += $dy * $dd
                    }
                    $vect[0] = {x => $n * $camel->{apd}{x}, y => $n * $camel->{apd}{y}};
                    my $dx = abs(250 - $target->{x});
                    my $dy = abs(250 - $target->{y});
                    my $d = $dx > $dy ? $dx : $dy;
                    if ($d > 240) {
                        $vect[4]{x} = $dx * $d;
                        $vect[4]{y} = $dy * $d;
                    }
                    for my $v (@vect) {
                        my $d = sqrt($v->{x}**2 + $v->{y}**2) + 1/(~0);
                        $v->{x} /= $d;
                        $v->{y} /= $d;
                    }
                    for my $beast (@{$camel->{beasts}}, $camel) {
                        my $dd = sq_dist($target->{x}, $target->{y}, $beast->{x}, $beast->{y});
                        next if $dd > 900;
                        $vect[3]{x} += $target->{x} - $beast->{x};
                        $vect[3]{y} += $target->{y} - $beast->{y};
                    }
                    $vector[0] = 5 * 1   * $vect[0]{x}
                               + 5 * 1   * $vect[1]{x}
                               + 5 * .96 * $vect[2]{x}
                               + 1 * 2   * $vect[3]{x}
                               + 5 * 4   * $vect[4]{x};
                    $vector[1] = 5 * 1   * $vect[0]{y}
                               + 5 * 1   * $vect[1]{y}
                               + 5 * .96 * $vect[2]{y}
                               + 1 * 2   * $vect[3]{y}
                               + 5 * 4   * $vect[4]{y};
                    my $dd = $vector[0]**2 + $vector[1]**2;
                    if ($dd > 36) {
                        my $d = sqrt($dd);
                        @vector = map {$_ * 6.1 /$d} @vector
                    }
                }
            }
            else {
                @vector = patrol(250, 250, $patrol_radius_hunt, $camel)
            }
        }
        elsif ($role eq 'P') {
            @vector = patrol(250, 250, $patrol_radius_hunt, $camel)
        }
        else {
            my $r = $role eq 'C' 
                ? $patrol_radius_center 
                : $patrol_radius_corner;
            @vector = patrol($places{$role}{x}, $places{$role}{y}, $r, $camel)
        }
        my $id_x = $camel->{num} << 1;
        my $id_y = $id_x + 1;
        @out[$id_x, $id_y] = @vector
    }

    # And let the cruel world know about it

    print @out;
    print "\0"
}

__END__

5
এটি এখন পর্যন্ত এই সাইটে আমি দেখেছি সবচেয়ে সুস্পষ্ট পার্ল স্ক্রিপ্ট।
জিওবিটস

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

@ আসরফাল্ফ, আমি যেমন বলেছিলাম: পরিকল্পনাটি কার্যকর হয়নি। কোণে বসে প্যারাসাইটগুলি কোনওভাবেই শিকারটিকে ছাড়ায় না। এইচএম-এম, সম্ভবত এক কোণে টহল দিচ্ছে 2 বা ততোধিক প্রাণী।
ব্যবহারকারী 2846289

আপনার উট আসলে খুব ভাল! ধন্যবাদ (আমার জন্য) আমি আমার দাবিদার উন্নতি করেছি, তাই বেশিরভাগ সময় (সর্বদা নয়), আমার যুদ্ধ শেষ যুদ্ধের সময় আপনার বিরুদ্ধে জিতেছে। মজাদার!
জাস্টহেল্ফ

1
আপনি যদি শিকার থেকে 8 (20-2 * * 6) ইউনিটের বেশি কাছাকাছি থাকেন তবে আমরা বর্তমান পালাক্রমে আমাদের শিকারের 30 টি ইউনিটের মধ্যে থাকা অন্যান্য সমস্ত প্রাইয়ের যে কোনও চলন দেখতে পাই। এবং vecসম্পত্তিটি মূলত পূর্ববর্তী পালা থেকে বর্তমান টার্নের স্থানচ্যুতি মাত্র। এবং যেমনটি আমি বলেছিলাম, কোন শিকার কোন পথে চলে যায় তা অনুসন্ধান করার জন্য আমরা পূর্ববর্তী মোড় থেকে ম্যাচিং করি, আমরা শিকারের আদেশের উপর নির্ভর করতে পারি না। এটি সম্ভবত সম্ভব কারণ প্রাকগুলি (সাধারণত দৃশ্যে) একে অপরের থেকে পর্যাপ্ত দূরত্ব রাখে (> 12 ইউনিট), এবং তাই বেশিরভাগ সময় আমরা আগের টার্নে প্রিয়ার সাথে মেলে রাখতে পারি বর্তমান টার্নে।
justhalf

4

এবলডোগস - পিএইচপি

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

কোডটি একটি AbleDogsফাইলে রাখুন এবং এটি দিয়ে চালানphp AbleDogs

<?php
// simulation parameters

define ("ARENA_SIZE", 500);

define ("HUNGER_MAX", 1000);

define ("PREY_SPEED", 6);
define ("PRED_SPEED", 6.1);

define ("PREY_VISION", 30);
define ("PRED_VISION", 50);

define ("WALL_BOUNCE", 10); // distance from a wall from which a prey starts bouncing

// derived constants

define ("PRED_SPEED2" , PRED_SPEED  * PRED_SPEED );
define ("PRED_VISION2", PRED_VISION * PRED_VISION);
define ("PREY_VISION2", PREY_VISION * PREY_VISION);

// grid to speedup preys lookup

define ("GRID_SIZE", ceil (ARENA_SIZE/PRED_VISION));
define ("GRID_STEP", ARENA_SIZE/GRID_SIZE);

// search patterns

define ("SEARCH_OFFSET", WALL_BOUNCE+PRED_VISION/sqrt(2));
define ("SEARCH_WIDTH" , 2*sqrt(PRED_VISION2-PRED_SPEED2/4));
define ("SEARCH_HEIGHT", ARENA_SIZE-2*SEARCH_OFFSET);
define ("SEARCH_SIZE"  , ceil(SEARCH_HEIGHT/SEARCH_WIDTH));
define ("SEARCH_STEP"  , SEARCH_HEIGHT/SEARCH_SIZE);
define ("SEARCH_LEGS"  , 2*SEARCH_SIZE+1);

// tracking

define ("MAX_TRACK_ERROR", 10); // max abs distance for prey tracking correlation
define ("TRACKING_HUNGER_START", HUNGER_MAX*.9); // hunger limit to try and eat the tracked prey (start of game)
define ("TRACKING_HUNGER_END", 4);     // idem, for endgame
define ("TRACKING_DISTANCE", PREY_SPEED*2.5);
define ("TRACKING_DISTANCE2", TRACKING_DISTANCE * TRACKING_DISTANCE);

class Point {
    public $x = 0;
    public $y = 0;

    function __construct ($x=0, $y=0)
    {
        $this->x = (float)$x;
        $this->y = (float)$y;
    }

    function __toString() // for comparisons
    {
        return "$this->x,$this->y";
    }

    function multiply ($scalar)
    {
        return new Point ($this->x * $scalar, $this->y * $scalar);
    }

    function add ($v)
    {
        return new Point ($this->x + $v->x, $this->y + $v->y);
    }

    function dot($v)
    {
        return $this->x * $v->x + $this->y * $v->y;
    }

    function rotate90()
    {
        return new Point (-$this->y, $this->x);
    }

    function vector_to ($goal)
    {
        return new Point ($goal->x - $this->x, $goal->y - $this->y);
    }

    function norm2 ()
    {
        return $this->dot ($this);
    }

    function norm ()
    {
        return sqrt ($this->norm2());
    }

    function normalize ($norm = 1)
    {
        $n = $this->norm();
        if ($n != 0) $n = $norm/$n;
        return $this->multiply ($n);
    }

    function limit ($norm)
    {
        return $this->norm() > $norm
             ? $this->normalize($norm)
             : clone $this;
    }
}

class Search {

    function __construct ($direction)
    {
        switch ($direction % 4)
        {
            case 0: $this->pos = new Point (          0,           0); break;
            case 1: $this->pos = new Point (SEARCH_SIZE,           0); break;
            case 2: $this->pos = new Point (SEARCH_SIZE, SEARCH_SIZE); break;
            case 3: $this->pos = new Point (          0, SEARCH_SIZE); break;
        }
        $this->start();
    }

    private function start ()
    {
        $this->dir = $this->pos->x == $this->pos->y;
        $this->adj = $this->pos->x ? -1 : 1;
        $this->target = new Point ($this->pos->x * SEARCH_STEP + SEARCH_OFFSET,
                                   $this->pos->y * SEARCH_STEP + SEARCH_OFFSET);
        $this->leg = 0;
    }

    function point ($pos)
    {
        if ($pos == $this->target)
        {
            if ($this->leg % 2)
            {
                if ($this->dir) $this->pos->y+= $this->adj;
                else            $this->pos->x+= $this->adj;
            }
            else
            {
                if ($this->dir) $this->pos->x = $this->pos->x ? 0 : SEARCH_SIZE;
                else            $this->pos->y = $this->pos->y ? 0 : SEARCH_SIZE;
            }
            $this->leg++;
            if ($this->leg == SEARCH_LEGS) $this->start();
            $this->target = new Point ($this->pos->x * SEARCH_STEP + SEARCH_OFFSET,
                                       $this->pos->y * SEARCH_STEP + SEARCH_OFFSET);
        }
        return $this->target;
    }
}

class Pack {

    public static $turn;   // turn number
    public static $size;   // number of live members
    public static $member; // array of members

    public static $prev_preys;     // previous coordinates of all preys
    public static $prev_preds;     // previous coordinates of foreign predators

    public static $n_preys; // total number of preys     (including those not currently seen)
    public static $n_preds; // total number of predators (including those not currently seen)

    public static $preys;     // coordinates of all preys
    public static $preds;     // coordinates of all predators
    public static $own_preds; // coordinates of all predators in our pack
    public static $foe_preds; // coordinates of all foreign predators

    public static $arena_center; // arena center

    private static $output_order; // to send output according to input order

    function init ()
    {
        Pack::$member = array();
        Pack::$arena_center = new Point (ARENA_SIZE/2, ARENA_SIZE/2);
    }

    function read_line ($line)
    {
        $values = array();
        if ($line == "") return $values;
        $input = explode ("\t", $line);
        $num = count($input);
        if ($num % 2) panic ("read_line: invalid input $line num $num");
        $num /= 2;
        for ($i = 0 ; $i != $num ; $i++)
        {
            $values[] = new Point ($input[$i*2  ], $input[$i*2+1]);
        }
        return $values;
    }

    function read_input ()
    {
        // read controller input (blocking)
        $input = "";
        while (($in = fread(STDIN, 1)) !== false)
        {
            if ($in == "\0") break;
            $input .= $in;
        }

        // check extinction
        if ($input == "dead") return false;
        $lines = explode ("\n", $input);

        // save previous predators and preys positions
        Pack::$prev_preys = Pack::$preys;
        Pack::$prev_preds = Pack::$foe_preds;

        // line 0: turn, preys, predators
        list (self::$turn, Pack::$n_preys, Pack::$n_preds) = explode ("\t", $lines[0]);

        // line 1: list of ids and hunger levels
        $id = array();
        Pack::$size = 0;
        Pack::$output_order = array();
        foreach (Pack::read_line($lines[1]) as $i=>$v)
        {
            $id[$i] = $v->x;
            Pack::$output_order[] = $id[$i];

            if (!isset (Pack::$member[$id[$i]])) Pack::$member[$id[$i]] = static::new_member();
            Pack::$size++;
            Pack::$member[$id[$i]]->hunger = $v->y;
            Pack::$member[$id[$i]]->ttl = self::$turn;
        }

        // line 2: member positions
        Pack::$own_preds = array();
        foreach (Pack::read_line($lines[2]) as $i=>$pos)
        {
            Pack::$member[$id[$i]]->pos = $pos;
            Pack::$own_preds[] = $pos;
        }

        // lines 3 to 2*#members+3: coordinates of all visible preys and predators
        $preys = array();
        $preds = array();
        $y_seen = array();
        $d_seen = array();
        for ($i = 0 ; $i != Pack::$size ; $i++)
        {
            // visible preys
            foreach (Pack::read_line($lines[2*$i+3]) as $coords)
            {
                if (!in_array ($coords, $preys) || !isset($y_seen[(string)$coords]))
                {
                    $preys[] = $coords;
                }
            }
            foreach ($preys as $p) $y_seen[(string)$p] = true;

            // visible predators
            foreach (Pack::read_line($lines[2*$i+4]) as $coords)
            {
                if (!in_array ($coords, $preds) || !isset($d_seen[(string)$coords]))
                {
                    $preds[] = $coords;
                }
            }
            foreach ($preds as $p) $d_seen[(string)$p] = true;
        }

        // remove dead members
        foreach (Pack::$member as $k => $m)
        {
            if ($m->ttl != self::$turn)
            {
                unset (Pack::$member[$k]);
            }
        }

        // filter out own positions from predators list
        Pack::$foe_preds = array_diff ($preds, Pack::$own_preds);
        Pack::$preds = Pack::$foe_preds;
        foreach (Pack::$own_preds as $p) Pack::$preds[] = $p;
        Pack::$preys = $preys;

        // done
        return true;
    }

    function output_moves ()
    {
        $output = array();
        foreach (Pack::$output_order as $i)
        {
            $output[] = Pack::$member[$i]->move->x;
            $output[] = Pack::$member[$i]->move->y;
        }
        echo implode ("\t", $output) . "\0";
    }

    static function point_closest_to_walls ($pos)
    {
        $delta = $pos->vector_to (Pack::$arena_center);
        if (abs ($delta->x) > abs ($delta->y))
        {
            $y = $pos->y;
            $x = $delta->x > 0 ? -1 : ARENA_SIZE+1;
        }
        else
        {
            $x = $pos->x;
            $y = $delta->y > 0 ? -1 : ARENA_SIZE+1;
        }
        return new Point ($x, $y);
    }

    static function in_arena ($pos)
    {
        $delta = $pos->vector_to (Pack::$arena_center);
        return abs ($delta->x) <= ARENA_SIZE/2 && abs ($delta->y) <= ARENA_SIZE/2;
    }

    static function clamp_to_arena (&$pos)
    {
        // mimics the slightly strange behaviour of the Java engine setInZeroBounds function
        if ($pos->x >= ARENA_SIZE) $pos->x = ARENA_SIZE-1; // should rather be ARENA_SIZE
        if ($pos->x <           0) $pos->x = 0;
        if ($pos->y >= ARENA_SIZE) $pos->y = ARENA_SIZE-1;
        if ($pos->y <           0) $pos->y = 0;
    }

    function get_closest ($pos, $set, $max_dist)
    {
        // check for empty set
        if (count ($set) == 0) return null;

        // construct an array of distances with the same indexes as the points
        $dist = array();
        $max_dist *= $max_dist;
        foreach ($set as $k=>$pt)
        {
            $d = $pos->vector_to($pt)->norm2();
            if ($d <= $max_dist) $dist[$k] = $d;
        }
        if (count($dist) == 0) return false;

        // get the key of the smallest distance and use it to retrieve the closest point
        $keys = array_keys ($dist, min($dist));
        return $set[$keys[0]];
    }

    function get_visible ($pos, $set)
    {
        $res = array();
        $skipped = false;
        $pts = 0;
        foreach ($set as $point)
        {
            $d = $pos->vector_to($point)->norm2();
            if ($d == 0 && !$skipped)
            {
                $skipped = true;
                continue; // skip ourself
            }
            if ($d > PREY_VISION2) continue; // skip far points
            $res[] = $point;
            if ($pts++ > 10) break; // too many points are useless since prediction will go haywire anyway
        }
        return $res;
    }
}
Pack::init();

class PackMember {
    public $pos; // current position
    public $ttl; // last turn reported alive

    function move_to ($goal)
    {
        $this->move = $this->pos->vector_to ($goal);
    }

    function intercept ($target_pos, $target_speed)
    {
        // change reference to position difference
        $delta = $this->pos->vector_to($target_pos);
        $i = $delta->normalize();
        $j = $i->rotate90();

        // match tangential speeds
        $vj = $target_speed->dot ($j);

        // deduce axial speed
        $vi = PRED_SPEED2 - $vj*$vj; // this should always be positive since predators are faster than preys
        $vi = sqrt ($vi);

        // return intercept speed in original reference coordinates
        return $i->multiply($vi)->add($j->multiply($vj));
    }
}

class Target {
    public $pos;      // current position
    public $pos_next; // predicted position
    public $speed;    // estimated speed

    function __construct ($pos)
    {
        $this->pos    = $pos;
        $this->speed  = new Point(0,0);
        $this->predict();
    }

    private function predict()
    {
        // predators contribution
        $preds = Pack::get_visible ($this->pos, Pack::$preds);
        $this->preds = count ($preds);
        $res = new Point();
        foreach ($preds as $predator)
        {
            $res = $res->add ($predator->vector_to ($this->pos));
        }
        $res = $res->multiply (2);

        // preys contribution
        $preys = Pack::get_visible ($this->pos, Pack::$preys);
        $this->preys = count ($preys);

        $f_cohesion  = new Point;
        $f_separate  = new Point();
        foreach ($preys as $prey)
        {
            $delta = $this->pos->vector_to ($prey);
            $d2 = $delta->norm2();
            if ($d2 != 0)
            {
                $f_cohesion  = $f_cohesion ->add ($delta->multiply ($d2));
                $f_separate  = $f_separate ->add ($delta->multiply (-1/$d2));
            }
        }

        $res = $res
        ->add ($this->speed->normalize(5*.96)) // assume all preys have same speed as target
        ->add ($f_cohesion ->normalize(5*1))
        ->add ($f_separate ->normalize(5*1));
        $delta = $this->pos->vector_to(Pack::$arena_center);
        $dist = max (abs($delta->x), abs($delta->y));
        if ($dist > (ARENA_SIZE/2-WALL_BOUNCE))
        {
            $res = $res->add ($delta->normalize(5*4));
        }

        $this->raw_speed = $res;
        $this->speed = $res->limit(PREY_SPEED);
        $this->pos_next = $this->pos->add ($this->speed);
        Pack::clamp_to_arena ($this->pos_next);
    }

    function track ()
    {
        // see if we can find our prey at the start of a new turn
        $min = 1e10;
        foreach (Raptors::$free_preys as $k=>$prey)
        {
            $dist = abs ($this->pos_next->x - $prey->x) + abs ($this->pos_next->y - $prey->y);
            if ($dist < $min)
            {
                $min = $dist;
                $new_pos = $prey;
                $new_k = $k;
                if ($min < .001) break;
            }
        }
        if ($min > MAX_TRACK_ERROR) return false;

        // remove this prey from free preys
        unset(Raptors::$free_preys[$new_k]);

        $delta = $new_pos->vector_to($this->pos_next);

        // update postion and speed
        if ($this->speed->norm2() == 0)
        {
            // this can be either an endgame prey not yet moving
            // OR initial speed for a new target
            $this->speed = $this->pos->vector_to ($new_pos);
        }
        $this->pos = $new_pos;

        // predict speed and position
        $this->predict();
        return true;
    }
}

class Raptor extends PackMember {

    // possible states
    const IDLE     = 1;
    const TRACKING = 2;
    const HUNTING  = 3;
    const RUSHING  = 4;
    public $state;

    public  $target;  // current prey
    public  $patrol;  // patrol governor

    private static $id_gen;

    function __construct ()
    {
        $this->patrol = new Search (++self::$id_gen);
        $this->target  = null;
        $this->state = Raptor::IDLE;
        $this->pos = null;
        $this->hunger = HUNGER_MAX;
    }

    function __destruct ()
    {
        $this->tracking_lost();
    }

    function tracking_lost()
    {
        $this->target  = null;
        $this->state = Raptor::IDLE;
    }

    function track_prey()
    {
        // stop tracking if hunger went back to max
        if ($this->hunger == HUNGER_MAX)
        {
            $this->tracking_lost();
        }

        // try to acquire a new target
        if (!$this->target)
        {
            $victim = Pack::get_closest ($this->pos, Raptors::$free_preys, PRED_VISION);
            if (!$victim) return;
            $this->target = new Target ($victim);
            $this->state = Raptor::TRACKING;
        }

        // track prey
        if (!$this->target->track (Pack::$preys))
        {
            // prey was eaten or move prediction failed
            $this->tracking_lost();
        }
    }

    function beat_competition ()
    {
        if ($this->target === null) return;
        $pm = $this->target->pos_next->vector_to ($this->pos);
        $dm = $pm->norm2();
        foreach (Pack::$foe_preds as $f)
        {
            $pf = $this->target->pos_next->vector_to($f);
            $df = $pf->norm2();
            if ($df > PRED_VISION2) continue;
//          if ($df < ($dm*2))
            {
                $this->state = Raptor::RUSHING;
                return;
            }
        }
        if ($this->state == Raptor::RUSHING) $this->state = Raptor::TRACKING;
        return;
    }
}

class Raptors extends Pack {
    public static $free_preys; // coordinates of all preys that are not targeted

    // allows generic Pack to create a proper pack member instance
    static function new_member()
    {
        return new Raptor();
    }

    // main AI loop
    static function think ()
    {
        $hunger_limit = Pack::$n_preys > 2 * Pack::$n_preds ? TRACKING_HUNGER_START : TRACKING_HUNGER_END;
        self::$free_preys = static::$preys;

        // update targets and members states
        foreach (Pack::$member as $m)
        {
            // track current targets
            $m->track_prey();

            // rush to target if a competitor draws near
            $m->beat_competition();

            // hunt if hungry enough
            if ($m->state == Raptor::TRACKING && $m->hunger < $hunger_limit)
            {
                $m->state = Raptor::HUNTING;
            }
        }

        // move members
        foreach (Pack::$member as $m)
        {
            switch ($m->state)
            {
            case Raptor::IDLE:
                $destination = $m->patrol->point($m->pos);
                break;
            case Raptor::TRACKING:
                $wall_point = Pack::point_closest_to_walls ($m->target->pos_next);
                $destination = $wall_point->vector_to ($m->target->pos_next)->normalize (TRACKING_DISTANCE)->add($m->target->pos_next);
                break;
            case Raptor::HUNTING:
                $wall_point = Pack::point_closest_to_walls ($m->target->pos_next);
                $to_hunter = $m->target->pos_next->vector_to ($m->pos);
                $dist_to_target = $to_hunter->norm();

                if ($dist_to_target > (PREY_VISION-PREY_SPEED)) // intercept the prey
                {
                    // use actual speed (i.e. true position delta, including wall stops)
                    $target_true_speed = $m->target->pos->vector_to ($m->target->pos_next);
                    $intercept_speed = $m->intercept ($m->target->pos, $target_true_speed);
                    $destination = $m->pos->add ($intercept_speed);
                }
                else if ($dist_to_target < PRED_SPEED) // pounce on the prey!
                {
                    $destination = $m->target->pos_next;
                }
                else if ($to_hunter->dot($m->target->speed) > 0)
                {
                    $destination = $m->target->pos_next;
                }
                else // goad the prey
                {
                    $to_wall = $m->target->pos->vector_to ($wall_point);
                    $wall_point = $wall_point;
                    $raw_speed = $m->target->raw_speed->add($m->target->pos->vector_to($m->pos)->multiply(2))->multiply (-0.5);
                    $wpd_t = $m->target->pos->vector_to ($wall_point)->normalize()->rotate90(); // wpd = Wanted Prey Direction
                    $delta = $wpd_t->multiply ($raw_speed->dot ($wpd_t));
                    $destination = $delta->vector_to ($m->target->pos_next);
                    if (!Pack::in_arena ($destination)) $destination = $m->target->pos_next;
                }
                break;
            case Raptor::RUSHING:
                $destination = $m->target->pos_next;
                break;
            }
            $m->move_to ($destination);
        }
    }
}

while (Raptors::read_input())
{
    Raptors::think();
    Raptors::output_moves();
}
?>

সাধারণ বিবেচ্য বিষয়

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

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

  • একটি শিকার আন্দোলনের পূর্বাভাসকারী মূলত বাধ্যতামূলক। আপনার নিজের ভবিষ্যদ্বাণী না করে ভবিষ্যদ্বাণীভিত্তিক প্রোগ্রামটি মারধর করার আমি কল্পনা করতে পারি না।

লেজ তাড়া

শিকারটিকে ধরার সবচেয়ে অদক্ষ উপায় হল এটির পিছনে তাড়া করা। একক শিকারী একা শিকারের পিছনে তাড়া করে এবং কোনও বাহ্যিক প্রভাব (দেয়াল, অন্যান্য প্রি, ইত্যাদি) ধরে নিলে, একটি লেজ তাড়া চিরকাল স্থায়ী হতে পারে। আপনি 30 ইউনিটের শিকার দর্শনের ব্যাসার্ধের প্রবেশের সাথে সাথে শিকারটি আপনার 6.1 এর গতি 6 হিসাবে ছুটে যায়, সুতরাং আপনি প্রতি ঘুরে .1 দূরত্ব অর্জন করেন: একটি সরল রেখায়, এটি পেতে আপনার প্রায় 300 টার্ন প্রয়োজন।

ক্ষেত্রের আকারটি বিবেচনায় নিয়ে, কোনও প্রাচীর বা কোণে আঘাত করার আগে একটি শিকার 500 ইউনিট বর্গক্ষেত্রের সর্বাধিক তির্যক ভ্রমণ করবে, এতে প্রায় 117 টি মোড় নেবে।

বিজয়ী কৌশলটি স্পষ্টতই শিকারগুলির গতি কমিয়ে দেওয়ার উপায় খুঁজে পাবে, যার সামনে অন্য কোনও শিকারী বা তার সামনে কোনও প্রাচীর / কোণা রয়েছে।

predictor

6 এর শিকারের গতিতে একটি শিকার 36 * পাই ইউনিট স্কোয়ারের অঞ্চলে যেতে পারে। 1 এর আকর্ষণীয় ব্যাসার্ধের সাথে, শিকারটি পরবর্তী দিকে কোথায় থাকবে সে সম্পর্কে অন্ধ অনুমানের 1/36 * পাই (প্রায় 1%) সফল হওয়ার সুযোগ রয়েছে। স্পষ্টতই কিছুটা বাড়ানোর দরকার আছে!

সিমুলেশন ইঞ্জিন কোডটি দেখে আপনি দেখতে পাবেন যে ইনপুটগুলি হ'ল:

  • দৃশ্যমান শিকার এবং শিকারী অবস্থান
  • পূর্ববর্তী শিকারের গতি

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

একক শিকারের ক্ষেত্রে, খুব বেশি সমস্যা ছাড়াই গতিটি ট্র্যাক করা যেতে পারে, যা ঝাঁক থেকে বিচ্ছিন্ন শিকারকে ধরতে একটি "নিখুঁত" ভবিষ্যদ্বাণী তৈরি করতে দেয়। প্রিমগুলি একে অপরের সাথে ইন্টারঅ্যাক্ট করার জন্য খুব কম হলে মূলত এন্ডগেমের জন্য আপনার যা প্রয়োজন তা হ'ল। যখন শিকারগুলি প্রচুর পরিমাণে হয় এবং ঝাঁকজোর প্রভাব ভবিষ্যদ্বাণীকে বোকা বানানোর পক্ষে যথেষ্ট শক্তিশালী হয়, তখন প্রাইসের নিখুঁত ঘনত্ব ত্রুটিগুলির জন্য ক্ষতিপূরণ দেয় (যদি আপনি যার জন্য লক্ষ্য রেখেছিলেন, এটি ধরেন না, তবে সম্ভাবনা রয়েছে যে আপনি তার নিকটতম বন্ধুদের মধ্যে একটি পাবেন) )।

গোডিং প্রি

শিকারের গতির গণনার সঠিক জ্ঞানের সাথে, শিকারীর অবস্থানকে সামঞ্জস্য করে একটি পছন্দসই শিকারকে একটি পছন্দসই দিকের দিকে চালিত করা সম্ভব।

এটি কোনও প্রাচীরের বিরুদ্ধে একটি শিকারকে পিন করতে বা অন্য প্যাক সদস্যের দিকে পরিচালিত করতে সহায়তা করে। আমি দুটি প্যাক সদস্যের মধ্যে শিকারকে চিমটি দেওয়ার মতো কয়েকটি পরিশ্রুত কৌশল চেষ্টা করেছি। দুর্ভাগ্যক্রমে, এটি বর্তমান "পিন এবং স্ক্যান" রুটিনের চেয়ে কম দক্ষ প্রমাণিত হয়েছে, যেহেতু দুটি শিকারীকে একটি শিকারকে তাড়া করতে ব্যস্ত রাখার ফলে বিরোধীরা অনেক বেশি শিকারীকে চারণভূমিতে মুক্ত রাখতে পারে না leaves

চুরি চুরি

শিকারের আচরণের একটি বৈশিষ্ট্য হ'ল শিকারীর প্রভাব শিকার থেকে তার দূরত্বের সাথে আনুপাতিকভাবে বৃদ্ধি পায় (তবে এটি শিকার দৃষ্টি ব্যাসার্ধের মধ্যে থাকে)। নিকটতম কোনও শিকারী শিকারে আসে, কমপক্ষে শিকার এটি থেকে দূরে চলে যাবে।

এর অর্থ হ'ল যখন দুটি শিকারী শিকার শিকার করার জন্য প্রতিযোগিতা করে, তখন নিকটতমটি প্রথমে এটি পেতে বাধ্য হয়। এমনকি একটি দুর্দান্ত স্মার্ট প্রতিযোগী যা চেজার / শিকার অক্ষের সামনে নিজেকে ঠিক পরিচালনা করতে পারে মূলত প্রতিযোগীর চোয়ালের মধ্যে শিকারকে ভয় দেখায়।

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

এছাড়াও, দিকনির্দেশের প্রতিটি পরিবর্তন প্রতিযোগিতাটিকে শিকারের দিকে কাটাতে অনুমতি দেয় এবং প্রতিযোগীর পিছনে রাখা কেবল তখনই সম্ভব যখন "গোডার" ক্রিয়াকলাপের শুরুতে শিকারের কাছাকাছি থাকলে।

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

প্রস্তাবিত পরিবর্তনসমূহ

আরও জটিল কৌশলগুলির জন্য অনুমতি দেওয়ার জন্য, শিকারী শীর্ষ গতির উপরে শিকারীকে সরিয়ে নেওয়া ক্ষুধা পয়েন্টগুলিতে ব্যয় হতে পারে, অতিরিক্ত গতির তুলনায় আনুপাতিক। উদাহরণস্বরূপ বলুন 6 গতিতে চলে যাওয়া নিখরচায় এবং 6 গতির উপরে প্রতিটি গতি পয়েন্ট 100 টি ক্ষুধার্ত পয়েন্টের দাম পড়বে (6.3 এর জন্য প্রতি 30 টি ক্ষুধার্ত পয়েন্ট পড়বে, 1000 ক্ষুধার্ত পয়েন্টগুলি এক বারের জন্য 16 গতিতে পৌঁছাতে পারবে - এবং আপনি ডান না হলে মারা যান) এমন করে শিকারকে ধরবে না!)।

একাধিক শিকার শিকার খাওয়ার জন্য কাছে এলে এলোমেলো শিকারীকে কিল দেওয়ার পরিবর্তে, আমি লাভটি ভাগ করার পরামর্শ দিই (উদাহরণস্বরূপ 3 শিকারি প্রত্যেকে ৩৩৩.৩৩ টি ক্ষুধা পয়েন্ট পাবেন)। এটি আরও অন্তর্নিহিত এন্ডগেম কৌশলগুলির জন্য মঞ্জুরি দেয় (উদাহরণস্বরূপ, যদি আপনার আরও ক্ষুধা পয়েন্ট থাকে তবে আপনি যদি শত্রু শিকারীর ছায়া কাটা দরকারী হন))

প্রথম প্যাকটির জন্য বিশেষ রঙটি দেখতে এটি বরং কঠিন। আমি নীল পরিবর্তে সায়ান বা কমলা প্রস্তাব দিই।


শেষ পর্যন্ত আরেক প্রতিযোগী! শিকারের চুরি ব্যতীত আপনার উল্লিখিত প্রতিটি পয়েন্ট আমি উদ্দেশ্যমূলকভাবে প্রয়োগ করেছি, যার জন্য আমি বর্তমান পার্শ্ব-প্রতিক্রিয়ায় সন্তুষ্ট ছিলাম। আপনার মন্তব্য থেকে মনে হচ্ছে আপনি আমার দাবীদার বিরুদ্ধে জিতেছেন? এটি আকর্ষণীয়, আমি আগামীকাল পরীক্ষা করব। = ডি। এছাড়াও, আপনি আরও ভাল (কমপক্ষে আমার মতে) গ্রাফিকগুলি দেখতে আমার জিইউআই আপডেটটি চেষ্টা করতে পারেন।
justhalf

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

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

এটি আপনার জন্য ভেক্টর পাটিগণিত :) :) এটিই আমি আমার পোস্টে ব্যাখ্যা করার চেষ্টা করেছি: একক শিকারের জন্য, আপনি সমস্ত চলাচলের পরামিতিগুলি (পূর্ববর্তী গতি অন্তর্ভুক্ত) জানেন so

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

3

অলস প্যাক হাস্কেল

import Control.Monad
import Control.Concurrent

main :: IO ()
main=do
    t<-forkIO $ forever $ (putStrLn "Pack is paralyzed with indecision.\0")
    loop
    killThread t
        where
            loop=do
                line <- getLine
                case line of
                    "dead\0" -> return ()
                    _        -> loop

এটি চালানোর জন্য আপনার হ্যাশেল প্ল্যাটফর্মের প্রয়োজন হবে । তারপরে আপনি runhaskellএটি চালানোর জন্য কমান্ডটি ব্যবহার করুন । আমার প্যাকটি তাদের কাছে শিকারের জন্য অপেক্ষা করে।


একটি নতুন ভাষায় কঙ্কাল সমাধানের জন্য +1। সম্ভবত মানুষ এর উপরে নতুন কৌশল তৈরি করতে খুশি?
ট্রাইকোপল্যাক্স

অবশ্যই, কেন না। (যদিও, এটি ধ্রুবক আউটপুট উত্পাদন করা এবং "মৃত \ 0" এ ছাড়ার পাশাপাশি কিছু করে না, সুতরাং এটি খুব দরকারী হবে কিনা তা সম্পর্কে আমি নিশ্চিত নই))
পাইরুলেজ

আমি এখনও এই -silentবিকল্পটি ব্যবহার করার জন্য যে কেউ এটি
চালনাতে পরামর্শ দেব

3

কোনও এন্ট্রি নয়, আমি সর্বদা অংশগ্রহণকারীদের প্রবেশের জন্য কাস্টমাইজড রঙ যুক্ত করতে আগ্রহী ;)

এবং খাওয়ার প্রক্রিয়াটি রঙ পরিবর্তন করে ভিজ্যুয়ালাইজ করা হয় না, পরিবর্তে আকার পরিবর্তন করা হয়, যাতে আমরা স্বল্প সময়ে একাধিক খাওয়ার ঘটনা দেখতে পাই।

Game.java

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.swing.JFrame;

public class Game {

    static int preyStartCount = 0; // 0 means 1500 + (packs * 50)
    static int turn;
    static boolean silent = false;
    long startTime;

    JFrame frame;
    BufferedImage img;
    Color[] colors;

    Island map;
    List<Prey> preys;
    List<Predator> predators;
    List<Pack> packs;
    List<Pack> initPacks;

    public static void main(String[] args) throws InterruptedException {

        Game game = new Game();
        game.init(args);
        if (game.packs.size() > 0){
            game.run();
            game.score();
        }
        game.end();
    }

    void end() {
        frame.setVisible(false);
        frame.dispose();
        for (Pack pack : packs)
            pack.handler.end();
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
        } finally {
            for (Pack pack : packs)
                pack.handler.shutdown();
        }

        System.exit(0);
    }

    void score() {
        Collections.sort(initPacks);
        int score = 100;
        initPacks.get(0).score = score;
        for (int i = 1; i < initPacks.size(); i++) {
            Pack pack = initPacks.get(i);
            if (pack.extinctionTurn < initPacks.get(i - 1).extinctionTurn)
                score = score < 1 ? score : score * 80 / 100;
            pack.score = score;
        }
        print("", true);
        print("Done in " + getElapsedTime(), true);
        for (Pack pack : initPacks)
            print(pack.toString() + "\t: Turn " + pack.extinctionTurn + "\t: Score " + pack.score, true);
    }

    String getElapsedTime(){
        double elapsed = (System.currentTimeMillis() - startTime) / 1000d;
        if(elapsed < 60)
            return String.format("%.2f", elapsed) + " seconds";
        elapsed /= 60;
        if(elapsed < 60)
            return String.format("%.2f", elapsed) + " minutes";
        elapsed /= 60;
        return String.format("%.2f", elapsed) + " hours";       
    }


    public Game() {
        initPacks = new ArrayList<Pack>();
        packs = new ArrayList<Pack>();
        preys = new ArrayList<Prey>();
        predators = new ArrayList<Predator>();
    }

    void run() throws InterruptedException {
        frame.setVisible(true);
        turn = 0;
        Graphics2D g = img.createGraphics();

        printStatus();
        while (true) {
            turn++;

            getAllMoves();
            moveAll();
            spawn();
            removeDead();
            shuffle();

            if (turn % 500 == 0)
                printStatus();
            paint(frame, g);
            Thread.sleep(5);
            if (packs.size() < 1)
                break;
        }
    }

    void getAllMoves(){
        for (Prey prey : preys)
            prey.setNextMove();
        for (Pack pack : packs){    
            pack.talk(preys.size(), predators.size(), turn);
        }
        while(true){
            int doneCount = 0;
            for(Pack pack : packs)
                if(pack.doneTalking)
                    doneCount++;
            if(doneCount >= packs.size())
                break;
            try {Thread.sleep(1);}catch(InterruptedException e){}
        }
    }

    void moveAll(){
        for (Creature prey : preys) 
            prey.move();
        for(Pack pack : packs){
            for (Predator predator : pack.members) {
                predator.move();
                predator.eatOrStarve();
            }
        }
    }

    void paint(JFrame frame, Graphics2D g){
        g.setPaint(Color.BLACK);
        g.fillRect(0, 0, img.getWidth(), img.getHeight());

        for(Prey prey : preys)
            prey.paint(g);
        for(Pack pack : packs)
            for(Predator predator : pack.members)
                predator.paint(g);

        frame.repaint();
    }

    List<Prey> deadPreys;
    List<Predator> deadPredators;
    List<Pack> deadPacks;

    void removeDead(){
        deadPreys.clear();
        for (Prey prey : preys)
            if (!prey.alive)
                deadPreys.add(prey);
        preys.removeAll(deadPreys);

        deadPredators.clear();
        for (Predator predator : predators)
            if (!predator.alive)
                deadPredators.add(predator);
        predators.removeAll(deadPredators);

        deadPacks.clear();
        for (Pack pack : packs)
            if (!pack.alive)
                deadPacks.add(pack);
        packs.removeAll(deadPacks);

        for (Pack pack : packs) {
            pack.members.removeAll(deadPredators);
        }

        map.rebuildLists(preys, predators);
    }

    void shuffle(){
        Collections.shuffle(packs);
        for(Pack pack : packs)
            Collections.shuffle(pack.members);
    }

    void spawn(){
        if(turn % 5000 == 0)
            addPredators(1);
        if(turn % 1000 == 0)
            populatePrey(predators.size()-1, false);
    }

    void addPredators(int count){
        for(Pack pack : packs){
            if(!pack.alive)
                continue;
            if(pack.aliveCount == 0)
                continue;
            Predator parent = null;
            for(Predator predator : pack.members)
                if(predator.alive)
                    parent = predator;
            if(parent != null){
                for(int i=0;i<count;i++){
                    XY pos = new XY(Math.random() * 30, Math.random()   * 30);
                    pos.add(parent.pos);
                    pos.setInZeroBounds(Island.SIZE, Island.SIZE);
                    Predator child = new Predator(pack);
                    child.color = colors[pack.id];
                    child.moveTo(pos, Island.getCellByPosition(pos));
                    predators.add(child);
                    pack.members.add(child);
                    pack.aliveCount++;
                }
            }
        }
    }

    Color[] generateColors(int n){
        Color[] result = new Color[n];
        double maxR = -1000;
        double minR = 1000;
        double maxG = -1000;
        double minG = 1000;
        double maxB = -1000;
        double minB = 1000;
        double[][] colors = new double[n][3];
        for(int i=0; i<n; i++){
            double cos = Math.cos(i * 2 * Math.PI / n);
            double sin = Math.sin(i * 2 * Math.PI / n);
            double bright = 1;
            colors[i][0] = bright + sin/0.88;
            colors[i][1] = bright - 0.38*cos - 0.58*sin;
            colors[i][2] = bright + cos/0.49;
            maxR = Math.max(maxR, colors[i][0]);
            minR = Math.min(minR, colors[i][0]);
            maxG = Math.max(maxG, colors[i][1]);
            minG = Math.min(minG, colors[i][1]);
            maxB = Math.max(maxB, colors[i][2]);
            minB = Math.min(minB, colors[i][2]);
        }
        double scaleR = 255/(maxR-minR);
        double scaleG = 255/(maxG-minG);
        double scaleB = 255/(maxB-minB);
        for(int i=0; i<n; i++){
            int R = (int)Math.round(scaleR*(colors[i][0]-minR));
            int G = (int)Math.round(scaleG*(colors[i][1]-minG));
            int B = (int)Math.round(scaleB*(colors[i][2]-minB));
            result[i] = new Color(R,G,B);
        }
        return result;
    }

    void populatePredators(String[] args) {
        int start = 0;
        if(args[0].equals("-silent")){
            silent = true;
            start = 1;
        }

        colors = generateColors(args.length-start);
        if(colors.length==1){
            colors[0] = Color.BLUE;
        }

        for (int i = start; i < args.length; i++) {
            Pack pack = new Pack(args[i]);
            if (pack.handler.init()) {
                packs.add(pack);
                initPacks.add(pack);
            }
        }
        Collections.shuffle(packs);
        XY[] positions = map.getPackStartLocations(packs.size());
        XY offset = new XY(-15, -15);
        for(int i=0;i<packs.size();i++){
            Pack pack = packs.get(i);
            for (Predator predator : pack.members) {
                predator.color = colors[pack.id];
                XY pos = new XY(Math.random() * 30, Math.random()   * 30);
                pos.add(positions[i]);
                pos.add(offset);
                pos.setInZeroBounds(Island.SIZE, Island.SIZE);
                predator.moveTo(pos, Island.getCellByPosition(pos));
                predators.add(predator);
            }
        }
        deadPredators = new ArrayList<Predator>(predators.size());
        deadPacks = new ArrayList<Pack>(packs.size());
    }

    void populatePrey(int count, boolean center) {
        XY pos = new XY();
        for (int i = 0; i < count; i++) {
            Prey prey = new Prey();
            if(center){
                pos.x = Math.random() * 100 + 200;
                pos.y = Math.random() * 100 + 200;
            } else {
                pos.x = Math.random() * 500;
                pos.y = Math.random() * 500;
            }

            prey.moveTo(pos, Island.getCellByPosition(pos));
            preys.add(prey);
        }
        deadPreys = new ArrayList<Prey>(preys.size());
    }

    static void print(String txt){
        print(txt, false);
    }

    static void print(String txt, boolean override){
        if(!silent || override)
            System.out.println(txt);
    }

    void printStatus(){
        print("Turn " + turn + " : Prey " + preys.size()
                + " : Predators " + predators.size() + " (" + getElapsedTime() + " elapsed)");
    }

    @SuppressWarnings("serial")
    void init(String[] args) {
        startTime = System.currentTimeMillis();
        map = new Island();
        populatePredators(args);
        if (preyStartCount == 0)
            preyStartCount = 1500 + (packs.size() * 50);

        populatePrey(preyStartCount, true);
        map.rebuildLists(preys, predators);
        img = new BufferedImage(Island.SIZE, Island.SIZE, 1);
        frame = new JFrame() {
            @Override
            public void paint(Graphics g) {
                g.drawImage(img, 32, 32, null);
            }
        };
        frame.setSize(Island.SIZE+64, Island.SIZE+64);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                for (Pack pack : packs)
                    pack.handler.end();
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                } finally {
                    for (Pack pack : packs)
                        pack.handler.shutdown();
                }
            }
        });
    }
}

Predator.java

import java.awt.Graphics2D;


public class Predator extends Creature {

    static int count = 0;

    int id;
    int hunger;
    Pack pack;

    public Prey eatOrStarve() {
        for (Prey prey : preys) {
            if (prey.alive && pos.isCloserThan(prey.pos, eatDist)) {
                prey.die();
                hunger = MAX_HUNGER;
                return prey;
            }
        }
        if (hunger-- < 1)
            die();
        return null;
    }

    @Override
    public void die() {
        super.die();
        pack.aliveCount--;
        Game.print(pack.toString() + " starved! " + pack.aliveCount + " members remaining.");
    }

    @Override
    void paint(Graphics2D g){
        g.setPaint(color);
        int size = ((hunger + 10) > MAX_HUNGER && Game.turn > 10) ? 3+(int)Math.pow((hunger+10-MAX_HUNGER)/4,3) : 3;
        g.drawOval((int)pos.x - 1, (int)pos.y - 1, size, size);
        g.fillOval((int)pos.x - 1, (int)pos.y - 1, size, size);
    }

    Predator(Pack pack) {
        super();
        id = count++;
        this.pack = pack;
        MAX_SPEED = 6.1;
        VISIBLE = 50;
        hunger = MAX_HUNGER;
    }

    final double eatDist = 1;
    final static int MAX_HUNGER = 1000;
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.